mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-18 21:27:56 +00:00
parent
4cdfb9bc2f
commit
47878bd3e1
@ -44,7 +44,12 @@ namespace Genode {
|
||||
/**
|
||||
* Return address of message buffer
|
||||
*/
|
||||
inline void *addr() { return &rcv_fpage; };
|
||||
inline void *msg_start() { return &rcv_fpage; };
|
||||
|
||||
/**
|
||||
* Return pointer of message data payload
|
||||
*/
|
||||
inline void *data() { return buf; };
|
||||
};
|
||||
|
||||
|
||||
|
@ -29,35 +29,6 @@ namespace Fiasco {
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_ostream **
|
||||
*****************/
|
||||
|
||||
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg) :
|
||||
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
|
||||
_snd_msg(snd_msg), _dst(dst)
|
||||
{
|
||||
_write_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_istream **
|
||||
*****************/
|
||||
|
||||
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg):
|
||||
Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()),
|
||||
Native_capability(Fiasco::l4_myself(), 0),
|
||||
_rcv_msg(rcv_msg)
|
||||
{
|
||||
using namespace Fiasco;
|
||||
_read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::~Ipc_istream() { }
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_client **
|
||||
****************/
|
||||
@ -69,16 +40,16 @@ void Ipc_client::_call()
|
||||
l4_msgdope_t ipc_result;
|
||||
long rec_badge;
|
||||
|
||||
_snd_msg->send_dope = L4_IPC_DOPE((_write_offset + 2*sizeof(umword_t) - 1)>>2, 0);
|
||||
_rcv_msg->size_dope = L4_IPC_DOPE(_rcv_msg->size()>>2, 0);
|
||||
_snd_msg.send_dope = L4_IPC_DOPE((_write_offset + 2*sizeof(umword_t) - 1)>>2, 0);
|
||||
_rcv_msg.size_dope = L4_IPC_DOPE(_rcv_msg.size()>>2, 0);
|
||||
|
||||
l4_ipc_call(Ipc_ostream::_dst.dst(),
|
||||
_write_offset <= 2*sizeof(umword_t) ? L4_IPC_SHORT_MSG : _snd_msg->addr(),
|
||||
Ipc_ostream::_dst.local_name(),
|
||||
*reinterpret_cast<l4_umword_t *>(&_snd_msg->buf[sizeof(umword_t)]),
|
||||
_rcv_msg->addr(),
|
||||
l4_ipc_call(_dst.dst(),
|
||||
_write_offset <= 2*sizeof(umword_t) ? L4_IPC_SHORT_MSG : _snd_msg.msg_start(),
|
||||
_dst.local_name(),
|
||||
*reinterpret_cast<l4_umword_t *>(&_snd_msg.buf[sizeof(umword_t)]),
|
||||
_rcv_msg.msg_start(),
|
||||
reinterpret_cast<l4_umword_t *>(&rec_badge),
|
||||
reinterpret_cast<l4_umword_t *>(&_rcv_msg->buf[sizeof(umword_t)]),
|
||||
reinterpret_cast<l4_umword_t *>(&_rcv_msg.buf[sizeof(umword_t)]),
|
||||
L4_IPC_NEVER, &ipc_result);
|
||||
|
||||
if (L4_IPC_IS_ERROR(ipc_result)) {
|
||||
@ -103,10 +74,13 @@ void Ipc_client::_call()
|
||||
}
|
||||
|
||||
|
||||
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
|
||||
Msgbuf_base *rcv_msg, unsigned short):
|
||||
Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0)
|
||||
{ }
|
||||
Ipc_client::Ipc_client(Native_capability const &dst,
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg, unsigned short)
|
||||
:
|
||||
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
|
||||
{
|
||||
_read_offset = _write_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
@ -126,7 +100,7 @@ void Ipc_server::_prepare_next_reply_wait()
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_wait()
|
||||
void Ipc_server::wait()
|
||||
{
|
||||
/* wait for new server request */
|
||||
try {
|
||||
@ -142,11 +116,11 @@ void Ipc_server::_wait()
|
||||
* client. The server does not bother.
|
||||
*/
|
||||
do {
|
||||
_rcv_msg->size_dope = L4_IPC_DOPE(_rcv_msg->size()>>2, 0);
|
||||
_rcv_msg.size_dope = L4_IPC_DOPE(_rcv_msg.size()>>2, 0);
|
||||
|
||||
l4_ipc_wait(&_rcv_cs.caller, _rcv_msg->addr(),
|
||||
reinterpret_cast<l4_umword_t *>(&_rcv_msg->buf[0]),
|
||||
reinterpret_cast<l4_umword_t *>(&_rcv_msg->buf[sizeof(umword_t)]),
|
||||
l4_ipc_wait(&_rcv_cs.caller, _rcv_msg.msg_start(),
|
||||
reinterpret_cast<l4_umword_t *>(&_rcv_msg.buf[0]),
|
||||
reinterpret_cast<l4_umword_t *>(&_rcv_msg.buf[sizeof(umword_t)]),
|
||||
L4_IPC_NEVER, &result);
|
||||
|
||||
if (L4_IPC_IS_ERROR(result))
|
||||
@ -160,22 +134,23 @@ void Ipc_server::_wait()
|
||||
} catch (Blocking_canceled) { }
|
||||
|
||||
/* define destination of next reply */
|
||||
Ipc_ostream::_dst = Native_capability(_rcv_cs.caller, badge());
|
||||
_caller = Native_capability(_rcv_cs.caller, 0);
|
||||
_badge = reinterpret_cast<unsigned long *>(&_rcv_msg.buf)[0];
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply()
|
||||
void Ipc_server::reply()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
_snd_msg->send_dope = L4_IPC_DOPE((_write_offset + sizeof(umword_t) - 1)>>2, 0);
|
||||
_snd_msg.send_dope = L4_IPC_DOPE((_write_offset + sizeof(umword_t) - 1)>>2, 0);
|
||||
|
||||
l4_msgdope_t result;
|
||||
l4_ipc_send(Ipc_ostream::_dst.dst(), _snd_msg->addr(),
|
||||
Ipc_ostream::_dst.local_name(),
|
||||
*reinterpret_cast<l4_umword_t *>(&_snd_msg->buf[sizeof(umword_t)]),
|
||||
l4_ipc_send(_caller.dst(), _snd_msg.msg_start(),
|
||||
_caller.local_name(),
|
||||
*reinterpret_cast<l4_umword_t *>(&_snd_msg.buf[sizeof(umword_t)]),
|
||||
L4_IPC_SEND_TIMEOUT_0, &result);
|
||||
|
||||
if (L4_IPC_IS_ERROR(result))
|
||||
@ -185,7 +160,7 @@ void Ipc_server::_reply()
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply_wait()
|
||||
void Ipc_server::reply_wait()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
@ -193,8 +168,8 @@ void Ipc_server::_reply_wait()
|
||||
|
||||
l4_msgdope_t ipc_result;
|
||||
|
||||
_snd_msg->send_dope = L4_IPC_DOPE((_write_offset + sizeof(umword_t) - 1)>>2, 0);
|
||||
_rcv_msg->size_dope = L4_IPC_DOPE(_rcv_msg->size()>>2, 0);
|
||||
_snd_msg.send_dope = L4_IPC_DOPE((_write_offset + sizeof(umword_t) - 1)>>2, 0);
|
||||
_rcv_msg.size_dope = L4_IPC_DOPE(_rcv_msg.size()>>2, 0);
|
||||
|
||||
/*
|
||||
* Use short IPC for reply if possible.
|
||||
@ -202,13 +177,13 @@ void Ipc_server::_reply_wait()
|
||||
* an integer as RPC result.
|
||||
*/
|
||||
l4_ipc_reply_and_wait(
|
||||
Ipc_ostream::_dst.dst(),
|
||||
_write_offset <= 2*sizeof(umword_t) ? L4_IPC_SHORT_MSG : _snd_msg->addr(),
|
||||
Ipc_ostream::_dst.local_name(),
|
||||
*reinterpret_cast<l4_umword_t *>(&_snd_msg->buf[sizeof(umword_t)]),
|
||||
&_rcv_cs.caller, _rcv_msg->addr(),
|
||||
reinterpret_cast<l4_umword_t *>(&_rcv_msg->buf[0]),
|
||||
reinterpret_cast<l4_umword_t *>(&_rcv_msg->buf[sizeof(umword_t)]),
|
||||
_caller.dst(),
|
||||
_write_offset <= 2*sizeof(umword_t) ? L4_IPC_SHORT_MSG : _snd_msg.msg_start(),
|
||||
_caller.local_name(),
|
||||
*reinterpret_cast<l4_umword_t *>(&_snd_msg.buf[sizeof(umword_t)]),
|
||||
&_rcv_cs.caller, _rcv_msg.msg_start(),
|
||||
reinterpret_cast<l4_umword_t *>(&_rcv_msg.buf[0]),
|
||||
reinterpret_cast<l4_umword_t *>(&_rcv_msg.buf[sizeof(umword_t)]),
|
||||
L4_IPC_SEND_TIMEOUT_0, &ipc_result);
|
||||
|
||||
if (L4_IPC_IS_ERROR(ipc_result)) {
|
||||
@ -222,24 +197,28 @@ void Ipc_server::_reply_wait()
|
||||
* the user but want to wait for the next proper incoming
|
||||
* message. So let's just wait now.
|
||||
*/
|
||||
_wait();
|
||||
wait();
|
||||
}
|
||||
|
||||
} else _wait();
|
||||
} else wait();
|
||||
|
||||
/* define destination of next reply */
|
||||
Ipc_ostream::_dst = Native_capability(_rcv_cs.caller, badge());
|
||||
_caller = Native_capability(_rcv_cs.caller, 0);
|
||||
_badge = reinterpret_cast<unsigned long *>(_rcv_msg.buf)[0];
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::Ipc_server(Native_connection_state &cs,
|
||||
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg)
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
|
||||
:
|
||||
Ipc_istream(rcv_msg),
|
||||
Ipc_ostream(Native_capability(), snd_msg), _reply_needed(false), _rcv_cs(cs)
|
||||
{ }
|
||||
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
|
||||
Native_capability(Fiasco::l4_myself(), 0),
|
||||
_reply_needed(false), _rcv_cs(cs)
|
||||
{
|
||||
_read_offset = _write_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::~Ipc_server() { }
|
||||
|
@ -88,9 +88,9 @@ namespace Genode {
|
||||
inline size_t size() const { return _size; };
|
||||
|
||||
/**
|
||||
* Return address of message buffer
|
||||
* Return pointer of message data payload
|
||||
*/
|
||||
inline void *addr() { return &_msg_start[0]; };
|
||||
inline void *data() { return &_msg_start[0]; };
|
||||
|
||||
/**
|
||||
* Reset portal capability selector payload
|
||||
|
@ -47,21 +47,21 @@ using namespace Fiasco;
|
||||
** IPC marshalling support **
|
||||
*****************************/
|
||||
|
||||
void Ipc_ostream::_marshal_capability(Native_capability const &cap)
|
||||
void Ipc_marshaller::insert(Native_capability const &cap)
|
||||
{
|
||||
if (cap.valid()) {
|
||||
if (!l4_msgtag_label(l4_task_cap_valid(L4_BASE_TASK_CAP, cap.dst()))) {
|
||||
_write_to_buf(0);
|
||||
insert(0UL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* transfer capability id */
|
||||
_write_to_buf(cap.local_name());
|
||||
insert(cap.local_name());
|
||||
|
||||
/* only transfer kernel-capability if it's a valid one */
|
||||
if (cap.valid())
|
||||
_snd_msg->snd_append_cap_sel(cap.dst());
|
||||
_snd_msg.snd_append_cap_sel(cap.dst());
|
||||
|
||||
ASSERT(!cap.valid() ||
|
||||
l4_msgtag_label(l4_task_cap_valid(L4_BASE_TASK_CAP, cap.dst())),
|
||||
@ -69,12 +69,12 @@ void Ipc_ostream::_marshal_capability(Native_capability const &cap)
|
||||
}
|
||||
|
||||
|
||||
void Ipc_istream::_unmarshal_capability(Native_capability &cap)
|
||||
void Ipc_unmarshaller::extract(Native_capability &cap)
|
||||
{
|
||||
long value = 0;
|
||||
|
||||
/* extract capability id from message buffer */
|
||||
_read_from_buf(value);
|
||||
extract(value);
|
||||
|
||||
/* if id is zero an invalid capability was transfered */
|
||||
if (!value) {
|
||||
@ -83,7 +83,7 @@ void Ipc_istream::_unmarshal_capability(Native_capability &cap)
|
||||
}
|
||||
|
||||
/* try to insert received capability in the map and return it */
|
||||
cap = Native_capability(cap_map()->insert_map(value, _rcv_msg->rcv_cap_sel()));
|
||||
cap = Native_capability(cap_map()->insert_map(value, _rcv_msg.rcv_cap_sel()));
|
||||
}
|
||||
|
||||
|
||||
@ -117,7 +117,7 @@ static inline bool ipc_error(l4_msgtag_t tag, bool print)
|
||||
/**
|
||||
* Copy message registers from UTCB to destination message buffer
|
||||
*/
|
||||
static void copy_utcb_to_msgbuf(l4_msgtag_t tag, Msgbuf_base *rcv_msg)
|
||||
static void copy_utcb_to_msgbuf(l4_msgtag_t tag, Msgbuf_base &rcv_msg)
|
||||
{
|
||||
unsigned num_msg_words = l4_msgtag_words(tag);
|
||||
unsigned num_cap_sel = l4_msgtag_items(tag);
|
||||
@ -125,11 +125,11 @@ static void copy_utcb_to_msgbuf(l4_msgtag_t tag, Msgbuf_base *rcv_msg)
|
||||
return;
|
||||
|
||||
/* look up and validate destination message buffer to receive the payload */
|
||||
l4_mword_t *msg_buf = (l4_mword_t *)rcv_msg->buf;
|
||||
if (num_msg_words*sizeof(l4_mword_t) > rcv_msg->size()) {
|
||||
l4_mword_t *msg_buf = (l4_mword_t *)rcv_msg.buf;
|
||||
if (num_msg_words*sizeof(l4_mword_t) > rcv_msg.size()) {
|
||||
if (DEBUG_MSG)
|
||||
outstring("receive message buffer too small");
|
||||
num_msg_words = rcv_msg->size()/sizeof(l4_mword_t);
|
||||
num_msg_words = rcv_msg.size()/sizeof(l4_mword_t);
|
||||
}
|
||||
|
||||
/* read message payload into destination message buffer */
|
||||
@ -138,19 +138,19 @@ static void copy_utcb_to_msgbuf(l4_msgtag_t tag, Msgbuf_base *rcv_msg)
|
||||
for (unsigned i = 0; i < num_msg_words; i++)
|
||||
*dst++ = *src++;
|
||||
|
||||
rcv_msg->rcv_reset();
|
||||
rcv_msg.rcv_reset();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy message registers from message buffer to UTCB and create message tag.
|
||||
*/
|
||||
static l4_msgtag_t copy_msgbuf_to_utcb(Msgbuf_base *snd_msg, unsigned offset,
|
||||
static l4_msgtag_t copy_msgbuf_to_utcb(Msgbuf_base &snd_msg, unsigned offset,
|
||||
Native_capability dst)
|
||||
{
|
||||
l4_mword_t *msg_buf = (l4_mword_t *)snd_msg->buf;
|
||||
l4_mword_t *msg_buf = (l4_mword_t *)snd_msg.buf;
|
||||
unsigned num_msg_words = offset/sizeof(l4_mword_t);
|
||||
unsigned num_cap_sel = snd_msg->snd_cap_sel_cnt();
|
||||
unsigned num_cap_sel = snd_msg.snd_cap_sel_cnt();
|
||||
|
||||
if (num_msg_words + 2 * num_cap_sel > L4_UTCB_GENERIC_DATA_SIZE) {
|
||||
if (DEBUG_MSG)
|
||||
@ -169,47 +169,17 @@ static l4_msgtag_t copy_msgbuf_to_utcb(Msgbuf_base *snd_msg, unsigned offset,
|
||||
for (unsigned i = 0; i < num_cap_sel; i++) {
|
||||
unsigned idx = num_msg_words + 2*i;
|
||||
l4_utcb_mr()->mr[idx] = L4_ITEM_MAP/* | L4_ITEM_CONT*/;
|
||||
l4_utcb_mr()->mr[idx + 1] = l4_obj_fpage(snd_msg->snd_cap_sel(i),
|
||||
l4_utcb_mr()->mr[idx + 1] = l4_obj_fpage(snd_msg.snd_cap_sel(i),
|
||||
0, L4_FPAGE_RWX).raw;
|
||||
}
|
||||
|
||||
/* we have consumed capability selectors, reset message buffer */
|
||||
snd_msg->snd_reset();
|
||||
snd_msg.snd_reset();
|
||||
|
||||
return l4_msgtag(0, num_msg_words, num_cap_sel, 0);
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_ostream **
|
||||
*****************/
|
||||
|
||||
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
|
||||
:
|
||||
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
|
||||
_snd_msg(snd_msg), _dst(dst)
|
||||
{
|
||||
_write_offset = sizeof(l4_mword_t);
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_istream **
|
||||
*****************/
|
||||
|
||||
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
|
||||
:
|
||||
Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()),
|
||||
Native_capability((Cap_index*)Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE]),
|
||||
_rcv_msg(rcv_msg)
|
||||
{
|
||||
_read_offset = sizeof(l4_mword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::~Ipc_istream() { }
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_client **
|
||||
****************/
|
||||
@ -219,7 +189,7 @@ void Ipc_client::_call()
|
||||
/* copy call message to the UTCBs message registers */
|
||||
l4_msgtag_t tag = copy_msgbuf_to_utcb(_snd_msg, _write_offset, _dst);
|
||||
|
||||
addr_t rcv_cap_sel = _rcv_msg->rcv_cap_sel_base();
|
||||
addr_t rcv_cap_sel = _rcv_msg.rcv_cap_sel_base();
|
||||
for (int i = 0; i < Msgbuf_base::MAX_CAP_ARGS; i++) {
|
||||
l4_utcb_br()->br[i] = rcv_cap_sel | L4_RCV_ITEM_SINGLE_CAP;
|
||||
rcv_cap_sel += L4_CAP_SIZE;
|
||||
@ -238,9 +208,13 @@ void Ipc_client::_call()
|
||||
}
|
||||
|
||||
|
||||
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
|
||||
Msgbuf_base *rcv_msg, unsigned short)
|
||||
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0) { }
|
||||
Ipc_client::Ipc_client(Native_capability const &dst,
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg, unsigned short)
|
||||
:
|
||||
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
|
||||
{
|
||||
_read_offset = _write_offset = sizeof(l4_mword_t);
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
@ -260,12 +234,11 @@ void Ipc_server::_prepare_next_reply_wait()
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_wait()
|
||||
void Ipc_server::wait()
|
||||
{
|
||||
/* wait for new server request */
|
||||
try {
|
||||
l4_umword_t label = 0;
|
||||
addr_t rcv_cap_sel = _rcv_msg->rcv_cap_sel_base();
|
||||
addr_t rcv_cap_sel = _rcv_msg.rcv_cap_sel_base();
|
||||
for (int i = 0; i < Msgbuf_base::MAX_CAP_ARGS; i++) {
|
||||
l4_utcb_br()->br[i] = rcv_cap_sel | L4_RCV_ITEM_SINGLE_CAP;
|
||||
rcv_cap_sel += L4_CAP_SIZE;
|
||||
@ -274,12 +247,11 @@ void Ipc_server::_wait()
|
||||
|
||||
l4_msgtag_t tag;
|
||||
do {
|
||||
l4_umword_t label = 0;
|
||||
tag = l4_ipc_wait(l4_utcb(), &label, L4_IPC_NEVER);
|
||||
_rcv_msg.label(label);
|
||||
} while (ipc_error(tag, DEBUG_MSG));
|
||||
|
||||
/* copy received label into message buffer */
|
||||
_rcv_msg->label(label);
|
||||
|
||||
/* copy message from the UTCBs message registers to the receive buffer */
|
||||
copy_utcb_to_msgbuf(tag, _rcv_msg);
|
||||
|
||||
@ -288,26 +260,24 @@ void Ipc_server::_wait()
|
||||
|
||||
} catch (Blocking_canceled) { }
|
||||
|
||||
/* we only have an unknown implicit reply capability */
|
||||
/* _dst = ???; */
|
||||
_badge = *reinterpret_cast<unsigned long *>(_rcv_msg.data());
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply()
|
||||
void Ipc_server::reply()
|
||||
{
|
||||
l4_msgtag_t tag = copy_msgbuf_to_utcb(_snd_msg, _write_offset, _dst);
|
||||
l4_msgtag_t tag = copy_msgbuf_to_utcb(_snd_msg, _write_offset, Native_capability());
|
||||
tag = l4_ipc_send(L4_SYSF_REPLY, l4_utcb(), tag, L4_IPC_SEND_TIMEOUT_0);
|
||||
ipc_error(tag, DEBUG_MSG);
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply_wait()
|
||||
void Ipc_server::reply_wait()
|
||||
{
|
||||
if (_reply_needed) {
|
||||
l4_umword_t label;
|
||||
addr_t rcv_cap_sel = _rcv_msg->rcv_cap_sel_base();
|
||||
addr_t rcv_cap_sel = _rcv_msg.rcv_cap_sel_base();
|
||||
for (int i = 0; i < Msgbuf_base::MAX_CAP_ARGS; i++) {
|
||||
l4_utcb_br()->br[i] = rcv_cap_sel | L4_RCV_ITEM_SINGLE_CAP;
|
||||
rcv_cap_sel += L4_CAP_SIZE;
|
||||
@ -315,8 +285,11 @@ void Ipc_server::_reply_wait()
|
||||
|
||||
l4_utcb_br()->bdr &= ~L4_BDR_OFFSET_MASK;
|
||||
|
||||
l4_msgtag_t tag = copy_msgbuf_to_utcb(_snd_msg, _write_offset, _dst);
|
||||
l4_umword_t label = 0;
|
||||
|
||||
l4_msgtag_t tag = copy_msgbuf_to_utcb(_snd_msg, _write_offset, Native_capability());
|
||||
tag = l4_ipc_reply_and_wait(l4_utcb(), tag, &label, L4_IPC_SEND_TIMEOUT_0);
|
||||
_rcv_msg.label(label);
|
||||
if (ipc_error(tag, false)) {
|
||||
/*
|
||||
* The error conditions could be a message cut (which
|
||||
@ -326,31 +299,30 @@ void Ipc_server::_reply_wait()
|
||||
* the user but want to wait for the next proper incoming
|
||||
* message. So let's just wait now.
|
||||
*/
|
||||
_wait();
|
||||
wait();
|
||||
} else {
|
||||
|
||||
/* copy received label into message buffer */
|
||||
_rcv_msg->label(label);
|
||||
|
||||
/* copy request message from the UTCBs message registers */
|
||||
copy_utcb_to_msgbuf(tag, _rcv_msg);
|
||||
}
|
||||
} else
|
||||
_wait();
|
||||
wait();
|
||||
|
||||
_badge = *reinterpret_cast<unsigned long *>(_rcv_msg.data());
|
||||
|
||||
/* reply capability is implicit in fiasco.oc and unknown to us */
|
||||
/* _dst = ???; */
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::Ipc_server(Native_connection_state &cs,
|
||||
Msgbuf_base *snd_msg,
|
||||
Msgbuf_base *rcv_msg)
|
||||
: Ipc_istream(rcv_msg),
|
||||
Ipc_ostream(Native_capability(), snd_msg),
|
||||
_reply_needed(false), _rcv_cs(cs)
|
||||
{ }
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
|
||||
:
|
||||
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
|
||||
Native_capability((Cap_index*)Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE]),
|
||||
_reply_needed(false), _rcv_cs(cs)
|
||||
{
|
||||
_read_offset = _write_offset = sizeof(l4_mword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::~Ipc_server() { }
|
||||
|
@ -45,7 +45,7 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
|
||||
void Rpc_entrypoint::entry()
|
||||
{
|
||||
Native_connection_state cs;
|
||||
Ipc_server srv(cs, &_snd_buf, &_rcv_buf);
|
||||
Ipc_server srv(cs, _snd_buf, _rcv_buf);
|
||||
_ipc_server = &srv;
|
||||
_cap = srv;
|
||||
_cap_valid.unlock();
|
||||
@ -63,17 +63,12 @@ void Rpc_entrypoint::entry()
|
||||
|
||||
int opcode = 0;
|
||||
|
||||
srv >> IPC_REPLY_WAIT >> opcode;
|
||||
srv.reply_wait();
|
||||
srv.extract(opcode);
|
||||
|
||||
/* set default return value */
|
||||
srv.ret(Ipc_client::ERR_INVALID_OBJECT);
|
||||
|
||||
/* check whether capability's label fits global id */
|
||||
if (((unsigned long)srv.badge()) != _rcv_buf.label()) {
|
||||
PWRN("somebody tries to fake us!");
|
||||
continue;
|
||||
}
|
||||
|
||||
apply(srv.badge(), [&] (Rpc_object_base *obj) {
|
||||
if (!obj) return;
|
||||
|
||||
@ -84,7 +79,7 @@ void Rpc_entrypoint::entry()
|
||||
}
|
||||
|
||||
/* answer exit call, thereby wake up '~Rpc_entrypoint' */
|
||||
srv << IPC_REPLY;
|
||||
srv.reply();
|
||||
|
||||
/* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
|
||||
_delay_exit.lock();
|
||||
|
@ -129,8 +129,9 @@ void Platform_thread::resume()
|
||||
|
||||
/* Send a message to the exception handler, to unblock the client */
|
||||
Msgbuf<16> snd, rcv;
|
||||
Ipc_client ipc_client(_pager_obj->cap(), &snd, &rcv);
|
||||
ipc_client << _pager_obj << IPC_CALL;
|
||||
Ipc_client ipc_client(_pager_obj->cap(), snd, rcv);
|
||||
ipc_client.insert(_pager_obj);
|
||||
ipc_client.call();
|
||||
}
|
||||
|
||||
|
||||
|
@ -69,9 +69,9 @@ class Genode::Msgbuf_base
|
||||
size_t size() const { return _size; }
|
||||
|
||||
/**
|
||||
* Return address of message buffer
|
||||
* Return pointer of message data payload
|
||||
*/
|
||||
void *addr() { return &buf[0]; }
|
||||
void *data() { return &buf[0]; }
|
||||
|
||||
/**
|
||||
* Reset capability buffer.
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* \brief Implementation of the Genode IPC-framework
|
||||
* \author Martin Stein
|
||||
* \author Norman Feske
|
||||
* \date 2012-02-12
|
||||
*/
|
||||
|
||||
@ -50,44 +51,12 @@ enum
|
||||
** IPC marshalling support **
|
||||
*****************************/
|
||||
|
||||
void Ipc_ostream::_marshal_capability(Native_capability const &cap) {
|
||||
_snd_msg->cap_add(cap); }
|
||||
void Ipc_marshaller::insert(Native_capability const &cap) {
|
||||
_snd_msg.cap_add(cap); }
|
||||
|
||||
|
||||
void Ipc_istream::_unmarshal_capability(Native_capability &cap) {
|
||||
cap = _rcv_msg->cap_get(); }
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_ostream **
|
||||
*****************/
|
||||
|
||||
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
|
||||
:
|
||||
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
|
||||
_snd_msg(snd_msg), _dst(dst)
|
||||
{
|
||||
_write_offset = align_natural<unsigned>(RPC_OBJECT_ID_SIZE);
|
||||
_snd_msg->reset();
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_istream **
|
||||
*****************/
|
||||
|
||||
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
|
||||
:
|
||||
Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()),
|
||||
Native_capability(Thread_base::myself() ? Thread_base::myself()->native_thread().cap
|
||||
: Hw::_main_thread_cap),
|
||||
_rcv_msg(rcv_msg)
|
||||
{
|
||||
_read_offset = align_natural<unsigned>(RPC_OBJECT_ID_SIZE);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::~Ipc_istream() { }
|
||||
void Ipc_unmarshaller::extract(Native_capability &cap) {
|
||||
cap = _rcv_msg.cap_get(); }
|
||||
|
||||
|
||||
/****************
|
||||
@ -100,16 +69,16 @@ void Ipc_client::_call()
|
||||
[&] () {
|
||||
|
||||
/* send request and receive corresponding reply */
|
||||
Thread_base::myself()->utcb()->copy_from(*_snd_msg, _write_offset);
|
||||
Thread_base::myself()->utcb()->copy_from(_snd_msg, _write_offset);
|
||||
|
||||
switch (Kernel::send_request_msg(Ipc_ostream::dst().dst(),
|
||||
_rcv_msg->cap_rcv_window())) {
|
||||
switch (Kernel::send_request_msg(_dst.dst(),
|
||||
_rcv_msg.cap_rcv_window())) {
|
||||
case -1: throw Blocking_canceled();
|
||||
case -2: throw Allocator::Out_of_memory();
|
||||
default:
|
||||
_rcv_msg->reset();
|
||||
_snd_msg->reset();
|
||||
Thread_base::myself()->utcb()->copy_to(*_rcv_msg);
|
||||
_rcv_msg.reset();
|
||||
_snd_msg.reset();
|
||||
Thread_base::myself()->utcb()->copy_to(_rcv_msg);
|
||||
|
||||
/* reset unmarshaller */
|
||||
_write_offset = _read_offset =
|
||||
@ -121,26 +90,24 @@ void Ipc_client::_call()
|
||||
}
|
||||
|
||||
|
||||
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
|
||||
Msgbuf_base *rcv_msg, unsigned short rcv_caps)
|
||||
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0) {
|
||||
rcv_msg->cap_rcv_window(rcv_caps); }
|
||||
Ipc_client::Ipc_client(Native_capability const &dst,
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
|
||||
unsigned short rcv_caps)
|
||||
:
|
||||
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
|
||||
{
|
||||
_read_offset = align_natural<unsigned>(RPC_OBJECT_ID_SIZE);
|
||||
_write_offset = align_natural<unsigned>(RPC_OBJECT_ID_SIZE);
|
||||
_snd_msg.reset();
|
||||
|
||||
_rcv_msg.cap_rcv_window(rcv_caps);
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_server **
|
||||
****************/
|
||||
|
||||
Ipc_server::Ipc_server(Native_connection_state &cs,
|
||||
Msgbuf_base *snd_msg,
|
||||
Msgbuf_base *rcv_msg)
|
||||
:
|
||||
Ipc_istream(rcv_msg),
|
||||
Ipc_ostream(Native_capability(), snd_msg),
|
||||
_reply_needed(false), _rcv_cs(cs)
|
||||
{ }
|
||||
|
||||
|
||||
void Ipc_server::_prepare_next_reply_wait()
|
||||
{
|
||||
/* now we have a request to reply */
|
||||
@ -155,7 +122,7 @@ void Ipc_server::_prepare_next_reply_wait()
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_wait()
|
||||
void Ipc_server::wait()
|
||||
{
|
||||
retry<Genode::Allocator::Out_of_memory>(
|
||||
[&] () {
|
||||
@ -165,8 +132,9 @@ void Ipc_server::_wait()
|
||||
case -1: throw Blocking_canceled();
|
||||
case -2: throw Allocator::Out_of_memory();
|
||||
default:
|
||||
_rcv_msg->reset();
|
||||
Thread_base::myself()->utcb()->copy_to(*_rcv_msg);
|
||||
_rcv_msg.reset();
|
||||
Thread_base::myself()->utcb()->copy_to(_rcv_msg);
|
||||
_badge = *reinterpret_cast<unsigned long *>(_rcv_msg.data());
|
||||
|
||||
/* update server state */
|
||||
_prepare_next_reply_wait();
|
||||
@ -177,33 +145,34 @@ void Ipc_server::_wait()
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply()
|
||||
void Ipc_server::reply()
|
||||
{
|
||||
Thread_base::myself()->utcb()->copy_from(*_snd_msg, _write_offset);
|
||||
_snd_msg->reset();
|
||||
Thread_base::myself()->utcb()->copy_from(_snd_msg, _write_offset);
|
||||
_snd_msg.reset();
|
||||
Kernel::send_reply_msg(0, false);
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply_wait()
|
||||
void Ipc_server::reply_wait()
|
||||
{
|
||||
/* if there is no reply, wait for request */
|
||||
if (!_reply_needed) {
|
||||
_wait();
|
||||
wait();
|
||||
return;
|
||||
}
|
||||
|
||||
retry<Genode::Allocator::Out_of_memory>(
|
||||
[&] () {
|
||||
/* send reply and receive next request */
|
||||
Thread_base::myself()->utcb()->copy_from(*_snd_msg, _write_offset);
|
||||
Thread_base::myself()->utcb()->copy_from(_snd_msg, _write_offset);
|
||||
switch (Kernel::send_reply_msg(Msgbuf_base::MAX_CAP_ARGS, true)) {
|
||||
case -1: throw Blocking_canceled();
|
||||
case -2: throw Allocator::Out_of_memory();
|
||||
default:
|
||||
_rcv_msg->reset();
|
||||
_snd_msg->reset();
|
||||
Thread_base::myself()->utcb()->copy_to(*_rcv_msg);
|
||||
_rcv_msg.reset();
|
||||
_snd_msg.reset();
|
||||
Thread_base::myself()->utcb()->copy_to(_rcv_msg);
|
||||
_badge = *reinterpret_cast<unsigned long *>(_rcv_msg.data());
|
||||
|
||||
/* update server state */
|
||||
_prepare_next_reply_wait();
|
||||
@ -214,4 +183,18 @@ void Ipc_server::_reply_wait()
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::Ipc_server(Native_connection_state &cs,
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
|
||||
:
|
||||
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
|
||||
Native_capability(Thread_base::myself() ? Thread_base::myself()->native_thread().cap
|
||||
: Hw::_main_thread_cap),
|
||||
_reply_needed(false), _rcv_cs(cs)
|
||||
{
|
||||
_read_offset = align_natural<unsigned>(RPC_OBJECT_ID_SIZE);
|
||||
_write_offset = align_natural<unsigned>(RPC_OBJECT_ID_SIZE);
|
||||
_snd_msg.reset();
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::~Ipc_server() { }
|
||||
|
@ -43,7 +43,7 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
|
||||
void Rpc_entrypoint::entry()
|
||||
{
|
||||
Native_connection_state cs;
|
||||
Ipc_server srv(cs, &_snd_buf, &_rcv_buf);
|
||||
Ipc_server srv(cs, _snd_buf, _rcv_buf);
|
||||
_ipc_server = &srv;
|
||||
_cap = srv;
|
||||
_cap_valid.unlock();
|
||||
@ -61,7 +61,8 @@ void Rpc_entrypoint::entry()
|
||||
|
||||
int opcode = 0;
|
||||
|
||||
srv >> IPC_REPLY_WAIT >> opcode;
|
||||
srv.reply_wait();
|
||||
srv.extract(opcode);
|
||||
|
||||
/* set default return value */
|
||||
srv.ret(Ipc_client::ERR_INVALID_OBJECT);
|
||||
@ -77,7 +78,7 @@ void Rpc_entrypoint::entry()
|
||||
}
|
||||
|
||||
/* answer exit call, thereby wake up '~Rpc_entrypoint' */
|
||||
srv << IPC_REPLY;
|
||||
srv.reply();
|
||||
|
||||
/* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
|
||||
_delay_exit.lock();
|
||||
|
@ -62,9 +62,9 @@ namespace Genode {
|
||||
inline Genode::size_t size() const { return _size; };
|
||||
|
||||
/**
|
||||
* Return address of message buffer
|
||||
* Return pointer of message data payload
|
||||
*/
|
||||
inline void *addr() { return &_msg_start[0]; };
|
||||
inline void *data() { return &_msg_start[0]; };
|
||||
|
||||
void reset_caps() { _used_caps = 0; _read_cap_index = 0; }
|
||||
|
||||
|
@ -52,22 +52,22 @@ using namespace Genode;
|
||||
** IPC marshalling support **
|
||||
*****************************/
|
||||
|
||||
void Ipc_ostream::_marshal_capability(Native_capability const &cap)
|
||||
void Ipc_marshaller::insert(Native_capability const &cap)
|
||||
{
|
||||
if (cap.valid()) {
|
||||
_write_to_buf(cap.local_name());
|
||||
insert(cap.local_name());
|
||||
|
||||
_snd_msg->append_cap(cap.dst().socket);
|
||||
_snd_msg.append_cap(cap.dst().socket);
|
||||
} else {
|
||||
_write_to_buf(-1L);
|
||||
insert(-1L);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Ipc_istream::_unmarshal_capability(Native_capability &cap)
|
||||
void Ipc_unmarshaller::extract(Native_capability &cap)
|
||||
{
|
||||
long local_name = 0;
|
||||
_read_from_buf(local_name);
|
||||
extract(local_name);
|
||||
|
||||
if (local_name == -1) {
|
||||
|
||||
@ -77,7 +77,7 @@ void Ipc_istream::_unmarshal_capability(Native_capability &cap)
|
||||
} else {
|
||||
|
||||
/* construct valid capability */
|
||||
int const socket = _rcv_msg->read_cap();
|
||||
int const socket = _rcv_msg.read_cap();
|
||||
cap = Native_capability(Cap_dst_policy::Dst(socket), local_name);
|
||||
}
|
||||
}
|
||||
@ -439,83 +439,31 @@ static inline void lx_reply(int reply_socket,
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_ostream **
|
||||
*****************/
|
||||
|
||||
/*
|
||||
* XXX This class will be removed soon.
|
||||
*/
|
||||
|
||||
void Ipc_ostream::_prepare_next_send()
|
||||
{
|
||||
PRAW("unexpected call to %s (%p)", __PRETTY_FUNCTION__, this);
|
||||
}
|
||||
|
||||
|
||||
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg):
|
||||
Ipc_marshaller(snd_msg->buf, snd_msg->size()), _snd_msg(snd_msg), _dst(dst)
|
||||
{ }
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_istream **
|
||||
*****************/
|
||||
|
||||
/*
|
||||
* XXX This class will be removed soon.
|
||||
*/
|
||||
|
||||
void Ipc_istream::_prepare_next_receive()
|
||||
{
|
||||
PRAW("unexpected call to %s (%p)", __PRETTY_FUNCTION__, this);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
|
||||
:
|
||||
Ipc_unmarshaller(rcv_msg->buf, rcv_msg->size()),
|
||||
Native_capability(Dst(-1), 0),
|
||||
_rcv_msg(rcv_msg)
|
||||
{ }
|
||||
|
||||
|
||||
Ipc_istream::~Ipc_istream() { }
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_client **
|
||||
****************/
|
||||
|
||||
void Ipc_client::_prepare_next_call()
|
||||
void Ipc_client::_call()
|
||||
{
|
||||
lx_call(_dst.dst().socket, _snd_msg, _write_offset, _rcv_msg);
|
||||
}
|
||||
|
||||
|
||||
Ipc_client::Ipc_client(Native_capability const &dst,
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg, unsigned short)
|
||||
:
|
||||
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
|
||||
{
|
||||
/* prepare next request in buffer */
|
||||
long const local_name = Ipc_ostream::_dst.local_name();
|
||||
|
||||
_write_offset = 0;
|
||||
_write_to_buf(local_name);
|
||||
long const local_name = _dst.local_name();
|
||||
|
||||
/* prepare response buffer */
|
||||
_read_offset = sizeof(long);
|
||||
_write_offset = 0;
|
||||
|
||||
_snd_msg->reset_caps();
|
||||
}
|
||||
insert(local_name);
|
||||
|
||||
|
||||
void Ipc_client::_call()
|
||||
{
|
||||
if (Ipc_ostream::_dst.valid())
|
||||
lx_call(Ipc_ostream::_dst.dst().socket, *_snd_msg, _write_offset, *_rcv_msg);
|
||||
|
||||
_prepare_next_call();
|
||||
}
|
||||
|
||||
|
||||
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
|
||||
Msgbuf_base *rcv_msg, unsigned short)
|
||||
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0)
|
||||
{
|
||||
_prepare_next_call();
|
||||
_snd_msg.reset_caps();
|
||||
}
|
||||
|
||||
|
||||
@ -530,18 +478,18 @@ void Ipc_server::_prepare_next_reply_wait()
|
||||
|
||||
/* prepare next reply */
|
||||
_write_offset = 0;
|
||||
long local_name = Ipc_ostream::_dst.local_name();
|
||||
_write_to_buf(local_name); /* XXX unused, needed by de/marshaller */
|
||||
long local_name = _caller.local_name();
|
||||
insert(local_name); /* XXX unused, needed by de/marshaller */
|
||||
|
||||
/* leave space for exc code at the beginning of the msgbuf */
|
||||
_write_offset += align_natural(sizeof(int));
|
||||
|
||||
/* reset capability slots of send message buffer */
|
||||
_snd_msg->reset_caps();
|
||||
_snd_msg.reset_caps();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_wait()
|
||||
void Ipc_server::wait()
|
||||
{
|
||||
_reply_needed = true;
|
||||
|
||||
@ -555,7 +503,7 @@ void Ipc_server::_wait()
|
||||
}
|
||||
|
||||
try {
|
||||
int const reply_socket = lx_wait(_rcv_cs, *_rcv_msg);
|
||||
int const reply_socket = lx_wait(_rcv_cs, _rcv_msg);
|
||||
|
||||
/*
|
||||
* Remember reply capability
|
||||
@ -566,38 +514,40 @@ void Ipc_server::_wait()
|
||||
*/
|
||||
enum { DUMMY_LOCAL_NAME = -1 };
|
||||
typedef Native_capability::Dst Dst;
|
||||
Ipc_ostream::_dst = Native_capability(Dst(reply_socket), DUMMY_LOCAL_NAME);
|
||||
_caller = Native_capability(Dst(reply_socket), DUMMY_LOCAL_NAME);
|
||||
_badge = reinterpret_cast<unsigned long *>(_rcv_msg.data())[0];
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
} catch (Blocking_canceled) { }
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply()
|
||||
void Ipc_server::reply()
|
||||
{
|
||||
try {
|
||||
lx_reply(Ipc_ostream::_dst.dst().socket, *_snd_msg, _write_offset); }
|
||||
lx_reply(_caller.dst().socket, _snd_msg, _write_offset); }
|
||||
catch (Ipc_error) { }
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply_wait()
|
||||
void Ipc_server::reply_wait()
|
||||
{
|
||||
/* when first called, there was no request yet */
|
||||
if (_reply_needed)
|
||||
lx_reply(Ipc_ostream::_dst.dst().socket, *_snd_msg, _write_offset);
|
||||
lx_reply(_caller.dst().socket, _snd_msg, _write_offset);
|
||||
|
||||
_wait();
|
||||
wait();
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::Ipc_server(Native_connection_state &cs,
|
||||
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg)
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
|
||||
:
|
||||
Ipc_istream(rcv_msg),
|
||||
Ipc_ostream(Native_capability(), snd_msg), _reply_needed(false), _rcv_cs(cs)
|
||||
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
|
||||
Native_capability(Dst(-1), 0),
|
||||
_reply_needed(false), _rcv_cs(cs)
|
||||
{
|
||||
Thread_base *thread = Thread_base::myself();
|
||||
|
||||
@ -619,7 +569,7 @@ Ipc_server::Ipc_server(Native_connection_state &cs,
|
||||
thread->native_thread().is_ipc_server = true;
|
||||
}
|
||||
|
||||
/* override capability initialization performed by 'Ipc_istream' */
|
||||
/* override capability initialization */
|
||||
*static_cast<Native_capability *>(this) =
|
||||
Native_capability(Native_capability::Dst(_rcv_cs.client_sd), 0);
|
||||
|
||||
|
@ -125,9 +125,9 @@ namespace Genode {
|
||||
inline size_t size() const { return _size; }
|
||||
|
||||
/**
|
||||
* Return address of message buffer
|
||||
* Return pointer of message data payload
|
||||
*/
|
||||
inline void *addr() { return &_msg_start[0]; }
|
||||
inline void *data() { return &_msg_start[0]; }
|
||||
|
||||
/**
|
||||
* Reset portal capability selector payload
|
||||
|
@ -28,15 +28,15 @@ using namespace Nova;
|
||||
** IPC marshalling support **
|
||||
*****************************/
|
||||
|
||||
void Ipc_ostream::_marshal_capability(Native_capability const &cap)
|
||||
void Ipc_marshaller::insert(Native_capability const &cap)
|
||||
{
|
||||
_snd_msg->snd_append_pt_sel(cap);
|
||||
_snd_msg.snd_append_pt_sel(cap);
|
||||
}
|
||||
|
||||
|
||||
void Ipc_istream::_unmarshal_capability(Native_capability &cap)
|
||||
void Ipc_unmarshaller::extract(Native_capability &cap)
|
||||
{
|
||||
_rcv_msg->rcv_pt_sel(cap);
|
||||
_rcv_msg.rcv_pt_sel(cap);
|
||||
}
|
||||
|
||||
|
||||
@ -47,17 +47,17 @@ void Ipc_istream::_unmarshal_capability(Native_capability &cap)
|
||||
/**
|
||||
* Copy message registers from UTCB to destination message buffer
|
||||
*/
|
||||
static void copy_utcb_to_msgbuf(Nova::Utcb *utcb, Msgbuf_base *rcv_msg)
|
||||
static void copy_utcb_to_msgbuf(Nova::Utcb *utcb, Msgbuf_base &rcv_msg)
|
||||
{
|
||||
size_t num_msg_words = utcb->msg_words();
|
||||
if (num_msg_words == 0) return;
|
||||
|
||||
/* look up and validate destination message buffer to receive the payload */
|
||||
mword_t *msg_buf = (mword_t *)rcv_msg->buf;
|
||||
if (num_msg_words*sizeof(mword_t) > rcv_msg->size()) {
|
||||
mword_t *msg_buf = (mword_t *)rcv_msg.buf;
|
||||
if (num_msg_words*sizeof(mword_t) > rcv_msg.size()) {
|
||||
PERR("receive message buffer too small msg size=%zx, buf size=%zd",
|
||||
num_msg_words*sizeof(mword_t), rcv_msg->size());
|
||||
num_msg_words = rcv_msg->size()/sizeof(mword_t);
|
||||
num_msg_words*sizeof(mword_t), rcv_msg.size());
|
||||
num_msg_words = rcv_msg.size()/sizeof(mword_t);
|
||||
}
|
||||
|
||||
/* read message payload into destination message buffer */
|
||||
@ -71,11 +71,11 @@ static void copy_utcb_to_msgbuf(Nova::Utcb *utcb, Msgbuf_base *rcv_msg)
|
||||
/**
|
||||
* Copy message payload to UTCB message registers
|
||||
*/
|
||||
static bool copy_msgbuf_to_utcb(Nova::Utcb *utcb, Msgbuf_base *snd_msg,
|
||||
static bool copy_msgbuf_to_utcb(Nova::Utcb *utcb, Msgbuf_base &snd_msg,
|
||||
unsigned num_msg_words, mword_t local_name)
|
||||
{
|
||||
/* look up address and size of message payload */
|
||||
mword_t *msg_buf = (mword_t *)snd_msg->buf;
|
||||
mword_t *msg_buf = (mword_t *)snd_msg.buf;
|
||||
|
||||
/*
|
||||
* XXX determine correct number of message registers
|
||||
@ -97,9 +97,9 @@ static bool copy_msgbuf_to_utcb(Nova::Utcb *utcb, Msgbuf_base *snd_msg,
|
||||
utcb->set_msg_word(num_msg_words);
|
||||
|
||||
/* append portal capability selectors */
|
||||
for (unsigned i = 0; i < snd_msg->snd_pt_sel_cnt(); i++) {
|
||||
for (unsigned i = 0; i < snd_msg.snd_pt_sel_cnt(); i++) {
|
||||
bool trans_map = true;
|
||||
Nova::Obj_crd crd = snd_msg->snd_pt_sel(i, trans_map);
|
||||
Nova::Obj_crd crd = snd_msg.snd_pt_sel(i, trans_map);
|
||||
if (crd.base() == ~0UL) continue;
|
||||
|
||||
if (!utcb->append_item(crd, i, false, false, trans_map))
|
||||
@ -107,39 +107,12 @@ static bool copy_msgbuf_to_utcb(Nova::Utcb *utcb, Msgbuf_base *snd_msg,
|
||||
}
|
||||
|
||||
/* we have consumed portal capability selectors, reset message buffer */
|
||||
snd_msg->snd_reset();
|
||||
snd_msg.snd_reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_ostream **
|
||||
*****************/
|
||||
|
||||
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
|
||||
:
|
||||
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
|
||||
_snd_msg(snd_msg), _dst(dst)
|
||||
{
|
||||
_write_offset = sizeof(mword_t);
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_istream **
|
||||
*****************/
|
||||
|
||||
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
|
||||
: Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()), _rcv_msg(rcv_msg)
|
||||
{
|
||||
_read_offset = sizeof(mword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::~Ipc_istream() { }
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_client **
|
||||
****************/
|
||||
@ -149,18 +122,18 @@ void Ipc_client::_call()
|
||||
Nova::Utcb *utcb = (Nova::Utcb *)Thread_base::myself()->utcb();
|
||||
|
||||
if (!copy_msgbuf_to_utcb(utcb, _snd_msg, _write_offset/sizeof(mword_t),
|
||||
Ipc_ostream::_dst.local_name())) {
|
||||
_dst.local_name())) {
|
||||
PERR("could not setup IPC");
|
||||
return;
|
||||
}
|
||||
|
||||
/* if we can't setup receive window, die in order to recognize the issue */
|
||||
if (!_rcv_msg->prepare_rcv_window(utcb, Ipc_ostream::_dst.rcv_window()))
|
||||
if (!_rcv_msg.prepare_rcv_window(utcb, _dst.rcv_window()))
|
||||
/* printf doesn't work here since for IPC also rcv_prepare* is used */
|
||||
nova_die();
|
||||
|
||||
/* establish the mapping via a portal traversal */
|
||||
uint8_t res = Nova::call(Ipc_ostream::_dst.local_name());
|
||||
uint8_t res = Nova::call(_dst.local_name());
|
||||
if (res != Nova::NOVA_OK) {
|
||||
/* If an error occurred, reset word&item count (not done by kernel). */
|
||||
utcb->set_msg_word(0);
|
||||
@ -168,17 +141,19 @@ void Ipc_client::_call()
|
||||
ret(ERR_INVALID_OBJECT);
|
||||
}
|
||||
|
||||
_rcv_msg->post_ipc(utcb, Ipc_ostream::_dst.rcv_window());
|
||||
_rcv_msg.post_ipc(utcb, _dst.rcv_window());
|
||||
copy_utcb_to_msgbuf(utcb, _rcv_msg);
|
||||
_snd_msg->snd_reset();
|
||||
_snd_msg.snd_reset();
|
||||
|
||||
_write_offset = _read_offset = sizeof(mword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
|
||||
Msgbuf_base *rcv_msg, unsigned short const rcv_caps)
|
||||
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0)
|
||||
Ipc_client::Ipc_client(Native_capability const &dst,
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
|
||||
unsigned short const rcv_caps)
|
||||
:
|
||||
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
|
||||
{
|
||||
if (rcv_caps == ~0)
|
||||
/* use default values for rcv_wnd */
|
||||
@ -188,7 +163,9 @@ Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
|
||||
unsigned short log2_max = rcv_caps ? log2(rcv_caps) : 0;
|
||||
if ((1U << log2_max) < rcv_caps) log2_max ++;
|
||||
|
||||
rcv_msg->rcv_wnd(log2_max);
|
||||
rcv_msg.rcv_wnd(log2_max);
|
||||
|
||||
_read_offset = _write_offset = sizeof(mword_t);
|
||||
}
|
||||
|
||||
|
||||
@ -196,7 +173,7 @@ Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
|
||||
** Ipc_server **
|
||||
****************/
|
||||
|
||||
void Ipc_server::_wait()
|
||||
void Ipc_server::wait()
|
||||
{
|
||||
/*
|
||||
* This function is only called by the portal dispatcher of server
|
||||
@ -207,7 +184,7 @@ void Ipc_server::_wait()
|
||||
|
||||
Nova::Utcb *utcb = (Nova::Utcb *)Thread_base::myself()->utcb();
|
||||
|
||||
_rcv_msg->post_ipc(utcb);
|
||||
_rcv_msg.post_ipc(utcb);
|
||||
copy_utcb_to_msgbuf(utcb, _rcv_msg);
|
||||
|
||||
/* reset unmarshaller */
|
||||
@ -216,25 +193,26 @@ void Ipc_server::_wait()
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply()
|
||||
void Ipc_server::reply()
|
||||
{
|
||||
Nova::Utcb *utcb = (Nova::Utcb *)Thread_base::myself()->utcb();
|
||||
|
||||
copy_msgbuf_to_utcb(utcb, _snd_msg, _write_offset/sizeof(mword_t),
|
||||
Ipc_ostream::_dst.local_name());
|
||||
copy_msgbuf_to_utcb(utcb, _snd_msg, _write_offset/sizeof(mword_t), 0);
|
||||
|
||||
Nova::reply(Thread_base::myself()->stack_top());
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply_wait() { }
|
||||
void Ipc_server::reply_wait() { }
|
||||
|
||||
|
||||
Ipc_server::Ipc_server(Native_connection_state &cs,
|
||||
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg)
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
|
||||
:
|
||||
Ipc_istream(rcv_msg), Ipc_ostream(Native_capability(), snd_msg), _rcv_cs(cs)
|
||||
{ }
|
||||
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _rcv_cs(cs)
|
||||
{
|
||||
_read_offset = _write_offset = sizeof(mword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::~Ipc_server() { }
|
||||
|
@ -122,8 +122,9 @@ void Rpc_entrypoint::_activation_entry()
|
||||
int opcode = 0;
|
||||
|
||||
Native_connection_state cs;
|
||||
Ipc_server srv(cs, &ep->_snd_buf, &ep->_rcv_buf);
|
||||
srv >> IPC_WAIT >> opcode;
|
||||
Ipc_server srv(cs, ep->_snd_buf, ep->_rcv_buf);
|
||||
srv.wait();
|
||||
srv.extract(opcode);
|
||||
|
||||
/* set default return value */
|
||||
srv.ret(Ipc_client::ERR_INVALID_OBJECT);
|
||||
@ -132,7 +133,7 @@ void Rpc_entrypoint::_activation_entry()
|
||||
if (ep->_cap.local_name() == id_pt) {
|
||||
if (!ep->_rcv_buf.prepare_rcv_window((Nova::Utcb *)ep->utcb()))
|
||||
PWRN("out of capability selectors for handling server requests");
|
||||
srv << IPC_REPLY;
|
||||
srv.reply();
|
||||
}
|
||||
|
||||
{
|
||||
@ -157,7 +158,7 @@ void Rpc_entrypoint::_activation_entry()
|
||||
if (!ep->_rcv_buf.prepare_rcv_window((Nova::Utcb *)ep->utcb()))
|
||||
PWRN("out of capability selectors for handling server requests");
|
||||
|
||||
srv << IPC_REPLY;
|
||||
srv.reply();
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,9 +45,9 @@ namespace Genode {
|
||||
inline size_t size() const { return _size; };
|
||||
|
||||
/**
|
||||
* Return address of message buffer
|
||||
* Return pointer of message data payload
|
||||
*/
|
||||
inline void *addr() { return &_msg_start[0]; };
|
||||
inline void *data() { return &_msg_start[0]; };
|
||||
};
|
||||
|
||||
|
||||
|
@ -51,17 +51,17 @@ static void kdb_emergency_print(const char *s)
|
||||
/**
|
||||
* Copy message registers from UTCB to destination message buffer
|
||||
*/
|
||||
static void copy_utcb_to_msgbuf(L4_MsgTag_t rcv_tag, Msgbuf_base *rcv_msg)
|
||||
static void copy_utcb_to_msgbuf(L4_MsgTag_t rcv_tag, Msgbuf_base &rcv_msg)
|
||||
{
|
||||
int num_msg_words = (int)L4_UntypedWords(rcv_tag);
|
||||
if (num_msg_words <= 0) return;
|
||||
|
||||
/* look up and validate destination message buffer to receive the payload */
|
||||
L4_Word_t *msg_buf = (L4_Word_t *)rcv_msg->buf;
|
||||
if (num_msg_words*sizeof(L4_Word_t) > rcv_msg->size()) {
|
||||
L4_Word_t *msg_buf = (L4_Word_t *)rcv_msg.buf;
|
||||
if (num_msg_words*sizeof(L4_Word_t) > rcv_msg.size()) {
|
||||
PERR("receive message buffer too small msg size=%zd, buf size=%zd",
|
||||
num_msg_words*sizeof(L4_Word_t), rcv_msg->size());
|
||||
num_msg_words = rcv_msg->size()/sizeof(L4_Word_t);
|
||||
num_msg_words*sizeof(L4_Word_t), rcv_msg.size());
|
||||
num_msg_words = rcv_msg.size()/sizeof(L4_Word_t);
|
||||
}
|
||||
|
||||
/* read message payload into destination message buffer */
|
||||
@ -77,11 +77,11 @@ static void copy_utcb_to_msgbuf(L4_MsgTag_t rcv_tag, Msgbuf_base *rcv_msg)
|
||||
* 1 is used for the local name. All subsequent message registers hold the
|
||||
* message payload.
|
||||
*/
|
||||
static void copy_msgbuf_to_utcb(Msgbuf_base *snd_msg, unsigned num_msg_words,
|
||||
static void copy_msgbuf_to_utcb(Msgbuf_base &snd_msg, unsigned num_msg_words,
|
||||
L4_Word_t local_name)
|
||||
{
|
||||
/* look up address and size of message payload */
|
||||
L4_Word_t *msg_buf = (L4_Word_t *)snd_msg->buf;
|
||||
L4_Word_t *msg_buf = (L4_Word_t *)snd_msg.buf;
|
||||
|
||||
num_msg_words += 1;
|
||||
|
||||
@ -99,51 +99,6 @@ static void copy_msgbuf_to_utcb(Msgbuf_base *snd_msg, unsigned num_msg_words,
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_ostream **
|
||||
*****************/
|
||||
|
||||
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
|
||||
:
|
||||
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
|
||||
_snd_msg(snd_msg), _dst(dst)
|
||||
{
|
||||
_write_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_istream **
|
||||
*****************/
|
||||
|
||||
/**
|
||||
* Return the global thread ID of the calling thread
|
||||
*
|
||||
* On OKL4 we cannot use 'L4_Myself()' to determine our own thread's
|
||||
* identity. By convention, each thread stores its global ID in a
|
||||
* defined entry of its UTCB.
|
||||
*/
|
||||
static inline Okl4::L4_ThreadId_t thread_get_my_global_id()
|
||||
{
|
||||
Okl4::L4_ThreadId_t myself;
|
||||
myself.raw = Okl4::__L4_TCR_ThreadWord(UTCB_TCR_THREAD_WORD_MYSELF);
|
||||
return myself;
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
|
||||
:
|
||||
Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()),
|
||||
Native_capability(thread_get_my_global_id(), 0),
|
||||
_rcv_msg(rcv_msg)
|
||||
{
|
||||
_read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::~Ipc_istream() { }
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_client **
|
||||
****************/
|
||||
@ -152,10 +107,10 @@ void Ipc_client::_call()
|
||||
{
|
||||
/* copy call message to the UTCBs message registers */
|
||||
copy_msgbuf_to_utcb(_snd_msg, _write_offset/sizeof(L4_Word_t),
|
||||
Ipc_ostream::_dst.local_name());
|
||||
_dst.local_name());
|
||||
|
||||
L4_Accept(L4_UntypedWordsAcceptor);
|
||||
L4_MsgTag_t rcv_tag = L4_Call(Ipc_ostream::_dst.dst());
|
||||
L4_MsgTag_t rcv_tag = L4_Call(_dst.dst());
|
||||
|
||||
enum { ERROR_MASK = 0xe, ERROR_CANCELED = 3 << 1 };
|
||||
if (L4_IpcFailed(rcv_tag) &&
|
||||
@ -175,9 +130,13 @@ void Ipc_client::_call()
|
||||
}
|
||||
|
||||
|
||||
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
|
||||
Msgbuf_base *rcv_msg, unsigned short)
|
||||
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0) { }
|
||||
Ipc_client::Ipc_client(Native_capability const &dst,
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg, unsigned short)
|
||||
:
|
||||
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
|
||||
{
|
||||
_write_offset = _read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
@ -197,7 +156,7 @@ void Ipc_server::_prepare_next_reply_wait()
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_wait()
|
||||
void Ipc_server::wait()
|
||||
{
|
||||
/* wait for new server request */
|
||||
try {
|
||||
@ -218,20 +177,21 @@ void Ipc_server::_wait()
|
||||
} catch (Blocking_canceled) { }
|
||||
|
||||
/* define destination of next reply */
|
||||
Ipc_ostream::_dst = Native_capability(_rcv_cs.caller, badge());
|
||||
_caller = Native_capability(_rcv_cs.caller, badge());
|
||||
_badge = reinterpret_cast<unsigned long *>(_rcv_msg.data())[0];
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply()
|
||||
void Ipc_server::reply()
|
||||
{
|
||||
/* copy reply to the UTCBs message registers */
|
||||
copy_msgbuf_to_utcb(_snd_msg, _write_offset/sizeof(L4_Word_t),
|
||||
Ipc_ostream::_dst.local_name());
|
||||
_caller.local_name());
|
||||
|
||||
/* perform non-blocking IPC send operation */
|
||||
L4_MsgTag_t rcv_tag = L4_Reply(Ipc_ostream::_dst.dst());
|
||||
L4_MsgTag_t rcv_tag = L4_Reply(_caller.dst());
|
||||
|
||||
if (L4_IpcFailed(rcv_tag))
|
||||
PERR("ipc error in _reply - gets ignored");
|
||||
@ -240,15 +200,15 @@ void Ipc_server::_reply()
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply_wait()
|
||||
void Ipc_server::reply_wait()
|
||||
{
|
||||
if (_reply_needed) {
|
||||
|
||||
/* copy reply to the UTCBs message registers */
|
||||
copy_msgbuf_to_utcb(_snd_msg, _write_offset/sizeof(L4_Word_t),
|
||||
Ipc_ostream::_dst.local_name());
|
||||
_caller.local_name());
|
||||
|
||||
L4_MsgTag_t rcv_tag = L4_ReplyWait(Ipc_ostream::_dst.dst(), &_rcv_cs.caller);
|
||||
L4_MsgTag_t rcv_tag = L4_ReplyWait(_caller.dst(), &_rcv_cs.caller);
|
||||
|
||||
/*
|
||||
* TODO: Check for IPC error
|
||||
@ -258,22 +218,40 @@ void Ipc_server::_reply_wait()
|
||||
copy_utcb_to_msgbuf(rcv_tag, _rcv_msg);
|
||||
|
||||
/* define destination of next reply */
|
||||
Ipc_ostream::_dst = Native_capability(_rcv_cs.caller, badge());
|
||||
_caller = Native_capability(_rcv_cs.caller, badge());
|
||||
_badge = reinterpret_cast<unsigned long *>(_rcv_msg.data())[0];
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
|
||||
} else
|
||||
_wait();
|
||||
wait();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the global thread ID of the calling thread
|
||||
*
|
||||
* On OKL4 we cannot use 'L4_Myself()' to determine our own thread's
|
||||
* identity. By convention, each thread stores its global ID in a
|
||||
* defined entry of its UTCB.
|
||||
*/
|
||||
static inline Okl4::L4_ThreadId_t thread_get_my_global_id()
|
||||
{
|
||||
Okl4::L4_ThreadId_t myself;
|
||||
myself.raw = Okl4::__L4_TCR_ThreadWord(UTCB_TCR_THREAD_WORD_MYSELF);
|
||||
return myself;
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::Ipc_server(Native_connection_state &cs,
|
||||
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg)
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
|
||||
:
|
||||
Ipc_istream(rcv_msg),
|
||||
Ipc_ostream(Native_capability(), snd_msg),
|
||||
Ipc_marshaller(snd_msg),
|
||||
Ipc_unmarshaller(rcv_msg),
|
||||
Native_capability(thread_get_my_global_id(), 0),
|
||||
_reply_needed(false), _rcv_cs(cs)
|
||||
{ }
|
||||
|
||||
{
|
||||
_read_offset = _write_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
Ipc_server::~Ipc_server() { }
|
||||
|
@ -32,8 +32,7 @@ namespace Genode {
|
||||
* Begin of message buffer layout
|
||||
*/
|
||||
Pistachio::L4_Fpage_t rcv_fpage;
|
||||
/* Send message */
|
||||
/* Recv message */
|
||||
|
||||
char buf[];
|
||||
|
||||
/**
|
||||
@ -42,9 +41,9 @@ namespace Genode {
|
||||
inline size_t size() const { return _size; };
|
||||
|
||||
/**
|
||||
* Return address of message buffer
|
||||
* Return pointer of message data payload
|
||||
*/
|
||||
inline void *addr() { return &_msg_start[0]; };
|
||||
inline void *data() { return &_msg_start[0]; };
|
||||
};
|
||||
|
||||
|
||||
|
@ -47,23 +47,6 @@ using namespace Pistachio;
|
||||
#endif
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_ostream **
|
||||
*****************/
|
||||
|
||||
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg) :
|
||||
Ipc_marshaller(&snd_msg->buf[0], snd_msg->size()),
|
||||
_snd_msg(snd_msg), _dst(dst)
|
||||
{
|
||||
_write_offset = sizeof(umword_t);
|
||||
IPCDEBUG("Ipc_ostream constructed.\n");
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_istream **
|
||||
*****************/
|
||||
|
||||
/**
|
||||
* Assert that we got 1 untyped word and 2 typed words
|
||||
*/
|
||||
@ -101,37 +84,21 @@ static inline void check_ipc_result(L4_MsgTag_t result, L4_Word_t error_code)
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg) :
|
||||
Ipc_unmarshaller(&rcv_msg->buf[0], rcv_msg->size()),
|
||||
Native_capability(Pistachio::L4_Myself(), 0),
|
||||
_rcv_msg(rcv_msg)
|
||||
{
|
||||
IPCDEBUG("Ipc_istream constructed.\n");
|
||||
_read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::~Ipc_istream() { }
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_client **
|
||||
****************/
|
||||
|
||||
void Ipc_client::_call()
|
||||
{
|
||||
IPCDEBUG("Starting to _call (with %u bytes of data).\n", _write_offset);
|
||||
L4_Msg_t msg;
|
||||
L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg->buf);
|
||||
L4_Word_t local_name = Ipc_ostream::_dst.local_name();
|
||||
|
||||
IPCDEBUG("Destination local_name = 0x%x\n", local_name);
|
||||
L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg.buf);
|
||||
L4_Word_t const local_name = _dst.local_name();
|
||||
|
||||
L4_MsgBuffer_t msgbuf;
|
||||
|
||||
/* prepare message buffer */
|
||||
L4_Clear (&msgbuf);
|
||||
L4_Append (&msgbuf, L4_StringItem (_rcv_msg->size(), _rcv_msg->buf));
|
||||
L4_Append (&msgbuf, L4_StringItem (_rcv_msg.size(), _rcv_msg.buf));
|
||||
L4_Accept(L4_UntypedWordsAcceptor);
|
||||
L4_Accept(L4_StringItemsAcceptor, &msgbuf);
|
||||
|
||||
@ -141,21 +108,20 @@ void Ipc_client::_call()
|
||||
L4_Append(&msg, sitem);
|
||||
L4_Load(&msg);
|
||||
|
||||
L4_MsgTag_t result = L4_Call(Ipc_ostream::_dst.dst());
|
||||
L4_MsgTag_t result = L4_Call(_dst.dst());
|
||||
|
||||
_write_offset = _read_offset = sizeof(umword_t);
|
||||
|
||||
check_ipc_result(result, L4_ErrorCode());
|
||||
|
||||
IPCDEBUG("Call done.\n");
|
||||
}
|
||||
|
||||
|
||||
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
|
||||
Msgbuf_base *rcv_msg, unsigned short) :
|
||||
Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0)
|
||||
Ipc_client::Ipc_client(Native_capability const &dst,
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg, unsigned short)
|
||||
:
|
||||
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
|
||||
{
|
||||
IPCDEBUG("Ipc_client constructed.\n");
|
||||
_read_offset = _write_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
@ -176,7 +142,7 @@ void Ipc_server::_prepare_next_reply_wait()
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_wait()
|
||||
void Ipc_server::wait()
|
||||
{
|
||||
/* wait for new server request */
|
||||
try {
|
||||
@ -184,14 +150,12 @@ void Ipc_server::_wait()
|
||||
L4_MsgTag_t result;
|
||||
L4_MsgBuffer_t msgbuf;
|
||||
|
||||
IPCDEBUG("_wait.\n");
|
||||
|
||||
do {
|
||||
|
||||
IPCDEBUG("_wait loop start (more than once means IpcError)\n");
|
||||
|
||||
L4_Clear (&msgbuf);
|
||||
L4_Append (&msgbuf, L4_StringItem (_rcv_msg->size(), _rcv_msg->buf));
|
||||
L4_Append (&msgbuf, L4_StringItem (_rcv_msg.size(), _rcv_msg.buf));
|
||||
L4_Accept(L4_UntypedWordsAcceptor);
|
||||
L4_Accept(L4_StringItemsAcceptor, &msgbuf);
|
||||
|
||||
@ -200,46 +164,38 @@ void Ipc_server::_wait()
|
||||
|
||||
} while (L4_IpcFailed(result));
|
||||
|
||||
IPCDEBUG("Got something from 0x%x.\n", _rcv_cs.caller);
|
||||
L4_Msg_t msg;
|
||||
|
||||
L4_Store(result, &msg);
|
||||
|
||||
check_ipc_result(result, L4_ErrorCode());
|
||||
|
||||
/* get the local name */
|
||||
L4_Word_t local_name = L4_Get(&msg,0);
|
||||
/* remember badge of invoked object */
|
||||
_badge = L4_Get(&msg, 0);
|
||||
|
||||
/*
|
||||
* Store local_name where badge() looks for it.
|
||||
* XXX Check this...
|
||||
*/
|
||||
*((long *)_rcv_msg->buf) = local_name;
|
||||
_read_offset = sizeof(umword_t);
|
||||
|
||||
IPCDEBUG("_wait successful\n");
|
||||
|
||||
} catch (Blocking_canceled) { }
|
||||
|
||||
/* define destination of next reply */
|
||||
Ipc_ostream::_dst = Native_capability(_rcv_cs.caller, badge());
|
||||
_caller = Native_capability(_rcv_cs.caller, badge());
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply()
|
||||
void Ipc_server::reply()
|
||||
{
|
||||
L4_Msg_t msg;
|
||||
L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg->buf);
|
||||
L4_Word_t local_name = Ipc_ostream::_dst.local_name();
|
||||
L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg.buf);
|
||||
L4_Word_t const local_name = _caller.local_name();
|
||||
|
||||
L4_Clear(&msg);
|
||||
L4_Append(&msg, local_name);
|
||||
L4_Append(&msg, sitem);
|
||||
L4_Load(&msg);
|
||||
|
||||
L4_MsgTag_t result = L4_Reply(Ipc_ostream::_dst.dst());
|
||||
L4_MsgTag_t result = L4_Reply(_caller.dst());
|
||||
if (L4_IpcFailed(result))
|
||||
PERR("ipc error in _reply, ignored");
|
||||
|
||||
@ -247,17 +203,14 @@ void Ipc_server::_reply()
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply_wait()
|
||||
void Ipc_server::reply_wait()
|
||||
{
|
||||
IPCDEBUG("Starting to _reply_wait. (with %u bytes of data)\n",
|
||||
_reply_needed ? _write_offset : 0);
|
||||
|
||||
if (_reply_needed) {
|
||||
|
||||
/* prepare massage */
|
||||
L4_Msg_t msg;
|
||||
L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg->buf);
|
||||
L4_Word_t local_name = Ipc_ostream::_dst.local_name();
|
||||
L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg.buf);
|
||||
L4_Word_t const local_name = _caller.local_name();
|
||||
|
||||
L4_Clear(&msg);
|
||||
L4_Append(&msg, local_name);
|
||||
@ -267,13 +220,12 @@ void Ipc_server::_reply_wait()
|
||||
/* Prepare message buffer */
|
||||
L4_MsgBuffer_t msgbuf;
|
||||
L4_Clear(&msgbuf);
|
||||
L4_Append(&msgbuf, L4_StringItem (_rcv_msg->size(), _rcv_msg->buf));
|
||||
L4_Append(&msgbuf, L4_StringItem (_rcv_msg.size(), _rcv_msg.buf));
|
||||
L4_Accept(L4_UntypedWordsAcceptor);
|
||||
L4_Accept(L4_StringItemsAcceptor, &msgbuf);
|
||||
|
||||
L4_MsgTag_t result = L4_Ipc(Ipc_ostream::_dst.dst(), L4_anythread,
|
||||
L4_MsgTag_t result = L4_Ipc(_caller.dst(), L4_anythread,
|
||||
L4_Timeouts(L4_ZeroTime, L4_Never), &_rcv_cs.caller);
|
||||
IPCDEBUG("Got something from 0x%x.\n", L4_ThreadNo(L4_GlobalId(_rcv_cs.caller)));
|
||||
|
||||
/* error handling - check whether send or receive failed */
|
||||
if (L4_IpcFailed(result)) {
|
||||
@ -283,7 +235,7 @@ void Ipc_server::_reply_wait()
|
||||
|
||||
PERR("IPC %s error %02lx, offset %08lx -> _wait() instead.",
|
||||
phase ? "receive" : "send", error, errcode >> 4);
|
||||
_wait();
|
||||
wait();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -298,36 +250,32 @@ void Ipc_server::_reply_wait()
|
||||
* the error to the user.
|
||||
*/
|
||||
IPCDEBUG("Bad IPC content -> _wait() instead.\n");
|
||||
_wait();
|
||||
wait();
|
||||
return;
|
||||
}
|
||||
|
||||
/* get the local name */
|
||||
local_name = L4_Get(&msg, 0);
|
||||
|
||||
/*
|
||||
* Store local_name where badge() looks for it.
|
||||
* XXX Check this...
|
||||
*/
|
||||
*((long *)_rcv_msg->buf) = local_name;
|
||||
IPCDEBUG("local_name = 0x%lx\n", badge());
|
||||
/* remember badge of invoked object */
|
||||
_badge = L4_Get(&msg, 0);
|
||||
|
||||
/* define destination of next reply */
|
||||
Ipc_ostream::_dst = Native_capability(_rcv_cs.caller, badge());
|
||||
_caller = Native_capability(_rcv_cs.caller, badge());
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
|
||||
} else
|
||||
_wait();
|
||||
wait();
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::Ipc_server(Native_connection_state &cs,
|
||||
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg) :
|
||||
Ipc_istream(rcv_msg),
|
||||
Ipc_ostream(Native_capability(), snd_msg),
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
|
||||
:
|
||||
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
|
||||
Native_capability(Pistachio::L4_Myself(), 0),
|
||||
_reply_needed(false), _rcv_cs(cs)
|
||||
{ }
|
||||
{
|
||||
_read_offset = _write_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_server::~Ipc_server() { }
|
||||
|
@ -121,8 +121,7 @@ static seL4_MessageInfo_t new_seL4_message(Msgbuf_base &msg,
|
||||
/**
|
||||
* Convert seL4 message into Genode::Msgbuf_base
|
||||
*/
|
||||
static void decode_seL4_message(umword_t badge,
|
||||
seL4_MessageInfo_t const &msg_info,
|
||||
static void decode_seL4_message(seL4_MessageInfo_t const &msg_info,
|
||||
Msgbuf_base &dst_msg)
|
||||
{
|
||||
/*
|
||||
@ -249,11 +248,6 @@ static void decode_seL4_message(umword_t badge,
|
||||
umword_t *dst = (umword_t *)dst_msg.data();
|
||||
for (size_t i = 0; i < seL4_MessageInfo_get_length(msg_info); i++)
|
||||
*dst++ = seL4_GetMR(MR_IDX_DATA + i);
|
||||
|
||||
/*
|
||||
* Store RPC object key of invoked object to be picked up by server.cc
|
||||
*/
|
||||
*(long *)dst_msg.data() = badge;
|
||||
}
|
||||
|
||||
|
||||
@ -261,54 +255,25 @@ static void decode_seL4_message(umword_t badge,
|
||||
** IPC marshalling support **
|
||||
*****************************/
|
||||
|
||||
void Ipc_ostream::_marshal_capability(Native_capability const &cap)
|
||||
void Ipc_marshaller::insert(Native_capability const &cap)
|
||||
{
|
||||
_snd_msg->append_cap(cap);
|
||||
_snd_msg.append_cap(cap);
|
||||
}
|
||||
|
||||
|
||||
void Ipc_istream::_unmarshal_capability(Native_capability &cap)
|
||||
void Ipc_unmarshaller::extract(Native_capability &cap)
|
||||
{
|
||||
cap = _rcv_msg->extract_cap();
|
||||
cap = _rcv_msg.extract_cap();
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_ostream **
|
||||
*****************/
|
||||
|
||||
Ipc_ostream::Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg)
|
||||
:
|
||||
Ipc_marshaller((char *)snd_msg->data(), snd_msg->size()),
|
||||
_snd_msg(snd_msg), _dst(dst)
|
||||
{
|
||||
_write_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Ipc_istream **
|
||||
*****************/
|
||||
|
||||
Ipc_istream::Ipc_istream(Msgbuf_base *rcv_msg)
|
||||
:
|
||||
Ipc_unmarshaller((char *)rcv_msg->data(), rcv_msg->size()),
|
||||
_rcv_msg(rcv_msg)
|
||||
{
|
||||
_read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_istream::~Ipc_istream() { }
|
||||
|
||||
|
||||
/****************
|
||||
** Ipc_client **
|
||||
****************/
|
||||
|
||||
void Ipc_client::_call()
|
||||
{
|
||||
if (!Ipc_ostream::_dst.valid()) {
|
||||
if (!_dst.valid()) {
|
||||
PERR("Trying to invoke an invalid capability, stop.");
|
||||
kernel_debugger_panic("IPC destination is invalid");
|
||||
}
|
||||
@ -317,23 +282,27 @@ void Ipc_client::_call()
|
||||
rcv_sel() = Capability_space::alloc_rcv_sel();
|
||||
|
||||
seL4_MessageInfo_t const request_msg_info =
|
||||
new_seL4_message(*_snd_msg, _write_offset);
|
||||
new_seL4_message(_snd_msg, _write_offset);
|
||||
|
||||
unsigned const dst_sel = Capability_space::ipc_cap_data(_dst).sel.value();
|
||||
|
||||
seL4_MessageInfo_t const reply_msg_info =
|
||||
seL4_Call(dst_sel, request_msg_info);
|
||||
|
||||
decode_seL4_message(0, reply_msg_info, *_rcv_msg);
|
||||
decode_seL4_message(reply_msg_info, _rcv_msg);
|
||||
|
||||
_write_offset = _read_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
Ipc_client::Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
|
||||
Msgbuf_base *rcv_msg, unsigned short)
|
||||
: Ipc_istream(rcv_msg), Ipc_ostream(srv, snd_msg), _result(0)
|
||||
{ }
|
||||
Ipc_client::Ipc_client(Native_capability const &dst,
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
|
||||
unsigned short)
|
||||
:
|
||||
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _result(0), _dst(dst)
|
||||
{
|
||||
_read_offset = _write_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
@ -351,46 +320,45 @@ void Ipc_server::_prepare_next_reply_wait()
|
||||
/* receive buffer offset */
|
||||
_read_offset = sizeof(umword_t);
|
||||
|
||||
_rcv_msg->reset_read_cap_index();
|
||||
_snd_msg->reset_caps();
|
||||
_rcv_msg.reset_read_cap_index();
|
||||
_snd_msg.reset_caps();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_wait()
|
||||
void Ipc_server::wait()
|
||||
{
|
||||
seL4_Word badge = Rpc_obj_key::INVALID;
|
||||
seL4_MessageInfo_t const msg_info =
|
||||
seL4_Recv(Thread_base::myself()->native_thread().ep_sel, &badge);
|
||||
seL4_Recv(Thread_base::myself()->native_thread().ep_sel,
|
||||
(seL4_Word *)&_badge);
|
||||
|
||||
decode_seL4_message(badge, msg_info, *_rcv_msg);
|
||||
decode_seL4_message(msg_info, _rcv_msg);
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply()
|
||||
void Ipc_server::reply()
|
||||
{
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
|
||||
void Ipc_server::_reply_wait()
|
||||
void Ipc_server::reply_wait()
|
||||
{
|
||||
if (!_reply_needed) {
|
||||
|
||||
_wait();
|
||||
wait();
|
||||
|
||||
} else {
|
||||
|
||||
seL4_Word badge = Rpc_obj_key::INVALID;
|
||||
seL4_MessageInfo_t const reply_msg_info =
|
||||
new_seL4_message(*_snd_msg, _write_offset);
|
||||
new_seL4_message(_snd_msg, _write_offset);
|
||||
|
||||
seL4_MessageInfo_t const request_msg_info =
|
||||
seL4_ReplyRecv(Thread_base::myself()->native_thread().ep_sel,
|
||||
reply_msg_info, &badge);
|
||||
reply_msg_info, (seL4_Word *)&_badge);
|
||||
|
||||
decode_seL4_message(badge, request_msg_info, *_rcv_msg);
|
||||
decode_seL4_message(request_msg_info, _rcv_msg);
|
||||
}
|
||||
|
||||
_prepare_next_reply_wait();
|
||||
@ -398,13 +366,15 @@ void Ipc_server::_reply_wait()
|
||||
|
||||
|
||||
Ipc_server::Ipc_server(Native_connection_state &cs,
|
||||
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg)
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
|
||||
:
|
||||
Ipc_istream(rcv_msg), Ipc_ostream(Native_capability(), snd_msg),
|
||||
Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
|
||||
_reply_needed(false), _rcv_cs(cs)
|
||||
{
|
||||
*static_cast<Native_capability *>(this) =
|
||||
Native_capability(Capability_space::create_ep_cap(*Thread_base::myself()));
|
||||
|
||||
_read_offset = _write_offset = sizeof(umword_t);
|
||||
}
|
||||
|
||||
|
||||
|
@ -46,7 +46,7 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
|
||||
void Rpc_entrypoint::entry()
|
||||
{
|
||||
Native_connection_state cs;
|
||||
Ipc_server srv(cs, &_snd_buf, &_rcv_buf);
|
||||
Ipc_server srv(cs, _snd_buf, _rcv_buf);
|
||||
_ipc_server = &srv;
|
||||
_cap = srv;
|
||||
_cap_valid.unlock();
|
||||
@ -64,7 +64,8 @@ void Rpc_entrypoint::entry()
|
||||
|
||||
int opcode = 0;
|
||||
|
||||
srv >> IPC_REPLY_WAIT >> opcode;
|
||||
srv.reply_wait();
|
||||
srv.extract(opcode);
|
||||
|
||||
/* set default return value */
|
||||
srv.ret(Ipc_client::ERR_INVALID_OBJECT);
|
||||
@ -81,7 +82,7 @@ void Rpc_entrypoint::entry()
|
||||
}
|
||||
|
||||
/* answer exit call, thereby wake up '~Rpc_entrypoint' */
|
||||
srv << IPC_REPLY;
|
||||
srv.reply();
|
||||
|
||||
/* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
|
||||
_delay_exit.lock();
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include <util/misc_math.h>
|
||||
#include <util/string.h>
|
||||
#include <util/noncopyable.h>
|
||||
#include <base/exception.h>
|
||||
#include <base/capability.h>
|
||||
#include <base/ipc_msgbuf.h>
|
||||
@ -33,16 +34,9 @@ namespace Genode {
|
||||
|
||||
class Native_connection_state;
|
||||
|
||||
enum Ipc_istream_wait { IPC_WAIT };
|
||||
enum Ipc_client_call { IPC_CALL };
|
||||
enum Ipc_server_reply { IPC_REPLY };
|
||||
enum Ipc_server_reply_wait { IPC_REPLY_WAIT };
|
||||
|
||||
class Ipc_error;
|
||||
class Ipc_marshaller;
|
||||
class Ipc_unmarshaller;
|
||||
class Ipc_ostream;
|
||||
class Ipc_istream;
|
||||
class Ipc_client;
|
||||
class Ipc_server;
|
||||
}
|
||||
@ -61,71 +55,68 @@ class Genode::Ipc_marshaller
|
||||
{
|
||||
protected:
|
||||
|
||||
char *_sndbuf;
|
||||
size_t _sndbuf_size;
|
||||
unsigned _write_offset;
|
||||
Msgbuf_base &_snd_msg;
|
||||
unsigned _write_offset = 0;
|
||||
|
||||
protected:
|
||||
private:
|
||||
|
||||
char *_snd_buf = (char *)_snd_msg.data();
|
||||
size_t const _snd_buf_size = _snd_msg.size();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Write value to send buffer
|
||||
*/
|
||||
template <typename T>
|
||||
void _write_to_buf(T const &value)
|
||||
void insert(T const &value)
|
||||
{
|
||||
/* check buffer range */
|
||||
if (_write_offset + sizeof(T) >= _sndbuf_size) return;
|
||||
if (_write_offset + sizeof(T) >= _snd_buf_size) return;
|
||||
|
||||
/* write integer to buffer */
|
||||
*reinterpret_cast<T *>(&_sndbuf[_write_offset]) = value;
|
||||
*reinterpret_cast<T *>(&_snd_buf[_write_offset]) = value;
|
||||
|
||||
/* increment write pointer to next dword-aligned value */
|
||||
_write_offset += align_natural(sizeof(T));
|
||||
}
|
||||
|
||||
template <size_t MAX_BUFFER_SIZE>
|
||||
void insert(Rpc_in_buffer<MAX_BUFFER_SIZE> const &b)
|
||||
{
|
||||
size_t const size = b.size();
|
||||
insert(size);
|
||||
insert(b.base(), size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write bytes to send buffer
|
||||
*/
|
||||
void _write_to_buf(char const *src_addr, unsigned num_bytes)
|
||||
void insert(char const *src_addr, unsigned num_bytes)
|
||||
{
|
||||
/* check buffer range */
|
||||
if (_write_offset + num_bytes >= _sndbuf_size) return;
|
||||
if (_write_offset + num_bytes >= _snd_buf_size) return;
|
||||
|
||||
/* copy buffer */
|
||||
memcpy(&_sndbuf[_write_offset], src_addr, num_bytes);
|
||||
memcpy(&_snd_buf[_write_offset], src_addr, num_bytes);
|
||||
|
||||
/* increment write pointer to next dword-aligned value */
|
||||
_write_offset += align_natural(num_bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 'Rpc_in_buffer' to send buffer
|
||||
* Insert capability to message buffer
|
||||
*/
|
||||
void _write_buffer_to_buf(Rpc_in_buffer_base const &b)
|
||||
void insert(Native_capability const &cap);
|
||||
|
||||
template <typename IT>
|
||||
void insert(Capability<IT> const &typed_cap)
|
||||
{
|
||||
size_t size = b.size();
|
||||
_write_to_buf(size);
|
||||
_write_to_buf(b.base(), size);
|
||||
Native_capability untyped_cap = typed_cap;
|
||||
insert(untyped_cap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write array to send buffer
|
||||
*/
|
||||
template <typename T, size_t N>
|
||||
void _write_to_buf(T const (&array)[N])
|
||||
{
|
||||
/* check buffer range */
|
||||
if (_write_offset + sizeof(array) >= _sndbuf_size)
|
||||
PERR("send buffer overrun");
|
||||
|
||||
memcpy(&_sndbuf[_write_offset], array, sizeof(array));
|
||||
_write_offset += align_natural(sizeof(array));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Ipc_marshaller(char *sndbuf, size_t sndbuf_size)
|
||||
: _sndbuf(sndbuf), _sndbuf_size(sndbuf_size), _write_offset(0) { }
|
||||
Ipc_marshaller(Msgbuf_base &snd_msg) : _snd_msg(snd_msg) { }
|
||||
};
|
||||
|
||||
|
||||
@ -136,36 +127,33 @@ class Genode::Ipc_unmarshaller
|
||||
{
|
||||
protected:
|
||||
|
||||
char *_rcvbuf;
|
||||
size_t _rcvbuf_size;
|
||||
unsigned _read_offset;
|
||||
Msgbuf_base &_rcv_msg;
|
||||
unsigned _read_offset = 0;
|
||||
|
||||
protected:
|
||||
private:
|
||||
|
||||
/**
|
||||
* Read value of type T from buffer
|
||||
*/
|
||||
template <typename T>
|
||||
void _read_from_buf(T &value)
|
||||
char *_rcv_buf = (char *)_rcv_msg.data();
|
||||
size_t const _rcv_buf_size = _rcv_msg.size();
|
||||
|
||||
public:
|
||||
|
||||
template <typename IT>
|
||||
void extract(Capability<IT> &typed_cap)
|
||||
{
|
||||
/* check receive buffer range */
|
||||
if (_read_offset + sizeof(T) >= _rcvbuf_size) return;
|
||||
|
||||
/* return value from receive buffer */
|
||||
value = *reinterpret_cast<T *>(&_rcvbuf[_read_offset]);
|
||||
|
||||
/* increment read pointer to next dword-aligned value */
|
||||
_read_offset += align_natural(sizeof(T));
|
||||
Native_capability untyped_cap;
|
||||
extract(untyped_cap);
|
||||
typed_cap = reinterpret_cap_cast<IT>(untyped_cap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 'Rpc_in_buffer' from receive buffer
|
||||
*/
|
||||
void _read_bytebuf_from_buf(Rpc_in_buffer_base &b)
|
||||
template <size_t SIZE>
|
||||
void extract(Rpc_in_buffer<SIZE> &b)
|
||||
{
|
||||
size_t size = 0;
|
||||
_read_from_buf(size);
|
||||
b = Rpc_in_buffer_base(0, 0);
|
||||
extract(size);
|
||||
b = Rpc_in_buffer<SIZE>(0, 0);
|
||||
|
||||
/*
|
||||
* Check receive buffer range
|
||||
@ -173,241 +161,62 @@ class Genode::Ipc_unmarshaller
|
||||
* Note: The addr of the Rpc_in_buffer_base is a null pointer when this
|
||||
* condition triggers.
|
||||
*/
|
||||
if (_read_offset + size >= _rcvbuf_size) {
|
||||
if (_read_offset + size >= _rcv_buf_size) {
|
||||
PERR("message buffer overrun");
|
||||
return;
|
||||
}
|
||||
|
||||
b = Rpc_in_buffer_base(&_rcvbuf[_read_offset], size);
|
||||
b = Rpc_in_buffer<SIZE>(&_rcv_buf[_read_offset], size);
|
||||
_read_offset += align_natural(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read array from receive buffer
|
||||
*/
|
||||
template <typename T, size_t N>
|
||||
void _read_from_buf(T (&array)[N])
|
||||
{
|
||||
if (_read_offset + sizeof(array) >= _rcvbuf_size) {
|
||||
PERR("receive buffer overrun");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(array, &_rcvbuf[_read_offset], sizeof(array));
|
||||
_read_offset += align_natural(sizeof(array));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read long value at specified byte index of receive buffer
|
||||
*/
|
||||
long _long_at_idx(int idx) { return *(long *)(&_rcvbuf[idx]); }
|
||||
|
||||
public:
|
||||
|
||||
Ipc_unmarshaller(char *rcvbuf, size_t rcvbuf_size)
|
||||
: _rcvbuf(rcvbuf), _rcvbuf_size(rcvbuf_size), _read_offset(0) { }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Stream for sending information via a capability to an endpoint
|
||||
*/
|
||||
class Genode::Ipc_ostream : public Ipc_marshaller
|
||||
{
|
||||
protected:
|
||||
|
||||
Msgbuf_base *_snd_msg; /* send message buffer */
|
||||
Native_capability _dst;
|
||||
|
||||
/**
|
||||
* Reset marshaller and write badge at the beginning of the message
|
||||
*/
|
||||
void _prepare_next_send();
|
||||
|
||||
/**
|
||||
* Insert capability to message buffer
|
||||
*/
|
||||
void _marshal_capability(Native_capability const &cap);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg);
|
||||
|
||||
/**
|
||||
* Return true if Ipc_ostream is ready for send
|
||||
*/
|
||||
bool ready_for_send() const { return _dst.valid(); }
|
||||
|
||||
/**
|
||||
* Insert value into send buffer
|
||||
*/
|
||||
template <typename T>
|
||||
Ipc_ostream &operator << (T const &value)
|
||||
{
|
||||
_write_to_buf(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert byte buffer to send buffer
|
||||
*/
|
||||
Ipc_ostream &operator << (Rpc_in_buffer_base const &b)
|
||||
{
|
||||
_write_buffer_to_buf(b);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert capability to send buffer
|
||||
*/
|
||||
Ipc_ostream &operator << (Native_capability const &cap)
|
||||
{
|
||||
_marshal_capability(cap);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert typed capability to send buffer
|
||||
*/
|
||||
template <typename IT>
|
||||
Ipc_ostream &operator << (Capability<IT> const &typed_cap)
|
||||
{
|
||||
_marshal_capability(typed_cap);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return current 'IPC_SEND' destination
|
||||
*
|
||||
* This method is typically needed by a server than sends replies
|
||||
* in a different order as the incoming calls.
|
||||
*/
|
||||
Native_capability dst() const { return _dst; }
|
||||
|
||||
/**
|
||||
* Set destination for the next 'IPC_SEND'
|
||||
*/
|
||||
void dst(Native_capability const &dst) { _dst = dst; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Stream for receiving information
|
||||
*/
|
||||
class Genode::Ipc_istream : public Ipc_unmarshaller, public Native_capability
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* Prevent 'Ipc_istream' objects from being copied
|
||||
*
|
||||
* Copying an 'Ipc_istream' object would result in a duplicated
|
||||
* (and possibly inconsistent) connection state both the original
|
||||
* and the copied object.
|
||||
*/
|
||||
Ipc_istream(const Ipc_istream &);
|
||||
|
||||
protected:
|
||||
|
||||
Msgbuf_base *_rcv_msg;
|
||||
|
||||
/**
|
||||
* Obtain capability from message buffer
|
||||
*/
|
||||
void _unmarshal_capability(Native_capability &cap);
|
||||
|
||||
protected:
|
||||
void extract(Native_capability &cap);
|
||||
|
||||
/**
|
||||
* Reset unmarshaller
|
||||
* Read value of type T from buffer
|
||||
*/
|
||||
void _prepare_next_receive();
|
||||
template <typename T>
|
||||
void extract(T &value)
|
||||
{
|
||||
/* check receive buffer range */
|
||||
if (_read_offset + sizeof(T) >= _rcv_buf_size) return;
|
||||
|
||||
/* return value from receive buffer */
|
||||
value = *reinterpret_cast<T *>(&_rcv_buf[_read_offset]);
|
||||
|
||||
/* increment read pointer to next dword-aligned value */
|
||||
_read_offset += align_natural(sizeof(T));
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
explicit Ipc_istream(Msgbuf_base *rcv_msg);
|
||||
|
||||
~Ipc_istream();
|
||||
|
||||
/**
|
||||
* Read badge that was supplied with the message
|
||||
*/
|
||||
long badge() { return _long_at_idx(0); }
|
||||
|
||||
/**
|
||||
* Read values from receive buffer
|
||||
*/
|
||||
template <typename T>
|
||||
Ipc_istream &operator >> (T &value)
|
||||
{
|
||||
_read_from_buf(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read byte buffer from receive buffer
|
||||
*/
|
||||
Ipc_istream &operator >> (Rpc_in_buffer_base &b)
|
||||
{
|
||||
_read_bytebuf_from_buf(b);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read byte buffer from receive buffer
|
||||
*/
|
||||
template <size_t MAX_BUFFER_SIZE>
|
||||
Ipc_istream &operator >> (Rpc_in_buffer<MAX_BUFFER_SIZE> &b)
|
||||
{
|
||||
_read_bytebuf_from_buf(b);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read capability from receive buffer
|
||||
*/
|
||||
Ipc_istream &operator >> (Native_capability &cap)
|
||||
{
|
||||
_unmarshal_capability(cap);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read typed capability from receive buffer
|
||||
*/
|
||||
template <typename IT>
|
||||
Ipc_istream &operator >> (Capability<IT> &typed_cap)
|
||||
{
|
||||
_unmarshal_capability(typed_cap);
|
||||
return *this;
|
||||
}
|
||||
Ipc_unmarshaller(Msgbuf_base &rcv_msg) : _rcv_msg(rcv_msg) { }
|
||||
};
|
||||
|
||||
|
||||
class Genode::Ipc_client: public Ipc_istream, public Ipc_ostream
|
||||
class Genode::Ipc_client : public Ipc_marshaller, public Ipc_unmarshaller,
|
||||
public Noncopyable
|
||||
{
|
||||
protected:
|
||||
|
||||
int _result; /* result of most recent call */
|
||||
int _result = 0; /* result of most recent call */
|
||||
|
||||
void _prepare_next_call();
|
||||
|
||||
/**
|
||||
* Send RPC message and wait for result
|
||||
*/
|
||||
void _call();
|
||||
Native_capability _dst;
|
||||
|
||||
/**
|
||||
* Set return value if call to server failed
|
||||
*/
|
||||
void ret(int retval)
|
||||
{
|
||||
*reinterpret_cast<int *>(&_rcvbuf[sizeof(umword_t)]) = retval;
|
||||
reinterpret_cast<umword_t *>(_rcv_msg.data())[1] = retval;
|
||||
}
|
||||
|
||||
void _call();
|
||||
|
||||
public:
|
||||
|
||||
enum { ERR_INVALID_OBJECT = -70000, };
|
||||
@ -415,119 +224,41 @@ class Genode::Ipc_client: public Ipc_istream, public Ipc_ostream
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg,
|
||||
Msgbuf_base *rcv_msg, unsigned short rcv_caps = ~0);
|
||||
Ipc_client(Native_capability const &dst,
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
|
||||
unsigned short rcv_caps = ~0);
|
||||
|
||||
/**
|
||||
* Operator that issues an IPC call
|
||||
* Send RPC message and wait for result
|
||||
*
|
||||
* \throw Ipc_error
|
||||
* \throw Blocking_canceled
|
||||
*/
|
||||
Ipc_client &operator << (Ipc_client_call)
|
||||
void call()
|
||||
{
|
||||
_call();
|
||||
_read_from_buf(_result);
|
||||
extract(_result);
|
||||
if (_result == ERR_INVALID_OBJECT)
|
||||
throw Ipc_error();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Ipc_client &operator << (T const &value)
|
||||
{
|
||||
_write_to_buf(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Ipc_client &operator << (Rpc_in_buffer_base const &b)
|
||||
{
|
||||
_write_buffer_to_buf(b);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t MAX_BUFFER_SIZE>
|
||||
Ipc_client &operator << (Rpc_in_buffer<MAX_BUFFER_SIZE> const &b)
|
||||
{
|
||||
_write_buffer_to_buf(b);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Ipc_client &operator << (Native_capability const &cap)
|
||||
{
|
||||
_marshal_capability(cap);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename IT>
|
||||
Ipc_client &operator << (Capability<IT> const &typed_cap)
|
||||
{
|
||||
_marshal_capability(typed_cap);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Ipc_client &operator >> (Native_capability &cap)
|
||||
{
|
||||
_unmarshal_capability(cap);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename IT>
|
||||
Ipc_client &operator >> (Capability<IT> &typed_cap)
|
||||
{
|
||||
_unmarshal_capability(typed_cap);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Ipc_client &operator >> (T &value)
|
||||
{
|
||||
_read_from_buf(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Ipc_client &operator >> (Rpc_in_buffer_base &b)
|
||||
{
|
||||
_read_bytebuf_from_buf(b);
|
||||
return *this;
|
||||
}
|
||||
|
||||
int result() const { return _result; }
|
||||
};
|
||||
|
||||
|
||||
class Genode::Ipc_server : public Ipc_istream, public Ipc_ostream
|
||||
class Genode::Ipc_server : public Ipc_marshaller, public Ipc_unmarshaller,
|
||||
public Noncopyable, public Native_capability
|
||||
{
|
||||
protected:
|
||||
|
||||
bool _reply_needed; /* false for the first reply_wait */
|
||||
|
||||
Native_capability _caller;
|
||||
|
||||
Native_connection_state &_rcv_cs;
|
||||
|
||||
void _prepare_next_reply_wait();
|
||||
|
||||
/**
|
||||
* Wait for incoming call
|
||||
*
|
||||
* In constrast to 'Ipc_istream::_wait()', this method stores the
|
||||
* next reply destination from into 'dst' of the 'Ipc_ostream'.
|
||||
*/
|
||||
void _wait();
|
||||
|
||||
/**
|
||||
* Send reply to destination
|
||||
*
|
||||
* In contrast to 'Ipc_ostream::_send()', this method prepares
|
||||
* the 'Ipc_server' to send another subsequent reply without the
|
||||
* calling '_wait()' in between. This is needed when a server
|
||||
* answers calls out of order.
|
||||
*/
|
||||
void _reply();
|
||||
|
||||
/**
|
||||
* Send result of previous RPC request and wait for new one
|
||||
*/
|
||||
void _reply_wait();
|
||||
unsigned long _badge;
|
||||
|
||||
public:
|
||||
|
||||
@ -535,81 +266,48 @@ class Genode::Ipc_server : public Ipc_istream, public Ipc_ostream
|
||||
* Constructor
|
||||
*/
|
||||
Ipc_server(Native_connection_state &,
|
||||
Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg);
|
||||
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg);
|
||||
|
||||
~Ipc_server();
|
||||
|
||||
/**
|
||||
* Wait for incoming call
|
||||
*/
|
||||
void wait();
|
||||
|
||||
/**
|
||||
* Send reply to destination
|
||||
*/
|
||||
void reply();
|
||||
|
||||
/**
|
||||
* Send result of previous RPC request and wait for new one
|
||||
*/
|
||||
void reply_wait();
|
||||
|
||||
/**
|
||||
* Set return value of server call
|
||||
*/
|
||||
void ret(int retval)
|
||||
{
|
||||
*reinterpret_cast<int *>(&_sndbuf[sizeof(umword_t)]) = retval;
|
||||
reinterpret_cast<umword_t *>(_snd_msg.data())[1] = retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read badge that was supplied with the message
|
||||
*/
|
||||
unsigned long badge() const { return _badge; }
|
||||
|
||||
/**
|
||||
* Set reply destination
|
||||
*/
|
||||
void dst(Native_capability const &reply_dst)
|
||||
void caller(Native_capability const &caller)
|
||||
{
|
||||
Ipc_ostream::dst(reply_dst);
|
||||
_reply_needed = reply_dst.valid();
|
||||
_caller = caller;
|
||||
_reply_needed = caller.valid();
|
||||
}
|
||||
|
||||
using Ipc_ostream::dst;
|
||||
|
||||
/**
|
||||
* Block for an incoming message filling the receive buffer
|
||||
*/
|
||||
Ipc_server &operator >> (Ipc_istream_wait)
|
||||
{
|
||||
_wait();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue the sending of the message buffer
|
||||
*/
|
||||
Ipc_server &operator << (Ipc_server_reply)
|
||||
{
|
||||
_reply();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reply current request and wait for a new one
|
||||
*/
|
||||
Ipc_server &operator >> (Ipc_server_reply_wait)
|
||||
{
|
||||
_reply_wait();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write value to send buffer
|
||||
*
|
||||
* This operator is only used by test programs
|
||||
*/
|
||||
template <typename T>
|
||||
Ipc_server &operator << (T const &value)
|
||||
{
|
||||
_write_to_buf(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read value from receive buffer
|
||||
*
|
||||
* This operator should only be used by the server framework for
|
||||
* reading the function offset. The server-side processing of the
|
||||
* payload is done using 'Ipc_istream' and 'Ipc_ostream'.
|
||||
*/
|
||||
template <typename T>
|
||||
Ipc_server &operator >> (T &value)
|
||||
{
|
||||
_read_from_buf(value);
|
||||
return *this;
|
||||
}
|
||||
Native_capability caller() const { return _caller; }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__BASE__IPC_H_ */
|
||||
|
@ -61,7 +61,7 @@ namespace Genode {
|
||||
_marshal_args(Ipc_client &ipc_client, ATL &args) const
|
||||
{
|
||||
if (Trait::Rpc_direction<typename ATL::Head>::Type::IN)
|
||||
ipc_client << args.get();
|
||||
ipc_client.insert(args.get());
|
||||
|
||||
_marshal_args(ipc_client, args._2);
|
||||
}
|
||||
@ -73,7 +73,7 @@ namespace Genode {
|
||||
_unmarshal_result(Ipc_client &ipc_client, T &arg,
|
||||
Meta::Overload_selector<Rpc_arg_out>) const
|
||||
{
|
||||
ipc_client >> arg;
|
||||
ipc_client.extract(arg);
|
||||
}
|
||||
|
||||
|
||||
@ -124,14 +124,14 @@ namespace Genode {
|
||||
Msgbuf<CALL_MSG_SIZE + PROTOCOL_OVERHEAD> call_buf;
|
||||
Msgbuf<REPLY_MSG_SIZE + PROTOCOL_OVERHEAD> reply_buf;
|
||||
|
||||
Ipc_client ipc_client(*this, &call_buf, &reply_buf, CAP_BY_VALUE);
|
||||
Ipc_client ipc_client(*this, call_buf, reply_buf, CAP_BY_VALUE);
|
||||
|
||||
/* determine opcode of RPC function */
|
||||
typedef typename RPC_INTERFACE::Rpc_functions Rpc_functions;
|
||||
Rpc_opcode opcode = static_cast<int>(Meta::Index_of<Rpc_functions, IF>::Value);
|
||||
|
||||
/* marshal opcode and RPC input arguments */
|
||||
ipc_client << opcode;
|
||||
ipc_client.insert(opcode);
|
||||
_marshal_args(ipc_client, args);
|
||||
|
||||
{
|
||||
@ -139,7 +139,8 @@ namespace Genode {
|
||||
}
|
||||
|
||||
/* perform RPC, unmarshal return value */
|
||||
ipc_client << IPC_CALL >> ret;
|
||||
ipc_client.call();
|
||||
ipc_client.extract(ret);
|
||||
|
||||
{
|
||||
Trace::Rpc_returned trace_event(IF::name(), reply_buf);
|
||||
|
@ -60,26 +60,26 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
|
||||
protected:
|
||||
|
||||
template <typename ARG_LIST>
|
||||
void _read_args(Ipc_istream &is, ARG_LIST &args)
|
||||
void _read_args(Ipc_unmarshaller &msg, ARG_LIST &args)
|
||||
{
|
||||
if (Trait::Rpc_direction<typename ARG_LIST::Head>::Type::IN)
|
||||
is >> args._1;
|
||||
msg.extract(args._1);
|
||||
|
||||
_read_args(is, args._2);
|
||||
_read_args(msg, args._2);
|
||||
}
|
||||
|
||||
void _read_args(Ipc_istream &, Meta::Empty) { }
|
||||
void _read_args(Ipc_unmarshaller &, Meta::Empty) { }
|
||||
|
||||
template <typename ARG_LIST>
|
||||
void _write_results(Ipc_ostream &os, ARG_LIST &args)
|
||||
void _write_results(Ipc_marshaller &msg, ARG_LIST &args)
|
||||
{
|
||||
if (Trait::Rpc_direction<typename ARG_LIST::Head>::Type::OUT)
|
||||
os << args._1;
|
||||
msg.insert(args._1);
|
||||
|
||||
_write_results(os, args._2);
|
||||
_write_results(msg, args._2);
|
||||
}
|
||||
|
||||
void _write_results(Ipc_ostream &, Meta::Empty) { }
|
||||
void _write_results(Ipc_marshaller &, Meta::Empty) { }
|
||||
|
||||
template <typename RPC_FUNCTION, typename EXC_TL>
|
||||
Rpc_exception_code _do_serve(typename RPC_FUNCTION::Server_args &args,
|
||||
@ -104,7 +104,8 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
|
||||
}
|
||||
|
||||
template <typename RPC_FUNCTIONS_TO_CHECK>
|
||||
Rpc_exception_code _do_dispatch(Rpc_opcode opcode, Ipc_istream &is, Ipc_ostream &os,
|
||||
Rpc_exception_code _do_dispatch(Rpc_opcode opcode,
|
||||
Ipc_unmarshaller &in, Ipc_marshaller &out,
|
||||
Meta::Overload_selector<RPC_FUNCTIONS_TO_CHECK>)
|
||||
{
|
||||
using namespace Meta;
|
||||
@ -115,8 +116,8 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
|
||||
|
||||
typename This_rpc_function::Server_args args{};
|
||||
|
||||
/* read arguments from istream */
|
||||
_read_args(is, args);
|
||||
/* read arguments from incoming message */
|
||||
_read_args(in, args);
|
||||
|
||||
{
|
||||
Trace::Rpc_dispatch trace_event(This_rpc_function::name());
|
||||
@ -132,23 +133,23 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
|
||||
typename This_rpc_function::Ret_type ret { };
|
||||
Rpc_exception_code exc;
|
||||
exc = _do_serve(args, ret, Overload_selector<This_rpc_function, Exceptions>());
|
||||
os << ret;
|
||||
out.insert(ret);
|
||||
|
||||
{
|
||||
Trace::Rpc_reply trace_event(This_rpc_function::name());
|
||||
}
|
||||
|
||||
/* write results to ostream 'os' */
|
||||
_write_results(os, args);
|
||||
/* write results to outgoing message */
|
||||
_write_results(out, args);
|
||||
|
||||
return exc;
|
||||
}
|
||||
|
||||
typedef typename RPC_FUNCTIONS_TO_CHECK::Tail Tail;
|
||||
return _do_dispatch(opcode, is, os, Overload_selector<Tail>());
|
||||
return _do_dispatch(opcode, in, out, Overload_selector<Tail>());
|
||||
}
|
||||
|
||||
int _do_dispatch(int opcode, Ipc_istream &, Ipc_ostream &,
|
||||
int _do_dispatch(int opcode, Ipc_unmarshaller &, Ipc_marshaller &,
|
||||
Meta::Overload_selector<Meta::Empty>)
|
||||
{
|
||||
PERR("invalid opcode %d\n", opcode);
|
||||
@ -158,7 +159,8 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
|
||||
/**
|
||||
* Handle corner case of having an RPC interface with no RPC functions
|
||||
*/
|
||||
Rpc_exception_code _do_dispatch(int opcode, Ipc_istream &, Ipc_ostream &,
|
||||
Rpc_exception_code _do_dispatch(int opcode,
|
||||
Ipc_unmarshaller &, Ipc_marshaller &,
|
||||
Meta::Overload_selector<Meta::Type_list<> >)
|
||||
{
|
||||
return 0;
|
||||
@ -173,9 +175,10 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
|
||||
|
||||
public:
|
||||
|
||||
Rpc_exception_code dispatch(int opcode, Ipc_istream &is, Ipc_ostream &os)
|
||||
Rpc_exception_code dispatch(int opcode,
|
||||
Ipc_unmarshaller &in, Ipc_marshaller &out)
|
||||
{
|
||||
return _do_dispatch(opcode, is, os,
|
||||
return _do_dispatch(opcode, in, out,
|
||||
Meta::Overload_selector<Rpc_functions>());
|
||||
}
|
||||
};
|
||||
@ -191,10 +194,10 @@ class Genode::Rpc_object_base : public Object_pool<Rpc_object_base>::Entry
|
||||
* Interface to be implemented by a derived class
|
||||
*
|
||||
* \param op opcode of invoked method
|
||||
* \param is Ipc_input stream with method arguments
|
||||
* \param os Ipc_output stream for storing method results
|
||||
* \param in incoming message with method arguments
|
||||
* \param out outgoing message for storing method results
|
||||
*/
|
||||
virtual int dispatch(int op, Ipc_istream &is, Ipc_ostream &os) = 0;
|
||||
virtual int dispatch(int op, Ipc_unmarshaller &in, Ipc_marshaller &out) = 0;
|
||||
};
|
||||
|
||||
|
||||
@ -212,9 +215,9 @@ struct Genode::Rpc_object : Rpc_object_base, Rpc_dispatcher<RPC_INTERFACE, SERVE
|
||||
** Server-object interface **
|
||||
*****************************/
|
||||
|
||||
Rpc_exception_code dispatch(int opcode, Ipc_istream &is, Ipc_ostream &os)
|
||||
Rpc_exception_code dispatch(int opcode, Ipc_unmarshaller &in, Ipc_marshaller &out)
|
||||
{
|
||||
return Rpc_dispatcher<RPC_INTERFACE, SERVER>::dispatch(opcode, is, os);
|
||||
return Rpc_dispatcher<RPC_INTERFACE, SERVER>::dispatch(opcode, in, out);
|
||||
}
|
||||
|
||||
Capability<RPC_INTERFACE> const cap() const
|
||||
|
@ -19,16 +19,18 @@ using namespace Genode;
|
||||
/**
|
||||
* Marshalling of capabilities as plain data representation
|
||||
*/
|
||||
void Ipc_ostream::_marshal_capability(Native_capability const &cap)
|
||||
void Ipc_marshaller::insert(Native_capability const &cap)
|
||||
{
|
||||
_write_to_buf(cap);
|
||||
insert((char const *)&cap, sizeof(Native_capability));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unmarshalling of capabilities as plain data representation
|
||||
*/
|
||||
void Ipc_istream::_unmarshal_capability(Native_capability &cap)
|
||||
void Ipc_unmarshaller::extract(Native_capability &cap)
|
||||
{
|
||||
_read_from_buf(cap);
|
||||
struct Raw { char buf[sizeof(Native_capability)]; } raw;
|
||||
extract(raw);
|
||||
(Raw &)(cap) = raw;
|
||||
}
|
||||
|
@ -38,14 +38,14 @@ void Rpc_entrypoint::_block_until_cap_valid()
|
||||
|
||||
Untyped_capability Rpc_entrypoint::reply_dst()
|
||||
{
|
||||
return _ipc_server ? _ipc_server->dst() : Untyped_capability();
|
||||
return _ipc_server ? _ipc_server->caller() : Untyped_capability();
|
||||
}
|
||||
|
||||
|
||||
void Rpc_entrypoint::omit_reply()
|
||||
{
|
||||
/* set current destination to an invalid capability */
|
||||
if (_ipc_server) _ipc_server->dst(Untyped_capability());
|
||||
if (_ipc_server) _ipc_server->caller(Untyped_capability());
|
||||
}
|
||||
|
||||
|
||||
@ -55,15 +55,16 @@ void Rpc_entrypoint::reply_signal_info(Untyped_capability reply_cap,
|
||||
if (!_ipc_server) return;
|
||||
|
||||
/* backup reply capability of current request */
|
||||
Untyped_capability last_reply_cap = _ipc_server->dst();
|
||||
Untyped_capability last_reply_cap = _ipc_server->caller();
|
||||
|
||||
/* direct ipc server to the specified reply destination */
|
||||
_ipc_server->ret(0);
|
||||
_ipc_server->dst(reply_cap);
|
||||
*_ipc_server << Signal_source::Signal(imprint, cnt) << IPC_REPLY;
|
||||
_ipc_server->caller(reply_cap);
|
||||
_ipc_server->insert(Signal_source::Signal(imprint, cnt));
|
||||
_ipc_server->reply();
|
||||
|
||||
/* restore reply capability of the original request */
|
||||
_ipc_server->dst(last_reply_cap);
|
||||
_ipc_server->caller(last_reply_cap);
|
||||
}
|
||||
|
||||
|
||||
|
@ -48,7 +48,7 @@ void Rpc_entrypoint::entry()
|
||||
using Pool = Object_pool<Rpc_object_base>;
|
||||
|
||||
Native_connection_state cs;
|
||||
Ipc_server srv(cs, &_snd_buf, &_rcv_buf);
|
||||
Ipc_server srv(cs, _snd_buf, _rcv_buf);
|
||||
_ipc_server = &srv;
|
||||
_cap = srv;
|
||||
_cap_valid.unlock();
|
||||
@ -66,7 +66,8 @@ void Rpc_entrypoint::entry()
|
||||
|
||||
int opcode = 0;
|
||||
|
||||
srv >> IPC_REPLY_WAIT >> opcode;
|
||||
srv.reply_wait();
|
||||
srv.extract(opcode);
|
||||
|
||||
/* set default return value */
|
||||
srv.ret(Ipc_client::ERR_INVALID_OBJECT);
|
||||
@ -81,7 +82,7 @@ void Rpc_entrypoint::entry()
|
||||
}
|
||||
|
||||
/* answer exit call, thereby wake up '~Rpc_entrypoint' */
|
||||
srv << IPC_REPLY;
|
||||
srv.reply();
|
||||
|
||||
/* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
|
||||
_delay_exit.lock();
|
||||
|
@ -22,8 +22,9 @@ void Pager_object::wake_up()
|
||||
/* notify pager to wake up faulter */
|
||||
Msgbuf<16> snd, rcv;
|
||||
Native_capability pager = cap();
|
||||
Ipc_client ipc_client(pager, &snd, &rcv);
|
||||
ipc_client << this << IPC_CALL;
|
||||
Ipc_client ipc_client(pager, snd, rcv);
|
||||
ipc_client.insert(this);
|
||||
ipc_client.call();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user