mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-11 20:01:48 +00:00
committed by
Norman Feske
parent
1e7eb4512e
commit
6f935af278
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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; }
|
||||||
|
@ -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; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user