Remove 'Ipc_istream' and 'Ipc_ostream' from API

Fixes #610
This commit is contained in:
Norman Feske 2016-03-13 22:55:48 +01:00 committed by Christian Helmuth
parent 4cdfb9bc2f
commit 47878bd3e1
27 changed files with 544 additions and 1076 deletions

View File

@ -44,7 +44,12 @@ namespace Genode {
/**
* Return address of message buffer
*/
inline void *addr() { return &rcv_fpage; };
inline void *msg_start() { return &rcv_fpage; };
/**
* Return pointer of message data payload
*/
inline void *data() { return buf; };
};

View File

@ -29,35 +29,6 @@ namespace Fiasco {
using namespace Genode;
/*****************
** Ipc_ostream **
*****************/
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg) :
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
_snd_msg(snd_msg), _dst(dst)
{
_write_offset = sizeof(umword_t);
}
/*****************
** Ipc_istream **
*****************/
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg):
Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()),
Native_capability(Fiasco::l4_myself(), 0),
_rcv_msg(rcv_msg)
{
using namespace Fiasco;
_read_offset = sizeof(umword_t);
}
Ipc_istream::~Ipc_istream() { }
/****************
** Ipc_client **
****************/
@ -69,16 +40,16 @@ void Ipc_client::_call()
l4_msgdope_t ipc_result;
long rec_badge;
_snd_msg->send_dope = L4_IPC_DOPE((_write_offset + 2*sizeof(umword_t) - 1)>>2, 0);
_rcv_msg->size_dope = L4_IPC_DOPE(_rcv_msg->size()>>2, 0);
_snd_msg.send_dope = L4_IPC_DOPE((_write_offset + 2*sizeof(umword_t) - 1)>>2, 0);
_rcv_msg.size_dope = L4_IPC_DOPE(_rcv_msg.size()>>2, 0);
l4_ipc_call(Ipc_ostream::_dst.dst(),
_write_offset <= 2*sizeof(umword_t) ? L4_IPC_SHORT_MSG : _snd_msg->addr(),
Ipc_ostream::_dst.local_name(),
*reinterpret_cast<l4_umword_t *>(&_snd_msg->buf[sizeof(umword_t)]),
_rcv_msg->addr(),
l4_ipc_call(_dst.dst(),
_write_offset <= 2*sizeof(umword_t) ? L4_IPC_SHORT_MSG : _snd_msg.msg_start(),
_dst.local_name(),
*reinterpret_cast<l4_umword_t *>(&_snd_msg.buf[sizeof(umword_t)]),
_rcv_msg.msg_start(),
reinterpret_cast<l4_umword_t *>(&rec_badge),
reinterpret_cast<l4_umword_t *>(&_rcv_msg->buf[sizeof(umword_t)]),
reinterpret_cast<l4_umword_t *>(&_rcv_msg.buf[sizeof(umword_t)]),
L4_IPC_NEVER, &ipc_result);
if (L4_IPC_IS_ERROR(ipc_result)) {
@ -103,10 +74,13 @@ void Ipc_client::_call()
}
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
Msgbuf_base *rcv_msg, unsigned short):
Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0)
{ }
Ipc_client::Ipc_client(Native_capability const &dst,
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg, unsigned short)
:
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
{
_read_offset = _write_offset = sizeof(umword_t);
}
/****************
@ -126,7 +100,7 @@ void Ipc_server::_prepare_next_reply_wait()
}
void Ipc_server::_wait()
void Ipc_server::wait()
{
/* wait for new server request */
try {
@ -142,11 +116,11 @@ void Ipc_server::_wait()
* client. The server does not bother.
*/
do {
_rcv_msg->size_dope = L4_IPC_DOPE(_rcv_msg->size()>>2, 0);
_rcv_msg.size_dope = L4_IPC_DOPE(_rcv_msg.size()>>2, 0);
l4_ipc_wait(&_rcv_cs.caller, _rcv_msg->addr(),
reinterpret_cast<l4_umword_t *>(&_rcv_msg->buf[0]),
reinterpret_cast<l4_umword_t *>(&_rcv_msg->buf[sizeof(umword_t)]),
l4_ipc_wait(&_rcv_cs.caller, _rcv_msg.msg_start(),
reinterpret_cast<l4_umword_t *>(&_rcv_msg.buf[0]),
reinterpret_cast<l4_umword_t *>(&_rcv_msg.buf[sizeof(umword_t)]),
L4_IPC_NEVER, &result);
if (L4_IPC_IS_ERROR(result))
@ -160,22 +134,23 @@ void Ipc_server::_wait()
} catch (Blocking_canceled) { }
/* define destination of next reply */
Ipc_ostream::_dst = Native_capability(_rcv_cs.caller, badge());
_caller = Native_capability(_rcv_cs.caller, 0);
_badge = reinterpret_cast<unsigned long *>(&_rcv_msg.buf)[0];
_prepare_next_reply_wait();
}
void Ipc_server::_reply()
void Ipc_server::reply()
{
using namespace Fiasco;
_snd_msg->send_dope = L4_IPC_DOPE((_write_offset + sizeof(umword_t) - 1)>>2, 0);
_snd_msg.send_dope = L4_IPC_DOPE((_write_offset + sizeof(umword_t) - 1)>>2, 0);
l4_msgdope_t result;
l4_ipc_send(Ipc_ostream::_dst.dst(), _snd_msg->addr(),
Ipc_ostream::_dst.local_name(),
*reinterpret_cast<l4_umword_t *>(&_snd_msg->buf[sizeof(umword_t)]),
l4_ipc_send(_caller.dst(), _snd_msg.msg_start(),
_caller.local_name(),
*reinterpret_cast<l4_umword_t *>(&_snd_msg.buf[sizeof(umword_t)]),
L4_IPC_SEND_TIMEOUT_0, &result);
if (L4_IPC_IS_ERROR(result))
@ -185,7 +160,7 @@ void Ipc_server::_reply()
}
void Ipc_server::_reply_wait()
void Ipc_server::reply_wait()
{
using namespace Fiasco;
@ -193,8 +168,8 @@ void Ipc_server::_reply_wait()
l4_msgdope_t ipc_result;
_snd_msg->send_dope = L4_IPC_DOPE((_write_offset + sizeof(umword_t) - 1)>>2, 0);
_rcv_msg->size_dope = L4_IPC_DOPE(_rcv_msg->size()>>2, 0);
_snd_msg.send_dope = L4_IPC_DOPE((_write_offset + sizeof(umword_t) - 1)>>2, 0);
_rcv_msg.size_dope = L4_IPC_DOPE(_rcv_msg.size()>>2, 0);
/*
* Use short IPC for reply if possible.
@ -202,13 +177,13 @@ void Ipc_server::_reply_wait()
* an integer as RPC result.
*/
l4_ipc_reply_and_wait(
Ipc_ostream::_dst.dst(),
_write_offset <= 2*sizeof(umword_t) ? L4_IPC_SHORT_MSG : _snd_msg->addr(),
Ipc_ostream::_dst.local_name(),
*reinterpret_cast<l4_umword_t *>(&_snd_msg->buf[sizeof(umword_t)]),
&_rcv_cs.caller, _rcv_msg->addr(),
reinterpret_cast<l4_umword_t *>(&_rcv_msg->buf[0]),
reinterpret_cast<l4_umword_t *>(&_rcv_msg->buf[sizeof(umword_t)]),
_caller.dst(),
_write_offset <= 2*sizeof(umword_t) ? L4_IPC_SHORT_MSG : _snd_msg.msg_start(),
_caller.local_name(),
*reinterpret_cast<l4_umword_t *>(&_snd_msg.buf[sizeof(umword_t)]),
&_rcv_cs.caller, _rcv_msg.msg_start(),
reinterpret_cast<l4_umword_t *>(&_rcv_msg.buf[0]),
reinterpret_cast<l4_umword_t *>(&_rcv_msg.buf[sizeof(umword_t)]),
L4_IPC_SEND_TIMEOUT_0, &ipc_result);
if (L4_IPC_IS_ERROR(ipc_result)) {
@ -222,24 +197,28 @@ void Ipc_server::_reply_wait()
* the user but want to wait for the next proper incoming
* message. So let's just wait now.
*/
_wait();
wait();
}
} else _wait();
} else wait();
/* define destination of next reply */
Ipc_ostream::_dst = Native_capability(_rcv_cs.caller, badge());
_caller = Native_capability(_rcv_cs.caller, 0);
_badge = reinterpret_cast<unsigned long *>(_rcv_msg.buf)[0];
_prepare_next_reply_wait();
}
Ipc_server::Ipc_server(Native_connection_state &cs,
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg)
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
:
Ipc_istream(rcv_msg),
Ipc_ostream(Native_capability(), snd_msg), _reply_needed(false), _rcv_cs(cs)
{ }
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
Native_capability(Fiasco::l4_myself(), 0),
_reply_needed(false), _rcv_cs(cs)
{
_read_offset = _write_offset = sizeof(umword_t);
}
Ipc_server::~Ipc_server() { }

View File

