parent
45d37e275d
commit
96bbca6191
|
@ -341,7 +341,7 @@ namespace Kernel
|
||||||
* \retval -1 failed
|
* \retval -1 failed
|
||||||
*
|
*
|
||||||
* If the call returns successful the callers UTCB provides
|
* If the call returns successful the callers UTCB provides
|
||||||
* a valid reply message and its size.
|
* a valid reply message and its metadata.
|
||||||
*/
|
*/
|
||||||
inline int request_and_wait(unsigned const id)
|
inline int request_and_wait(unsigned const id)
|
||||||
{
|
{
|
||||||
|
@ -352,23 +352,33 @@ namespace Kernel
|
||||||
/**
|
/**
|
||||||
* Wait for next IPC request, discard current request
|
* Wait for next IPC request, discard current request
|
||||||
*
|
*
|
||||||
* \return size of received request (beginning with the callers UTCB base)
|
* \retval 0 succeeded
|
||||||
|
* \retval -1 failed
|
||||||
|
*
|
||||||
|
* If the call returns successful the callers UTCB provides
|
||||||
|
* a valid request message and its metadata.
|
||||||
*/
|
*/
|
||||||
inline size_t wait_for_request() {
|
inline int wait_for_request()
|
||||||
return (size_t)syscall(WAIT_FOR_REQUEST); }
|
{
|
||||||
|
return (int)syscall(WAIT_FOR_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reply to last IPC request
|
* Reply to last IPC request
|
||||||
*
|
*
|
||||||
* \param size reply size (beginning with the callers UTCB base)
|
|
||||||
* \param await_request if the call shall await and fetch next request
|
* \param await_request if the call shall await and fetch next request
|
||||||
*
|
*
|
||||||
* \return request size (beginning with the callers UTCB base)
|
* \retval 0 succeeded
|
||||||
* if await_request was set
|
* \retval -1 failed to receive request
|
||||||
|
*
|
||||||
|
* If await_request = 1 and the call returns successful the callers UTCB
|
||||||
|
* provides a valid request message and its metadata.
|
||||||
*/
|
*/
|
||||||
inline size_t reply(size_t const size, bool const await_request) {
|
inline int reply(bool const await_request)
|
||||||
return (size_t)syscall(REPLY, size, await_request); }
|
{
|
||||||
|
return (int)syscall(REPLY, await_request);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -38,68 +38,25 @@ enum
|
||||||
***************/
|
***************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Limit message size to the size of UTCB and message buffer
|
* Copy message from the callers UTCB to message buffer
|
||||||
*/
|
*/
|
||||||
void limit_msg_size(Msgbuf_base * const msgbuf, Native_utcb * const utcb,
|
static void utcb_to_msgbuf(Msgbuf_base * const msgbuf)
|
||||||
size_t & size)
|
|
||||||
{
|
|
||||||
if (size > utcb->size() || size > msgbuf->size()) {
|
|
||||||
kernel_log() << __PRETTY_FUNCTION__ << ": truncate message\n";
|
|
||||||
size = utcb->size() < msgbuf->size() ? utcb->size() : msgbuf->size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy message payload to message buffer
|
|
||||||
*/
|
|
||||||
static void utcb_to_msgbuf(Msgbuf_base * const msgbuf, size_t size)
|
|
||||||
{
|
|
||||||
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
|
||||||
limit_msg_size(msgbuf, utcb, size);
|
|
||||||
memcpy(msgbuf->buf, utcb->base(), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy message payload with size header to message buffer
|
|
||||||
*
|
|
||||||
* This function pioneers IPC messages with headers and will
|
|
||||||
* replace utcb_to_msgbuf sometime.
|
|
||||||
*/
|
|
||||||
static void sized_utcb_to_msgbuf(Msgbuf_base * const msgbuf)
|
|
||||||
{
|
{
|
||||||
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
||||||
size_t msg_size = utcb->ipc_msg_size();
|
size_t msg_size = utcb->ipc_msg_size();
|
||||||
if (msg_size > utcb->max_ipc_msg_size()) {
|
if (msg_size > msgbuf->size()) {
|
||||||
kernel_log() << "oversized IPC message\n";
|
kernel_log() << "oversized IPC message\n";
|
||||||
msg_size = utcb->max_ipc_msg_size();
|
msg_size = msgbuf->size();
|
||||||
}
|
}
|
||||||
memcpy(msgbuf->buf, utcb->ipc_msg_base(), msg_size);
|
memcpy(msgbuf->buf, utcb->ipc_msg_base(), msg_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy message payload to the UTCB
|
* Copy message from message buffer to the callers UTCB
|
||||||
*/
|
*/
|
||||||
static void msgbuf_to_utcb(Msgbuf_base * const msgbuf, size_t size,
|
static void msgbuf_to_utcb(Msgbuf_base * const msg_buf, size_t msg_size,
|
||||||
unsigned const local_name)
|
unsigned const local_name)
|
||||||
{
|
|
||||||
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
|
||||||
*(unsigned *)utcb->base() = local_name;
|
|
||||||
size += sizeof(local_name);
|
|
||||||
limit_msg_size(msgbuf, utcb, size);
|
|
||||||
memcpy((unsigned *)utcb->base() + 1, (unsigned *)msgbuf->buf + 1, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy message payload with size header to the UTCB
|
|
||||||
*
|
|
||||||
* This function pioneers IPC messages with headers and will
|
|
||||||
* replace msgbuf_to_utcb sometime.
|
|
||||||
*/
|
|
||||||
static void msgbuf_to_sized_utcb(Msgbuf_base * const msg_buf, size_t msg_size,
|
|
||||||
unsigned const local_name)
|
|
||||||
{
|
{
|
||||||
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
||||||
enum { NAME_SIZE = sizeof(local_name) };
|
enum { NAME_SIZE = sizeof(local_name) };
|
||||||
|
@ -161,10 +118,10 @@ void Ipc_client::_call()
|
||||||
|
|
||||||
/* send request and receive reply */
|
/* send request and receive reply */
|
||||||
unsigned const local_name = Ipc_ostream::_dst.local_name();
|
unsigned const local_name = Ipc_ostream::_dst.local_name();
|
||||||
msgbuf_to_sized_utcb(_snd_msg, _write_offset, local_name);
|
msgbuf_to_utcb(_snd_msg, _write_offset, local_name);
|
||||||
int error = request_and_wait(Ipc_ostream::_dst.dst());
|
int error = request_and_wait(Ipc_ostream::_dst.dst());
|
||||||
if (error) { throw Blocking_canceled(); }
|
if (error) { throw Blocking_canceled(); }
|
||||||
sized_utcb_to_msgbuf(_rcv_msg);
|
utcb_to_msgbuf(_rcv_msg);
|
||||||
|
|
||||||
/* reset unmarshaller */
|
/* reset unmarshaller */
|
||||||
_write_offset = _read_offset = RPC_OBJECT_ID_SIZE;
|
_write_offset = _read_offset = RPC_OBJECT_ID_SIZE;
|
||||||
|
@ -204,14 +161,23 @@ void Ipc_server::_prepare_next_reply_wait()
|
||||||
void Ipc_server::_wait()
|
void Ipc_server::_wait()
|
||||||
{
|
{
|
||||||
/* receive next request */
|
/* receive next request */
|
||||||
utcb_to_msgbuf(_rcv_msg, Kernel::wait_for_request());
|
int const error = Kernel::wait_for_request();
|
||||||
|
if (!error) { utcb_to_msgbuf(_rcv_msg); }
|
||||||
|
else {
|
||||||
|
PERR("failed to receive request");
|
||||||
|
throw Blocking_canceled();
|
||||||
|
}
|
||||||
/* update server state */
|
/* update server state */
|
||||||
_prepare_next_reply_wait();
|
_prepare_next_reply_wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Ipc_server::_reply() { Kernel::reply(_write_offset, 0); }
|
void Ipc_server::_reply()
|
||||||
|
{
|
||||||
|
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
||||||
|
utcb->ipc_msg_size(_write_offset);
|
||||||
|
Kernel::reply(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Ipc_server::_reply_wait()
|
void Ipc_server::_reply_wait()
|
||||||
|
@ -223,9 +189,14 @@ void Ipc_server::_reply_wait()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* send reply and receive next request */
|
/* send reply and receive next request */
|
||||||
msgbuf_to_utcb(_snd_msg, _write_offset, Ipc_ostream::_dst.local_name());
|
unsigned const local_name = Ipc_ostream::_dst.local_name();
|
||||||
utcb_to_msgbuf(_rcv_msg, Kernel::reply(_write_offset, 1));
|
msgbuf_to_utcb(_snd_msg, _write_offset, local_name);
|
||||||
|
int const error = Kernel::reply(1);
|
||||||
|
if (!error) { utcb_to_msgbuf(_rcv_msg); }
|
||||||
|
else {
|
||||||
|
PERR("failed to receive request");
|
||||||
|
throw Blocking_canceled();
|
||||||
|
}
|
||||||
/* update server state */
|
/* update server state */
|
||||||
_prepare_next_reply_wait();
|
_prepare_next_reply_wait();
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,17 +95,24 @@ Pager_capability Pager_entrypoint::manage(Pager_object * const o)
|
||||||
|
|
||||||
void Ipc_pager::wait_for_first_fault()
|
void Ipc_pager::wait_for_first_fault()
|
||||||
{
|
{
|
||||||
/* receive message */
|
while (Kernel::wait_for_request()) { PERR("failed to receive fault"); }
|
||||||
size_t const s = Kernel::wait_for_request();
|
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
||||||
_wait_for_fault(s);
|
_wait_for_fault(utcb->ipc_msg_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Ipc_pager::wait_for_fault()
|
void Ipc_pager::wait_for_fault()
|
||||||
{
|
{
|
||||||
/* receive first message */
|
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
||||||
size_t const s = Kernel::reply(0, 1);
|
utcb->ipc_msg_size(0);
|
||||||
_wait_for_fault(s);
|
int err = Kernel::reply(1);
|
||||||
|
if (err) {
|
||||||
|
PERR("failed to receive fault");
|
||||||
|
while (Kernel::wait_for_request()) {
|
||||||
|
PERR("failed to receive fault");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_wait_for_fault(utcb->ipc_msg_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,7 +129,7 @@ void Ipc_pager::_wait_for_fault(size_t s)
|
||||||
|
|
||||||
/* message is a pagefault */
|
/* message is a pagefault */
|
||||||
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
||||||
Pagefault * const pf = (Pagefault *)utcb;
|
Pagefault * const pf = (Pagefault *)utcb->ipc_msg_base();
|
||||||
if (pf->valid())
|
if (pf->valid())
|
||||||
{
|
{
|
||||||
/* give our caller the chance to handle the fault */
|
/* give our caller the chance to handle the fault */
|
||||||
|
@ -140,11 +147,19 @@ void Ipc_pager::_wait_for_fault(size_t s)
|
||||||
|
|
||||||
/* message is a release request from a RM session */
|
/* message is a release request from a RM session */
|
||||||
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
||||||
Pagefault_resolved * const msg = (Pagefault_resolved *)utcb;
|
void * const msg_base = utcb->ipc_msg_base();
|
||||||
|
Pagefault_resolved * const msg = (Pagefault_resolved *)msg_base;
|
||||||
|
|
||||||
/* resume faulter, send ack to RM and get the next message */
|
/* resume faulter, send ack to RM and get the next message */
|
||||||
Kernel::resume_thread(msg->pager_object->badge());
|
Kernel::resume_thread(msg->pager_object->badge());
|
||||||
s = Kernel::reply(0, 1);
|
utcb->ipc_msg_size(0);
|
||||||
|
if (Kernel::reply(1)) {
|
||||||
|
PERR("failed to receive fault");
|
||||||
|
while (Kernel::wait_for_request()) {
|
||||||
|
PERR("failed to receive fault");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s = utcb->ipc_msg_size();
|
||||||
continue; }
|
continue; }
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
|
|
|
@ -102,7 +102,7 @@ class Kernel::Ipc_node
|
||||||
/* update state */
|
/* update state */
|
||||||
if (_state != PREPARE_AND_AWAIT_REPLY) { _state = INACTIVE; }
|
if (_state != PREPARE_AND_AWAIT_REPLY) { _state = INACTIVE; }
|
||||||
else { _state = PREPARE_REPLY; }
|
else { _state = PREPARE_REPLY; }
|
||||||
_await_ipc_succeeded(1, _inbuf.size);
|
_await_ipc_succeeded(_inbuf.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,7 +113,7 @@ class Kernel::Ipc_node
|
||||||
/* directly receive request if we've awaited it */
|
/* directly receive request if we've awaited it */
|
||||||
if (_state == AWAIT_REQUEST) {
|
if (_state == AWAIT_REQUEST) {
|
||||||
_receive_request(r);
|
_receive_request(r);
|
||||||
_await_ipc_succeeded(0, _inbuf.size);
|
_await_ipc_succeeded(_inbuf.size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* cannot receive yet, so queue request */
|
/* cannot receive yet, so queue request */
|
||||||
|
@ -175,7 +175,7 @@ class Kernel::Ipc_node
|
||||||
_outbuf_dst = 0;
|
_outbuf_dst = 0;
|
||||||
if (!_inbuf.src) { _state = INACTIVE; }
|
if (!_inbuf.src) { _state = INACTIVE; }
|
||||||
else { _state = PREPARE_REPLY; }
|
else { _state = PREPARE_REPLY; }
|
||||||
_await_ipc_failed(1);
|
_await_ipc_failed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,17 +192,14 @@ class Kernel::Ipc_node
|
||||||
/**
|
/**
|
||||||
* IPC node returned from waiting due to message receipt
|
* IPC node returned from waiting due to message receipt
|
||||||
*
|
*
|
||||||
* \param s size of incoming message
|
* \param s size of incoming message
|
||||||
* \param reply wether the received message is a reply
|
|
||||||
*/
|
*/
|
||||||
virtual void _await_ipc_succeeded(bool const reply, size_t const s) = 0;
|
virtual void _await_ipc_succeeded(size_t const s) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IPC node returned from waiting due to cancellation
|
* IPC node returned from waiting due to cancellation
|
||||||
*
|
|
||||||
* \param reply wether the received message is a reply
|
|
||||||
*/
|
*/
|
||||||
virtual void _await_ipc_failed(bool const reply) = 0;
|
virtual void _await_ipc_failed() = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -319,16 +316,16 @@ class Kernel::Ipc_node
|
||||||
case AWAIT_REPLY:
|
case AWAIT_REPLY:
|
||||||
_cancel_outbuf_request();
|
_cancel_outbuf_request();
|
||||||
_state = INACTIVE;
|
_state = INACTIVE;
|
||||||
_await_ipc_failed(1);
|
_await_ipc_failed();
|
||||||
return;
|
return;
|
||||||
case AWAIT_REQUEST:
|
case AWAIT_REQUEST:
|
||||||
_state = INACTIVE;
|
_state = INACTIVE;
|
||||||
_await_ipc_failed(0);
|
_await_ipc_failed();
|
||||||
return;
|
return;
|
||||||
case PREPARE_AND_AWAIT_REPLY:
|
case PREPARE_AND_AWAIT_REPLY:
|
||||||
_cancel_outbuf_request();
|
_cancel_outbuf_request();
|
||||||
_state = PREPARE_REPLY;
|
_state = PREPARE_REPLY;
|
||||||
_await_ipc_failed(1);
|
_await_ipc_failed();
|
||||||
return;
|
return;
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,8 @@ void Thread::_received_ipc_request(size_t const s)
|
||||||
{
|
{
|
||||||
switch (_state) {
|
switch (_state) {
|
||||||
case SCHEDULED:
|
case SCHEDULED:
|
||||||
user_arg_0(s);
|
_phys_utcb->ipc_msg_size(s);
|
||||||
|
user_arg_0(0);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
PERR("wrong thread state to receive IPC");
|
PERR("wrong thread state to receive IPC");
|
||||||
|
@ -116,19 +117,13 @@ void Thread::_await_ipc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Thread::_await_ipc_succeeded(bool const reply, size_t const s)
|
void Thread::_await_ipc_succeeded(size_t const s)
|
||||||
{
|
{
|
||||||
switch (_state) {
|
switch (_state) {
|
||||||
case AWAITS_IPC:
|
case AWAITS_IPC:
|
||||||
/* FIXME: return error codes on all IPC transfers */
|
_phys_utcb->ipc_msg_size(s);
|
||||||
if (reply) {
|
user_arg_0(0);
|
||||||
_phys_utcb->ipc_msg_size(s);
|
_schedule();
|
||||||
user_arg_0(0);
|
|
||||||
_schedule();
|
|
||||||
} else {
|
|
||||||
user_arg_0(s);
|
|
||||||
_schedule();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
case AWAITS_PAGER_IPC:
|
case AWAITS_PAGER_IPC:
|
||||||
_schedule();
|
_schedule();
|
||||||
|
@ -144,18 +139,12 @@ void Thread::_await_ipc_succeeded(bool const reply, size_t const s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Thread::_await_ipc_failed(bool const reply)
|
void Thread::_await_ipc_failed()
|
||||||
{
|
{
|
||||||
switch (_state) {
|
switch (_state) {
|
||||||
case AWAITS_IPC:
|
case AWAITS_IPC:
|
||||||
/* FIXME: return error codes on all IPC transfers */
|
user_arg_0(-1);
|
||||||
if (reply) {
|
_schedule();
|
||||||
user_arg_0(-1);
|
|
||||||
_schedule();
|
|
||||||
} else {
|
|
||||||
PERR("failed to receive IPC");
|
|
||||||
_stop();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
case SCHEDULED:
|
case SCHEDULED:
|
||||||
PERR("failed to receive IPC");
|
PERR("failed to receive IPC");
|
||||||
|
@ -615,7 +604,9 @@ void Thread::_syscall_get_thread()
|
||||||
*/
|
*/
|
||||||
void Thread::_syscall_wait_for_request()
|
void Thread::_syscall_wait_for_request()
|
||||||
{
|
{
|
||||||
Ipc_node::await_request(_phys_utcb->base(), _phys_utcb->size());
|
void * const buf_base = _phys_utcb->ipc_msg_base();
|
||||||
|
size_t const buf_size = _phys_utcb->max_ipc_msg_size();
|
||||||
|
Ipc_node::await_request(buf_base, buf_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -641,12 +632,15 @@ void Thread::_syscall_request_and_wait()
|
||||||
*/
|
*/
|
||||||
void Thread::_syscall_reply()
|
void Thread::_syscall_reply()
|
||||||
{
|
{
|
||||||
size_t const msg_size = user_arg_1();
|
bool const await_request = user_arg_1();
|
||||||
bool const await_request = user_arg_2();
|
void * const msg_base = _phys_utcb->ipc_msg_base();
|
||||||
|
size_t const msg_size = _phys_utcb->ipc_msg_size();
|
||||||
|
Ipc_node::send_reply(msg_base, msg_size);
|
||||||
|
|
||||||
Ipc_node::send_reply(_phys_utcb->base(), msg_size);
|
|
||||||
if (await_request) {
|
if (await_request) {
|
||||||
Ipc_node::await_request(_phys_utcb->base(), _phys_utcb->size());
|
void * const buf_base = _phys_utcb->ipc_msg_base();
|
||||||
|
size_t const buf_size = _phys_utcb->max_ipc_msg_size();
|
||||||
|
Ipc_node::await_request(buf_base, buf_size);
|
||||||
} else { user_arg_0(0); }
|
} else { user_arg_0(0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -209,8 +209,8 @@ class Kernel::Thread
|
||||||
|
|
||||||
void _received_ipc_request(size_t const s);
|
void _received_ipc_request(size_t const s);
|
||||||
void _await_ipc();
|
void _await_ipc();
|
||||||
void _await_ipc_succeeded(bool const reply, size_t const s);
|
void _await_ipc_succeeded(size_t const s);
|
||||||
void _await_ipc_failed(bool const reply);
|
void _await_ipc_failed();
|
||||||
|
|
||||||
|
|
||||||
/***************
|
/***************
|
||||||
|
|
Loading…
Reference in New Issue