hw: send reply size & receive request size by UTCB

ref #874
This commit is contained in:
Martin Stein 2013-10-17 13:51:17 +02:00 committed by Norman Feske
parent 45d37e275d
commit 96bbca6191
6 changed files with 101 additions and 114 deletions

View File

@ -341,7 +341,7 @@ namespace Kernel
* \retval -1 failed
*
* If the call returns successful the callers UTCB provides
* a valid reply message and its size.
* a valid reply message and its metadata.
*/
inline int request_and_wait(unsigned const id)
{
@ -352,23 +352,33 @@ namespace Kernel
/**
* Wait for next IPC request, discard current request
*
* \return size of received request (beginning with the callers UTCB base)
* \retval 0 succeeded
* \retval -1 failed
*
* If the call returns successful the callers UTCB provides
* a valid request message and its metadata.
*/
inline size_t wait_for_request() {
return (size_t)syscall(WAIT_FOR_REQUEST); }
inline int wait_for_request()
{
return (int)syscall(WAIT_FOR_REQUEST);
}
/**
* Reply to last IPC request
*
* \param size reply size (beginning with the callers UTCB base)
* \param await_request if the call shall await and fetch next request
*
* \return request size (beginning with the callers UTCB base)
* if await_request was set
* \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.
*/
inline size_t reply(size_t const size, bool const await_request) {
return (size_t)syscall(REPLY, size, await_request); }
inline int reply(bool const await_request)
{
return (int)syscall(REPLY, await_request);
}
/**

View File

@ -38,68 +38,25 @@ enum
***************/
/**
* Limit message size to the size of UTCB and message buffer
* Copy message from the callers UTCB to message buffer
*/
void limit_msg_size(Msgbuf_base * const msgbuf, Native_utcb * const utcb,
size_t & size)
{
if (size > utcb->size() || size > msgbuf->size()) {
kernel_log() << __PRETTY_FUNCTION__ << ": truncate message\n";
size = utcb->size() < msgbuf->size() ? utcb->size() : msgbuf->size();
}
}
/**
* Copy message payload to message buffer
*/
static void utcb_to_msgbuf(Msgbuf_base * const msgbuf, size_t size)
{
Native_utcb * const utcb = Thread_base::myself()->utcb();
limit_msg_size(msgbuf, utcb, size);
memcpy(msgbuf->buf, utcb->base(), size);
}
/**
* Copy message payload with size header to 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)
static void 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()) {
if (msg_size > msgbuf->size()) {
kernel_log() << "oversized IPC message\n";
msg_size = utcb->max_ipc_msg_size();
msg_size = msgbuf->size();
}
memcpy(msgbuf->buf, utcb->ipc_msg_base(), msg_size);
}
/**
* Copy message payload to the UTCB
* Copy message from message buffer to the callers UTCB
*/
static void msgbuf_to_utcb(Msgbuf_base * const msgbuf, size_t size,
static void msgbuf_to_utcb(Msgbuf_base * const msg_buf, size_t msg_size,
unsigned const local_name)
{
Native_utcb * const utcb = Thread_base::myself()->utcb();
*(unsigned *)utcb->base() = local_name;
size += sizeof(local_name);
limit_msg_size(msgbuf, utcb, size);
memcpy((unsigned *)utcb->base() + 1, (unsigned *)msgbuf->buf + 1, size);
}
/**
* Copy message payload with size header to the UTCB
*
* This function pioneers IPC messages with headers and will
* replace msgbuf_to_utcb sometime.
*/
static void msgbuf_to_sized_utcb(Msgbuf_base * const msg_buf, size_t msg_size,
unsigned const local_name)
{
Native_utcb * const utcb = Thread_base::myself()->utcb();
enum { NAME_SIZE = sizeof(local_name) };
@ -161,10 +118,10 @@ void Ipc_client::_call()
/* send request and receive reply */
unsigned const local_name = Ipc_ostream::_dst.local_name();
msgbuf_to_sized_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());
if (error) { throw Blocking_canceled(); }
sized_utcb_to_msgbuf(_rcv_msg);
utcb_to_msgbuf(_rcv_msg);
/* reset unmarshaller */
_write_offset = _read_offset = RPC_OBJECT_ID_SIZE;
@ -204,14 +161,23 @@ void Ipc_server::_prepare_next_reply_wait()
void Ipc_server::_wait()
{
/* receive next request */
utcb_to_msgbuf(_rcv_msg, Kernel::wait_for_request());
int const error = Kernel::wait_for_request();
if (!error) { utcb_to_msgbuf(_rcv_msg); }
else {
PERR("failed to receive request");
throw Blocking_canceled();
}
/* update server state */
_prepare_next_reply_wait();
}
void Ipc_server::_reply() { Kernel::reply(_write_offset, 0); }
void Ipc_server::_reply()
{
Native_utcb * const utcb = Thread_base::myself()->utcb();
utcb->ipc_msg_size(_write_offset);
Kernel::reply(0);
}
void Ipc_server::_reply_wait()
@ -223,9 +189,14 @@ void Ipc_server::_reply_wait()
return;
}
/* send reply and receive next request */
msgbuf_to_utcb(_snd_msg, _write_offset, Ipc_ostream::_dst.local_name());
utcb_to_msgbuf(_rcv_msg, Kernel::reply(_write_offset, 1));
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 {
PERR("failed to receive request");
throw Blocking_canceled();
}
/* update server state */
_prepare_next_reply_wait();
}