@ -88,9 +88,9 @@ namespace Genode {
inline size_t size() const { return _size; };
/**
* Return address of message buffer
* Return pointer of message data payload
*/
inline void *addr() { return &_msg_start[0]; };
inline void *data() { return &_msg_start[0]; };
/**
* Reset portal capability selector payload

View File

@ -47,21 +47,21 @@ using namespace Fiasco;
** IPC marshalling support **
*****************************/
void Ipc_ostream::_marshal_capability(Native_capability const &cap)
void Ipc_marshaller::insert(Native_capability const &cap)
{
if (cap.valid()) {
if (!l4_msgtag_label(l4_task_cap_valid(L4_BASE_TASK_CAP, cap.dst()))) {
_write_to_buf(0);
insert(0UL);
return;
}
}
/* transfer capability id */
_write_to_buf(cap.local_name());
insert(cap.local_name());
/* only transfer kernel-capability if it's a valid one */
if (cap.valid())
_snd_msg->snd_append_cap_sel(cap.dst());
_snd_msg.snd_append_cap_sel(cap.dst());
ASSERT(!cap.valid() ||
l4_msgtag_label(l4_task_cap_valid(L4_BASE_TASK_CAP, cap.dst())),
@ -69,12 +69,12 @@ void Ipc_ostream::_marshal_capability(Native_capability const &cap)
}
void Ipc_istream::_unmarshal_capability(Native_capability &cap)
void Ipc_unmarshaller::extract(Native_capability &cap)
{
long value = 0;
/* extract capability id from message buffer */
_read_from_buf(value);
extract(value);
/* if id is zero an invalid capability was transfered */
if (!value) {
@ -83,7 +83,7 @@ void Ipc_istream::_unmarshal_capability(Native_capability &cap)
}
/* try to insert received capability in the map and return it */
cap = Native_capability(cap_map()->insert_map(value, _rcv_msg->rcv_cap_sel()));
cap = Native_capability(cap_map()->insert_map(value, _rcv_msg.rcv_cap_sel()));
}
@ -117,7 +117,7 @@ static inline bool ipc_error(l4_msgtag_t tag, bool print)
/**
* Copy message registers from UTCB to destination message buffer
*/
static void copy_utcb_to_msgbuf(l4_msgtag_t tag, Msgbuf_base *rcv_msg)
static void copy_utcb_to_msgbuf(l4_msgtag_t tag, Msgbuf_base &rcv_msg)
{
unsigned num_msg_words = l4_msgtag_words(tag);
unsigned num_cap_sel = l4_msgtag_items(tag);
@ -125,11 +125,11 @@ static void copy_utcb_to_msgbuf(l4_msgtag_t tag, Msgbuf_base *rcv_msg)
return;
/* look up and validate destination message buffer to receive the payload */
l4_mword_t *msg_buf = (l4_mword_t *)rcv_msg->buf;
if (num_msg_words*sizeof(l4_mword_t) > rcv_msg->size()) {
l4_mword_t *msg_buf = (l4_mword_t *)rcv_msg.buf;
if (num_msg_words*sizeof(l4_mword_t) > rcv_msg.size()) {
if (DEBUG_MSG)
outstring("receive message buffer too small");
num_msg_words = rcv_msg->size()/sizeof(l4_mword_t);
num_msg_words = rcv_msg.size()/sizeof(l4_mword_t);
}
/* read message payload into destination message buffer */
@ -138,19 +138,19 @@ static void copy_utcb_to_msgbuf(l4_msgtag_t tag, Msgbuf_base *rcv_msg)
for (unsigned i = 0; i < num_msg_words; i++)
*dst++ = *src++;
rcv_msg->rcv_reset();
rcv_msg.rcv_reset();
}
/**
* Copy message registers from message buffer to UTCB and create message tag.
*/
static l4_msgtag_t copy_msgbuf_to_utcb(Msgbuf_base *snd_msg, unsigned offset,
static l4_msgtag_t copy_msgbuf_to_utcb(Msgbuf_base &snd_msg, unsigned offset,
Native_capability dst)
{
l4_mword_t *msg_buf = (l4_mword_t *)snd_msg->buf;
l4_mword_t *msg_buf = (l4_mword_t *)snd_msg.buf;
unsigned num_msg_words = offset/sizeof(l4_mword_t);
unsigned num_cap_sel = snd_msg->snd_cap_sel_cnt();
unsigned num_cap_sel = snd_msg.snd_cap_sel_cnt();
if (num_msg_words + 2 * num_cap_sel > L4_UTCB_GENERIC_DATA_SIZE) {
if (DEBUG_MSG)
@ -169,47 +169,17 @@ static l4_msgtag_t copy_msgbuf_to_utcb(Msgbuf_base *snd_msg, unsigned offset,
for (unsigned i = 0; i < num_cap_sel; i++) {
unsigned idx = num_msg_words + 2*i;
l4_utcb_mr()->mr[idx] = L4_ITEM_MAP/* | L4_ITEM_CONT*/;
l4_utcb_mr()->mr[idx + 1] = l4_obj_fpage(snd_msg->snd_cap_sel(i),
l4_utcb_mr()->mr[idx + 1] = l4_obj_fpage(snd_msg.snd_cap_sel(i),
0, L4_FPAGE_RWX).raw;
}
/* we have consumed capability selectors, reset message buffer */
snd_msg->snd_reset();
snd_msg.snd_reset();
return l4_msgtag(0, num_msg_words, num_cap_sel, 0);
}
/*****************
** Ipc_ostream **
*****************/
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
:
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
_snd_msg(snd_msg), _dst(dst)
{
_write_offset = sizeof(l4_mword_t);
}
/*****************
** Ipc_istream **
*****************/
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
:
Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()),
Native_capability((Cap_index*)Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE]),
_rcv_msg(rcv_msg)
{
_read_offset = sizeof(l4_mword_t);
}
Ipc_istream::~Ipc_istream() { }
/****************
** Ipc_client **
****************/
@ -219,7 +189,7 @@ void Ipc_client::_call()
/* copy call message to the UTCBs message registers */
l4_msgtag_t tag = copy_msgbuf_to_utcb(_snd_msg, _write_offset, _dst);
addr_t rcv_cap_sel = _rcv_msg->rcv_cap_sel_base();
addr_t rcv_cap_sel = _rcv_msg.rcv_cap_sel_base();
for (int i = 0; i < Msgbuf_base::MAX_CAP_ARGS; i++) {
l4_utcb_br()->br[i] = rcv_cap_sel | L4_RCV_ITEM_SINGLE_CAP;
rcv_cap_sel += L4_CAP_SIZE;
@ -238,9 +208,13 @@ void Ipc_client::_call()
}
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
Msgbuf_base *rcv_msg, unsigned short)
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0) { }
Ipc_client::Ipc_client(Native_capability const &dst,
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg, unsigned short)
:
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
{
_read_offset = _write_offset = sizeof(l4_mword_t);
}
/****************
@ -260,12 +234,11 @@ void Ipc_server::_prepare_next_reply_wait()
}
void Ipc_server::_wait()
void Ipc_server::wait()
{
/* wait for new server request */
try {
l4_umword_t label = 0;
addr_t rcv_cap_sel = _rcv_msg->rcv_cap_sel_base();
addr_t rcv_cap_sel = _rcv_msg.rcv_cap_sel_base();
for (int i = 0; i < Msgbuf_base::MAX_CAP_ARGS; i++) {
l4_utcb_br()->br[i] = rcv_cap_sel | L4_RCV_ITEM_SINGLE_CAP;
rcv_cap_sel += L4_CAP_SIZE;
@ -274,12 +247,11 @@ void Ipc_server::_wait()
l4_msgtag_t tag;
do {
l4_umword_t label = 0;
tag = l4_ipc_wait(l4_utcb(), &label, L4_IPC_NEVER);
_rcv_msg.label(label);
} while (ipc_error(tag, DEBUG_MSG));
/* copy received label into message buffer */
_rcv_msg->label(label);
/* copy message from the UTCBs message registers to the receive buffer */
copy_utcb_to_msgbuf(tag, _rcv_msg);
@ -288,26 +260,24 @@ void Ipc_server::_wait()
} catch (Blocking_canceled) { }
/* we only have an unknown implicit reply capability */
/* _dst = ???; */
_badge = *reinterpret_cast<unsigned long *>(_rcv_msg.data());
_prepare_next_reply_wait();
}
void Ipc_server::_reply()
void Ipc_server::reply()
{
l4_msgtag_t tag = copy_msgbuf_to_utcb(_snd_msg, _write_offset, _dst);
l4_msgtag_t tag = copy_msgbuf_to_utcb(_snd_msg, _write_offset, Native_capability());
tag = l4_ipc_send(L4_SYSF_REPLY, l4_utcb(), tag, L4_IPC_SEND_TIMEOUT_0);
ipc_error(tag, DEBUG_MSG);
}
void Ipc_server::_reply_wait()
void Ipc_server::reply_wait()
{
if (_reply_needed) {
l4_umword_t label;
addr_t rcv_cap_sel = _rcv_msg->rcv_cap_sel_base();
addr_t rcv_cap_sel = _rcv_msg.rcv_cap_sel_base();
for (int i = 0; i < Msgbuf_base::MAX_CAP_ARGS; i++) {
l4_utcb_br()->br[i] = rcv_cap_sel | L4_RCV_ITEM_SINGLE_CAP;
rcv_cap_sel += L4_CAP_SIZE;
@ -315,8 +285,11 @@ void Ipc_server::_reply_wait()
l4_utcb_br()->bdr &= ~L4_BDR_OFFSET_MASK;
l4_msgtag_t tag = copy_msgbuf_to_utcb(_snd_msg, _write_offset, _dst);
l4_umword_t label = 0;
l4_msgtag_t tag = copy_msgbuf_to_utcb(_snd_msg, _write_offset, Native_capability());
tag = l4_ipc_reply_and_wait(l4_utcb(), tag, &label, L4_IPC_SEND_TIMEOUT_0);
_rcv_msg.label(label);
if (ipc_error(tag, false)) {
/*
* The error conditions could be a message cut (which
@ -326,31 +299,30 @@ void Ipc_server::_reply_wait()
* the user but want to wait for the next proper incoming
* message. So let's just wait now.
*/
_wait();
wait();
} else {
/* copy received label into message buffer */
_rcv_msg->label(label);
/* copy request message from the UTCBs message registers */
copy_utcb_to_msgbuf(tag, _rcv_msg);
}
} else
_wait();
wait();
_badge = *reinterpret_cast<unsigned long *>(_rcv_msg.data());
/* reply capability is implicit in fiasco.oc and unknown to us */
/* _dst = ???; */
_prepare_next_reply_wait();
}
Ipc_server::Ipc_server(Native_connection_state &cs,
Msgbuf_base *snd_msg,
Msgbuf_base *rcv_msg)
: Ipc_istream(rcv_msg),
Ipc_ostream(Native_capability(), snd_msg),
_reply_needed(false), _rcv_cs(cs)
{ }
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
:
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
Native_capability((Cap_index*)Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE]),
_reply_needed(false), _rcv_cs(cs)
{
_read_offset = _write_offset = sizeof(l4_mword_t);
}
Ipc_server::~Ipc_server() { }

View File

@ -45,7 +45,7 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
void Rpc_entrypoint::entry()
{
Native_connection_state cs;
Ipc_server srv(cs, &_snd_buf, &_rcv_buf);
Ipc_server srv(cs, _snd_buf, _rcv_buf);
_ipc_server = &srv;
_cap = srv;
_cap_valid.unlock();
@ -63,17 +63,12 @@ void Rpc_entrypoint::entry()
int opcode = 0;
srv >> IPC_REPLY_WAIT >> opcode;
srv.reply_wait();
srv.extract(opcode);
/* set default return value */
srv.ret(Ipc_client::ERR_INVALID_OBJECT);
/* check whether capability's label fits global id */
if (((unsigned long)srv.badge()) != _rcv_buf.label()) {
PWRN("somebody tries to fake us!");
continue;
}
apply(srv.badge(), [&] (Rpc_object_base *obj) {
if (!obj) return;
@ -84,7 +79,7 @@ void Rpc_entrypoint::entry()
}
/* answer exit call, thereby wake up '~Rpc_entrypoint' */
srv << IPC_REPLY;
srv.reply();
/* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
_delay_exit.lock();

View File

@ -129,8 +129,9 @@ void Platform_thread::resume()
/* Send a message to the exception handler, to unblock the client */
Msgbuf<16> snd, rcv;
Ipc_client ipc_client(_pager_obj->cap(), &snd, &rcv);
ipc_client << _pager_obj << IPC_CALL;
Ipc_client ipc_client(_pager_obj->cap(), snd, rcv);
ipc_client.insert(_pager_obj);
ipc_client.call();
}

View File

@ -69,9 +69,9 @@ class Genode::Msgbuf_base
size_t size() const { return _size; }
/**
* Return address of message buffer
* Return pointer of message data payload
*/
void *addr() { return &buf[0]; }
void *data() { return &buf[0]; }
/**
* Reset capability buffer.

View File

@ -1,6 +1,7 @@
/*
* \brief Implementation of the Genode IPC-framework
* \author Martin Stein
* \author Norman Feske
* \date 2012-02-12
*/
@ -50,44 +51,12 @@ enum
** IPC marshalling support **
*****************************/
void Ipc_ostream::_marshal_capability(Native_capability const &cap) {
_snd_msg->cap_add(cap); }
void Ipc_marshaller::insert(Native_capability const &cap) {
_snd_msg.cap_add(cap); }
void Ipc_istream::_unmarshal_capability(Native_capability &cap) {
cap = _rcv_msg->cap_get(); }
/*****************
** Ipc_ostream **
*****************/
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
:
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
_snd_msg(snd_msg), _dst(dst)
{
_write_offset = align_natural<unsigned>(RPC_OBJECT_ID_SIZE);
_snd_msg->reset();
}
/*****************
** Ipc_istream **
*****************/
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
:
Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()),
Native_capability(Thread_base::myself() ? Thread_base::myself()->native_thread().cap
: Hw::_main_thread_cap),
_rcv_msg(rcv_msg)
{
_read_offset = align_natural<unsigned>(RPC_OBJECT_ID_SIZE);
}
Ipc_istream::~Ipc_istream() { }
void Ipc_unmarshaller::extract(Native_capability &cap) {
cap = _rcv_msg.cap_get(); }
/****************
@ -100,16 +69,16 @@ void Ipc_client::_call()
[&] () {
/* send request and receive corresponding reply */
Thread_base::myself()->utcb()->copy_from(*_snd_msg, _write_offset);
Thread_base::myself()->utcb()->copy_from(_snd_msg, _write_offset);
switch (Kernel::send_request_msg(Ipc_ostream::dst().dst(),
_rcv_msg->cap_rcv_window())) {
switch (Kernel::send_request_msg(_dst.dst(),
_rcv_msg.cap_rcv_window())) {
case -1: throw Blocking_canceled();
case -2: throw Allocator::Out_of_memory();
default:
_rcv_msg->reset();
_snd_msg->reset();
Thread_base::myself()->utcb()->copy_to(*_rcv_msg);
_rcv_msg.reset();
_snd_msg.reset();
Thread_base::myself()->utcb()->copy_to(_rcv_msg);
/* reset unmarshaller */
_write_offset = _read_offset =
@ -121,26 +90,24 @@ void Ipc_client::_call()
}
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
Msgbuf_base *rcv_msg, unsigned short rcv_caps)
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0) {
rcv_msg->cap_rcv_window(rcv_caps); }
Ipc_client::Ipc_client(Native_capability const &dst,
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
unsigned short rcv_caps)
:
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
{
_read_offset = align_natural<unsigned>(RPC_OBJECT_ID_SIZE);
_write_offset = align_natural<unsigned>(RPC_OBJECT_ID_SIZE);
_snd_msg.reset();
_rcv_msg.cap_rcv_window(rcv_caps);
}
/****************
** Ipc_server **
****************/
Ipc_server::Ipc_server(Native_connection_state &cs,
Msgbuf_base *snd_msg,
Msgbuf_base *rcv_msg)
:
Ipc_istream(rcv_msg),
Ipc_ostream(Native_capability(), snd_msg),
_reply_needed(false), _rcv_cs(cs)
{ }
void Ipc_server::_prepare_next_reply_wait()
{
/* now we have a request to reply */
@ -155,7 +122,7 @@ void Ipc_server::_prepare_next_reply_wait()
}
void Ipc_server::_wait()
void Ipc_server::wait()
{
retry<Genode::Allocator::Out_of_memory>(
[&] () {
@ -165,8 +132,9 @@ void Ipc_server::_wait()
case -1: throw Blocking_canceled();
case -2: throw Allocator::Out_of_memory();
default:
_rcv_msg->reset();
Thread_base::myself()->utcb()->copy_to(*_rcv_msg);
_rcv_msg.reset();
Thread_base::myself()->utcb()->copy_to(_rcv_msg);
_badge = *reinterpret_cast<unsigned long *>(_rcv_msg.data());
/* update server state */
_prepare_next_reply_wait();
@ -177,33 +145,34 @@ void Ipc_server::_wait()
}
void Ipc_server::_reply()
void Ipc_server::reply()
{
Thread_base::myself()->utcb()->copy_from(*_snd_msg, _write_offset);
_snd_msg->reset();
Thread_base::myself()->utcb()->copy_from(_snd_msg, _write_offset);
_snd_msg.reset();
Kernel::send_reply_msg(0, false);
}
void Ipc_server::_reply_wait()
void Ipc_server::reply_wait()
{
/* if there is no reply, wait for request */
if (!_reply_needed) {
_wait();
wait();
return;
}
retry<Genode::Allocator::Out_of_memory>(
[&] () {
/* send reply and receive next request */
Thread_base::myself()->utcb()->copy_from(*_snd_msg, _write_offset);
Thread_base::myself()->utcb()->copy_from(_snd_msg, _write_offset);
switch (Kernel::send_reply_msg(Msgbuf_base::MAX_CAP_ARGS, true)) {
case -1: throw Blocking_canceled();
case -2: throw Allocator::Out_of_memory();
default:
_rcv_msg->reset();
_snd_msg->reset();
Thread_base::myself()->utcb()->copy_to(*_rcv_msg);
_rcv_msg.reset();
_snd_msg.reset();
Thread_base::myself()->utcb()->copy_to(_rcv_msg);
_badge = *reinterpret_cast<unsigned long *>(_rcv_msg.data());
/* update server state */
_prepare_next_reply_wait();
@ -214,4 +183,18 @@ void Ipc_server::_reply_wait()
}
Ipc_server::Ipc_server(Native_connection_state &cs,
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
:
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
Native_capability(Thread_base::myself() ? Thread_base::myself()->native_thread().cap
: Hw::_main_thread_cap),
_reply_needed(false), _rcv_cs(cs)
{
_read_offset = align_natural<unsigned>(RPC_OBJECT_ID_SIZE);
_write_offset = align_natural<unsigned>(RPC_OBJECT_ID_SIZE);
_snd_msg.reset();
}
Ipc_server::~Ipc_server() { }

View File

@ -43,7 +43,7 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
void Rpc_entrypoint::entry()
{
Native_connection_state cs;
Ipc_server srv(cs, &_snd_buf, &_rcv_buf);
Ipc_server srv(cs, _snd_buf, _rcv_buf);
_ipc_server = &srv;
_cap = srv;
_cap_valid.unlock();
@ -61,7 +61,8 @@ void Rpc_entrypoint::entry()
int opcode = 0;
srv >> IPC_REPLY_WAIT >> opcode;
srv.reply_wait();
srv.extract(opcode);
/* set default return value */
srv.ret(Ipc_client::ERR_INVALID_OBJECT);
@ -77,7 +78,7 @@ void Rpc_entrypoint::entry()
}
/* answer exit call, thereby wake up '~Rpc_entrypoint' */
srv << IPC_REPLY;
srv.reply();
/* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
_delay_exit.lock();

View File

@ -62,9 +62,9 @@ namespace Genode {
inline Genode::size_t size() const { return _size; };
/**
* Return address of message buffer
* Return pointer of message data payload
*/
inline void *addr() { return &_msg_start[0]; };
inline void *data() { return &_msg_start[0]; };
void reset_caps() { _used_caps = 0; _read_cap_index = 0; }

View File

@ -52,22 +52,22 @@ using namespace Genode;
** IPC marshalling support **
*****************************/
void Ipc_ostream::_marshal_capability(Native_capability const &cap)
void Ipc_marshaller::insert(Native_capability const &cap)
{
if (cap.valid()) {
_write_to_buf(cap.local_name());
insert(cap.local_name());
_snd_msg->append_cap(cap.dst().socket);
_snd_msg.append_cap(cap.dst().socket);
} else {
_write_to_buf(-1L);
insert(-1L);
}
}
void Ipc_istream::_unmarshal_capability(Native_capability &cap)
void Ipc_unmarshaller::extract(Native_capability &cap)
{
long local_name = 0;
_read_from_buf(local_name);
extract(local_name);
if (local_name == -1) {
@ -77,7 +77,7 @@ void Ipc_istream::_unmarshal_capability(Native_capability &cap)
} else {
/* construct valid capability */
int const socket = _rcv_msg->read_cap();
int const socket = _rcv_msg.read_cap();
cap = Native_capability(Cap_dst_policy::Dst(socket), local_name);
}
}
@ -439,83 +439,31 @@ static inline void lx_reply(int reply_socket,
}
/*****************
** Ipc_ostream **
*****************/
/*
* XXX This class will be removed soon.
*/
void Ipc_ostream::_prepare_next_send()
{
PRAW("unexpected call to %s (%p)", __PRETTY_FUNCTION__, this);
}
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg):
Ipc_marshaller(snd_msg->buf, snd_msg->size()), _snd_msg(snd_msg), _dst(dst)
{ }
/*****************
** Ipc_istream **
*****************/
/*
* XXX This class will be removed soon.
*/
void Ipc_istream::_prepare_next_receive()
{
PRAW("unexpected call to %s (%p)", __PRETTY_FUNCTION__, this);
}
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
:
Ipc_unmarshaller(rcv_msg->buf, rcv_msg->size()),
Native_capability(Dst(-1), 0),
_rcv_msg(rcv_msg)
{ }
Ipc_istream::~Ipc_istream() { }
/****************
** Ipc_client **
****************/
void Ipc_client::_prepare_next_call()
void Ipc_client::_call()
{
lx_call(_dst.dst().socket, _snd_msg, _write_offset, _rcv_msg);
}
Ipc_client::Ipc_client(Native_capability const &dst,
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg, unsigned short)
:
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
{
/* prepare next request in buffer */
long const local_name = Ipc_ostream::_dst.local_name();
_write_offset = 0;
_write_to_buf(local_name);
long const local_name = _dst.local_name();
/* prepare response buffer */
_read_offset = sizeof(long);
_write_offset = 0;
_snd_msg->reset_caps();
}
insert(local_name);
void Ipc_client::_call()
{
if (Ipc_ostream::_dst.valid())
lx_call(Ipc_ostream::_dst.dst().socket, *_snd_msg, _write_offset, *_rcv_msg);
_prepare_next_call();
}
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
Msgbuf_base *rcv_msg, unsigned short)
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0)
{
_prepare_next_call();
_snd_msg.reset_caps();
}
@ -530,18 +478,18 @@ void Ipc_server::_prepare_next_reply_wait()
/* prepare next reply */
_write_offset = 0;
long local_name = Ipc_ostream::_dst.local_name();
_write_to_buf(local_name); /* XXX unused, needed by de/marshaller */
long local_name = _caller.local_name();
insert(local_name); /* XXX unused, needed by de/marshaller */
/* leave space for exc code at the beginning of the msgbuf */
_write_offset += align_natural(sizeof(int));
/* reset capability slots of send message buffer */
_snd_msg->reset_caps();
_snd_msg.reset_caps();
}
void Ipc_server::_wait()
void Ipc_server::wait()
{
_reply_needed = true;
@ -555,7 +503,7 @@ void Ipc_server::_wait()
}
try {
int const reply_socket = lx_wait(_rcv_cs, *_rcv_msg);
int const reply_socket = lx_wait(_rcv_cs, _rcv_msg);
/*
* Remember reply capability
@ -566,38 +514,40 @@ void Ipc_server::_wait()
*/
enum { DUMMY_LOCAL_NAME = -1 };
typedef Native_capability::Dst Dst;
Ipc_ostream::_dst = Native_capability(Dst(reply_socket), DUMMY_LOCAL_NAME);
_caller = Native_capability(Dst(reply_socket), DUMMY_LOCAL_NAME);
_badge = reinterpret_cast<unsigned long *>(_rcv_msg.data())[0];
_prepare_next_reply_wait();
} catch (Blocking_canceled) { }
}
void Ipc_server::_reply()
void Ipc_server::reply()
{
try {
lx_reply(Ipc_ostream::_dst.dst().socket, *_snd_msg, _write_offset); }
lx_reply(_caller.dst().socket, _snd_msg, _write_offset); }
catch (Ipc_error) { }
_prepare_next_reply_wait();
}
void Ipc_server::_reply_wait()
void Ipc_server::reply_wait()
{
/* when first called, there was no request yet */
if (_reply_needed)
lx_reply(Ipc_ostream::_dst.dst().socket, *_snd_msg, _write_offset);
lx_reply(_caller.dst().socket, _snd_msg, _write_offset);
_wait();
wait();
}
Ipc_server::Ipc_server(Native_connection_state &cs,
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg)
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
:
Ipc_istream(rcv_msg),
Ipc_ostream(Native_capability(), snd_msg), _reply_needed(false), _rcv_cs(cs)
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
Native_capability(Dst(-1), 0),
_reply_needed(false), _rcv_cs(cs)
{
Thread_base *thread = Thread_base::myself();
@ -619,7 +569,7 @@ Ipc_server::Ipc_server(Native_connection_state &cs,
thread->native_thread().is_ipc_server = true;
}
/* override capability initialization performed by 'Ipc_istream' */
/* override capability initialization */
*static_cast<Native_capability *>(this) =
Native_capability(Native_capability::Dst(_rcv_cs.client_sd), 0);

View File

@ -125,9 +125,9 @@ namespace Genode {
inline size_t size() const { return _size; }
/**
* Return address of message buffer
* Return pointer of message data payload
*/
inline void *addr() { return &_msg_start[0]; }
inline void *data() { return &_msg_start[0]; }
/**
* Reset portal capability selector payload

View File

@ -28,15 +28,15 @@ using namespace Nova;
** IPC marshalling support **
*****************************/
void Ipc_ostream::_marshal_capability(Native_capability const &cap)
void Ipc_marshaller::insert(Native_capability const &cap)
{
_snd_msg->snd_append_pt_sel(cap);
_snd_msg.snd_append_pt_sel(cap);
}
void Ipc_istream::_unmarshal_capability(Native_capability &cap)
void Ipc_unmarshaller::extract(Native_capability &cap)
{
_rcv_msg->rcv_pt_sel(cap);
_rcv_msg.rcv_pt_sel(cap);
}
@ -47,17 +47,17 @@ void Ipc_istream::_unmarshal_capability(Native_capability &cap)
/**
* Copy message registers from UTCB to destination message buffer
*/
static void copy_utcb_to_msgbuf(Nova::Utcb *utcb, Msgbuf_base *rcv_msg)
static void copy_utcb_to_msgbuf(Nova::Utcb *utcb, Msgbuf_base &rcv_msg)
{
size_t num_msg_words = utcb->msg_words();
if (num_msg_words == 0) return;
/* look up and validate destination message buffer to receive the payload */
mword_t *msg_buf = (mword_t *)rcv_msg->buf;
if (num_msg_words*sizeof(mword_t) > rcv_msg->size()) {
mword_t *msg_buf = (mword_t *)rcv_msg.buf;
if (num_msg_words*sizeof(mword_t) > rcv_msg.size()) {
PERR("receive message buffer too small msg size=%zx, buf size=%zd",
num_msg_words*sizeof(mword_t), rcv_msg->size());
num_msg_words = rcv_msg->size()/sizeof(mword_t);
num_msg_words*sizeof(mword_t), rcv_msg.size());
num_msg_words = rcv_msg.size()/sizeof(mword_t);
}
/* read message payload into destination message buffer */
@ -71,11 +71,11 @@ static void copy_utcb_to_msgbuf(Nova::Utcb *utcb, Msgbuf_base *rcv_msg)
/**
* Copy message payload to UTCB message registers
*/
static bool copy_msgbuf_to_utcb(Nova::Utcb *utcb, Msgbuf_base *snd_msg,
static bool copy_msgbuf_to_utcb(Nova::Utcb *utcb, Msgbuf_base &snd_msg,
unsigned num_msg_words, mword_t local_name)
{
/* look up address and size of message payload */
mword_t *msg_buf = (mword_t *)snd_msg->buf;
mword_t *msg_buf = (mword_t *)snd_msg.buf;
/*
* XXX determine correct number of message registers
@ -97,9 +97,9 @@ static bool copy_msgbuf_to_utcb(Nova::Utcb *utcb, Msgbuf_base *snd_msg,
utcb->set_msg_word(num_msg_words);
/* append portal capability selectors */
for (unsigned i = 0; i < snd_msg->snd_pt_sel_cnt(); i++) {
for (unsigned i = 0; i < snd_msg.snd_pt_sel_cnt(); i++) {
bool trans_map = true;
Nova::Obj_crd crd = snd_msg->snd_pt_sel(i, trans_map);
Nova::Obj_crd crd = snd_msg.snd_pt_sel(i, trans_map);
if (crd.base() == ~0UL) continue;
if (!utcb->append_item(crd, i, false, false, trans_map))
@ -107,39 +107,12 @@ static bool copy_msgbuf_to_utcb(Nova::Utcb *utcb, Msgbuf_base *snd_msg,
}
/* we have consumed portal capability selectors, reset message buffer */
snd_msg->snd_reset();
snd_msg.snd_reset();
return true;
}
/*****************
** Ipc_ostream **
*****************/
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
:
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
_snd_msg(snd_msg), _dst(dst)
{
_write_offset = sizeof(mword_t);
}
/*****************
** Ipc_istream **
*****************/
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
: Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()), _rcv_msg(rcv_msg)
{
_read_offset = sizeof(mword_t);
}
Ipc_istream::~Ipc_istream() { }
/****************
** Ipc_client **
****************/
@ -149,18 +122,18 @@ void Ipc_client::_call()
Nova::Utcb *utcb = (Nova::Utcb *)Thread_base::myself()->utcb();
if (!copy_msgbuf_to_utcb(utcb, _snd_msg, _write_offset/sizeof(mword_t),
Ipc_ostream::_dst.local_name())) {
_dst.local_name())) {
PERR("could not setup IPC");
return;
}
/* if we can't setup receive window, die in order to recognize the issue */
if (!_rcv_msg->prepare_rcv_window(utcb, Ipc_ostream::_dst.rcv_window()))
if (!_rcv_msg.prepare_rcv_window(utcb, _dst.rcv_window()))
/* printf doesn't work here since for IPC also rcv_prepare* is used */
nova_die();
/* establish the mapping via a portal traversal */
uint8_t res = Nova::call(Ipc_ostream::_dst.local_name());
uint8_t res = Nova::call(_dst.local_name());
if (res != Nova::NOVA_OK) {
/* If an error occurred, reset word&item count (not done by kernel). */
utcb->set_msg_word(0);
@ -168,17 +141,19 @@ void Ipc_client::_call()
ret(ERR_INVALID_OBJECT);
}
_rcv_msg->post_ipc(utcb, Ipc_ostream::_dst.rcv_window());
_rcv_msg.post_ipc(utcb, _dst.rcv_window());
copy_utcb_to_msgbuf(utcb, _rcv_msg);
_snd_msg->snd_reset();
_snd_msg.snd_reset();
_write_offset = _read_offset = sizeof(mword_t);
}
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
Msgbuf_base *rcv_msg, unsigned short const rcv_caps)
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0)
Ipc_client::Ipc_client(Native_capability const &dst,
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
unsigned short const rcv_caps)
:
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
{
if (rcv_caps == ~0)
/* use default values for rcv_wnd */
@ -188,7 +163,9 @@ Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
unsigned short log2_max = rcv_caps ? log2(rcv_caps) : 0;
if ((1U << log2_max) < rcv_caps) log2_max ++;
rcv_msg->rcv_wnd(log2_max);
rcv_msg.rcv_wnd(log2_max);
_read_offset = _write_offset = sizeof(mword_t);
}
@ -196,7 +173,7 @@ Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
** Ipc_server **
****************/
void Ipc_server::_wait()
void Ipc_server::wait()
{
/*
* This function is only called by the portal dispatcher of server
@ -207,7 +184,7 @@ void Ipc_server::_wait()
Nova::Utcb *utcb = (Nova::Utcb *)Thread_base::myself()->utcb();
_rcv_msg->post_ipc(utcb);
_rcv_msg.post_ipc(utcb);
copy_utcb_to_msgbuf(utcb, _rcv_msg);
/* reset unmarshaller */
@ -216,25 +193,26 @@ void Ipc_server::_wait()
}
void Ipc_server::_reply()
void Ipc_server::reply()
{
Nova::Utcb *utcb = (Nova::Utcb *)Thread_base::myself()->utcb();
copy_msgbuf_to_utcb(utcb, _snd_msg, _write_offset/sizeof(mword_t),
Ipc_ostream::_dst.local_name());
copy_msgbuf_to_utcb(utcb, _snd_msg, _write_offset/sizeof(mword_t), 0);
Nova::reply(Thread_base::myself()->stack_top());
}
void Ipc_server::_reply_wait() { }
void Ipc_server::reply_wait() { }
Ipc_server::Ipc_server(Native_connection_state &cs,
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg)
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
:
Ipc_istream(rcv_msg), Ipc_ostream(Native_capability(), snd_msg), _rcv_cs(cs)
{ }
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _rcv_cs(cs)
{
_read_offset = _write_offset = sizeof(mword_t);
}
Ipc_server::~Ipc_server() { }

View File

@ -122,8 +122,9 @@ void Rpc_entrypoint::_activation_entry()
int opcode = 0;
Native_connection_state cs;
Ipc_server srv(cs, &ep->_snd_buf, &ep->_rcv_buf);
srv >> IPC_WAIT >> opcode;
Ipc_server srv(cs, ep->_snd_buf, ep->_rcv_buf);
srv.wait();
srv.extract(opcode);
/* set default return value */
srv.ret(Ipc_client::ERR_INVALID_OBJECT);
@ -132,7 +133,7 @@ void Rpc_entrypoint::_activation_entry()
if (ep->_cap.local_name() == id_pt) {
if (!ep->_rcv_buf.prepare_rcv_window((Nova::Utcb *)ep->utcb()))
PWRN("out of capability selectors for handling server requests");
srv << IPC_REPLY;
srv.reply();
}
{
@ -157,7 +158,7 @@ void Rpc_entrypoint::_activation_entry()
if (!ep->_rcv_buf.prepare_rcv_window((Nova::Utcb *)ep->utcb()))
PWRN("out of capability selectors for handling server requests");
srv << IPC_REPLY;
srv.reply();
}

View File

@ -45,9 +45,9 @@ namespace Genode {
inline size_t size() const { return _size; };
/**
* Return address of message buffer
* Return pointer of message data payload
*/
inline void *addr() { return &_msg_start[0]; };
inline void *data() { return &_msg_start[0]; };
};

View File

@ -51,17 +51,17 @@ static void kdb_emergency_print(const char *s)
/**
* Copy message registers from UTCB to destination message buffer
*/
static void copy_utcb_to_msgbuf(L4_MsgTag_t rcv_tag, Msgbuf_base *rcv_msg)
static void copy_utcb_to_msgbuf(L4_MsgTag_t rcv_tag, Msgbuf_base &rcv_msg)
{
int num_msg_words = (int)L4_UntypedWords(rcv_tag);
if (num_msg_words <= 0) return;
/* look up and validate destination message buffer to receive the payload */
L4_Word_t *msg_buf = (L4_Word_t *)rcv_msg->buf;
if (num_msg_words*sizeof(L4_Word_t) > rcv_msg->size()) {
L4_Word_t *msg_buf = (L4_Word_t *)rcv_msg.buf;
if (num_msg_words*sizeof(L4_Word_t) > rcv_msg.size()) {
PERR("receive message buffer too small msg size=%zd, buf size=%zd",
num_msg_words*sizeof(L4_Word_t), rcv_msg->size());
num_msg_words = rcv_msg->size()/sizeof(L4_Word_t);
num_msg_words*sizeof(L4_Word_t), rcv_msg.size());
num_msg_words = rcv_msg.size()/sizeof(L4_Word_t);
}
/* read message payload into destination message buffer */
@ -77,11 +77,11 @@ static void copy_utcb_to_msgbuf(L4_MsgTag_t rcv_tag, Msgbuf_base *rcv_msg)
* 1 is used for the local name. All subsequent message registers hold the
* message payload.
*/
static void copy_msgbuf_to_utcb(Msgbuf_base *snd_msg, unsigned num_msg_words,
static void copy_msgbuf_to_utcb(Msgbuf_base &snd_msg, unsigned num_msg_words,
L4_Word_t local_name)
{
/* look up address and size of message payload */
L4_Word_t *msg_buf = (L4_Word_t *)snd_msg->buf;
L4_Word_t *msg_buf = (L4_Word_t *)snd_msg.buf;
num_msg_words += 1;
@ -99,51 +99,6 @@ static void copy_msgbuf_to_utcb(Msgbuf_base *snd_msg, unsigned num_msg_words,
}
/*****************
** Ipc_ostream **
*****************/
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
:
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
_snd_msg(snd_msg), _dst(dst)
{
_write_offset = sizeof(umword_t);
}
/*****************
** Ipc_istream **
*****************/
/**
* Return the global thread ID of the calling thread
*
* On OKL4 we cannot use 'L4_Myself()' to determine our own thread's
* identity. By convention, each thread stores its global ID in a
* defined entry of its UTCB.
*/
static inline Okl4::L4_ThreadId_t thread_get_my_global_id()
{
Okl4::L4_ThreadId_t myself;
myself.raw = Okl4::__L4_TCR_ThreadWord(UTCB_TCR_THREAD_WORD_MYSELF);
return myself;
}
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
:
Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()),
Native_capability(thread_get_my_global_id(), 0),
_rcv_msg(rcv_msg)
{
_read_offset = sizeof(umword_t);
}
Ipc_istream::~Ipc_istream() { }
/****************
** Ipc_client **
****************/
@ -152,10 +107,10 @@ void Ipc_client::_call()
{
/* copy call message to the UTCBs message registers */
copy_msgbuf_to_utcb(_snd_msg, _write_offset/sizeof(L4_Word_t),
Ipc_ostream::_dst.local_name());
_dst.local_name());
L4_Accept(L4_UntypedWordsAcceptor);
L4_MsgTag_t rcv_tag = L4_Call(Ipc_ostream::_dst.dst());
L4_MsgTag_t rcv_tag = L4_Call(_dst.dst());
enum { ERROR_MASK = 0xe, ERROR_CANCELED = 3 << 1 };
if (L4_IpcFailed(rcv_tag) &&
@ -175,9 +130,13 @@ void Ipc_client::_call()
}
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
Msgbuf_base *rcv_msg, unsigned short)
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0) { }
Ipc_client::Ipc_client(Native_capability const &dst,
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg, unsigned short)
:
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
{
_write_offset = _read_offset = sizeof(umword_t);
}
/****************
@ -197,7 +156,7 @@ void Ipc_server::_prepare_next_reply_wait()
}
void Ipc_server::_wait()
void Ipc_server::wait()
{
/* wait for new server request */
try {
@ -218,20 +177,21 @@ void Ipc_server::_wait()
} catch (Blocking_canceled) { }
/* define destination of next reply */
Ipc_ostream::_dst = Native_capability(_rcv_cs.caller, badge());
_caller = Native_capability(_rcv_cs.caller, badge());
_badge = reinterpret_cast<unsigned long *>(_rcv_msg.data())[0];
_prepare_next_reply_wait();
}
void Ipc_server::_reply()
void Ipc_server::reply()
{
/* copy reply to the UTCBs message registers */
copy_msgbuf_to_utcb(_snd_msg, _write_offset/sizeof(L4_Word_t),
Ipc_ostream::_dst.local_name());
_caller.local_name());
/* perform non-blocking IPC send operation */
L4_MsgTag_t rcv_tag = L4_Reply(Ipc_ostream::_dst.dst());
L4_MsgTag_t rcv_tag = L4_Reply(_caller.dst());
if (L4_IpcFailed(rcv_tag))
PERR("ipc error in _reply - gets ignored");
@ -240,15 +200,15 @@ void Ipc_server::_reply()
}
void Ipc_server::_reply_wait()
void Ipc_server::reply_wait()
{
if (_reply_needed) {
/* copy reply to the UTCBs message registers */
copy_msgbuf_to_utcb(_snd_msg, _write_offset/sizeof(L4_Word_t),
Ipc_ostream::_dst.local_name());
_caller.local_name());
L4_MsgTag_t rcv_tag = L4_ReplyWait(Ipc_ostream::_dst.dst(), &_rcv_cs.caller);
L4_MsgTag_t rcv_tag = L4_ReplyWait(_caller.dst(), &_rcv_cs.caller);
/*
* TODO: Check for IPC error
@ -258,22 +218,40 @@ void Ipc_server::_reply_wait()
copy_utcb_to_msgbuf(rcv_tag, _rcv_msg);
/* define destination of next reply */
Ipc_ostream::_dst = Native_capability(_rcv_cs.caller, badge());
_caller = Native_capability(_rcv_cs.caller, badge());
_badge = reinterpret_cast<unsigned long *>(_rcv_msg.data())[0];
_prepare_next_reply_wait();
} else
_wait();
wait();
}
/**
* Return the global thread ID of the calling thread
*
* On OKL4 we cannot use 'L4_Myself()' to determine our own thread's
* identity. By convention, each thread stores its global ID in a
* defined entry of its UTCB.
*/
static inline Okl4::L4_ThreadId_t thread_get_my_global_id()
{
Okl4::L4_ThreadId_t myself;
myself.raw = Okl4::__L4_TCR_ThreadWord(UTCB_TCR_THREAD_WORD_MYSELF);
return myself;
}
Ipc_server::Ipc_server(Native_connection_state &cs,
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg)
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
:
Ipc_istream(rcv_msg),
Ipc_ostream(Native_capability(), snd_msg),
Ipc_marshaller(snd_msg),
Ipc_unmarshaller(rcv_msg),
Native_capability(thread_get_my_global_id(), 0),
_reply_needed(false), _rcv_cs(cs)
{ }
{
_read_offset = _write_offset = sizeof(umword_t);
}
Ipc_server::~Ipc_server() { }

