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

View File

@ -88,9 +88,9 @@ namespace Genode {
inline size_t size() const { return _size; }; 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 * Reset portal capability selector payload

View File

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

View File

@ -45,7 +45,7 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
void Rpc_entrypoint::entry() void Rpc_entrypoint::entry()
{ {
Native_connection_state cs; Native_connection_state cs;
Ipc_server srv(cs, &_snd_buf, &_rcv_buf); Ipc_server srv(cs, _snd_buf, _rcv_buf);
_ipc_server = &srv; _ipc_server = &srv;
_cap = srv; _cap = srv;
_cap_valid.unlock(); _cap_valid.unlock();
@ -63,17 +63,12 @@ void Rpc_entrypoint::entry()
int opcode = 0; int opcode = 0;
srv >> IPC_REPLY_WAIT >> opcode; srv.reply_wait();
srv.extract(opcode);
/* set default return value */ /* set default return value */
srv.ret(Ipc_client::ERR_INVALID_OBJECT); 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) { apply(srv.badge(), [&] (Rpc_object_base *obj) {
if (!obj) return; if (!obj) return;
@ -84,7 +79,7 @@ void Rpc_entrypoint::entry()
} }
/* answer exit call, thereby wake up '~Rpc_entrypoint' */ /* answer exit call, thereby wake up '~Rpc_entrypoint' */
srv << IPC_REPLY; srv.reply();
/* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */ /* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
_delay_exit.lock(); _delay_exit.lock();

View File

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

View File

@ -69,9 +69,9 @@ class Genode::Msgbuf_base
size_t size() const { return _size; } 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. * Reset capability buffer.

View File

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

View File

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

View File

@ -62,9 +62,9 @@ namespace Genode {
inline Genode::size_t size() const { return _size; }; 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; } void reset_caps() { _used_caps = 0; _read_cap_index = 0; }

View File

@ -52,22 +52,22 @@ using namespace Genode;
** IPC marshalling support ** ** IPC marshalling support **
*****************************/ *****************************/
void Ipc_ostream::_marshal_capability(Native_capability const &cap) void Ipc_marshaller::insert(Native_capability const &cap)
{ {
if (cap.valid()) { 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 { } 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; long local_name = 0;
_read_from_buf(local_name); extract(local_name);
if (local_name == -1) { if (local_name == -1) {
@ -77,7 +77,7 @@ void Ipc_istream::_unmarshal_capability(Native_capability &cap)
} else { } else {
/* construct valid capability */ /* 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); 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 ** ** 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 */ /* prepare next request in buffer */
long const local_name = Ipc_ostream::_dst.local_name(); long const local_name = _dst.local_name();
_write_offset = 0;
_write_to_buf(local_name);
/* prepare response buffer */ /* prepare response buffer */
_read_offset = sizeof(long); _read_offset = sizeof(long);
_write_offset = 0;
_snd_msg->reset_caps(); insert(local_name);
}
_snd_msg.reset_caps();
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();
} }
@ -530,18 +478,18 @@ void Ipc_server::_prepare_next_reply_wait()
/* prepare next reply */ /* prepare next reply */
_write_offset = 0; _write_offset = 0;
long local_name = Ipc_ostream::_dst.local_name(); long local_name = _caller.local_name();
_write_to_buf(local_name); /* XXX unused, needed by de/marshaller */ insert(local_name); /* XXX unused, needed by de/marshaller */
/* leave space for exc code at the beginning of the msgbuf */ /* leave space for exc code at the beginning of the msgbuf */
_write_offset += align_natural(sizeof(int)); _write_offset += align_natural(sizeof(int));
/* reset capability slots of send message buffer */ /* 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; _reply_needed = true;
@ -555,7 +503,7 @@ void Ipc_server::_wait()
} }
try { try {
int const reply_socket = lx_wait(_rcv_cs, *_rcv_msg); int const reply_socket = lx_wait(_rcv_cs, _rcv_msg);
/* /*
* Remember reply capability * Remember reply capability
@ -566,38 +514,40 @@ void Ipc_server::_wait()
*/ */
enum { DUMMY_LOCAL_NAME = -1 }; enum { DUMMY_LOCAL_NAME = -1 };
typedef Native_capability::Dst Dst; 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(); _prepare_next_reply_wait();
} catch (Blocking_canceled) { } } catch (Blocking_canceled) { }
} }
void Ipc_server::_reply() void Ipc_server::reply()
{ {
try { try {
lx_reply(Ipc_ostream::_dst.dst().socket, *_snd_msg, _write_offset); } lx_reply(_caller.dst().socket, _snd_msg, _write_offset); }
catch (Ipc_error) { } catch (Ipc_error) { }
_prepare_next_reply_wait(); _prepare_next_reply_wait();
} }
void Ipc_server::_reply_wait() void Ipc_server::reply_wait()
{ {
/* when first called, there was no request yet */ /* when first called, there was no request yet */
if (_reply_needed) 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, 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_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
Ipc_ostream(Native_capability(), snd_msg), _reply_needed(false), _rcv_cs(cs) Native_capability(Dst(-1), 0),
_reply_needed(false), _rcv_cs(cs)
{ {
Thread_base *thread = Thread_base::myself(); 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; thread->native_thread().is_ipc_server = true;
} }
/* override capability initialization performed by 'Ipc_istream' */ /* override capability initialization */
*static_cast<Native_capability *>(this) = *static_cast<Native_capability *>(this) =
Native_capability(Native_capability::Dst(_rcv_cs.client_sd), 0); 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; } 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 * Reset portal capability selector payload

View File

@ -28,15 +28,15 @@ using namespace Nova;
** IPC marshalling support ** ** 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 * 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(); size_t num_msg_words = utcb->msg_words();
if (num_msg_words == 0) return; if (num_msg_words == 0) return;
/* look up and validate destination message buffer to receive the payload */ /* look up and validate destination message buffer to receive the payload */
mword_t *msg_buf = (mword_t *)rcv_msg->buf; mword_t *msg_buf = (mword_t *)rcv_msg.buf;
if (num_msg_words*sizeof(mword_t) > rcv_msg->size()) { if (num_msg_words*sizeof(mword_t) > rcv_msg.size()) {
PERR("receive message buffer too small msg size=%zx, buf size=%zd", PERR("receive message buffer too small msg size=%zx, buf size=%zd",
num_msg_words*sizeof(mword_t), rcv_msg->size()); num_msg_words*sizeof(mword_t), rcv_msg.size());
num_msg_words = rcv_msg->size()/sizeof(mword_t); num_msg_words = rcv_msg.size()/sizeof(mword_t);
} }
/* read message payload into destination message buffer */ /* 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 * 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) unsigned num_msg_words, mword_t local_name)
{ {
/* look up address and size of message payload */ /* 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 * 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); utcb->set_msg_word(num_msg_words);
/* append portal capability selectors */ /* 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; 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 (crd.base() == ~0UL) continue;
if (!utcb->append_item(crd, i, false, false, trans_map)) 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 */ /* we have consumed portal capability selectors, reset message buffer */
snd_msg->snd_reset(); snd_msg.snd_reset();
return true; 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 ** ** Ipc_client **
****************/ ****************/
@ -149,18 +122,18 @@ void Ipc_client::_call()
Nova::Utcb *utcb = (Nova::Utcb *)Thread_base::myself()->utcb(); Nova::Utcb *utcb = (Nova::Utcb *)Thread_base::myself()->utcb();
if (!copy_msgbuf_to_utcb(utcb, _snd_msg, _write_offset/sizeof(mword_t), 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"); PERR("could not setup IPC");
return; return;
} }
/* if we can't setup receive window, die in order to recognize the issue */ /* 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 */ /* printf doesn't work here since for IPC also rcv_prepare* is used */
nova_die(); nova_die();
/* establish the mapping via a portal traversal */ /* 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 (res != Nova::NOVA_OK) {
/* If an error occurred, reset word&item count (not done by kernel). */ /* If an error occurred, reset word&item count (not done by kernel). */
utcb->set_msg_word(0); utcb->set_msg_word(0);
@ -168,17 +141,19 @@ void Ipc_client::_call()
ret(ERR_INVALID_OBJECT); 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); copy_utcb_to_msgbuf(utcb, _rcv_msg);
_snd_msg->snd_reset(); _snd_msg.snd_reset();
_write_offset = _read_offset = sizeof(mword_t); _write_offset = _read_offset = sizeof(mword_t);
} }
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg, Ipc_client::Ipc_client(Native_capability const &dst,
Msgbuf_base *rcv_msg, unsigned short const rcv_caps) Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0) unsigned short const rcv_caps)
:
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
{ {
if (rcv_caps == ~0) if (rcv_caps == ~0)
/* use default values for rcv_wnd */ /* 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; unsigned short log2_max = rcv_caps ? log2(rcv_caps) : 0;
if ((1U << log2_max) < rcv_caps) log2_max ++; 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 ** ** Ipc_server **
****************/ ****************/
void Ipc_server::_wait() void Ipc_server::wait()
{ {
/* /*
* This function is only called by the portal dispatcher of server * 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(); 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); copy_utcb_to_msgbuf(utcb, _rcv_msg);
/* reset unmarshaller */ /* 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(); Nova::Utcb *utcb = (Nova::Utcb *)Thread_base::myself()->utcb();
copy_msgbuf_to_utcb(utcb, _snd_msg, _write_offset/sizeof(mword_t), copy_msgbuf_to_utcb(utcb, _snd_msg, _write_offset/sizeof(mword_t), 0);
Ipc_ostream::_dst.local_name());
Nova::reply(Thread_base::myself()->stack_top()); 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, 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() { } Ipc_server::~Ipc_server() { }

View File

@ -122,8 +122,9 @@ void Rpc_entrypoint::_activation_entry()
int opcode = 0; int opcode = 0;
Native_connection_state cs; Native_connection_state cs;
Ipc_server srv(cs, &ep->_snd_buf, &ep->_rcv_buf); Ipc_server srv(cs, ep->_snd_buf, ep->_rcv_buf);
srv >> IPC_WAIT >> opcode; srv.wait();
srv.extract(opcode);
/* set default return value */ /* set default return value */
srv.ret(Ipc_client::ERR_INVALID_OBJECT); 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->_cap.local_name() == id_pt) {
if (!ep->_rcv_buf.prepare_rcv_window((Nova::Utcb *)ep->utcb())) if (!ep->_rcv_buf.prepare_rcv_window((Nova::Utcb *)ep->utcb()))
PWRN("out of capability selectors for handling server requests"); 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())) if (!ep->_rcv_buf.prepare_rcv_window((Nova::Utcb *)ep->utcb()))
PWRN("out of capability selectors for handling server requests"); 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; }; 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 * 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); int num_msg_words = (int)L4_UntypedWords(rcv_tag);
if (num_msg_words <= 0) return; if (num_msg_words <= 0) return;
/* look up and validate destination message buffer to receive the payload */ /* look up and validate destination message buffer to receive the payload */
L4_Word_t *msg_buf = (L4_Word_t *)rcv_msg->buf; L4_Word_t *msg_buf = (L4_Word_t *)rcv_msg.buf;
if (num_msg_words*sizeof(L4_Word_t) > rcv_msg->size()) { if (num_msg_words*sizeof(L4_Word_t) > rcv_msg.size()) {
PERR("receive message buffer too small msg size=%zd, buf size=%zd", 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*sizeof(L4_Word_t), rcv_msg.size());
num_msg_words = rcv_msg->size()/sizeof(L4_Word_t); num_msg_words = rcv_msg.size()/sizeof(L4_Word_t);
} }
/* read message payload into destination message buffer */ /* 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 * 1 is used for the local name. All subsequent message registers hold the
* message payload. * 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) L4_Word_t local_name)
{ {
/* look up address and size of message payload */ /* 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; 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 ** ** Ipc_client **
****************/ ****************/
@ -152,10 +107,10 @@ void Ipc_client::_call()
{ {
/* copy call message to the UTCBs message registers */ /* copy call message to the UTCBs message registers */
copy_msgbuf_to_utcb(_snd_msg, _write_offset/sizeof(L4_Word_t), 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_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 }; enum { ERROR_MASK = 0xe, ERROR_CANCELED = 3 << 1 };
if (L4_IpcFailed(rcv_tag) && 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, Ipc_client::Ipc_client(Native_capability const &dst,
Msgbuf_base *rcv_msg, unsigned short) Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg, unsigned short)
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0) { } :
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 */ /* wait for new server request */
try { try {
@ -218,20 +177,21 @@ void Ipc_server::_wait()
} catch (Blocking_canceled) { } } catch (Blocking_canceled) { }
/* define destination of next reply */ /* 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(); _prepare_next_reply_wait();
} }
void Ipc_server::_reply() void Ipc_server::reply()
{ {
/* copy reply to the UTCBs message registers */ /* copy reply to the UTCBs message registers */
copy_msgbuf_to_utcb(_snd_msg, _write_offset/sizeof(L4_Word_t), 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 */ /* 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)) if (L4_IpcFailed(rcv_tag))
PERR("ipc error in _reply - gets ignored"); 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) { if (_reply_needed) {
/* copy reply to the UTCBs message registers */ /* copy reply to the UTCBs message registers */
copy_msgbuf_to_utcb(_snd_msg, _write_offset/sizeof(L4_Word_t), 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 * TODO: Check for IPC error
@ -258,22 +218,40 @@ void Ipc_server::_reply_wait()
copy_utcb_to_msgbuf(rcv_tag, _rcv_msg); copy_utcb_to_msgbuf(rcv_tag, _rcv_msg);
/* define destination of next reply */ /* 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(); _prepare_next_reply_wait();
} else } 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, 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_marshaller(snd_msg),
Ipc_ostream(Native_capability(), snd_msg), Ipc_unmarshaller(rcv_msg),
Native_capability(thread_get_my_global_id(), 0),
_reply_needed(false), _rcv_cs(cs) _reply_needed(false), _rcv_cs(cs)
{ } {
_read_offset = _write_offset = sizeof(umword_t);
}
Ipc_server::~Ipc_server() { } Ipc_server::~Ipc_server() { }

View File

@ -32,8 +32,7 @@ namespace Genode {
* Begin of message buffer layout * Begin of message buffer layout
*/ */
Pistachio::L4_Fpage_t rcv_fpage; Pistachio::L4_Fpage_t rcv_fpage;
/* Send message */
/* Recv message */
char buf[]; char buf[];
/** /**
@ -42,9 +41,9 @@ namespace Genode {
inline size_t size() const { return _size; }; 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 #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 * 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 ** ** Ipc_client **
****************/ ****************/
void Ipc_client::_call() void Ipc_client::_call()
{ {
IPCDEBUG("Starting to _call (with %u bytes of data).\n", _write_offset);
L4_Msg_t msg; L4_Msg_t msg;
L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg->buf); L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg.buf);
L4_Word_t local_name = Ipc_ostream::_dst.local_name(); L4_Word_t const local_name = _dst.local_name();
IPCDEBUG("Destination local_name = 0x%x\n", local_name);
L4_MsgBuffer_t msgbuf; L4_MsgBuffer_t msgbuf;
/* prepare message buffer */ /* prepare message buffer */
L4_Clear (&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_UntypedWordsAcceptor);
L4_Accept(L4_StringItemsAcceptor, &msgbuf); L4_Accept(L4_StringItemsAcceptor, &msgbuf);
@ -141,21 +108,20 @@ void Ipc_client::_call()
L4_Append(&msg, sitem); L4_Append(&msg, sitem);
L4_Load(&msg); 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); _write_offset = _read_offset = sizeof(umword_t);
check_ipc_result(result, L4_ErrorCode()); check_ipc_result(result, L4_ErrorCode());
IPCDEBUG("Call done.\n");
} }
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg, Ipc_client::Ipc_client(Native_capability const &dst,
Msgbuf_base *rcv_msg, unsigned short) : Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg, unsigned short)
Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0) :
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 */ /* wait for new server request */
try { try {
@ -184,14 +150,12 @@ void Ipc_server::_wait()
L4_MsgTag_t result; L4_MsgTag_t result;
L4_MsgBuffer_t msgbuf; L4_MsgBuffer_t msgbuf;
IPCDEBUG("_wait.\n");
do { do {
IPCDEBUG("_wait loop start (more than once means IpcError)\n"); IPCDEBUG("_wait loop start (more than once means IpcError)\n");
L4_Clear (&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_UntypedWordsAcceptor);
L4_Accept(L4_StringItemsAcceptor, &msgbuf); L4_Accept(L4_StringItemsAcceptor, &msgbuf);
@ -200,46 +164,38 @@ void Ipc_server::_wait()
} while (L4_IpcFailed(result)); } while (L4_IpcFailed(result));
IPCDEBUG("Got something from 0x%x.\n", _rcv_cs.caller);
L4_Msg_t msg; L4_Msg_t msg;
L4_Store(result, &msg); L4_Store(result, &msg);
check_ipc_result(result, L4_ErrorCode()); check_ipc_result(result, L4_ErrorCode());
/* get the local name */ /* remember badge of invoked object */
L4_Word_t local_name = L4_Get(&msg,0); _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); _read_offset = sizeof(umword_t);
IPCDEBUG("_wait successful\n");
} catch (Blocking_canceled) { } } catch (Blocking_canceled) { }
/* define destination of next reply */ /* 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(); _prepare_next_reply_wait();
} }
void Ipc_server::_reply() void Ipc_server::reply()
{ {
L4_Msg_t msg; L4_Msg_t msg;
L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg->buf); L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg.buf);
L4_Word_t local_name = Ipc_ostream::_dst.local_name(); L4_Word_t const local_name = _caller.local_name();
L4_Clear(&msg); L4_Clear(&msg);
L4_Append(&msg, local_name); L4_Append(&msg, local_name);
L4_Append(&msg, sitem); L4_Append(&msg, sitem);
L4_Load(&msg); 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)) if (L4_IpcFailed(result))
PERR("ipc error in _reply, ignored"); 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) { if (_reply_needed) {
/* prepare massage */ /* prepare massage */
L4_Msg_t msg; L4_Msg_t msg;
L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg->buf); L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg.buf);
L4_Word_t local_name = Ipc_ostream::_dst.local_name(); L4_Word_t const local_name = _caller.local_name();
L4_Clear(&msg); L4_Clear(&msg);
L4_Append(&msg, local_name); L4_Append(&msg, local_name);
@ -267,13 +220,12 @@ void Ipc_server::_reply_wait()
/* Prepare message buffer */ /* Prepare message buffer */
L4_MsgBuffer_t msgbuf; L4_MsgBuffer_t msgbuf;
L4_Clear(&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_UntypedWordsAcceptor);
L4_Accept(L4_StringItemsAcceptor, &msgbuf); 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); 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 */ /* error handling - check whether send or receive failed */
if (L4_IpcFailed(result)) { if (L4_IpcFailed(result)) {
@ -283,7 +235,7 @@ void Ipc_server::_reply_wait()
PERR("IPC %s error %02lx, offset %08lx -> _wait() instead.", PERR("IPC %s error %02lx, offset %08lx -> _wait() instead.",
phase ? "receive" : "send", error, errcode >> 4); phase ? "receive" : "send", error, errcode >> 4);
_wait(); wait();
return; return;
} }
@ -298,36 +250,32 @@ void Ipc_server::_reply_wait()
* the error to the user. * the error to the user.
*/ */
IPCDEBUG("Bad IPC content -> _wait() instead.\n"); IPCDEBUG("Bad IPC content -> _wait() instead.\n");
_wait(); wait();
return; return;
} }
/* get the local name */ /* remember badge of invoked object */
local_name = L4_Get(&msg, 0); _badge = 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());
/* define destination of next reply */ /* 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(); _prepare_next_reply_wait();
} else } else
_wait(); wait();
} }
Ipc_server::Ipc_server(Native_connection_state &cs, 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(Pistachio::L4_Myself(), 0),
_reply_needed(false), _rcv_cs(cs) _reply_needed(false), _rcv_cs(cs)
{ } {
_read_offset = _write_offset = sizeof(umword_t);
}
Ipc_server::~Ipc_server() { } 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 * Convert seL4 message into Genode::Msgbuf_base
*/ */
static void decode_seL4_message(umword_t badge, static void decode_seL4_message(seL4_MessageInfo_t const &msg_info,
seL4_MessageInfo_t const &msg_info,
Msgbuf_base &dst_msg) Msgbuf_base &dst_msg)
{ {
/* /*
@ -249,11 +248,6 @@ static void decode_seL4_message(umword_t badge,
umword_t *dst = (umword_t *)dst_msg.data(); umword_t *dst = (umword_t *)dst_msg.data();
for (size_t i = 0; i < seL4_MessageInfo_get_length(msg_info); i++) for (size_t i = 0; i < seL4_MessageInfo_get_length(msg_info); i++)
*dst++ = seL4_GetMR(MR_IDX_DATA + 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 ** ** 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 ** ** Ipc_client **
****************/ ****************/
void Ipc_client::_call() void Ipc_client::_call()
{ {
if (!Ipc_ostream::_dst.valid()) { if (!_dst.valid()) {
PERR("Trying to invoke an invalid capability, stop."); PERR("Trying to invoke an invalid capability, stop.");
kernel_debugger_panic("IPC destination is invalid"); kernel_debugger_panic("IPC destination is invalid");
} }
@ -317,23 +282,27 @@ void Ipc_client::_call()
rcv_sel() = Capability_space::alloc_rcv_sel(); rcv_sel() = Capability_space::alloc_rcv_sel();
seL4_MessageInfo_t const request_msg_info = 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(); unsigned const dst_sel = Capability_space::ipc_cap_data(_dst).sel.value();
seL4_MessageInfo_t const reply_msg_info = seL4_MessageInfo_t const reply_msg_info =
seL4_Call(dst_sel, request_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); _write_offset = _read_offset = sizeof(umword_t);
} }
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg, Ipc_client::Ipc_client(Native_capability const &dst,
Msgbuf_base *rcv_msg, unsigned short) Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0) 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 */ /* receive buffer offset */
_read_offset = sizeof(umword_t); _read_offset = sizeof(umword_t);
_rcv_msg->reset_read_cap_index(); _rcv_msg.reset_read_cap_index();
_snd_msg->reset_caps(); _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_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(); _prepare_next_reply_wait();
} }
void Ipc_server::_reply() void Ipc_server::reply()
{ {
ASSERT(false); ASSERT(false);
} }
void Ipc_server::_reply_wait() void Ipc_server::reply_wait()
{ {
if (!_reply_needed) { if (!_reply_needed) {
_wait(); wait();
} else { } else {
seL4_Word badge = Rpc_obj_key::INVALID;
seL4_MessageInfo_t const reply_msg_info = 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_MessageInfo_t const request_msg_info =
seL4_ReplyRecv(Thread_base::myself()->native_thread().ep_sel, 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(); _prepare_next_reply_wait();
@ -398,13 +366,15 @@ void Ipc_server::_reply_wait()
Ipc_server::Ipc_server(Native_connection_state &cs, 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) _reply_needed(false), _rcv_cs(cs)
{ {
*static_cast<Native_capability *>(this) = *static_cast<Native_capability *>(this) =
Native_capability(Capability_space::create_ep_cap(*Thread_base::myself())); 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() void Rpc_entrypoint::entry()
{ {
Native_connection_state cs; Native_connection_state cs;
Ipc_server srv(cs, &_snd_buf, &_rcv_buf); Ipc_server srv(cs, _snd_buf, _rcv_buf);
_ipc_server = &srv; _ipc_server = &srv;
_cap = srv; _cap = srv;
_cap_valid.unlock(); _cap_valid.unlock();
@ -64,7 +64,8 @@ void Rpc_entrypoint::entry()
int opcode = 0; int opcode = 0;
srv >> IPC_REPLY_WAIT >> opcode; srv.reply_wait();
srv.extract(opcode);
/* set default return value */ /* set default return value */
srv.ret(Ipc_client::ERR_INVALID_OBJECT); srv.ret(Ipc_client::ERR_INVALID_OBJECT);
@ -81,7 +82,7 @@ void Rpc_entrypoint::entry()
} }
/* answer exit call, thereby wake up '~Rpc_entrypoint' */ /* answer exit call, thereby wake up '~Rpc_entrypoint' */
srv << IPC_REPLY; srv.reply();
/* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */ /* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
_delay_exit.lock(); _delay_exit.lock();

View File

@ -23,6 +23,7 @@
#include <util/misc_math.h> #include <util/misc_math.h>
#include <util/string.h> #include <util/string.h>
#include <util/noncopyable.h>
#include <base/exception.h> #include <base/exception.h>
#include <base/capability.h> #include <base/capability.h>
#include <base/ipc_msgbuf.h> #include <base/ipc_msgbuf.h>
@ -33,16 +34,9 @@ namespace Genode {
class Native_connection_state; 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_error;
class Ipc_marshaller; class Ipc_marshaller;
class Ipc_unmarshaller; class Ipc_unmarshaller;
class Ipc_ostream;
class Ipc_istream;
class Ipc_client; class Ipc_client;
class Ipc_server; class Ipc_server;
} }
@ -61,71 +55,68 @@ class Genode::Ipc_marshaller
{ {
protected: protected:
char *_sndbuf; Msgbuf_base &_snd_msg;
size_t _sndbuf_size; unsigned _write_offset = 0;
unsigned _write_offset;
protected: private:
char *_snd_buf = (char *)_snd_msg.data();
size_t const _snd_buf_size = _snd_msg.size();
public:
/** /**
* Write value to send buffer * Write value to send buffer
*/ */
template <typename T> template <typename T>
void _write_to_buf(T const &value) void insert(T const &value)
{ {
/* check buffer range */ /* check buffer range */
if (_write_offset + sizeof(T) >= _sndbuf_size) return; if (_write_offset + sizeof(T) >= _snd_buf_size) return;
/* write integer to buffer */ /* 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 */ /* increment write pointer to next dword-aligned value */
_write_offset += align_natural(sizeof(T)); _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 * 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 */ /* check buffer range */
if (_write_offset + num_bytes >= _sndbuf_size) return; if (_write_offset + num_bytes >= _snd_buf_size) return;
/* copy buffer */ /* 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 */ /* increment write pointer to next dword-aligned value */
_write_offset += align_natural(num_bytes); _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(); Native_capability untyped_cap = typed_cap;
_write_to_buf(size); insert(untyped_cap);
_write_to_buf(b.base(), size);
} }
/** Ipc_marshaller(Msgbuf_base &snd_msg) : _snd_msg(snd_msg) { }
* 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) { }
}; };
@ -136,36 +127,33 @@ class Genode::Ipc_unmarshaller
{ {
protected: protected:
char *_rcvbuf; Msgbuf_base &_rcv_msg;
size_t _rcvbuf_size; unsigned _read_offset = 0;
unsigned _read_offset;
protected: private:
/** char *_rcv_buf = (char *)_rcv_msg.data();
* Read value of type T from buffer size_t const _rcv_buf_size = _rcv_msg.size();
*/
template <typename T> public:
void _read_from_buf(T &value)
template <typename IT>
void extract(Capability<IT> &typed_cap)
{ {
/* check receive buffer range */ Native_capability untyped_cap;
if (_read_offset + sizeof(T) >= _rcvbuf_size) return; extract(untyped_cap);
typed_cap = reinterpret_cap_cast<IT>(untyped_cap);
/* 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));
} }
/** /**
* Read 'Rpc_in_buffer' from receive buffer * 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; size_t size = 0;
_read_from_buf(size); extract(size);
b = Rpc_in_buffer_base(0, 0); b = Rpc_in_buffer<SIZE>(0, 0);
/* /*
* Check receive buffer range * 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 * Note: The addr of the Rpc_in_buffer_base is a null pointer when this
* condition triggers. * condition triggers.
*/ */
if (_read_offset + size >= _rcvbuf_size) { if (_read_offset + size >= _rcv_buf_size) {
PERR("message buffer overrun"); PERR("message buffer overrun");
return; 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_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 * Obtain capability from message buffer
*/ */
void _unmarshal_capability(Native_capability &cap); void extract(Native_capability &cap);
protected:
/** /**
* 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: public:
explicit Ipc_istream(Msgbuf_base *rcv_msg); Ipc_unmarshaller(Msgbuf_base &rcv_msg) : _rcv_msg(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;
}
}; };
class Genode::Ipc_client: public Ipc_istream, public Ipc_ostream class Genode::Ipc_client : public Ipc_marshaller, public Ipc_unmarshaller,
public Noncopyable
{ {
protected: protected:
int _result; /* result of most recent call */ int _result = 0; /* result of most recent call */
void _prepare_next_call(); Native_capability _dst;
/**
* Send RPC message and wait for result
*/
void _call();
/** /**
* Set return value if call to server failed * Set return value if call to server failed
*/ */
void ret(int retval) void ret(int retval)
{ {
*reinterpret_cast<int *>(&_rcvbuf[sizeof(umword_t)]) = retval; reinterpret_cast<umword_t *>(_rcv_msg.data())[1] = retval;
} }
void _call();
public: public:
enum { ERR_INVALID_OBJECT = -70000, }; enum { ERR_INVALID_OBJECT = -70000, };
@ -415,119 +224,41 @@ class Genode::Ipc_client: public Ipc_istream, public Ipc_ostream
/** /**
* Constructor * Constructor
*/ */
Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg, Ipc_client(Native_capability const &dst,
Msgbuf_base *rcv_msg, unsigned short rcv_caps = ~0); 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 Ipc_error
* \throw Blocking_canceled
*/ */
Ipc_client &operator << (Ipc_client_call) void call()
{ {
_call(); _call();
_read_from_buf(_result); extract(_result);
if (_result == ERR_INVALID_OBJECT) if (_result == ERR_INVALID_OBJECT)
throw Ipc_error(); 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; } 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: protected:
bool _reply_needed; /* false for the first reply_wait */ bool _reply_needed; /* false for the first reply_wait */
Native_capability _caller;
Native_connection_state &_rcv_cs; Native_connection_state &_rcv_cs;
void _prepare_next_reply_wait(); void _prepare_next_reply_wait();
/** unsigned long _badge;
* 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();
public: public:
@ -535,81 +266,48 @@ class Genode::Ipc_server : public Ipc_istream, public Ipc_ostream
* Constructor * Constructor
*/ */
Ipc_server(Native_connection_state &, Ipc_server(Native_connection_state &,
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg); Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg);
~Ipc_server(); ~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 * Set return value of server call
*/ */
void ret(int retval) 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 * Set reply destination
*/ */
void dst(Native_capability const &reply_dst) void caller(Native_capability const &caller)
{ {
Ipc_ostream::dst(reply_dst); _caller = caller;
_reply_needed = reply_dst.valid(); _reply_needed = caller.valid();
} }
using Ipc_ostream::dst; Native_capability caller() const { return _caller; }
/**
* 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;
}
}; };
#endif /* _INCLUDE__BASE__IPC_H_ */ #endif /* _INCLUDE__BASE__IPC_H_ */

View File

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

View File

@ -60,26 +60,26 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
protected: protected:
template <typename ARG_LIST> 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) 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> 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) 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> template <typename RPC_FUNCTION, typename EXC_TL>
Rpc_exception_code _do_serve(typename RPC_FUNCTION::Server_args &args, 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> 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>) Meta::Overload_selector<RPC_FUNCTIONS_TO_CHECK>)
{ {
using namespace Meta; using namespace Meta;
@ -115,8 +116,8 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
typename This_rpc_function::Server_args args{}; typename This_rpc_function::Server_args args{};
/* read arguments from istream */ /* read arguments from incoming message */
_read_args(is, args); _read_args(in, args);
{ {
Trace::Rpc_dispatch trace_event(This_rpc_function::name()); 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 { }; typename This_rpc_function::Ret_type ret { };
Rpc_exception_code exc; Rpc_exception_code exc;
exc = _do_serve(args, ret, Overload_selector<This_rpc_function, Exceptions>()); 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()); Trace::Rpc_reply trace_event(This_rpc_function::name());
} }
/* write results to ostream 'os' */ /* write results to outgoing message */
_write_results(os, args); _write_results(out, args);
return exc; return exc;
} }
typedef typename RPC_FUNCTIONS_TO_CHECK::Tail Tail; 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>) Meta::Overload_selector<Meta::Empty>)
{ {
PERR("invalid opcode %d\n", opcode); 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 * 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<> >) Meta::Overload_selector<Meta::Type_list<> >)
{ {
return 0; return 0;
@ -173,9 +175,10 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
public: 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>()); 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 * Interface to be implemented by a derived class
* *
* \param op opcode of invoked method * \param op opcode of invoked method
* \param is Ipc_input stream with method arguments * \param in incoming message with method arguments
* \param os Ipc_output stream for storing method results * \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 ** ** 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 Capability<RPC_INTERFACE> const cap() const

View File

@ -19,16 +19,18 @@ using namespace Genode;
/** /**
* Marshalling of capabilities as plain data representation * 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 * 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() 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() void Rpc_entrypoint::omit_reply()
{ {
/* set current destination to an invalid capability */ /* 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; if (!_ipc_server) return;
/* backup reply capability of current request */ /* 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 */ /* direct ipc server to the specified reply destination */
_ipc_server->ret(0); _ipc_server->ret(0);
_ipc_server->dst(reply_cap); _ipc_server->caller(reply_cap);
*_ipc_server << Signal_source::Signal(imprint, cnt) << IPC_REPLY; _ipc_server->insert(Signal_source::Signal(imprint, cnt));
_ipc_server->reply();
/* restore reply capability of the original request */ /* 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>; using Pool = Object_pool<Rpc_object_base>;
Native_connection_state cs; Native_connection_state cs;
Ipc_server srv(cs, &_snd_buf, &_rcv_buf); Ipc_server srv(cs, _snd_buf, _rcv_buf);
_ipc_server = &srv; _ipc_server = &srv;
_cap = srv; _cap = srv;
_cap_valid.unlock(); _cap_valid.unlock();
@ -66,7 +66,8 @@ void Rpc_entrypoint::entry()
int opcode = 0; int opcode = 0;
srv >> IPC_REPLY_WAIT >> opcode; srv.reply_wait();
srv.extract(opcode);
/* set default return value */ /* set default return value */
srv.ret(Ipc_client::ERR_INVALID_OBJECT); srv.ret(Ipc_client::ERR_INVALID_OBJECT);
@ -81,7 +82,7 @@ void Rpc_entrypoint::entry()
} }
/* answer exit call, thereby wake up '~Rpc_entrypoint' */ /* answer exit call, thereby wake up '~Rpc_entrypoint' */
srv << IPC_REPLY; srv.reply();
/* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */ /* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
_delay_exit.lock(); _delay_exit.lock();

View File

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