View File

@ -95,17 +95,24 @@ Pager_capability Pager_entrypoint::manage(Pager_object * const o)
void Ipc_pager::wait_for_first_fault()
{
/* receive message */
size_t const s = Kernel::wait_for_request();
_wait_for_fault(s);
while (Kernel::wait_for_request()) { PERR("failed to receive fault"); }
Native_utcb * const utcb = Thread_base::myself()->utcb();
_wait_for_fault(utcb->ipc_msg_size());
}
void Ipc_pager::wait_for_fault()
{
/* receive first message */
size_t const s = Kernel::reply(0, 1);
_wait_for_fault(s);
Native_utcb * const utcb = Thread_base::myself()->utcb();
utcb->ipc_msg_size(0);
int err = Kernel::reply(1);
if (err) {
PERR("failed to receive fault");
while (Kernel::wait_for_request()) {
PERR("failed to receive fault");
}
}
_wait_for_fault(utcb->ipc_msg_size());
}
@ -122,7 +129,7 @@ void Ipc_pager::_wait_for_fault(size_t s)
/* message is a pagefault */
Native_utcb * const utcb = Thread_base::myself()->utcb();
Pagefault * const pf = (Pagefault *)utcb;
Pagefault * const pf = (Pagefault *)utcb->ipc_msg_base();
if (pf->valid())
{
/* give our caller the chance to handle the fault */
@ -140,11 +147,19 @@ void Ipc_pager::_wait_for_fault(size_t s)
/* message is a release request from a RM session */
Native_utcb * const utcb = Thread_base::myself()->utcb();
Pagefault_resolved * const msg = (Pagefault_resolved *)utcb;
void * const msg_base = utcb->ipc_msg_base();
Pagefault_resolved * const msg = (Pagefault_resolved *)msg_base;
/* resume faulter, send ack to RM and get the next message */
Kernel::resume_thread(msg->pager_object->badge());
s = Kernel::reply(0, 1);
utcb->ipc_msg_size(0);
if (Kernel::reply(1)) {
PERR("failed to receive fault");
while (Kernel::wait_for_request()) {
PERR("failed to receive fault");
}
}
s = utcb->ipc_msg_size();
continue; }
default: {

View File

@ -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(1, _inbuf.size);
_await_ipc_succeeded(_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(0, _inbuf.size);
_await_ipc_succeeded(_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(1);
_await_ipc_failed();
}
}
@ -192,17 +192,14 @@ class Kernel::Ipc_node
/**
* IPC node returned from waiting due to message receipt
*
* \param s size of incoming message
* \param reply wether the received message is a reply
* \param s size of incoming message
*/
virtual void _await_ipc_succeeded(bool const reply, size_t const s) = 0;
virtual void _await_ipc_succeeded(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(bool const reply) = 0;
virtual void _await_ipc_failed() = 0;
public:
@ -319,16 +316,16 @@ class Kernel::Ipc_node
case AWAIT_REPLY:
_cancel_outbuf_request();
_state = INACTIVE;
_await_ipc_failed(1);
_await_ipc_failed();
return;
case AWAIT_REQUEST:
_state = INACTIVE;
_await_ipc_failed(0);
_await_ipc_failed();
return;
case PREPARE_AND_AWAIT_REPLY:
_cancel_outbuf_request();
_state = PREPARE_REPLY;
_await_ipc_failed(1);
_await_ipc_failed();
return;
default: return;
}

View File

@ -90,7 +90,8 @@ void Thread::_received_ipc_request(size_t const s)
{
switch (_state) {
case SCHEDULED:
user_arg_0(s);
_phys_utcb->ipc_msg_size(s);
user_arg_0(0);
return;
default:
PERR("wrong thread state to receive IPC");
@ -116,19 +117,13 @@ void Thread::_await_ipc()
}
void Thread::_await_ipc_succeeded(bool const reply, size_t const s)
void Thread::_await_ipc_succeeded(size_t const s)
{
switch (_state) {
case AWAITS_IPC:
/* 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();
}
_phys_utcb->ipc_msg_size(s);
user_arg_0(0);
_schedule();
return;
case AWAITS_PAGER_IPC:
_schedule();
@ -144,18 +139,12 @@ void Thread::_await_ipc_succeeded(bool const reply, size_t const s)
}
void Thread::_await_ipc_failed(bool const reply)
void Thread::_await_ipc_failed()
{
switch (_state) {
case AWAITS_IPC:
/* FIXME: return error codes on all IPC transfers */
if (reply) {
user_arg_0(-1);
_schedule();
} else {
PERR("failed to receive IPC");
_stop();
}
user_arg_0(-1);
_schedule();
return;
case SCHEDULED:
PERR("failed to receive IPC");
@ -615,7 +604,9 @@ void Thread::_syscall_get_thread()
*/
void Thread::_syscall_wait_for_request()
{
Ipc_node::await_request(_phys_utcb->base(), _phys_utcb->size());
void * const buf_base = _phys_utcb->ipc_msg_base();
size_t const buf_size = _phys_utcb->max_ipc_msg_size();
Ipc_node::await_request(buf_base, buf_size);
}
@ -641,12 +632,15 @@ void Thread::_syscall_request_and_wait()
*/
void Thread::_syscall_reply()
{
size_t const msg_size = user_arg_1();
bool const await_request = user_arg_2();
bool const await_request = user_arg_1();
void * const msg_base = _phys_utcb->ipc_msg_base();
size_t const msg_size = _phys_utcb->ipc_msg_size();
Ipc_node::send_reply(msg_base, msg_size);
Ipc_node::send_reply(_phys_utcb->base(), msg_size);
if (await_request) {
Ipc_node::await_request(_phys_utcb->base(), _phys_utcb->size());
void * const buf_base = _phys_utcb->ipc_msg_base();
size_t const buf_size = _phys_utcb->max_ipc_msg_size();
Ipc_node::await_request(buf_base, buf_size);
} else { user_arg_0(0); }
}

View File

@ -209,8 +209,8 @@ class Kernel::Thread
void _received_ipc_request(size_t const s);
void _await_ipc();
void _await_ipc_succeeded(bool const reply, size_t const s);
void _await_ipc_failed(bool const reply);
void _await_ipc_succeeded(size_t const s);
void _await_ipc_failed();
/***************