From 6f935af278ae7034b7f8cc01e080ab121ba977f2 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Thu, 17 Oct 2013 16:07:47 +0200 Subject: [PATCH] hw: communicate message type through UTCB ref #874 --- base-hw/include/base/native_types.h | 39 ++++++++++++++++++++++------- base-hw/include/kernel/syscalls.h | 39 +++++++++++------------------ base-hw/src/base/ipc.cc | 37 +++++++++++++++++---------- base-hw/src/base/pager.cc | 21 ++++++++-------- base-hw/src/core/kernel/thread.cc | 9 ++++--- 5 files changed, 85 insertions(+), 60 deletions(-) diff --git a/base-hw/include/base/native_types.h b/base-hw/include/base/native_types.h index 5ec565502b..2ad8c7f23c 100644 --- a/base-hw/include/base/native_types.h +++ b/base-hw/include/base/native_types.h @@ -85,22 +85,43 @@ namespace Genode bool valid() const { return thread_id != 0; } }; + /** + * Types of synchronously communicated messages + */ + struct Msg_type + { + enum Id { + INVALID = 0, + IPC = 1, + }; + }; + + /** + * Message that is communicated synchronously + */ + struct Msg + { + Msg_type::Id type; + uint8_t data[]; + }; + + /** + * Message that is communicated between user threads + */ + struct Ipc_msg : Msg + { + size_t size; + uint8_t data[]; + }; + /** * Describes a userland-thread-context region */ struct Native_utcb { - /** - * Structure of an IPC message held by the UTCB - */ - struct Ipc_msg - { - size_t size; - uint8_t data[]; - }; - union { uint8_t data[1 << MIN_MAPPING_SIZE_LOG2]; + Msg msg; Ipc_msg ipc_msg; }; diff --git a/base-hw/include/kernel/syscalls.h b/base-hw/include/kernel/syscalls.h index 064aa137cb..a1f9e2d3d6 100644 --- a/base-hw/include/kernel/syscalls.h +++ b/base-hw/include/kernel/syscalls.h @@ -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 * - * \retval 0 successful - * \retval -1 failed - * - * If the call returns successful the callers UTCB provides - * a valid reply message and its metadata. + * As soon as call returns, callers UTCB provides received message. */ - 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 - * \retval -1 failed + * \return type of received message * - * If the call returns successful the callers UTCB provides - * a valid request message and its metadata. + * As soon as call returns, callers UTCB provides received message. */ - 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 - * \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. + * If await_request = 1, callers UTCB provides received message + * as soon as call returns */ - inline int reply(bool const await_request) + inline void reply(bool const await_message) { - return (int)syscall(REPLY, await_request); + syscall(REPLY, await_message); } diff --git a/base-hw/src/base/ipc.cc b/base-hw/src/base/ipc.cc index 46c56a6a6e..a016aca120 100644 --- a/base-hw/src/base/ipc.cc +++ b/base-hw/src/base/ipc.cc @@ -92,7 +92,7 @@ Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg) void Ipc_istream::_wait() { - /* FIXME this shall be not supported */ + /* FIXME: this shall be not supported */ Kernel::pause_thread(); } @@ -116,11 +116,17 @@ void Ipc_client::_call() { using namespace Kernel; - /* send request and receive reply */ + /* send request */ unsigned const local_name = Ipc_ostream::_dst.local_name(); msgbuf_to_utcb(_snd_msg, _write_offset, local_name); - int error = request_and_wait(Ipc_ostream::_dst.dst()); - if (error) { throw Blocking_canceled(); } + request_and_wait(Ipc_ostream::_dst.dst()); + + /* 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); /* reset unmarshaller */ @@ -161,12 +167,14 @@ void Ipc_server::_prepare_next_reply_wait() void Ipc_server::_wait() { /* receive next request */ - int const error = Kernel::wait_for_request(); - if (!error) { utcb_to_msgbuf(_rcv_msg); } - else { + Kernel::wait_for_request(); + Native_utcb * const utcb = Thread_base::myself()->utcb(); + if (utcb->msg.type != Msg_type::IPC) { PERR("failed to receive request"); throw Blocking_canceled(); } + utcb_to_msgbuf(_rcv_msg); + /* update server state */ _prepare_next_reply_wait(); } @@ -182,21 +190,24 @@ void Ipc_server::_reply() void Ipc_server::_reply_wait() { - /* if there is no reply simply do wait for request */ - /* FIXME this shall be not supported */ + /* if there is no reply, wait for request */ if (!_reply_needed) { _wait(); return; } - /* send reply and receive next request */ + /* send reply an await request */ unsigned const local_name = Ipc_ostream::_dst.local_name(); msgbuf_to_utcb(_snd_msg, _write_offset, local_name); - int const error = Kernel::reply(1); - if (!error) { utcb_to_msgbuf(_rcv_msg); } - else { + Kernel::reply(1); + + /* fetch request */ + Native_utcb * const utcb = Thread_base::myself()->utcb(); + if (utcb->msg.type != Msg_type::IPC) { PERR("failed to receive request"); throw Blocking_canceled(); } + utcb_to_msgbuf(_rcv_msg); + /* update server state */ _prepare_next_reply_wait(); } diff --git a/base-hw/src/base/pager.cc b/base-hw/src/base/pager.cc index c99157a614..8fc47fa5a7 100644 --- a/base-hw/src/base/pager.cc +++ b/base-hw/src/base/pager.cc @@ -95,8 +95,12 @@ Pager_capability Pager_entrypoint::manage(Pager_object * const o) 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(); + 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); } @@ -105,12 +109,10 @@ void Ipc_pager::wait_for_fault() { Native_utcb * const utcb = Thread_base::myself()->utcb(); utcb->ipc_msg.size = 0; - int err = Kernel::reply(1); - if (err) { + Kernel::reply(1); + while (utcb->msg.type != Msg_type::IPC) { PERR("failed to receive fault"); - while (Kernel::wait_for_request()) { - PERR("failed to receive fault"); - } + Kernel::wait_for_request(); } _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 */ Kernel::resume_thread(msg->pager_object->badge()); utcb->ipc_msg.size = 0; - if (Kernel::reply(1)) { + Kernel::reply(1); + while (utcb->msg.type != Msg_type::IPC) { PERR("failed to receive fault"); - while (Kernel::wait_for_request()) { - PERR("failed to receive fault"); - } + Kernel::wait_for_request(); } s = utcb->ipc_msg.size; continue; } diff --git a/base-hw/src/core/kernel/thread.cc b/base-hw/src/core/kernel/thread.cc index 579f36cef7..f5a9260f24 100644 --- a/base-hw/src/core/kernel/thread.cc +++ b/base-hw/src/core/kernel/thread.cc @@ -24,6 +24,7 @@ using namespace Kernel; typedef Genode::Thread_state Thread_state; +typedef Genode::Msg_type Msg_type; bool Thread::_core() const @@ -90,8 +91,8 @@ void Thread::_received_ipc_request(size_t const s) { switch (_state) { case SCHEDULED: + _phys_utcb->msg.type = Msg_type::IPC; _phys_utcb->ipc_msg.size = s; - user_arg_0(0); return; default: PERR("wrong thread state to receive IPC"); @@ -121,8 +122,8 @@ void Thread::_await_ipc_succeeded(size_t const s) { switch (_state) { case AWAITS_IPC: + _phys_utcb->msg.type = Msg_type::IPC; _phys_utcb->ipc_msg.size = s; - user_arg_0(0); _schedule(); return; case AWAITS_PAGER_IPC: @@ -143,7 +144,7 @@ void Thread::_await_ipc_failed() { switch (_state) { case AWAITS_IPC: - user_arg_0(-1); + _phys_utcb->msg.type = Msg_type::INVALID; _schedule(); return; case SCHEDULED: @@ -641,7 +642,7 @@ void Thread::_syscall_reply() void * const buf_base = _phys_utcb->ipc_msg.data; size_t const buf_size = _phys_utcb->ipc_msg_max_size(); Ipc_node::await_request(buf_base, buf_size); - } else { user_arg_0(0); } + } else { _phys_utcb->msg.type = Msg_type::INVALID; } }