hw: communicate message type through UTCB

ref #874
This commit is contained in:
Martin Stein
2013-10-17 16:07:47 +02:00
committed by Norman Feske
parent 1e7eb4512e
commit 6f935af278
5 changed files with 85 additions and 60 deletions

View File

@ -86,21 +86,42 @@ namespace Genode
}; };
/** /**
* Describes a userland-thread-context region * Types of synchronously communicated messages
*/ */
struct Native_utcb struct Msg_type
{ {
enum Id {
INVALID = 0,
IPC = 1,
};
};
/** /**
* Structure of an IPC message held by the UTCB * Message that is communicated synchronously
*/ */
struct Ipc_msg struct Msg
{
Msg_type::Id type;
uint8_t data[];
};
/**
* Message that is communicated between user threads
*/
struct Ipc_msg : Msg
{ {
size_t size; size_t size;
uint8_t data[]; uint8_t data[];
}; };
/**
* Describes a userland-thread-context region
*/
struct Native_utcb
{
union { union {
uint8_t data[1 << MIN_MAPPING_SIZE_LOG2]; uint8_t data[1 << MIN_MAPPING_SIZE_LOG2];
Msg msg;
Ipc_msg ipc_msg; Ipc_msg ipc_msg;
}; };

View File

@ -333,51 +333,42 @@ namespace Kernel
/** /**
* Send IPC request and wait for reply * Send IPC request and await corresponding IPC reply
* *
* \param id kernel name of the server thread * \param id kernel name of the server thread
* *
* \retval 0 successful * As soon as call returns, callers UTCB provides received message.
* \retval -1 failed
*
* If the call returns successful the callers UTCB provides
* a valid reply message and its metadata.
*/ */
inline int request_and_wait(unsigned const id) inline void request_and_wait(unsigned const id)
{ {
return (int)syscall(REQUEST_AND_WAIT, id); syscall(REQUEST_AND_WAIT, id);
} }
/** /**
* Wait for next IPC request, discard current request * Await the receipt of a message
* *
* \retval 0 succeeded * \return type of received message
* \retval -1 failed
* *
* If the call returns successful the callers UTCB provides * As soon as call returns, callers UTCB provides received message.
* a valid request message and its metadata.
*/ */
inline int wait_for_request() inline void wait_for_request()
{ {
return (int)syscall(WAIT_FOR_REQUEST); syscall(WAIT_FOR_REQUEST);
} }
/** /**
* Reply to last IPC request * Reply to lastly received message
* *
* \param await_request if the call shall await and fetch next request * \param await_message wether the call shall await receipt of a message
* *
* \retval 0 succeeded * If await_request = 1, callers UTCB provides received message
* \retval -1 failed to receive request * as soon as call returns
*
* If await_request = 1 and the call returns successful the callers UTCB
* provides a valid request message and its metadata.
*/ */
inline int reply(bool const await_request) inline void reply(bool const await_message)
{ {
return (int)syscall(REPLY, await_request); syscall(REPLY, await_message);
} }

View File

@ -92,7 +92,7 @@ Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
void Ipc_istream::_wait() void Ipc_istream::_wait()
{ {
/* FIXME this shall be not supported */ /* FIXME: this shall be not supported */
Kernel::pause_thread(); Kernel::pause_thread();
} }
@ -116,11 +116,17 @@ void Ipc_client::_call()
{ {
using namespace Kernel; using namespace Kernel;
/* send request and receive reply */ /* send request */
unsigned const local_name = Ipc_ostream::_dst.local_name(); unsigned const local_name = Ipc_ostream::_dst.local_name();
msgbuf_to_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()); request_and_wait(Ipc_ostream::_dst.dst());
if (error) { throw Blocking_canceled(); }
/* receive reply */
Native_utcb * const utcb = Thread_base::myself()->utcb();
if (utcb->msg.type != Msg_type::IPC) {
PERR("failed to receive reply");
throw Blocking_canceled();
}
utcb_to_msgbuf(_rcv_msg); utcb_to_msgbuf(_rcv_msg);
/* reset unmarshaller */ /* reset unmarshaller */
@ -161,12 +167,14 @@ void Ipc_server::_prepare_next_reply_wait()
void Ipc_server::_wait() void Ipc_server::_wait()
{ {
/* receive next request */ /* receive next request */
int const error = Kernel::wait_for_request(); Kernel::wait_for_request();
if (!error) { utcb_to_msgbuf(_rcv_msg); } Native_utcb * const utcb = Thread_base::myself()->utcb();
else { if (utcb->msg.type != Msg_type::IPC) {
PERR("failed to receive request"); PERR("failed to receive request");
throw Blocking_canceled(); throw Blocking_canceled();
} }
utcb_to_msgbuf(_rcv_msg);
/* update server state */ /* update server state */
_prepare_next_reply_wait(); _prepare_next_reply_wait();
} }
@ -182,21 +190,24 @@ void Ipc_server::_reply()
void Ipc_server::_reply_wait() void Ipc_server::_reply_wait()
{ {
/* if there is no reply simply do wait for request */ /* if there is no reply, wait for request */
/* FIXME this shall be not supported */
if (!_reply_needed) { if (!_reply_needed) {
_wait(); _wait();
return; return;
} }
/* send reply and receive next request */ /* send reply an await request */
unsigned const local_name = Ipc_ostream::_dst.local_name(); unsigned const local_name = Ipc_ostream::_dst.local_name();
msgbuf_to_utcb(_snd_msg, _write_offset, local_name); msgbuf_to_utcb(_snd_msg, _write_offset, local_name);
int const error = Kernel::reply(1); Kernel::reply(1);
if (!error) { utcb_to_msgbuf(_rcv_msg); }
else { /* fetch request */
Native_utcb * const utcb = Thread_base::myself()->utcb();
if (utcb->msg.type != Msg_type::IPC) {
PERR("failed to receive request"); PERR("failed to receive request");
throw Blocking_canceled(); throw Blocking_canceled();
} }
utcb_to_msgbuf(_rcv_msg);
/* update server state */ /* update server state */
_prepare_next_reply_wait(); _prepare_next_reply_wait();
} }

View File

@ -95,8 +95,12 @@ Pager_capability Pager_entrypoint::manage(Pager_object * const o)
void Ipc_pager::wait_for_first_fault() void Ipc_pager::wait_for_first_fault()
{ {
while (Kernel::wait_for_request()) { PERR("failed to receive fault"); }
Native_utcb * const utcb = Thread_base::myself()->utcb(); Native_utcb * const utcb = Thread_base::myself()->utcb();
while (1) {
Kernel::wait_for_request();
if (utcb->msg.type == Msg_type::IPC) { break; }
PERR("failed to receive fault");
}
_wait_for_fault(utcb->ipc_msg.size); _wait_for_fault(utcb->ipc_msg.size);
} }
@ -105,12 +109,10 @@ void Ipc_pager::wait_for_fault()
{ {
Native_utcb * const utcb = Thread_base::myself()->utcb(); Native_utcb * const utcb = Thread_base::myself()->utcb();
utcb->ipc_msg.size = 0; utcb->ipc_msg.size = 0;
int err = Kernel::reply(1); Kernel::reply(1);
if (err) { while (utcb->msg.type != Msg_type::IPC) {
PERR("failed to receive fault"); PERR("failed to receive fault");
while (Kernel::wait_for_request()) { Kernel::wait_for_request();
PERR("failed to receive fault");
}
} }
_wait_for_fault(utcb->ipc_msg.size); _wait_for_fault(utcb->ipc_msg.size);
} }
@ -153,11 +155,10 @@ void Ipc_pager::_wait_for_fault(size_t s)
/* 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());
utcb->ipc_msg.size = 0; utcb->ipc_msg.size = 0;
if (Kernel::reply(1)) { Kernel::reply(1);
while (utcb->msg.type != Msg_type::IPC) {
PERR("failed to receive fault"); PERR("failed to receive fault");
while (Kernel::wait_for_request()) { Kernel::wait_for_request();
PERR("failed to receive fault");
}
} }
s = utcb->ipc_msg.size; s = utcb->ipc_msg.size;
continue; } continue; }

View File

@ -24,6 +24,7 @@
using namespace Kernel; using namespace Kernel;
typedef Genode::Thread_state Thread_state; typedef Genode::Thread_state Thread_state;
typedef Genode::Msg_type Msg_type;
bool Thread::_core() const bool Thread::_core() const
@ -90,8 +91,8 @@ void Thread::_received_ipc_request(size_t const s)
{ {
switch (_state) { switch (_state) {
case SCHEDULED: case SCHEDULED:
_phys_utcb->msg.type = Msg_type::IPC;
_phys_utcb->ipc_msg.size = 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");
@ -121,8 +122,8 @@ void Thread::_await_ipc_succeeded(size_t const s)
{ {
switch (_state) { switch (_state) {
case AWAITS_IPC: case AWAITS_IPC:
_phys_utcb->msg.type = Msg_type::IPC;
_phys_utcb->ipc_msg.size = s; _phys_utcb->ipc_msg.size = s;
user_arg_0(0);
_schedule(); _schedule();
return; return;
case AWAITS_PAGER_IPC: case AWAITS_PAGER_IPC:
@ -143,7 +144,7 @@ void Thread::_await_ipc_failed()
{ {
switch (_state) { switch (_state) {
case AWAITS_IPC: case AWAITS_IPC:
user_arg_0(-1); _phys_utcb->msg.type = Msg_type::INVALID;
_schedule(); _schedule();
return; return;
case SCHEDULED: case SCHEDULED:
@ -641,7 +642,7 @@ void Thread::_syscall_reply()
void * const buf_base = _phys_utcb->ipc_msg.data; void * const buf_base = _phys_utcb->ipc_msg.data;
size_t const buf_size = _phys_utcb->ipc_msg_max_size(); size_t const buf_size = _phys_utcb->ipc_msg_max_size();
Ipc_node::await_request(buf_base, buf_size); Ipc_node::await_request(buf_base, buf_size);
} else { user_arg_0(0); } } else { _phys_utcb->msg.type = Msg_type::INVALID; }
} }