View File

@ -32,8 +32,7 @@ namespace Genode {
* Begin of message buffer layout
*/
Pistachio::L4_Fpage_t rcv_fpage;
/* Send message */
/* Recv message */
char buf[];
/**
@ -42,9 +41,9 @@ namespace Genode {
inline size_t size() const { return _size; };
/**
* Return address of message buffer
* Return pointer of message data payload
*/
inline void *addr() { return &_msg_start[0]; };
inline void *data() { return &_msg_start[0]; };
};

View File

@ -47,23 +47,6 @@ using namespace Pistachio;
#endif
/*****************
** Ipc_ostream **
*****************/
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg) :
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
_snd_msg(snd_msg), _dst(dst)
{
_write_offset = sizeof(umword_t);
IPCDEBUG("Ipc_ostream constructed.\n");
}
/*****************
** Ipc_istream **
*****************/
/**
* Assert that we got 1 untyped word and 2 typed words
*/
@ -101,37 +84,21 @@ static inline void check_ipc_result(L4_MsgTag_t result, L4_Word_t error_code)
}
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg) :
Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()),
Native_capability(Pistachio::L4_Myself(), 0),
_rcv_msg(rcv_msg)
{
IPCDEBUG("Ipc_istream constructed.\n");
_read_offset = sizeof(umword_t);
}
Ipc_istream::~Ipc_istream() { }
/****************
** Ipc_client **
****************/
void Ipc_client::_call()
{
IPCDEBUG("Starting to _call (with %u bytes of data).\n", _write_offset);
L4_Msg_t msg;
L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg->buf);
L4_Word_t local_name = Ipc_ostream::_dst.local_name();
IPCDEBUG("Destination local_name = 0x%x\n", local_name);
L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg.buf);
L4_Word_t const local_name = _dst.local_name();
L4_MsgBuffer_t msgbuf;
/* prepare message buffer */
L4_Clear (&msgbuf);
L4_Append (&msgbuf, L4_StringItem (_rcv_msg->size(), _rcv_msg->buf));
L4_Append (&msgbuf, L4_StringItem (_rcv_msg.size(), _rcv_msg.buf));
L4_Accept(L4_UntypedWordsAcceptor);
L4_Accept(L4_StringItemsAcceptor, &msgbuf);
@ -141,21 +108,20 @@ void Ipc_client::_call()
L4_Append(&msg, sitem);
L4_Load(&msg);
L4_MsgTag_t result = L4_Call(Ipc_ostream::_dst.dst());
L4_MsgTag_t result = L4_Call(_dst.dst());
_write_offset = _read_offset = sizeof(umword_t);
check_ipc_result(result, L4_ErrorCode());
IPCDEBUG("Call done.\n");
}
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
Msgbuf_base *rcv_msg, unsigned short) :
Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0)
Ipc_client::Ipc_client(Native_capability const &dst,
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg, unsigned short)
:
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
{
IPCDEBUG("Ipc_client constructed.\n");
_read_offset = _write_offset = sizeof(umword_t);
}
@ -176,7 +142,7 @@ void Ipc_server::_prepare_next_reply_wait()
}
void Ipc_server::_wait()
void Ipc_server::wait()
{
/* wait for new server request */
try {
@ -184,14 +150,12 @@ void Ipc_server::_wait()
L4_MsgTag_t result;
L4_MsgBuffer_t msgbuf;
IPCDEBUG("_wait.\n");
do {
IPCDEBUG("_wait loop start (more than once means IpcError)\n");
L4_Clear (&msgbuf);
L4_Append (&msgbuf, L4_StringItem (_rcv_msg->size(), _rcv_msg->buf));
L4_Append (&msgbuf, L4_StringItem (_rcv_msg.size(), _rcv_msg.buf));
L4_Accept(L4_UntypedWordsAcceptor);
L4_Accept(L4_StringItemsAcceptor, &msgbuf);
@ -200,46 +164,38 @@ void Ipc_server::_wait()
} while (L4_IpcFailed(result));
IPCDEBUG("Got something from 0x%x.\n", _rcv_cs.caller);
L4_Msg_t msg;
L4_Store(result, &msg);
check_ipc_result(result, L4_ErrorCode());
/* get the local name */
L4_Word_t local_name = L4_Get(&msg,0);
/* remember badge of invoked object */
_badge = L4_Get(&msg, 0);
/*
* Store local_name where badge() looks for it.
* XXX Check this...
*/
*((long *)_rcv_msg->buf) = local_name;
_read_offset = sizeof(umword_t);
IPCDEBUG("_wait successful\n");
} catch (Blocking_canceled) { }
/* define destination of next reply */
Ipc_ostream::_dst = Native_capability(_rcv_cs.caller, badge());
_caller = Native_capability(_rcv_cs.caller, badge());
_prepare_next_reply_wait();
}
void Ipc_server::_reply()
void Ipc_server::reply()
{
L4_Msg_t msg;
L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg->buf);
L4_Word_t local_name = Ipc_ostream::_dst.local_name();
L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg.buf);
L4_Word_t const local_name = _caller.local_name();
L4_Clear(&msg);
L4_Append(&msg, local_name);
L4_Append(&msg, sitem);
L4_Load(&msg);
L4_MsgTag_t result = L4_Reply(Ipc_ostream::_dst.dst());
L4_MsgTag_t result = L4_Reply(_caller.dst());
if (L4_IpcFailed(result))
PERR("ipc error in _reply, ignored");
@ -247,17 +203,14 @@ void Ipc_server::_reply()
}
void Ipc_server::_reply_wait()
void Ipc_server::reply_wait()
{
IPCDEBUG("Starting to _reply_wait. (with %u bytes of data)\n",
_reply_needed ? _write_offset : 0);
if (_reply_needed) {
/* prepare massage */
L4_Msg_t msg;
L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg->buf);
L4_Word_t local_name = Ipc_ostream::_dst.local_name();
L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg.buf);
L4_Word_t const local_name = _caller.local_name();
L4_Clear(&msg);
L4_Append(&msg, local_name);
@ -267,13 +220,12 @@ void Ipc_server::_reply_wait()
/* Prepare message buffer */
L4_MsgBuffer_t msgbuf;
L4_Clear(&msgbuf);
L4_Append(&msgbuf, L4_StringItem (_rcv_msg->size(), _rcv_msg->buf));
L4_Append(&msgbuf, L4_StringItem (_rcv_msg.size(), _rcv_msg.buf));
L4_Accept(L4_UntypedWordsAcceptor);
L4_Accept(L4_StringItemsAcceptor, &msgbuf);
L4_MsgTag_t result = L4_Ipc(Ipc_ostream::_dst.dst(), L4_anythread,
L4_MsgTag_t result = L4_Ipc(_caller.dst(), L4_anythread,
L4_Timeouts(L4_ZeroTime, L4_Never), &_rcv_cs.caller);
IPCDEBUG("Got something from 0x%x.\n", L4_ThreadNo(L4_GlobalId(_rcv_cs.caller)));
/* error handling - check whether send or receive failed */
if (L4_IpcFailed(result)) {
@ -283,7 +235,7 @@ void Ipc_server::_reply_wait()
PERR("IPC %s error %02lx, offset %08lx -> _wait() instead.",
phase ? "receive" : "send", error, errcode >> 4);
_wait();
wait();
return;
}
@ -298,36 +250,32 @@ void Ipc_server::_reply_wait()
* the error to the user.
*/
IPCDEBUG("Bad IPC content -> _wait() instead.\n");
_wait();
wait();
return;
}
/* get the local name */
local_name = L4_Get(&msg, 0);
/*
* Store local_name where badge() looks for it.
* XXX Check this...
*/
*((long *)_rcv_msg->buf) = local_name;
IPCDEBUG("local_name = 0x%lx\n", badge());
/* remember badge of invoked object */
_badge = L4_Get(&msg, 0);
/* define destination of next reply */
Ipc_ostream::_dst = Native_capability(_rcv_cs.caller, badge());
_caller = Native_capability(_rcv_cs.caller, badge());
_prepare_next_reply_wait();
} else
_wait();
wait();
}
Ipc_server::Ipc_server(Native_connection_state &cs,
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg) :
Ipc_istream(rcv_msg),
Ipc_ostream(Native_capability(), snd_msg),
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
:
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
Native_capability(Pistachio::L4_Myself(), 0),
_reply_needed(false), _rcv_cs(cs)
{ }
{
_read_offset = _write_offset = sizeof(umword_t);
}
Ipc_server::~Ipc_server() { }

