mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
parent
ae76e441b1
commit
0ad655f4be
@ -94,14 +94,39 @@ namespace Genode
|
||||
char payload[1<<MIN_MAPPING_SIZE_LOG2];
|
||||
|
||||
/**
|
||||
* Get the base of the UTCB
|
||||
* Get the base of the UTCB region
|
||||
*/
|
||||
void * base() { return payload; }
|
||||
|
||||
/**
|
||||
* Get the UTCB size
|
||||
* Get the size of the UTCB region
|
||||
*/
|
||||
size_t size() { return sizeof(payload); }
|
||||
|
||||
/**
|
||||
* Get the top of the UTCB region
|
||||
*/
|
||||
addr_t top() { return (addr_t)payload + size(); }
|
||||
|
||||
/**
|
||||
* Get the base of an IPC message that is held by the UTCB
|
||||
*/
|
||||
void * ipc_msg_base() { return (void *)((addr_t)base() + sizeof(size_t)); }
|
||||
|
||||
/**
|
||||
* Get the size of an IPC message that is held by the UTCB
|
||||
*/
|
||||
size_t ipc_msg_size() { return *(size_t *)base(); }
|
||||
|
||||
/**
|
||||
* Set the size of the IPC message that is held by the UTCB
|
||||
*/
|
||||
void ipc_msg_size(size_t const s) { *(size_t *)base() = s; }
|
||||
|
||||
/**
|
||||
* Maximum size of an IPC message that can be held by the UTCB
|
||||
*/
|
||||
size_t max_ipc_msg_size() { return top() - (addr_t)ipc_msg_base(); }
|
||||
};
|
||||
|
||||
struct Cap_dst_policy
|
||||
|
@ -335,16 +335,19 @@ namespace Kernel
|
||||
/**
|
||||
* Send IPC request and wait for reply
|
||||
*
|
||||
* \param id ID of the receiver thread
|
||||
* \param size request size (beginning with the callers UTCB base)
|
||||
* \param id kernel name of the server thread
|
||||
* \param size size of request message located in the callers UTCB
|
||||
*
|
||||
* \return size of received reply (beginning with the callers UTCB base)
|
||||
* \retval 0 successful
|
||||
* \retval -1 failed
|
||||
*
|
||||
* If the receiver exists, this blocks execution until a dedicated reply
|
||||
* message has been send by the receiver. The receiver may never do so.
|
||||
* If the call returns successful the callers UTCB provides
|
||||
* a valid reply message and its size.
|
||||
*/
|
||||
inline size_t request_and_wait(unsigned const id, size_t const size) {
|
||||
return (size_t)syscall(REQUEST_AND_WAIT, id, size); }
|
||||
inline int request_and_wait(unsigned const id, size_t const size)
|
||||
{
|
||||
return (int)syscall(REQUEST_AND_WAIT, id, size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
@ -60,6 +60,23 @@ static void utcb_to_msgbuf(Msgbuf_base * const msgbuf, size_t size)
|
||||
memcpy(msgbuf->buf, utcb->base(), size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy message payload with integrated size toion 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();
|
||||
size_t msg_size = utcb->ipc_msg_size();
|
||||
if (msg_size > utcb->max_ipc_msg_size()) {
|
||||
kernel_log() << "oversized IPC message\n";
|
||||
msg_size = utcb->max_ipc_msg_size();
|
||||
}
|
||||
memcpy(msgbuf->buf, utcb->ipc_msg_base(), msg_size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy message payload to the UTCB
|
||||
@ -120,8 +137,9 @@ void Ipc_client::_call()
|
||||
|
||||
/* send request and receive reply */
|
||||
msgbuf_to_utcb(_snd_msg, _write_offset, Ipc_ostream::_dst.local_name());
|
||||
size_t const s = request_and_wait(Ipc_ostream::_dst.dst(), _write_offset);
|
||||
utcb_to_msgbuf(_rcv_msg, s);
|
||||
int error = request_and_wait(Ipc_ostream::_dst.dst(), _write_offset);
|
||||
if (error) { throw Blocking_canceled(); }
|
||||
sized_utcb_to_msgbuf(_rcv_msg);
|
||||
|
||||
/* reset unmarshaller */
|
||||
_write_offset = _read_offset = RPC_OBJECT_ID_SIZE;
|
||||
|
@ -102,7 +102,7 @@ class Kernel::Ipc_node
|
||||
/* update state */
|
||||
if (_state != PREPARE_AND_AWAIT_REPLY) { _state = INACTIVE; }
|
||||
else { _state = PREPARE_REPLY; }
|
||||
_await_ipc_succeeded(_inbuf.size);
|
||||
_await_ipc_succeeded(1, _inbuf.size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -113,7 +113,7 @@ class Kernel::Ipc_node
|
||||
/* directly receive request if we've awaited it */
|
||||
if (_state == AWAIT_REQUEST) {
|
||||
_receive_request(r);
|
||||
_await_ipc_succeeded(_inbuf.size);
|
||||
_await_ipc_succeeded(0, _inbuf.size);
|
||||
return;
|
||||
}
|
||||
/* cannot receive yet, so queue request */
|
||||
@ -175,7 +175,7 @@ class Kernel::Ipc_node
|
||||
_outbuf_dst = 0;
|
||||
if (!_inbuf.src) { _state = INACTIVE; }
|
||||
else { _state = PREPARE_REPLY; }
|
||||
_await_ipc_failed();
|
||||
_await_ipc_failed(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,14 +192,17 @@ class Kernel::Ipc_node
|
||||
/**
|
||||
* 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(size_t const s) = 0;
|
||||
virtual void _await_ipc_succeeded(bool const reply, size_t const s) = 0;
|
||||
|
||||
/**
|
||||
* IPC node returned from waiting due to cancellation
|
||||
*
|
||||
* \param reply wether the received message is a reply
|
||||
*/
|
||||
virtual void _await_ipc_failed() = 0;
|
||||
virtual void _await_ipc_failed(bool const reply) = 0;
|
||||
|
||||
public:
|
||||
|
||||
@ -316,16 +319,16 @@ class Kernel::Ipc_node
|
||||
case AWAIT_REPLY:
|
||||
_cancel_outbuf_request();
|
||||
_state = INACTIVE;
|
||||
_await_ipc_failed();
|
||||
_await_ipc_failed(1);
|
||||
return;
|
||||
case AWAIT_REQUEST:
|
||||
_state = INACTIVE;
|
||||
_await_ipc_failed();
|
||||
_await_ipc_failed(0);
|
||||
return;
|
||||
case PREPARE_AND_AWAIT_REPLY:
|
||||
_cancel_outbuf_request();
|
||||
_state = PREPARE_REPLY;
|
||||
_await_ipc_failed();
|
||||
_await_ipc_failed(1);
|
||||
return;
|
||||
default: return;
|
||||
}
|
||||
|
@ -226,12 +226,19 @@ class Kernel::Thread
|
||||
}
|
||||
}
|
||||
|
||||
void _await_ipc_succeeded(size_t const s)
|
||||
void _await_ipc_succeeded(bool const reply, size_t const s)
|
||||
{
|
||||
switch (_state) {
|
||||
case AWAIT_IPC:
|
||||
_schedule();
|
||||
user_arg_0(s);
|
||||
/* FIXME: return error codes on all IPC transfers */
|
||||
if (reply) {
|
||||
phys_utcb()->ipc_msg_size(s);
|
||||
user_arg_0(0);
|
||||
_schedule();
|
||||
} else {
|
||||
user_arg_0(s);
|
||||
_schedule();
|
||||
}
|
||||
return;
|
||||
case AWAIT_PAGER_IPC:
|
||||
_schedule();
|
||||
@ -246,12 +253,18 @@ class Kernel::Thread
|
||||
}
|
||||
}
|
||||
|
||||
void _await_ipc_failed()
|
||||
void _await_ipc_failed(bool const reply)
|
||||
{
|
||||
switch (_state) {
|
||||
case AWAIT_IPC:
|
||||
PERR("failed to receive IPC");
|
||||
stop();
|
||||
/* FIXME: return error codes on all IPC transfers */
|
||||
if (reply) {
|
||||
user_arg_0(-1);
|
||||
_schedule();
|
||||
} else {
|
||||
PERR("failed to receive IPC");
|
||||
stop();
|
||||
}
|
||||
return;
|
||||
case SCHEDULED:
|
||||
PERR("failed to receive IPC");
|
||||
@ -429,8 +442,9 @@ class Kernel::Thread
|
||||
void request_and_wait(Thread * const dest, size_t const size)
|
||||
{
|
||||
Ipc_node::send_request_await_reply(
|
||||
dest, phys_utcb()->base(), size, phys_utcb()->base(),
|
||||
phys_utcb()->size());
|
||||
dest, phys_utcb()->base(), size,
|
||||
phys_utcb()->ipc_msg_base(),
|
||||
phys_utcb()->max_ipc_msg_size());
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user