mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-23 04:25:21 +00:00
parent
1e7eb4512e
commit
6f935af278
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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; }
|
||||
|
@ -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; }
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user