View File

@ -121,8 +121,7 @@ static seL4_MessageInfo_t new_seL4_message(Msgbuf_base &msg,
/**
* Convert seL4 message into Genode::Msgbuf_base
*/
static void decode_seL4_message(umword_t badge,
seL4_MessageInfo_t const &msg_info,
static void decode_seL4_message(seL4_MessageInfo_t const &msg_info,
Msgbuf_base &dst_msg)
{
/*
@ -249,11 +248,6 @@ static void decode_seL4_message(umword_t badge,
umword_t *dst = (umword_t *)dst_msg.data();
for (size_t i = 0; i < seL4_MessageInfo_get_length(msg_info); i++)
*dst++ = seL4_GetMR(MR_IDX_DATA + i);
/*
* Store RPC object key of invoked object to be picked up by server.cc
*/
*(long *)dst_msg.data() = badge;
}
@ -261,54 +255,25 @@ static void decode_seL4_message(umword_t badge,
** IPC marshalling support **
*****************************/
void Ipc_ostream::_marshal_capability(Native_capability const &cap)
void Ipc_marshaller::insert(Native_capability const &cap)
{
_snd_msg->append_cap(cap);
_snd_msg.append_cap(cap);
}
void Ipc_istream::_unmarshal_capability(Native_capability &cap)
void Ipc_unmarshaller::extract(Native_capability &cap)
{
cap = _rcv_msg->extract_cap();
cap = _rcv_msg.extract_cap();
}
/*****************
** Ipc_ostream **
*****************/
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
:
Ipc_marshaller((char *)snd_msg->data(), snd_msg->size()),
_snd_msg(snd_msg), _dst(dst)
{
_write_offset = sizeof(umword_t);
}
/*****************
** Ipc_istream **
*****************/
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
:
Ipc_unmarshaller((char *)rcv_msg->data(), rcv_msg->size()),
_rcv_msg(rcv_msg)
{
_read_offset = sizeof(umword_t);
}
Ipc_istream::~Ipc_istream() { }
/****************
** Ipc_client **
****************/
void Ipc_client::_call()
{
if (!Ipc_ostream::_dst.valid()) {
if (!_dst.valid()) {
PERR("Trying to invoke an invalid capability, stop.");
kernel_debugger_panic("IPC destination is invalid");
}
@ -317,23 +282,27 @@ void Ipc_client::_call()
rcv_sel() = Capability_space::alloc_rcv_sel();
seL4_MessageInfo_t const request_msg_info =
new_seL4_message(*_snd_msg, _write_offset);
new_seL4_message(_snd_msg, _write_offset);
unsigned const dst_sel = Capability_space::ipc_cap_data(_dst).sel.value();
seL4_MessageInfo_t const reply_msg_info =
seL4_Call(dst_sel, request_msg_info);
decode_seL4_message(0, reply_msg_info, *_rcv_msg);
decode_seL4_message(reply_msg_info, _rcv_msg);
_write_offset = _read_offset = sizeof(umword_t);
}
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
Msgbuf_base *rcv_msg, unsigned short)
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0)
{ }
Ipc_client::Ipc_client(Native_capability const &dst,
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
unsigned short)
:
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
{
_read_offset = _write_offset = sizeof(umword_t);
}
/****************
@ -351,46 +320,45 @@ void Ipc_server::_prepare_next_reply_wait()
/* receive buffer offset */
_read_offset = sizeof(umword_t);
_rcv_msg->reset_read_cap_index();
_snd_msg->reset_caps();
_rcv_msg.reset_read_cap_index();
_snd_msg.reset_caps();
}
void Ipc_server::_wait()
void Ipc_server::wait()
{
seL4_Word badge = Rpc_obj_key::INVALID;
seL4_MessageInfo_t const msg_info =
seL4_Recv(Thread_base::myself()->native_thread().ep_sel, &badge);
seL4_Recv(Thread_base::myself()->native_thread().ep_sel,
(seL4_Word *)&_badge);
decode_seL4_message(badge, msg_info, *_rcv_msg);
decode_seL4_message(msg_info, _rcv_msg);
_prepare_next_reply_wait();
}
void Ipc_server::_reply()
void Ipc_server::reply()
{
ASSERT(false);
}
void Ipc_server::_reply_wait()
void Ipc_server::reply_wait()
{
if (!_reply_needed) {
_wait();
wait();
} else {
seL4_Word badge = Rpc_obj_key::INVALID;
seL4_MessageInfo_t const reply_msg_info =
new_seL4_message(*_snd_msg, _write_offset);
new_seL4_message(_snd_msg, _write_offset);
seL4_MessageInfo_t const request_msg_info =
seL4_ReplyRecv(Thread_base::myself()->native_thread().ep_sel,
reply_msg_info, &badge);
reply_msg_info, (seL4_Word *)&_badge);
decode_seL4_message(badge, request_msg_info, *_rcv_msg);
decode_seL4_message(request_msg_info, _rcv_msg);
}
_prepare_next_reply_wait();
@ -398,13 +366,15 @@ void Ipc_server::_reply_wait()
Ipc_server::Ipc_server(Native_connection_state &cs,
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg)
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
:
Ipc_istream(rcv_msg), Ipc_ostream(Native_capability(), snd_msg),
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
_reply_needed(false), _rcv_cs(cs)
{
*static_cast<Native_capability *>(this) =
Native_capability(Capability_space::create_ep_cap(*Thread_base::myself()));
_read_offset = _write_offset = sizeof(umword_t);
}

View File

@ -46,7 +46,7 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
void Rpc_entrypoint::entry()
{
Native_connection_state cs;
Ipc_server srv(cs, &_snd_buf, &_rcv_buf);
Ipc_server srv(cs, _snd_buf, _rcv_buf);
_ipc_server = &srv;
_cap = srv;
_cap_valid.unlock();
@ -64,7 +64,8 @@ void Rpc_entrypoint::entry()
int opcode = 0;
srv >> IPC_REPLY_WAIT >> opcode;
srv.reply_wait();
srv.extract(opcode);
/* set default return value */
srv.ret(Ipc_client::ERR_INVALID_OBJECT);
@ -81,7 +82,7 @@ void Rpc_entrypoint::entry()
}
/* answer exit call, thereby wake up '~Rpc_entrypoint' */
srv << IPC_REPLY;
srv.reply();
/* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
_delay_exit.lock();

View File

@ -23,6 +23,7 @@
#include <util/misc_math.h>
#include <util/string.h>
#include <util/noncopyable.h>
#include <base/exception.h>
#include <base/capability.h>
#include <base/ipc_msgbuf.h>
@ -33,16 +34,9 @@ namespace Genode {
class Native_connection_state;
enum Ipc_istream_wait { IPC_WAIT };
enum Ipc_client_call { IPC_CALL };
enum Ipc_server_reply { IPC_REPLY };
enum Ipc_server_reply_wait { IPC_REPLY_WAIT };
class Ipc_error;
class Ipc_marshaller;
class Ipc_unmarshaller;
class Ipc_ostream;
class Ipc_istream;
class Ipc_client;
class Ipc_server;
}
@ -61,71 +55,68 @@ class Genode::Ipc_marshaller
{
protected:
char *_sndbuf;
size_t _sndbuf_size;
unsigned _write_offset;
Msgbuf_base &_snd_msg;
unsigned _write_offset = 0;
protected:
private:
char *_snd_buf = (char *)_snd_msg.data();
size_t const _snd_buf_size = _snd_msg.size();
public:
/**
* Write value to send buffer
*/
template <typename T>
void _write_to_buf(T const &value)
void insert(T const &value)
{
/* check buffer range */
if (_write_offset + sizeof(T) >= _sndbuf_size) return;
if (_write_offset + sizeof(T) >= _snd_buf_size) return;
/* write integer to buffer */
*reinterpret_cast<T *>(&_sndbuf[_write_offset]) = value;
*reinterpret_cast<T *>(&_snd_buf[_write_offset]) = value;
/* increment write pointer to next dword-aligned value */
_write_offset += align_natural(sizeof(T));
}
template <size_t MAX_BUFFER_SIZE>
void insert(Rpc_in_buffer<MAX_BUFFER_SIZE> const &b)
{
size_t const size = b.size();
insert(size);
insert(b.base(), size);
}
/**
* Write bytes to send buffer
*/
void _write_to_buf(char const *src_addr, unsigned num_bytes)
void insert(char const *src_addr, unsigned num_bytes)
{
/* check buffer range */
if (_write_offset + num_bytes >= _sndbuf_size) return;
if (_write_offset + num_bytes >= _snd_buf_size) return;
/* copy buffer */
memcpy(&_sndbuf[_write_offset], src_addr, num_bytes);
memcpy(&_snd_buf[_write_offset], src_addr, num_bytes);
/* increment write pointer to next dword-aligned value */
_write_offset += align_natural(num_bytes);
}
/**
* Write 'Rpc_in_buffer' to send buffer
* Insert capability to message buffer
*/
void _write_buffer_to_buf(Rpc_in_buffer_base const &b)
void insert(Native_capability const &cap);
template <typename IT>
void insert(Capability<IT> const &typed_cap)
{
size_t size = b.size();
_write_to_buf(size);
_write_to_buf(b.base(), size);
Native_capability untyped_cap = typed_cap;
insert(untyped_cap);
}
/**
* Write array to send buffer
*/
template <typename T, size_t N>
void _write_to_buf(T const (&array)[N])
{
/* check buffer range */
if (_write_offset + sizeof(array) >= _sndbuf_size)
PERR("send buffer overrun");
memcpy(&_sndbuf[_write_offset], array, sizeof(array));
_write_offset += align_natural(sizeof(array));
}
public:
Ipc_marshaller(char *sndbuf, size_t sndbuf_size)
: _sndbuf(sndbuf), _sndbuf_size(sndbuf_size), _write_offset(0) { }
Ipc_marshaller(Msgbuf_base &snd_msg) : _snd_msg(snd_msg) { }
};
@ -136,36 +127,33 @@ class Genode::Ipc_unmarshaller
{
protected:
char *_rcvbuf;
size_t _rcvbuf_size;
unsigned _read_offset;
Msgbuf_base &_rcv_msg;
unsigned _read_offset = 0;
protected:
private:
/**
* Read value of type T from buffer
*/
template <typename T>
void _read_from_buf(T &value)
char *_rcv_buf = (char *)_rcv_msg.data();
size_t const _rcv_buf_size = _rcv_msg.size();
public:
template <typename IT>
void extract(Capability<IT> &typed_cap)
{
/* check receive buffer range */
if (_read_offset + sizeof(T) >= _rcvbuf_size) return;
/* return value from receive buffer */
value = *reinterpret_cast<T *>(&_rcvbuf[_read_offset]);
/* increment read pointer to next dword-aligned value */
_read_offset += align_natural(sizeof(T));
Native_capability untyped_cap;
extract(untyped_cap);
typed_cap = reinterpret_cap_cast<IT>(untyped_cap);
}
/**
* Read 'Rpc_in_buffer' from receive buffer
*/
void _read_bytebuf_from_buf(Rpc_in_buffer_base &b)
template <size_t SIZE>
void extract(Rpc_in_buffer<SIZE> &b)
{
size_t size = 0;
_read_from_buf(size);
b = Rpc_in_buffer_base(0, 0);
extract(size);
b = Rpc_in_buffer<SIZE>(0, 0);
/*
* Check receive buffer range
@ -173,241 +161,62 @@ class Genode::Ipc_unmarshaller
* Note: The addr of the Rpc_in_buffer_base is a null pointer when this
* condition triggers.
*/
if (_read_offset + size >= _rcvbuf_size) {
if (_read_offset + size >= _rcv_buf_size) {
PERR("message buffer overrun");
return;
}
b = Rpc_in_buffer_base(&_rcvbuf[_read_offset], size);
b = Rpc_in_buffer<SIZE>(&_rcv_buf[_read_offset], size);
_read_offset += align_natural(size);
}
/**
* Read array from receive buffer
*/
template <typename T, size_t N>
void _read_from_buf(T (&array)[N])
{
if (_read_offset + sizeof(array) >= _rcvbuf_size) {
PERR("receive buffer overrun");
return;
}
memcpy(array, &_rcvbuf[_read_offset], sizeof(array));
_read_offset += align_natural(sizeof(array));
}
/**
* Read long value at specified byte index of receive buffer
*/
long _long_at_idx(int idx) { return *(long *)(&_rcvbuf[idx]); }
public:
Ipc_unmarshaller(char *rcvbuf, size_t rcvbuf_size)
: _rcvbuf(rcvbuf), _rcvbuf_size(rcvbuf_size), _read_offset(0) { }
};
/**
* Stream for sending information via a capability to an endpoint
*/
class Genode::Ipc_ostream : public Ipc_marshaller
{
protected:
Msgbuf_base *_snd_msg; /* send message buffer */
Native_capability _dst;
/**
* Reset marshaller and write badge at the beginning of the message
*/
void _prepare_next_send();
/**
* Insert capability to message buffer
*/
void _marshal_capability(Native_capability const &cap);
public:
/**
* Constructor
*/
Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg);
/**
* Return true if Ipc_ostream is ready for send
*/
bool ready_for_send() const { return _dst.valid(); }
/**
* Insert value into send buffer
*/
template <typename T>
Ipc_ostream &operator << (T const &value)
{
_write_to_buf(value);
return *this;
}
/**
* Insert byte buffer to send buffer
*/
Ipc_ostream &operator << (Rpc_in_buffer_base const &b)
{
_write_buffer_to_buf(b);
return *this;
}
/**
* Insert capability to send buffer
*/
Ipc_ostream &operator << (Native_capability const &cap)
{
_marshal_capability(cap);
return *this;
}
/**
* Insert typed capability to send buffer
*/
template <typename IT>
Ipc_ostream &operator << (Capability<IT> const &typed_cap)
{
_marshal_capability(typed_cap);
return *this;
}
/**
* Return current 'IPC_SEND' destination
*
* This method is typically needed by a server than sends replies
* in a different order as the incoming calls.
*/
Native_capability dst() const { return _dst; }
/**
* Set destination for the next 'IPC_SEND'
*/
void dst(Native_capability const &dst) { _dst = dst; }
};
/**
* Stream for receiving information
*/
class Genode::Ipc_istream : public Ipc_unmarshaller, public Native_capability
{
private:
/**
* Prevent 'Ipc_istream' objects from being copied
*
* Copying an 'Ipc_istream' object would result in a duplicated
* (and possibly inconsistent) connection state both the original
* and the copied object.
*/
Ipc_istream(const Ipc_istream &);
protected:
Msgbuf_base *_rcv_msg;
/**
* Obtain capability from message buffer
*/
void _unmarshal_capability(Native_capability &cap);
protected:
void extract(Native_capability &cap);
/**
* Reset unmarshaller
* Read value of type T from buffer
*/
void _prepare_next_receive();
template <typename T>
void extract(T &value)
{
/* check receive buffer range */
if (_read_offset + sizeof(T) >= _rcv_buf_size) return;
/* return value from receive buffer */
value = *reinterpret_cast<T *>(&_rcv_buf[_read_offset]);
/* increment read pointer to next dword-aligned value */
_read_offset += align_natural(sizeof(T));
}
public:
explicit Ipc_istream(Msgbuf_base *rcv_msg);
~Ipc_istream();
/**
* Read badge that was supplied with the message
*/
long badge() { return _long_at_idx(0); }
/**
* Read values from receive buffer
*/
template <typename T>
Ipc_istream &operator >> (T &value)
{
_read_from_buf(value);
return *this;
}
/**
* Read byte buffer from receive buffer
*/
Ipc_istream &operator >> (Rpc_in_buffer_base &b)
{
_read_bytebuf_from_buf(b);
return *this;
}
/**
* Read byte buffer from receive buffer
*/
template <size_t MAX_BUFFER_SIZE>
Ipc_istream &operator >> (Rpc_in_buffer<MAX_BUFFER_SIZE> &b)
{
_read_bytebuf_from_buf(b);
return *this;
}
/**
* Read capability from receive buffer
*/
Ipc_istream &operator >> (Native_capability &cap)
{
_unmarshal_capability(cap);
return *this;
}
/**
* Read typed capability from receive buffer
*/
template <typename IT>
Ipc_istream &operator >> (Capability<IT> &typed_cap)
{
_unmarshal_capability(typed_cap);
return *this;
}
Ipc_unmarshaller(Msgbuf_base &rcv_msg) : _rcv_msg(rcv_msg) { }
};
class Genode::Ipc_client: public Ipc_istream, public Ipc_ostream
class Genode::Ipc_client : public Ipc_marshaller, public Ipc_unmarshaller,
public Noncopyable
{
protected:
int _result; /* result of most recent call */
int _result = 0; /* result of most recent call */
void _prepare_next_call();
/**
* Send RPC message and wait for result
*/
void _call();
Native_capability _dst;
/**
* Set return value if call to server failed
*/
void ret(int retval)
{
*reinterpret_cast<int *>(&_rcvbuf[sizeof(umword_t)]) = retval;
reinterpret_cast<umword_t *>(_rcv_msg.data())[1] = retval;
}
void _call();
public:
enum { ERR_INVALID_OBJECT = -70000, };
@ -415,119 +224,41 @@ class Genode::Ipc_client: public Ipc_istream, public Ipc_ostream
/**
* Constructor
*/
Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
Msgbuf_base *rcv_msg, unsigned short rcv_caps = ~0);
Ipc_client(Native_capability const &dst,
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
unsigned short rcv_caps = ~0);
/**
* Operator that issues an IPC call
* Send RPC message and wait for result
*
* \throw Ipc_error
* \throw Blocking_canceled
*/
Ipc_client &operator << (Ipc_client_call)
void call()
{
_call();
_read_from_buf(_result);
extract(_result);
if (_result == ERR_INVALID_OBJECT)
throw Ipc_error();
return *this;
}
template <typename T>
Ipc_client &operator << (T const &value)
{
_write_to_buf(value);
return *this;
}
Ipc_client &operator << (Rpc_in_buffer_base const &b)
{
_write_buffer_to_buf(b);
return *this;
}
template <size_t MAX_BUFFER_SIZE>
Ipc_client &operator << (Rpc_in_buffer<MAX_BUFFER_SIZE> const &b)
{
_write_buffer_to_buf(b);
return *this;
}
Ipc_client &operator << (Native_capability const &cap)
{
_marshal_capability(cap);
return *this;
}
template <typename IT>
Ipc_client &operator << (Capability<IT> const &typed_cap)
{
_marshal_capability(typed_cap);
return *this;
}
Ipc_client &operator >> (Native_capability &cap)
{
_unmarshal_capability(cap);
return *this;
}
template <typename IT>
Ipc_client &operator >> (Capability<IT> &typed_cap)
{
_unmarshal_capability(typed_cap);
return *this;
}
template <typename T>
Ipc_client &operator >> (T &value)
{
_read_from_buf(value);
return *this;
}
Ipc_client &operator >> (Rpc_in_buffer_base &b)
{
_read_bytebuf_from_buf(b);
return *this;
}
int result() const { return _result; }
};
class Genode::Ipc_server : public Ipc_istream, public Ipc_ostream
class Genode::Ipc_server : public Ipc_marshaller, public Ipc_unmarshaller,
public Noncopyable, public Native_capability
{
protected:
bool _reply_needed; /* false for the first reply_wait */
Native_capability _caller;
Native_connection_state &_rcv_cs;
void _prepare_next_reply_wait();
/**
* Wait for incoming call
*
* In constrast to 'Ipc_istream::_wait()', this method stores the
* next reply destination from into 'dst' of the 'Ipc_ostream'.
*/
void _wait();
/**
* Send reply to destination
*
* In contrast to 'Ipc_ostream::_send()', this method prepares
* the 'Ipc_server' to send another subsequent reply without the
* calling '_wait()' in between. This is needed when a server
* answers calls out of order.
*/
void _reply();
/**
* Send result of previous RPC request and wait for new one
*/
void _reply_wait();
unsigned long _badge;
public:
@ -535,81 +266,48 @@ class Genode::Ipc_server : public Ipc_istream, public Ipc_ostream
* Constructor
*/
Ipc_server(Native_connection_state &,
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg);
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg);
~Ipc_server();
/**
* Wait for incoming call
*/
void wait();
/**
* Send reply to destination
*/
void reply();
/**
* Send result of previous RPC request and wait for new one
*/
void reply_wait();
/**
* Set return value of server call
*/
void ret(int retval)
{
*reinterpret_cast<int *>(&_sndbuf[sizeof(umword_t)]) = retval;
reinterpret_cast<umword_t *>(_snd_msg.data())[1] = retval;
}
/**
* Read badge that was supplied with the message
*/
unsigned long badge() const { return _badge; }
/**
* Set reply destination
*/
void dst(Native_capability const &reply_dst)
void caller(Native_capability const &caller)
{
Ipc_ostream::dst(reply_dst);
_reply_needed = reply_dst.valid();
_caller = caller;
_reply_needed = caller.valid();
}
using Ipc_ostream::dst;
/**
* Block for an incoming message filling the receive buffer
*/
Ipc_server &operator >> (Ipc_istream_wait)
{
_wait();
return *this;
}
/**
* Issue the sending of the message buffer
*/
Ipc_server &operator << (Ipc_server_reply)
{
_reply();
return *this;
}
/**
* Reply current request and wait for a new one
*/
Ipc_server &operator >> (Ipc_server_reply_wait)
{
_reply_wait();
return *this;
}
/**
* Write value to send buffer
*
* This operator is only used by test programs
*/
template <typename T>
Ipc_server &operator << (T const &value)
{
_write_to_buf(value);
return *this;
}
/**
* Read value from receive buffer
*
* This operator should only be used by the server framework for
* reading the function offset. The server-side processing of the
* payload is done using 'Ipc_istream' and 'Ipc_ostream'.
*/
template <typename T>
Ipc_server &operator >> (T &value)
{
_read_from_buf(value);
return *this;
}
Native_capability caller() const { return _caller; }
};
#endif /* _INCLUDE__BASE__IPC_H_ */

View File

@ -61,7 +61,7 @@ namespace Genode {
_marshal_args(Ipc_client &ipc_client, ATL &args) const
{
if (Trait::Rpc_direction<typename ATL::Head>::Type::IN)
ipc_client << args.get();
ipc_client.insert(args.get());
_marshal_args(ipc_client, args._2);
}
@ -73,7 +73,7 @@ namespace Genode {
_unmarshal_result(Ipc_client &ipc_client, T &arg,
Meta::Overload_selector<Rpc_arg_out>) const
{
ipc_client >> arg;
ipc_client.extract(arg);
}
@ -124,14 +124,14 @@ namespace Genode {
Msgbuf<CALL_MSG_SIZE + PROTOCOL_OVERHEAD> call_buf;
Msgbuf<REPLY_MSG_SIZE + PROTOCOL_OVERHEAD> reply_buf;
Ipc_client ipc_client(*this, &call_buf, &reply_buf, CAP_BY_VALUE);
Ipc_client ipc_client(*this, call_buf, reply_buf, CAP_BY_VALUE);
/* determine opcode of RPC function */
typedef typename RPC_INTERFACE::Rpc_functions Rpc_functions;
Rpc_opcode opcode = static_cast<int>(Meta::Index_of<Rpc_functions, IF>::Value);
/* marshal opcode and RPC input arguments */
ipc_client << opcode;
ipc_client.insert(opcode);
_marshal_args(ipc_client, args);
{
@ -139,7 +139,8 @@ namespace Genode {
}
/* perform RPC, unmarshal return value */
ipc_client << IPC_CALL >> ret;
ipc_client.call();
ipc_client.extract(ret);
{
Trace::Rpc_returned trace_event(IF::name(), reply_buf);

View File

@ -60,26 +60,26 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
protected:
template <typename ARG_LIST>
void _read_args(Ipc_istream &is, ARG_LIST &args)
void _read_args(Ipc_unmarshaller &msg, ARG_LIST &args)
{
if (Trait::Rpc_direction<typename ARG_LIST::Head>::Type::IN)
is >> args._1;
msg.extract(args._1);
_read_args(is, args._2);
_read_args(msg, args._2);
}
void _read_args(Ipc_istream &, Meta::Empty) { }
void _read_args(Ipc_unmarshaller &, Meta::Empty) { }
template <typename ARG_LIST>
void _write_results(Ipc_ostream &os, ARG_LIST &args)
void _write_results(Ipc_marshaller &msg, ARG_LIST &args)
{
if (Trait::Rpc_direction<typename ARG_LIST::Head>::Type::OUT)
os << args._1;
msg.insert(args._1);
_write_results(os, args._2);
_write_results(msg, args._2);
}
void _write_results(Ipc_ostream &, Meta::Empty) { }
void _write_results(Ipc_marshaller &, Meta::Empty) { }
template <typename RPC_FUNCTION, typename EXC_TL>
Rpc_exception_code _do_serve(typename RPC_FUNCTION::Server_args &args,
@ -104,7 +104,8 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
}
template <typename RPC_FUNCTIONS_TO_CHECK>
Rpc_exception_code _do_dispatch(Rpc_opcode opcode, Ipc_istream &is, Ipc_ostream &os,
Rpc_exception_code _do_dispatch(Rpc_opcode opcode,
Ipc_unmarshaller &in, Ipc_marshaller &out,
Meta::Overload_selector<RPC_FUNCTIONS_TO_CHECK>)
{
using namespace Meta;
@ -115,8 +116,8 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
typename This_rpc_function::Server_args args{};
/* read arguments from istream */
_read_args(is, args);
/* read arguments from incoming message */
_read_args(in, args);
{
Trace::Rpc_dispatch trace_event(This_rpc_function::name());
@ -132,23 +133,23 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
typename This_rpc_function::Ret_type ret { };
Rpc_exception_code exc;
exc = _do_serve(args, ret, Overload_selector<This_rpc_function, Exceptions>());
os << ret;
out.insert(ret);
{
Trace::Rpc_reply trace_event(This_rpc_function::name());
}
/* write results to ostream 'os' */
_write_results(os, args);
/* write results to outgoing message */
_write_results(out, args);
return exc;
}
typedef typename RPC_FUNCTIONS_TO_CHECK::Tail Tail;
return _do_dispatch(opcode, is, os, Overload_selector<Tail>());
return _do_dispatch(opcode, in, out, Overload_selector<Tail>());
}
int _do_dispatch(int opcode, Ipc_istream &, Ipc_ostream &,
int _do_dispatch(int opcode, Ipc_unmarshaller &, Ipc_marshaller &,
Meta::Overload_selector<Meta::Empty>)
{
PERR("invalid opcode %d\n", opcode);
@ -158,7 +159,8 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
/**
* Handle corner case of having an RPC interface with no RPC functions
*/
Rpc_exception_code _do_dispatch(int opcode, Ipc_istream &, Ipc_ostream &,
Rpc_exception_code _do_dispatch(int opcode,
Ipc_unmarshaller &, Ipc_marshaller &,
Meta::Overload_selector<Meta::Type_list<> >)
{
return 0;
@ -173,9 +175,10 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
public:
Rpc_exception_code dispatch(int opcode, Ipc_istream &is, Ipc_ostream &os)
Rpc_exception_code dispatch(int opcode,
Ipc_unmarshaller &in, Ipc_marshaller &out)
{
return _do_dispatch(opcode, is, os,
return _do_dispatch(opcode, in, out,
Meta::Overload_selector<Rpc_functions>());
}
};
@ -191,10 +194,10 @@ class Genode::Rpc_object_base : public Object_pool<Rpc_object_base>::Entry
* Interface to be implemented by a derived class
*
* \param op opcode of invoked method
* \param is Ipc_input stream with method arguments
* \param os Ipc_output stream for storing method results
* \param in incoming message with method arguments
* \param out outgoing message for storing method results
*/
virtual int dispatch(int op, Ipc_istream &is, Ipc_ostream &os) = 0;
virtual int dispatch(int op, Ipc_unmarshaller &in, Ipc_marshaller &out) = 0;
};
@ -212,9 +215,9 @@ struct Genode::Rpc_object : Rpc_object_base, Rpc_dispatcher<RPC_INTERFACE, SERVE
** Server-object interface **
*****************************/
Rpc_exception_code dispatch(int opcode, Ipc_istream &is, Ipc_ostream &os)
Rpc_exception_code dispatch(int opcode, Ipc_unmarshaller &in, Ipc_marshaller &out)
{
return Rpc_dispatcher<RPC_INTERFACE, SERVER>::dispatch(opcode, is, os);
return Rpc_dispatcher<RPC_INTERFACE, SERVER>::dispatch(opcode, in, out);
}
Capability<RPC_INTERFACE> const cap() const

View File

@ -19,16 +19,18 @@ using namespace Genode;
/**
* Marshalling of capabilities as plain data representation
*/
void Ipc_ostream::_marshal_capability(Native_capability const &cap)
void Ipc_marshaller::insert(Native_capability const &cap)
{
_write_to_buf(cap);
insert((char const *)&cap, sizeof(Native_capability));
}
/**
* Unmarshalling of capabilities as plain data representation
*/
void Ipc_istream::_unmarshal_capability(Native_capability &cap)
void Ipc_unmarshaller::extract(Native_capability &cap)
{
_read_from_buf(cap);
struct Raw { char buf[sizeof(Native_capability)]; } raw;
extract(raw);
(Raw &)(cap) = raw;
}

View File

@ -38,14 +38,14 @@ void Rpc_entrypoint::_block_until_cap_valid()
Untyped_capability Rpc_entrypoint::reply_dst()
{
return _ipc_server ? _ipc_server->dst() : Untyped_capability();
return _ipc_server ? _ipc_server->caller() : Untyped_capability();
}
void Rpc_entrypoint::omit_reply()
{
/* set current destination to an invalid capability */
if (_ipc_server) _ipc_server->dst(Untyped_capability());
if (_ipc_server) _ipc_server->caller(Untyped_capability());
}
@ -55,15 +55,16 @@ void Rpc_entrypoint::reply_signal_info(Untyped_capability reply_cap,
if (!_ipc_server) return;
/* backup reply capability of current request */
Untyped_capability last_reply_cap = _ipc_server->dst();
Untyped_capability last_reply_cap = _ipc_server->caller();
/* direct ipc server to the specified reply destination */
_ipc_server->ret(0);
_ipc_server->dst(reply_cap);
*_ipc_server << Signal_source::Signal(imprint, cnt) << IPC_REPLY;
_ipc_server->caller(reply_cap);
_ipc_server->insert(Signal_source::Signal(imprint, cnt));
_ipc_server->reply();
/* restore reply capability of the original request */
_ipc_server->dst(last_reply_cap);
_ipc_server->caller(last_reply_cap);
}

View File

@ -48,7 +48,7 @@ void Rpc_entrypoint::entry()
using Pool = Object_pool<Rpc_object_base>;
Native_connection_state cs;
Ipc_server srv(cs, &_snd_buf, &_rcv_buf);
Ipc_server srv(cs, _snd_buf, _rcv_buf);
_ipc_server = &srv;
_cap = srv;
_cap_valid.unlock();
@ -66,7 +66,8 @@ void Rpc_entrypoint::entry()
int opcode = 0;
srv >> IPC_REPLY_WAIT >> opcode;
srv.reply_wait();
srv.extract(opcode);
/* set default return value */
srv.ret(Ipc_client::ERR_INVALID_OBJECT);
@ -81,7 +82,7 @@ void Rpc_entrypoint::entry()
}
/* answer exit call, thereby wake up '~Rpc_entrypoint' */
srv << IPC_REPLY;
srv.reply();
/* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
_delay_exit.lock();

View File

@ -22,8 +22,9 @@ void Pager_object::wake_up()
/* notify pager to wake up faulter */
Msgbuf<16> snd, rcv;
Native_capability pager = cap();
Ipc_client ipc_client(pager, &snd, &rcv);
ipc_client << this << IPC_CALL;
Ipc_client ipc_client(pager, snd, rcv);
ipc_client.insert(this);
ipc_client.call();
}