diff --git a/repos/base-fiasco/include/base/ipc_msgbuf.h b/repos/base-fiasco/include/base/ipc_msgbuf.h
deleted file mode 100644
index acef59d106..0000000000
--- a/repos/base-fiasco/include/base/ipc_msgbuf.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * \brief Fiasco-specific layout of IPC message buffer
- * \author Norman Feske
- * \date 2006-06-14
- */
-
-/*
- * Copyright (C) 2006-2013 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
-#define _INCLUDE__BASE__IPC_MSGBUF_H_
-
-#include
-
-namespace Genode {
-
- class Ipc_marshaller;
-
- /**
- * IPC message buffer layout
- */
- class Msgbuf_base
- {
- private:
-
- size_t const _capacity;
-
- protected:
-
- size_t _data_size = 0;
-
- friend class Ipc_marshaller;
-
- Msgbuf_base(size_t capacity) : _capacity(capacity) { }
-
- struct Headroom { long space[4]; } _headroom;
-
- char buf[];
-
- public:
-
- template
- T &header()
- {
- static_assert(sizeof(T) <= sizeof(Headroom),
- "Header size exceeds message headroom");
- return *reinterpret_cast(buf - sizeof(T));
- }
-
- unsigned long &word(unsigned i)
- {
- return reinterpret_cast(buf)[i];
- }
-
- /**
- * Return size of message buffer
- */
- size_t capacity() const { return _capacity; };
-
- /**
- * Return pointer of message data payload
- */
- void *data() { return buf; };
- void const *data() const { return buf; };
-
- size_t data_size() const { return _data_size; }
- };
-
-
- /**
- * Instance of IPC message buffer with specified buffer size
- */
- template
- class Msgbuf : public Msgbuf_base
- {
- public:
-
- char buf[BUF_SIZE];
-
- Msgbuf() : Msgbuf_base(BUF_SIZE) { }
- };
-}
-
-#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
diff --git a/repos/base-fiasco/lib/mk/base-common.mk b/repos/base-fiasco/lib/mk/base-common.mk
index bb85cbe9cc..2920278b0e 100644
--- a/repos/base-fiasco/lib/mk/base-common.mk
+++ b/repos/base-fiasco/lib/mk/base-common.mk
@@ -7,7 +7,7 @@
LIBS += cxx startup
SRC_CC += cap_copy.cc
-SRC_CC += ipc/ipc.cc ipc/ipc_marshal_cap.cc
+SRC_CC += ipc/ipc.cc
SRC_CC += avl_tree/avl_tree.cc
SRC_CC += allocator/slab.cc
SRC_CC += allocator/allocator_avl.cc
diff --git a/repos/base-fiasco/src/base/ipc/ipc.cc b/repos/base-fiasco/src/base/ipc/ipc.cc
index 55e7e533c6..40e5ba0699 100644
--- a/repos/base-fiasco/src/base/ipc/ipc.cc
+++ b/repos/base-fiasco/src/base/ipc/ipc.cc
@@ -26,6 +26,8 @@ namespace Fiasco {
#include
}
+using namespace Genode;
+
class Msg_header
{
@@ -36,54 +38,90 @@ class Msg_header
Fiasco::l4_msgdope_t size_dope;
Fiasco::l4_msgdope_t send_dope;
+ public:
+
/*
- * First data word of message, used to transfer the local name of the
- * invoked object (when a client calls a server) or the exception code
- * (when the server replies). This data word is never fetched from
- * memory but transferred via the first short-IPC register. The
- * 'protocol_word' is needed as a spacer between the header fields
- * define above and the regular message payload..
+ * First two data words of message, used to transfer the local name of
+ * the invoked object (when a client calls a server) or the exception
+ * code (when the server replies), and the number of capability
+ * arguments. The kernel does not fetch these data words from memory
+ * but transfers them via the short-IPC registers.
*/
Fiasco::l4_umword_t protocol_word;
+ Fiasco::l4_umword_t num_caps;
+
+ private:
+
+ enum { MAX_CAPS_PER_MSG = Msgbuf_base::MAX_CAPS_PER_MSG };
+
+ Fiasco::l4_threadid_t _cap_tid [MAX_CAPS_PER_MSG];
+ unsigned long _cap_local_name [MAX_CAPS_PER_MSG];
+
+ size_t _num_msg_words(size_t num_data_words) const
+ {
+ size_t const caps_size = sizeof(_cap_tid) + sizeof(_cap_local_name);
+
+ /*
+ * Account for the transfer of the protocol word, capability count,
+ * and capability arguments in front of the payload.
+ */
+ return 2 + caps_size/sizeof(Fiasco::l4_umword_t) + num_data_words;
+ }
public:
void *msg_start() { return &rcv_fpage; }
/**
- * Define message size for sending
+ * Load header fields according to send-message buffer
*/
- void snd_size(Genode::size_t size)
+ void prepare_snd_msg(unsigned long protocol, Msgbuf_base const &snd_msg)
{
using namespace Fiasco;
- /* account for the transfer of the protocol word in front of the payload */
- Genode::size_t const snd_words = size/sizeof(l4_umword_t);
- send_dope = L4_IPC_DOPE(snd_words + 1, 0);
+ protocol_word = protocol;
+ num_caps = min((unsigned)MAX_CAPS_PER_MSG, snd_msg.used_caps());
+
+ size_t const snd_words = snd_msg.data_size()/sizeof(l4_umword_t);
+ send_dope = L4_IPC_DOPE(_num_msg_words(snd_words), 0);
+
+ /* reset _cap_tid and _cap_local_name */
+ for (unsigned i = 0; i < MAX_CAPS_PER_MSG; i++) {
+ _cap_tid[i] = L4_INVALID_ID;
+ _cap_local_name[i] = 0;
+ }
+
+ for (unsigned i = 0; i < num_caps; i++) {
+ Native_capability const &cap = snd_msg.cap(i);
+ _cap_tid[i] = cap.dst();
+ _cap_local_name[i] = cap.local_name();
+ }
}
/**
- * Define size of receive buffer
+ * Prepare header for receiving a message
*/
- void rcv_capacity(Genode::size_t capacity)
+ void prepare_rcv_msg(Msgbuf_base const &rcv_msg)
{
using namespace Fiasco;
- size_dope = L4_IPC_DOPE(capacity/sizeof(l4_umword_t), 0);
+ size_t const rcv_max_words = rcv_msg.capacity()/sizeof(l4_umword_t);
+
+ size_dope = L4_IPC_DOPE(_num_msg_words(rcv_max_words), 0);
}
- void *msg_type(Genode::size_t size)
+ /**
+ * Copy received capability arguments into receive message buffer
+ */
+ void extract_caps(Msgbuf_base &rcv_msg) const
{
- using namespace Fiasco;
-
- return size <= sizeof(l4_umword_t) ? L4_IPC_SHORT_MSG : msg_start();
+ for (unsigned i = 0; i < min((unsigned)MAX_CAPS_PER_MSG, num_caps); i++)
+ rcv_msg.insert(Native_capability(_cap_tid[i],
+ _cap_local_name[i]));
}
};
-using namespace Genode;
-
-
/****************
** IPC client **
****************/
@@ -95,156 +133,128 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
using namespace Fiasco;
Msg_header &snd_header = snd_msg.header();
- snd_header.snd_size(snd_msg.data_size());
+ snd_header.prepare_snd_msg(dst.local_name(), snd_msg);
Msg_header &rcv_header = rcv_msg.header();
- rcv_header.rcv_capacity(rcv_msg.capacity());
+ rcv_header.prepare_rcv_msg(rcv_msg);
l4_msgdope_t ipc_result;
- l4_umword_t exception_code = 0;
l4_ipc_call(dst.dst(),
- snd_header.msg_type(snd_msg.data_size()),
- dst.local_name(),
- snd_msg.word(0),
+ snd_header.msg_start(),
+ snd_header.protocol_word,
+ snd_header.num_caps,
rcv_header.msg_start(),
- &exception_code,
- &rcv_msg.word(0),
+ &rcv_header.protocol_word,
+ &rcv_header.num_caps,
L4_IPC_NEVER, &ipc_result);
+ rcv_header.extract_caps(rcv_msg);
+
if (L4_IPC_IS_ERROR(ipc_result)) {
if (L4_IPC_ERROR(ipc_result) == L4_IPC_RECANCELED)
throw Genode::Blocking_canceled();
- PERR("Ipc error %lx", L4_IPC_ERROR(ipc_result));
+ PERR("ipc_call error %lx", L4_IPC_ERROR(ipc_result));
throw Genode::Ipc_error();
}
- return Rpc_exception_code(exception_code);
+ return Rpc_exception_code(rcv_header.protocol_word);
}
/****************
- ** Ipc_server **
+ ** IPC server **
****************/
-void Ipc_server::_prepare_next_reply_wait()
-{
- _reply_needed = true;
- _read_offset = _write_offset = 0;
-}
-
-
-static umword_t wait(Native_connection_state &rcv_cs, Msgbuf_base &rcv_msg)
+void Genode::ipc_reply(Native_capability caller, Rpc_exception_code exc,
+ Msgbuf_base &snd_msg)
{
using namespace Fiasco;
- l4_msgdope_t result;
- umword_t badge = 0;
-
- /*
- * Wait until we get a proper message and thereby
- * ignore receive message cuts on the server-side.
- * This error condition should be handled by the
- * client. The server does not bother.
- */
- do {
- Msg_header &rcv_header = rcv_msg.header();
- rcv_header.rcv_capacity(rcv_msg.capacity());
-
- l4_ipc_wait(&rcv_cs.caller, rcv_header.msg_start(),
- &badge,
- &rcv_msg.word(0),
- L4_IPC_NEVER, &result);
-
- if (L4_IPC_IS_ERROR(result))
- PERR("Ipc error %lx", L4_IPC_ERROR(result));
-
- } while (L4_IPC_IS_ERROR(result));
-
- return badge;
-}
-
-
-void Ipc_server::reply()
-{
- using namespace Fiasco;
-
- Msg_header &snd_header = _snd_msg.header();
- snd_header.snd_size(_snd_msg.data_size());
+ Msg_header &snd_header = snd_msg.header();
+ snd_header.prepare_snd_msg(exc.value, snd_msg);
l4_msgdope_t result;
- l4_ipc_send(_caller.dst(), snd_header.msg_start(),
- _exception_code.value,
- _snd_msg.word(0),
+ l4_ipc_send(caller.dst(), snd_header.msg_start(),
+ snd_header.protocol_word,
+ snd_header.num_caps,
L4_IPC_SEND_TIMEOUT_0, &result);
if (L4_IPC_IS_ERROR(result))
- PERR("Ipc error %lx, ignored", L4_IPC_ERROR(result));
-
- _prepare_next_reply_wait();
+ PERR("ipc_send error %lx, ignored", L4_IPC_ERROR(result));
}
-void Ipc_server::reply_wait()
+Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller,
+ Rpc_exception_code exc,
+ Msgbuf_base &reply_msg,
+ Msgbuf_base &request_msg)
{
using namespace Fiasco;
- if (_reply_needed) {
+ l4_msgdope_t ipc_result;
- l4_msgdope_t ipc_result;
+ bool need_to_wait = true;
- Msg_header &snd_header = _snd_msg.header();
- snd_header.snd_size(_snd_msg.data_size());
+ Msg_header &snd_header = reply_msg.header();
+ snd_header.prepare_snd_msg(exc.value, reply_msg);
- Msg_header &rcv_header = _rcv_msg.header();
- rcv_header.rcv_capacity(_rcv_msg.capacity());
+ request_msg.reset();
+ Msg_header &rcv_header = request_msg.header();
+ rcv_header.prepare_rcv_msg(request_msg);
+
+ l4_threadid_t caller = L4_INVALID_ID;
+
+ if (last_caller.valid()) {
/*
* Use short IPC for reply if possible. This is the common case of
* returning an integer as RPC result.
*/
- l4_ipc_reply_and_wait(
- _caller.dst(),
- snd_header.msg_type(_snd_msg.data_size()),
- _exception_code.value,
- _snd_msg.word(0),
- &_rcv_cs.caller, rcv_header.msg_start(),
- &_badge,
- &_rcv_msg.word(0),
- L4_IPC_SEND_TIMEOUT_0, &ipc_result);
+ l4_ipc_reply_and_wait(last_caller.dst(), snd_header.msg_start(),
+ snd_header.protocol_word,
+ snd_header.num_caps,
+ &caller, rcv_header.msg_start(),
+ &rcv_header.protocol_word,
+ &rcv_header.num_caps,
+ L4_IPC_SEND_TIMEOUT_0, &ipc_result);
+ /*
+ * The error condition could be a message cut (which we want to ignore
+ * on the server side) or a reply failure (for example, if the caller
+ * went dead during the call. In both cases, we do not reflect the
+ * error condition to the user but want to wait for the next proper
+ * incoming message.
+ */
if (L4_IPC_IS_ERROR(ipc_result)) {
- PERR("Ipc error %lx", L4_IPC_ERROR(ipc_result));
-
- /*
- * The error conditions could be a message cut (which
- * we want to ignore on the server side) or a reply failure
- * (for example, if the caller went dead during the call.
- * In both cases, we do not reflect the error condition to
- * the user but want to wait for the next proper incoming
- * message. So let's just wait now.
- */
- _badge = wait(_rcv_cs, _rcv_msg);
+ PERR("ipc_reply_and_wait error %lx", L4_IPC_ERROR(ipc_result));
+ } else {
+ need_to_wait = false;
}
- } else {
- _badge = wait(_rcv_cs, _rcv_msg);
}
- /* define destination of next reply */
- _caller = Native_capability(_rcv_cs.caller, 0);
+ while (need_to_wait) {
- _prepare_next_reply_wait();
+ l4_ipc_wait(&caller, rcv_header.msg_start(),
+ &rcv_header.protocol_word,
+ &rcv_header.num_caps,
+ L4_IPC_NEVER, &ipc_result);
+
+ if (L4_IPC_IS_ERROR(ipc_result)) {
+ PERR("ipc_wait error %lx", L4_IPC_ERROR(ipc_result));
+ } else {
+ need_to_wait = false;
+ }
+ };
+
+ rcv_header.extract_caps(request_msg);
+
+ return Rpc_request(Native_capability(caller, 0), rcv_header.protocol_word);
}
-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(Fiasco::l4_myself(), 0),
- _rcv_cs(cs)
-{ }
+Ipc_server::Ipc_server() : Native_capability(Fiasco::l4_myself(), 0) { }
Ipc_server::~Ipc_server() { }
diff --git a/repos/base-fiasco/src/core/pager_object.cc b/repos/base-fiasco/src/core/pager_object.cc
new file mode 100644
index 0000000000..f04c0cc964
--- /dev/null
+++ b/repos/base-fiasco/src/core/pager_object.cc
@@ -0,0 +1,50 @@
+/*
+ * \brief Kernel-specific RM-faulter wake-up mechanism
+ * \author Norman Feske
+ * \date 2016-04-12
+ */
+
+/*
+ * Copyright (C) 2016 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+/* core includes */
+#include
+
+/* Fiasco includes */
+namespace Fiasco {
+#include
+#include
+#include
+}
+
+using namespace Genode;
+
+
+void Pager_object::wake_up()
+{
+ using namespace Fiasco;
+
+ /* kernel-defined message header */
+ struct {
+ l4_fpage_t rcv_fpage; /* unused */
+ l4_msgdope_t size_dope = L4_IPC_DOPE(0, 0);
+ l4_msgdope_t send_dope = L4_IPC_DOPE(0, 0);
+ } rcv_header;
+
+ l4_msgdope_t ipc_result;
+ l4_umword_t dummy = 0;
+ l4_ipc_call(cap().dst(), L4_IPC_SHORT_MSG,
+ 0, /* fault address */
+ (l4_umword_t)this, /* instruction pointer */
+ &rcv_header, &dummy, &dummy, L4_IPC_NEVER, &ipc_result);
+}
+
+
+void Pager_object::unresolved_page_fault_occurred()
+{
+ state.unresolved_page_fault = true;
+}
diff --git a/repos/base-fiasco/src/core/target.inc b/repos/base-fiasco/src/core/target.inc
index 4fcc7096b0..a087fb25a7 100644
--- a/repos/base-fiasco/src/core/target.inc
+++ b/repos/base-fiasco/src/core/target.inc
@@ -64,7 +64,6 @@ vpath trace_session_component.cc $(GEN_CORE_DIR)
vpath dataspace_component.cc $(GEN_CORE_DIR)
vpath dump_alloc.cc $(GEN_CORE_DIR)
vpath stack_area.cc $(GEN_CORE_DIR)
-vpath pager_object.cc $(GEN_CORE_DIR)
vpath pager_ep.cc $(GEN_CORE_DIR)
vpath core_printf.cc $(BASE_DIR)/src/base/console
vpath %.cc $(REP_DIR)/src/core
diff --git a/repos/base-fiasco/src/include/base/internal/native_connection_state.h b/repos/base-fiasco/src/include/base/internal/native_connection_state.h
deleted file mode 100644
index f3a16e317d..0000000000
--- a/repos/base-fiasco/src/include/base/internal/native_connection_state.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * \brief Connection state
- * \author Norman Feske
- * \date 2016-03-03
- */
-
-/*
- * Copyright (C) 2016 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__BASE__INTERNAL__NATIVE_CONNECTION_STATE_H_
-#define _INCLUDE__BASE__INTERNAL__NATIVE_CONNECTION_STATE_H_
-
-/* Genode includes */
-#include
-
-/* Fiasco includes */
-namespace Fiasco {
-#include
-}
-
-namespace Genode { struct Native_connection_state; }
-
-
-struct Genode::Native_connection_state
-{
- Fiasco::l4_threadid_t caller;
-};
-
-
-#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_CONNECTION_STATE_H_ */
diff --git a/repos/base-foc/include/base/ipc_msgbuf.h b/repos/base-foc/include/base/ipc_msgbuf.h
deleted file mode 100644
index 9c44a012da..0000000000
--- a/repos/base-foc/include/base/ipc_msgbuf.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * \brief IPC message buffer layout for Fiasco.OC
- * \author Stefan Kalkowski
- * \date 2010-11-30
- *
- * On Fiasco.OC, IPC is used to transmit plain data and capabilities.
- * Therefore the message buffer contains both categories of payload.
- */
-
-/*
- * Copyright (C) 2010-2013 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
-#define _INCLUDE__BASE__IPC_MSGBUF_H_
-
-/* Genode includes */
-#include
-
-/* Fiasco.OC includes */
-namespace Fiasco {
-#include
-#include
-}
-
-namespace Genode {
-
- class Ipc_marshaller;
-
- class Msgbuf_base
- {
- public:
-
- enum { MAX_CAP_ARGS_LOG2 = 2, MAX_CAP_ARGS = 1 << MAX_CAP_ARGS_LOG2 };
-
- protected:
-
- friend class Ipc_marshaller;
-
- size_t const _capacity;
-
- size_t _data_size = 0;
-
- /**
- * Number of capability selectors to send.
- */
- size_t _snd_cap_sel_cnt = 0;
-
- /**
- * Capability selectors to delegate.
- */
- addr_t _snd_cap_sel[MAX_CAP_ARGS];
-
- /**
- * Base of capability receive window.
- */
- Cap_index* _rcv_idx_base = nullptr;
-
- /**
- * Read counter for unmarshalling portal capability selectors
- */
- addr_t _rcv_cap_sel_cnt = 0;
-
- unsigned long _label = 0;
-
- char _msg_start[]; /* symbol marks start of message */
-
- /**
- * Constructor
- */
- Msgbuf_base(size_t capacity)
- :
- _capacity(capacity),
- _rcv_idx_base(cap_idx_alloc()->alloc_range(MAX_CAP_ARGS))
- {
- rcv_reset();
- snd_reset();
- }
-
- public:
-
- ~Msgbuf_base()
- {
- cap_idx_alloc()->free(_rcv_idx_base, MAX_CAP_ARGS);
- }
-
- /*
- * Begin of actual message buffer
- */
- char buf[];
-
- /**
- * Return size of message buffer
- */
- size_t capacity() const { return _capacity; };
-
- /**
- * Return pointer of message data payload
- */
- void *data() { return &_msg_start[0]; };
- void const *data() const { return &_msg_start[0]; };
-
- size_t data_size() const { return _data_size; }
-
- unsigned long &word(unsigned i)
- {
- return reinterpret_cast(buf)[i];
- }
-
- /**
- * Reset portal capability selector payload
- */
- void snd_reset() { _snd_cap_sel_cnt = 0; }
-
- /**
- * Append capability selector to message buffer
- */
- bool snd_append_cap_sel(addr_t cap_sel)
- {
- if (_snd_cap_sel_cnt >= MAX_CAP_ARGS)
- return false;
-
- _snd_cap_sel[_snd_cap_sel_cnt++] = cap_sel;
- return true;
- }
-
- /**
- * Return number of marshalled capability selectors
- */
- size_t snd_cap_sel_cnt() const { return _snd_cap_sel_cnt; }
-
- /**
- * Return capability selector to send.
- *
- * \param i index (0 ... 'snd_cap_sel_cnt()' - 1)
- * \return capability selector, or 0 if index is invalid
- */
- addr_t snd_cap_sel(unsigned i) const {
- return i < _snd_cap_sel_cnt ? _snd_cap_sel[i] : 0; }
-
- /**
- * Return address of capability receive window.
- */
- addr_t rcv_cap_sel_base() { return _rcv_idx_base->kcap(); }
-
- /**
- * Reset capability receive window
- */
- void rcv_reset() { _rcv_cap_sel_cnt = 0; }
-
- /**
- * Return next received capability selector.
- *
- * \return capability selector, or 0 if index is invalid
- */
- addr_t rcv_cap_sel() {
- return rcv_cap_sel_base() + _rcv_cap_sel_cnt++ * Fiasco::L4_CAP_SIZE; }
-
- void label(unsigned long label) { _label = label; }
- unsigned long label() { return _label & (~0UL << 2); }
- };
-
-
- template
- class Msgbuf : public Msgbuf_base
- {
- public:
-
- char buf[BUF_SIZE];
-
- Msgbuf() : Msgbuf_base(BUF_SIZE) { }
- };
-}
-
-#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
diff --git a/repos/base-foc/include/foc/native_thread.h b/repos/base-foc/include/foc/native_thread.h
index c293885630..fe624f9159 100644
--- a/repos/base-foc/include/foc/native_thread.h
+++ b/repos/base-foc/include/foc/native_thread.h
@@ -20,6 +20,7 @@
/* Genode includes */
#include
+#include
/* Fiasco.OC includes */
namespace Fiasco {
@@ -32,6 +33,9 @@ struct Genode::Native_thread
{
Fiasco::l4_cap_idx_t kcap = 0;
+ /* receive window for capability selectors received at the server side */
+ Receive_window rcv_window;
+
Native_thread() { }
explicit Native_thread(Fiasco::l4_cap_idx_t kcap) : kcap(kcap) { }
};
diff --git a/repos/base-foc/include/foc/receive_window.h b/repos/base-foc/include/foc/receive_window.h
new file mode 100644
index 0000000000..587eae26d8
--- /dev/null
+++ b/repos/base-foc/include/foc/receive_window.h
@@ -0,0 +1,65 @@
+/*
+ * \brief Receive window for capability selectors
+ * \author Norman Feske
+ * \date 2016-03-22
+ */
+
+/*
+ * Copyright (C) 2016 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _INCLUDE__FOC__RECEIVE_WINDOW_H_
+#define _INCLUDE__FOC__RECEIVE_WINDOW_H_
+
+/* Genode includes */
+#include
+#include
+#include
+
+namespace Genode { struct Receive_window; }
+
+
+class Genode::Receive_window
+{
+ private:
+
+ /**
+ * Base of capability receive window.
+ */
+ Cap_index* _rcv_idx_base = nullptr;
+
+ enum { MAX_CAPS_PER_MSG = Msgbuf_base::MAX_CAPS_PER_MSG };
+
+ public:
+
+ Receive_window() { }
+
+ ~Receive_window()
+ {
+ if (_rcv_idx_base)
+ cap_idx_alloc()->free(_rcv_idx_base, MAX_CAPS_PER_MSG);
+ }
+
+ void init()
+ {
+ _rcv_idx_base = cap_idx_alloc()->alloc_range(MAX_CAPS_PER_MSG);
+ }
+
+ /**
+ * Return address of capability receive window
+ */
+ addr_t rcv_cap_sel_base() { return _rcv_idx_base->kcap(); }
+
+ /**
+ * Return received selector with index i
+ *
+ * \return capability selector, or 0 if index is invalid
+ */
+ addr_t rcv_cap_sel(unsigned i) {
+ return rcv_cap_sel_base() + i*Fiasco::L4_CAP_SIZE; }
+};
+
+#endif /* _INCLUDE__FOC__RECEIVE_WINDOW_H_ */
diff --git a/repos/base-foc/include/signal_source/client.h b/repos/base-foc/include/signal_source/client.h
index aa8b42cbd0..72268b37a8 100644
--- a/repos/base-foc/include/signal_source/client.h
+++ b/repos/base-foc/include/signal_source/client.h
@@ -89,15 +89,23 @@ namespace Genode {
{
using namespace Fiasco;
- /* block on semaphore, will be unblocked if signal is available */
- l4_irq_receive(_sem.dst(), L4_IPC_NEVER);
+ Signal signal;
+ do {
- /*
- * Now that the server has unblocked the semaphore, we are sure
- * that there is a signal pending. The following 'wait_for_signal'
- * request will be immediately answered.
- */
- return call();
+ /* block on semaphore until signal context was submitted */
+ l4_irq_receive(_sem.dst(), L4_IPC_NEVER);
+
+ /*
+ * The following request will return immediately and either
+ * return a valid or a null signal. The latter may happen in
+ * the case a submitted signal context was destroyed (by the
+ * submitter) before we have a chance to raise our request.
+ */
+ signal = call();
+
+ } while (!signal.imprint());
+
+ return signal;
}
};
}
diff --git a/repos/base-foc/src/base/ipc/ipc.cc b/repos/base-foc/src/base/ipc/ipc.cc
index aa57805814..0b7814e06a 100644
--- a/repos/base-foc/src/base/ipc/ipc.cc
+++ b/repos/base-foc/src/base/ipc/ipc.cc
@@ -45,58 +45,11 @@ using namespace Genode;
using namespace Fiasco;
-/*****************************
- ** IPC marshalling support **
- *****************************/
-
-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()))) {
- insert(0UL);
- return;
- }
- }
-
- /* transfer capability id */
- 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());
-
- ASSERT(!cap.valid() ||
- l4_msgtag_label(l4_task_cap_valid(L4_BASE_TASK_CAP, cap.dst())),
- "Send invalid cap");
-}
-
-
-void Ipc_unmarshaller::extract(Native_capability &cap)
-{
- long value = 0;
-
- /* extract capability id from message buffer */
- extract(value);
-
- /* if id is zero an invalid capability was transfered */
- if (!value) {
- cap = Native_capability();
- return;
- }
-
- /* try to insert received capability in the map and return it */
- cap = Native_capability(cap_map()->insert_map(value, _rcv_msg.rcv_cap_sel()));
-}
-
-
/***************
** Utilities **
***************/
-enum Debug {
- DEBUG_MSG = 1,
- HALT_ON_ERROR = 0
-};
+enum Debug { DEBUG_MSG = 1, HALT_ON_ERROR = 0 };
static inline bool ipc_error(l4_msgtag_t tag, bool print)
@@ -116,39 +69,110 @@ static inline bool ipc_error(l4_msgtag_t tag, bool print)
}
+enum { INVALID_BADGE = ~0UL };
+
+
+/**
+ * Representation of a capability during UTCB marshalling/unmarshalling
+ */
+struct Cap_info
+{
+ bool valid = false;
+ unsigned long sel = 0;
+ unsigned long badge = 0;
+};
+
+
/**
* Copy message registers from UTCB to destination message buffer
*
* \return protocol word (local name or exception code)
*/
-static unsigned long extract_msg_from_utcb(l4_msgtag_t tag, Msgbuf_base &rcv_msg)
+static unsigned long extract_msg_from_utcb(l4_msgtag_t tag,
+ Receive_window &rcv_window,
+ Msgbuf_base &rcv_msg)
{
- unsigned const num_msg_words = l4_msgtag_words(tag);
- unsigned const num_cap_sel = l4_msgtag_items(tag);
+ unsigned num_msg_words = l4_msgtag_words(tag);
- /* each message has at least the protocol word */
- if (num_msg_words < 2 && num_cap_sel == 0)
+ l4_mword_t const *msg_words = (l4_mword_t const *)l4_utcb_mr();
+
+ /* each message has at least the protocol word and the capability count */
+ if (num_msg_words < 2)
return 0;
- /* the first message word is reserved for the protocol word */
- unsigned num_data_msg_words = num_msg_words - 1;
+ /* read badge / exception code from first message word */
+ unsigned long const protocol_word = *msg_words++;
- if ((num_data_msg_words)*sizeof(l4_mword_t) > rcv_msg.capacity()) {
- if (DEBUG_MSG)
- outstring("receive message buffer too small");
- num_data_msg_words = rcv_msg.capacity()/sizeof(l4_mword_t);
+ /* read number of capability arguments from second message word */
+ unsigned long const num_caps = min(*msg_words, Msgbuf_base::MAX_CAPS_PER_MSG);
+ msg_words++;
+
+ num_msg_words -= 2;
+ if (num_caps > 0 && num_msg_words < num_caps) {
+ outstring("unexpected end of message, capability info missing\n");
+ return 0;
}
- /* read protocol word from first UTCB message register */
- unsigned long const protocol_word = l4_utcb_mr()->mr[0];
+ /*
+ * Extract capabilities
+ *
+ * The badges are stored in the subsequent message registers. For each
+ * valid badge, we expect one capability selector to be present in the
+ * receive window. The content of the receive window is tracked via
+ * 'sel_idx'. If we encounter an invalid badge, the sender specified
+ * an invalid capabilty as argument.
+ */
+ unsigned const num_cap_sel = l4_msgtag_items(tag);
+
+ Cap_info caps[num_caps];
+
+ for (unsigned i = 0, sel_idx = 0; i < num_caps; i++) {
+
+ unsigned long const badge = *msg_words++;
+
+ if (badge == INVALID_BADGE)
+ continue;
+
+ /* received a delegated capability */
+ if (sel_idx == num_cap_sel) {
+ outstring("missing capability selector in message\n");
+ break;
+ }
+
+ caps[i].badge = badge;
+ caps[i].valid = true;
+ caps[i].sel = rcv_window.rcv_cap_sel(sel_idx++);
+ }
+ num_msg_words -= num_caps;
+
+ /* the remainder of the message contains the regular data payload */
+ if ((num_msg_words)*sizeof(l4_mword_t) > rcv_msg.capacity()) {
+ if (DEBUG_MSG)
+ outstring("receive message buffer too small\n");
+ num_msg_words = rcv_msg.capacity()/sizeof(l4_mword_t);
+ }
/* read message payload beginning from the second UTCB message register */
- l4_mword_t *src = (l4_mword_t *)l4_utcb_mr() + 1;
l4_mword_t *dst = (l4_mword_t *)rcv_msg.data();
- for (unsigned i = 0; i < num_data_msg_words; i++)
- *dst++ = *src++;
+ for (unsigned i = 0; i < num_msg_words; i++)
+ *dst++ = *msg_words++;
- rcv_msg.rcv_reset();
+ rcv_msg.data_size(sizeof(l4_mword_t)*num_msg_words);
+
+ /*
+ * Insert received capability selectors into cap map.
+ *
+ * Note that this operation pollutes the UTCB. Therefore we must perform
+ * it not before the entire message content is extracted.
+ */
+ for (unsigned i = 0; i < num_caps; i++) {
+ if (caps[i].valid) {
+ rcv_msg.insert(Native_capability(cap_map()->insert_map(caps[i].badge,
+ caps[i].sel)));
+ } else {
+ rcv_msg.insert(Native_capability());
+ }
+ }
return protocol_word;
}
@@ -164,31 +188,76 @@ static unsigned long extract_msg_from_utcb(l4_msgtag_t tag, Msgbuf_base &rcv_msg
static l4_msgtag_t copy_msgbuf_to_utcb(Msgbuf_base &snd_msg,
unsigned long protocol_word)
{
- unsigned const num_data_words = snd_msg.data_size() / sizeof(l4_mword_t);
- unsigned const num_msg_words = num_data_words + 1;
- unsigned const num_cap_sel = snd_msg.snd_cap_sel_cnt();
- /* account for message words, local name, and capability arguments */
- if (num_msg_words + 2*num_cap_sel > L4_UTCB_GENERIC_DATA_SIZE) {
- if (DEBUG_MSG)
- outstring("receive message buffer too small");
+ unsigned const num_data_words = snd_msg.data_size() / sizeof(l4_mword_t);
+ unsigned const num_caps = snd_msg.used_caps();
+
+ /* validate capabilities present in the message buffer */
+ for (unsigned i = 0; i < num_caps; i++) {
+
+ Native_capability &cap = snd_msg.cap(i);
+ if (!cap.valid())
+ continue;
+
+ if (!l4_msgtag_label(l4_task_cap_valid(L4_BASE_TASK_CAP, cap.dst())))
+ cap = Native_capability();
+ }
+
+ /*
+ * Obtain capability info from message buffer
+ *
+ * This step must be performed prior any write operation to the UTCB
+ * because the 'Genode::Capability' operations may indirectly trigger
+ * system calls, which pollute the UTCB.
+ */
+ Cap_info caps[num_caps];
+ for (unsigned i = 0; i < num_caps; i++) {
+ Native_capability const &cap = snd_msg.cap(i);
+ if (cap.valid()) {
+ caps[i].valid = true;
+ caps[i].badge = cap.local_name();
+ caps[i].sel = cap.dst();
+ }
+ }
+
+ /*
+ * The message consists of a protocol word, the capability count, one badge
+ * value per capability, and the data payload.
+ */
+ unsigned const num_msg_words = 2 + num_caps + num_data_words;
+
+ if (num_msg_words > L4_UTCB_GENERIC_DATA_SIZE) {
+ outstring("receive message buffer too small\n");
throw Ipc_error();
}
- /* copy badge / exception code to UTCB message register */
- l4_utcb_mr()->mr[0] = protocol_word;
+ l4_mword_t *msg_words = (l4_mword_t *)l4_utcb_mr();
+
+ *msg_words++ = protocol_word;
+ *msg_words++ = num_caps;
+
+ unsigned num_cap_sel = 0;
+
+ for (unsigned i = 0; i < num_caps; i++) {
+
+ Native_capability const &cap = snd_msg.cap(i);
+
+ /* store badge as normal message word */
+ *msg_words++ = caps[i].valid ? caps[i].badge : INVALID_BADGE;
+
+ /* setup flexpage for valid capability to delegate */
+ if (caps[i].valid) {
+ unsigned const idx = num_msg_words + 2*num_cap_sel;
+ l4_utcb_mr()->mr[idx] = L4_ITEM_MAP/* | L4_ITEM_CONT*/;
+ l4_utcb_mr()->mr[idx + 1] = l4_obj_fpage(caps[i].sel,
+ 0, L4_FPAGE_RWX).raw;
+ num_cap_sel++;
+ }
+ }
/* store message data into UTCB message registers */
for (unsigned i = 0; i < num_data_words; i++)
- l4_utcb_mr()->mr[i + 1] = snd_msg.word(i);
-
- /* setup flexpages of capabilities to send */
- for (unsigned i = 0; i < num_cap_sel; i++) {
- unsigned const 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),
- 0, L4_FPAGE_RWX).raw;
- }
+ *msg_words++ = snd_msg.word(i);
return l4_msgtag(0, num_msg_words, num_cap_sel, 0);
}
@@ -202,11 +271,15 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
size_t rcv_caps)
{
+ Receive_window rcv_window;
+ rcv_window.init();
+ rcv_msg.reset();
+
/* copy call message to the UTCBs message registers */
l4_msgtag_t const call_tag = copy_msgbuf_to_utcb(snd_msg, dst.local_name());
- addr_t rcv_cap_sel = rcv_msg.rcv_cap_sel_base();
- for (int i = 0; i < Msgbuf_base::MAX_CAP_ARGS; i++) {
+ addr_t rcv_cap_sel = rcv_window.rcv_cap_sel_base();
+ for (int i = 0; i < Msgbuf_base::MAX_CAPS_PER_MSG; i++) {
l4_utcb_br()->br[i] = rcv_cap_sel | L4_RCV_ITEM_SINGLE_CAP;
rcv_cap_sel += L4_CAP_SIZE;
}
@@ -220,106 +293,86 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
if (ipc_error(reply_tag, DEBUG_MSG))
throw Genode::Ipc_error();
- return Rpc_exception_code(extract_msg_from_utcb(reply_tag, rcv_msg));
+ return Rpc_exception_code(extract_msg_from_utcb(reply_tag, rcv_window, rcv_msg));
}
/****************
- ** Ipc_server **
+ ** IPC server **
****************/
-void Ipc_server::_prepare_next_reply_wait()
+static bool badge_matches_label(unsigned long badge, unsigned long label)
{
- _reply_needed = true;
- _read_offset = _write_offset = 0;
-
- _snd_msg.snd_reset();
+ return badge == (label & (~0UL << 2));
}
-static unsigned long wait(Msgbuf_base &rcv_msg)
+void Genode::ipc_reply(Native_capability caller, Rpc_exception_code exc,
+ Msgbuf_base &snd_msg)
{
- 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;
- }
- l4_utcb_br()->bdr = 0;
-
- 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 message from the UTCBs message registers to the receive buffer */
- return extract_msg_from_utcb(tag, rcv_msg);
-}
-
-
-void Ipc_server::reply()
-{
- l4_msgtag_t tag = copy_msgbuf_to_utcb(_snd_msg, _exception_code.value);
+ l4_msgtag_t tag = copy_msgbuf_to_utcb(snd_msg, exc.value);
tag = l4_ipc_send(L4_SYSF_REPLY, l4_utcb(), tag, L4_IPC_SEND_TIMEOUT_0);
ipc_error(tag, DEBUG_MSG);
- _snd_msg.snd_reset();
}
-void Ipc_server::reply_wait()
+Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller,
+ Rpc_exception_code exc,
+ Msgbuf_base &reply_msg,
+ Msgbuf_base &request_msg)
{
- if (_reply_needed) {
- addr_t rcv_cap_sel = _rcv_msg.rcv_cap_sel_base();
- for (int i = 0; i < Msgbuf_base::MAX_CAP_ARGS; i++) {
+ Receive_window &rcv_window = Thread_base::myself()->native_thread().rcv_window;
+
+ for (;;) {
+
+ request_msg.reset();
+
+ /* prepare receive window in UTCB */
+ addr_t rcv_cap_sel = rcv_window.rcv_cap_sel_base();
+ for (int i = 0; i < Msgbuf_base::MAX_CAPS_PER_MSG; i++) {
l4_utcb_br()->br[i] = rcv_cap_sel | L4_RCV_ITEM_SINGLE_CAP;
rcv_cap_sel += L4_CAP_SIZE;
}
-
l4_utcb_br()->bdr &= ~L4_BDR_OFFSET_MASK;
- l4_umword_t label = 0;
+ l4_msgtag_t request_tag;
+ l4_umword_t label = 0; /* kernel-protected label of invoked capability */
- l4_msgtag_t const reply_tag =
- copy_msgbuf_to_utcb(_snd_msg, _exception_code.value);
+ if (exc.value != Rpc_exception_code::INVALID_OBJECT) {
- l4_msgtag_t const request_tag =
- l4_ipc_reply_and_wait(l4_utcb(), reply_tag, &label,
- L4_IPC_SEND_TIMEOUT_0);
+ l4_msgtag_t const reply_tag = copy_msgbuf_to_utcb(reply_msg, exc.value);
- _rcv_msg.label(label);
-
- if (ipc_error(request_tag, false)) {
- /*
- * The error conditions could be a message cut (which
- * we want to ignore on the server side) or a reply failure
- * (for example, if the caller went dead during the call.
- * In both cases, we do not reflect the error condition to
- * the user but want to wait for the next proper incoming
- * message. So let's just wait now.
- */
- _badge = wait(_rcv_msg);
+ request_tag = l4_ipc_reply_and_wait(l4_utcb(), reply_tag, &label, L4_IPC_SEND_TIMEOUT_0);
} else {
-
- /* copy request message from the UTCBs message registers */
- _badge = extract_msg_from_utcb(request_tag, _rcv_msg);
+ request_tag = l4_ipc_wait(l4_utcb(), &label, L4_IPC_NEVER);
}
- } else
- _badge = wait(_rcv_msg);
- _prepare_next_reply_wait();
+ if (ipc_error(request_tag, false))
+ continue;
+
+ /* copy request message from the UTCBs message registers */
+ unsigned long const badge =
+ extract_msg_from_utcb(request_tag, rcv_window, request_msg);
+
+ /* ignore request if we detect a forged badge */
+ if (!badge_matches_label(badge, label)) {
+ outstring("badge does not match label, ignoring request\n");
+ continue;
+ }
+
+ return Rpc_request(Native_capability(), badge);
+ }
}
-Ipc_server::Ipc_server(Native_connection_state &cs,
- Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
+Ipc_server::Ipc_server()
:
- Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
- Native_capability((Cap_index*)Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE]),
- _rcv_cs(cs)
-{ }
+ Native_capability((Cap_index*)Fiasco::l4_utcb_tcr()->user[Fiasco::UTCB_TCR_BADGE])
+{
+ Thread_base::myself()->native_thread().rcv_window.init();
+}
Ipc_server::~Ipc_server() { }
diff --git a/repos/base-foc/src/base/server/server.cc b/repos/base-foc/src/base/server/server.cc
deleted file mode 100644
index b338f80659..0000000000
--- a/repos/base-foc/src/base/server/server.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * \brief Default version of platform-specific part of server framework
- * \author Norman Feske
- * \author Stefan Kalkowski
- * \date 2006-05-12
- *
- * This version is suitable for platforms similar to L4. Each platform
- * for which this implementation is not suited contains a platform-
- * specific version in its respective 'base-' repository.
- */
-
-/*
- * Copyright (C) 2006-2013 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-/* Genode includes */
-#include
-
-/* base-internal includes */
-#include
-
-using namespace Genode;
-
-
-/***********************
- ** Server entrypoint **
- ***********************/
-
-Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
-{
- Untyped_capability new_obj_cap = _alloc_rpc_cap(_pd_session, _cap);
-
- /* add server object to object pool */
- obj->cap(new_obj_cap);
- insert(obj);
-
- /* return capability that uses the object id as badge */
- return new_obj_cap;
-}
-
-
-void Rpc_entrypoint::entry()
-{
- Native_connection_state cs;
- Ipc_server srv(cs, _snd_buf, _rcv_buf);
- _ipc_server = &srv;
- _cap = srv;
- _cap_valid.unlock();
-
- /*
- * Now, the capability of the server activation is initialized
- * an can be passed around. However, the processing of capability
- * invocations should not happen until activation-using server
- * is completely initialized. Thus, we wait until the activation
- * gets explicitly unblocked by calling 'Rpc_entrypoint::activate()'.
- */
- _delay_start.lock();
-
- while (!_exit_handler.exit) {
-
- Rpc_opcode opcode(0);
-
- srv.reply_wait();
- srv.extract(opcode);
-
- /* set default return value */
- srv.ret(Rpc_exception_code(Rpc_exception_code::INVALID_OBJECT));
-
- apply(srv.badge(), [&] (Rpc_object_base *obj) {
- if (!obj) return;
-
- try {
- srv.ret(obj->dispatch(opcode, srv, srv));
- } catch(Blocking_canceled&) { }
- });
- }
-
- /* answer exit call, thereby wake up '~Rpc_entrypoint' */
- srv.reply();
-
- /* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
- _delay_exit.lock();
-}
diff --git a/repos/base-foc/src/core/pager_object.cc b/repos/base-foc/src/core/pager_object.cc
new file mode 100644
index 0000000000..4eb5001179
--- /dev/null
+++ b/repos/base-foc/src/core/pager_object.cc
@@ -0,0 +1,42 @@
+/*
+ * \brief Kernel-specific RM-faulter wake-up mechanism
+ * \author Norman Feske
+ * \date 2016-04-12
+ */
+
+/*
+ * Copyright (C) 2016 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+/* core includes */
+#include
+
+/* Fiasco.OC includes */
+namespace Fiasco {
+#include
+}
+
+using namespace Genode;
+
+
+void Pager_object::wake_up()
+{
+ using namespace Fiasco;
+
+ /*
+ * Issue IPC to pager, transmitting the pager-object pointer as 'IP'.
+ */
+ l4_utcb_mr()->mr[0] = 0; /* fault address */
+ l4_utcb_mr()->mr[1] = (l4_umword_t)this; /* instruction pointer */
+
+ l4_ipc_call(cap().dst(), l4_utcb(), l4_msgtag(0, 2, 0, 0), L4_IPC_NEVER);
+}
+
+
+void Pager_object::unresolved_page_fault_occurred()
+{
+ state.unresolved_page_fault = true;
+}
diff --git a/repos/base-foc/src/core/platform_thread.cc b/repos/base-foc/src/core/platform_thread.cc
index a023386f9b..daf6309360 100644
--- a/repos/base-foc/src/core/platform_thread.cc
+++ b/repos/base-foc/src/core/platform_thread.cc
@@ -140,8 +140,7 @@ void Platform_thread::resume()
/* Send a message to the exception handler, to unblock the client */
Msgbuf<16> snd, rcv;
- Ipc_marshaller marshaller(snd);
- marshaller.insert(_pager_obj);
+ snd.insert(_pager_obj);
ipc_call(_pager_obj->cap(), snd, rcv, 0);
}
diff --git a/repos/base-foc/src/core/target.inc b/repos/base-foc/src/core/target.inc
index a082af0240..7e8d67f097 100644
--- a/repos/base-foc/src/core/target.inc
+++ b/repos/base-foc/src/core/target.inc
@@ -63,7 +63,6 @@ vpath rm_session_component.cc $(GEN_CORE_DIR)
vpath rom_session_component.cc $(GEN_CORE_DIR)
vpath trace_session_component.cc $(GEN_CORE_DIR)
vpath core_rpc_cap_alloc.cc $(GEN_CORE_DIR)
-vpath pager_object.cc $(GEN_CORE_DIR)
vpath core_printf.cc $(BASE_DIR)/src/base/console
vpath %.cc $(REP_DIR)/src/core
vpath %.cc $(REP_DIR)/src/base/thread
diff --git a/repos/base-hw/include/base/ipc_msgbuf.h b/repos/base-hw/include/base/ipc_msgbuf.h
deleted file mode 100644
index 666667bd9f..0000000000
--- a/repos/base-hw/include/base/ipc_msgbuf.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * \brief IPC message buffers
- * \author Martin Stein
- * \author Stefan Kalkowski
- * \date 2012-01-03
- */
-
-/*
- * Copyright (C) 2012-2015 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
-#define _INCLUDE__BASE__IPC_MSGBUF_H_
-
-#include
-#include
-#include
-
-namespace Genode {
-
- class Native_utcb;
-
- class Ipc_marshaller;
-
- /**
- * IPC message buffer layout
- */
- class Msgbuf_base;
-
- /**
- * Instance of IPC message buffer with specified buffer size
- *
- * 'Msgbuf_base' must be the last class this class inherits from.
- */
- template class Msgbuf;
-}
-
-
-class Genode::Msgbuf_base
-{
- public:
-
- enum { MAX_CAP_ARGS = 4 };
-
- private:
-
- friend class Native_utcb;
- friend class Ipc_marshaller;
-
- size_t const _capacity; /* buffer size in bytes */
- size_t _data_size = 0; /* marshalled data in bytes */
- Native_capability _caps[MAX_CAP_ARGS]; /* capability buffer */
- size_t _snd_cap_cnt = 0; /* capability counter */
- size_t _rcv_cap_cnt = 0; /* capability counter */
-
- public:
-
- /*************************************************
- ** 'buf' must be the last member of this class **
- *************************************************/
-
- char buf[]; /* begin of actual message buffer */
-
- Msgbuf_base(size_t capacity) : _capacity(capacity) { }
-
- void const * base() const { return &buf; }
-
- /**
- * Return size of message buffer
- */
- size_t capacity() const { return _capacity; }
-
- /**
- * Return pointer of message data payload
- */
- void *data() { return &buf[0]; }
- void const *data() const { return &buf[0]; }
-
- size_t data_size() const { return _data_size; }
-
- /**
- * Reset capability buffer.
- */
- void reset()
- {
- _snd_cap_cnt = 0;
- _rcv_cap_cnt = 0;
- }
-
- /**
- * Return how many capabilities are accepted by this message buffer
- */
- size_t cap_rcv_window() { return _rcv_cap_cnt; }
-
- /**
- * Set how many capabilities are accepted by this message buffer
- */
- void cap_rcv_window(size_t cnt) { _rcv_cap_cnt = cnt; }
-
- /**
- * Add capability to buffer
- */
- void cap_add(Native_capability const &cap)
- {
- if (_snd_cap_cnt < MAX_CAP_ARGS)
- _caps[_snd_cap_cnt++] = cap;
- }
-
- /**
- * Return last capability from buffer.
- */
- Native_capability cap_get()
- {
- return (_rcv_cap_cnt < _snd_cap_cnt)
- ? _caps[_rcv_cap_cnt++] : Native_capability();
- }
-};
-
-
-template
-class Genode::Msgbuf : public Genode::Msgbuf_base
-{
- public:
-
- /**************************************************
- ** 'buf' must be the first member of this class **
- **************************************************/
-
- char buf[BUF_SIZE];
-
- /**
- * Constructor
- */
- Msgbuf() : Msgbuf_base(BUF_SIZE) { }
-};
-
-#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
diff --git a/repos/base-hw/src/base/ipc/ipc.cc b/repos/base-hw/src/base/ipc/ipc.cc
index 13f9e20caf..8f3ee42414 100644
--- a/repos/base-hw/src/base/ipc/ipc.cc
+++ b/repos/base-hw/src/base/ipc/ipc.cc
@@ -35,16 +35,55 @@ namespace Hw { extern Genode::Untyped_capability _main_thread_cap; }
using namespace Genode;
-/*****************************
- ** IPC marshalling support **
- *****************************/
+/**
+ * Copy data from the message buffer to UTCB
+ */
+static inline void copy_msg_to_utcb(Msgbuf_base const &snd_msg, Native_utcb &utcb)
+{
+ /* copy capabilities */
+ size_t const num_caps = min((size_t)Msgbuf_base::MAX_CAPS_PER_MSG,
+ snd_msg.used_caps());
-void Ipc_marshaller::insert(Native_capability const &cap) {
- _snd_msg.cap_add(cap); }
+ for (unsigned i = 0; i < num_caps; i++)
+ utcb.cap_set(i, snd_msg.cap(i).dst());
+
+ utcb.cap_cnt(num_caps);
+
+ /* copy data payload */
+ size_t const data_size = min(snd_msg.data_size(),
+ min(snd_msg.capacity(), utcb.capacity()));
+
+ memcpy(utcb.data(), snd_msg.data(), data_size);
+
+ utcb.data_size(data_size);
+}
-void Ipc_unmarshaller::extract(Native_capability &cap) {
- cap = _rcv_msg.cap_get(); }
+/**
+ * Copy data from UTCB to the message buffer
+ */
+static inline void copy_utcb_to_msg(Native_utcb const &utcb, Msgbuf_base &rcv_msg)
+{
+ /* copy capabilities */
+ size_t const num_caps = min((size_t)Msgbuf_base::MAX_CAPS_PER_MSG,
+ utcb.cap_cnt());
+
+ for (unsigned i = 0; i < num_caps; i++) {
+ rcv_msg.cap(i) = utcb.cap_get(i);
+ if (rcv_msg.cap(i).valid())
+ Kernel::ack_cap(rcv_msg.cap(i).dst());
+ }
+
+ rcv_msg.used_caps(num_caps);
+
+ /* copy data payload */
+ size_t const data_size = min(utcb.data_size(),
+ min(utcb.capacity(), rcv_msg.capacity()));
+
+ memcpy(rcv_msg.data(), utcb.data(), data_size);
+
+ rcv_msg.data_size(data_size);
+}
/****************
@@ -55,23 +94,19 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
size_t rcv_caps)
{
- rcv_msg.cap_rcv_window(rcv_caps);
-
Native_utcb &utcb = *Thread_base::myself()->utcb();
retry(
[&] () {
- /* send request and receive corresponding reply */
- Thread_base::myself()->utcb()->copy_from(snd_msg);
+ copy_msg_to_utcb(snd_msg, *Thread_base::myself()->utcb());
switch (Kernel::send_request_msg(dst.dst(),
- rcv_msg.cap_rcv_window())) {
+ rcv_caps)) {
case -1: throw Blocking_canceled();
case -2: throw Allocator::Out_of_memory();
default:
- rcv_msg.reset();
- utcb.copy_to(rcv_msg);
+ copy_utcb_to_msg(utcb, rcv_msg);
}
},
@@ -82,30 +117,36 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
/****************
- ** Ipc_server **
+ ** IPC server **
****************/
-void Ipc_server::reply()
+void Genode::ipc_reply(Native_capability caller, Rpc_exception_code exc,
+ Msgbuf_base &snd_msg)
{
- Thread_base::myself()->utcb()->copy_from(_snd_msg);
- _snd_msg.reset();
+ Native_utcb &utcb = *Thread_base::myself()->utcb();
+ copy_msg_to_utcb(snd_msg, utcb);
+ utcb.exception_code(exc.value);
+ snd_msg.reset();
Kernel::send_reply_msg(0, false);
}
-void Ipc_server::reply_wait()
+Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &,
+ Rpc_exception_code exc,
+ Msgbuf_base &reply_msg,
+ Msgbuf_base &request_msg)
{
Native_utcb &utcb = *Thread_base::myself()->utcb();
retry(
[&] () {
int ret = 0;
- if (_reply_needed) {
- utcb.copy_from(_snd_msg);
- utcb.exception_code(_exception_code.value);
- ret = Kernel::send_reply_msg(Msgbuf_base::MAX_CAP_ARGS, true);
+ if (exc.value != Rpc_exception_code::INVALID_OBJECT) {
+ copy_msg_to_utcb(reply_msg, utcb);
+ utcb.exception_code(exc.value);
+ ret = Kernel::send_reply_msg(Msgbuf_base::MAX_CAPS_PER_MSG, true);
} else {
- ret = Kernel::await_request_msg(Msgbuf_base::MAX_CAP_ARGS);
+ ret = Kernel::await_request_msg(Msgbuf_base::MAX_CAPS_PER_MSG);
}
switch (ret) {
@@ -116,27 +157,17 @@ void Ipc_server::reply_wait()
},
[&] () { upgrade_pd_session_quota(3*4096); });
- _rcv_msg.reset();
- _snd_msg.reset();
+ copy_utcb_to_msg(utcb, request_msg);
- utcb.copy_to(_rcv_msg);
- _badge = utcb.destination();
-
- _reply_needed = true;
- _read_offset = _write_offset = 0;
+ return Rpc_request(Native_capability(), utcb.destination());
}
-Ipc_server::Ipc_server(Native_connection_state &cs,
- Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
+Ipc_server::Ipc_server()
:
- Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
Native_capability(Thread_base::myself() ? Thread_base::myself()->native_thread().cap
- : Hw::_main_thread_cap),
- _rcv_cs(cs)
-{
- _snd_msg.reset();
-}
+ : Hw::_main_thread_cap)
+{ }
Ipc_server::~Ipc_server() { }
diff --git a/repos/base-hw/src/base/server/server.cc b/repos/base-hw/src/base/server/server.cc
deleted file mode 100644
index ce3d013348..0000000000
--- a/repos/base-hw/src/base/server/server.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * \brief base-hw specific part of RPC framework
- * \author Stefan Kalkowski
- * \date 2015-03-05
- */
-
-/*
- * Copyright (C) 2015 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-/* Genode includes */
-#include
-#include
-#include
-#include
-
-/* base-internal includes */
-#include
-
-using namespace Genode;
-
-
-/***********************
- ** Server entrypoint **
- ***********************/
-
-Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
-{
- Untyped_capability new_obj_cap = _alloc_rpc_cap(_pd_session, _cap);
-
- /* add server object to object pool */
- obj->cap(new_obj_cap);
- insert(obj);
-
- /* return capability that uses the object id as badge */
- return new_obj_cap;
-}
-
-
-void Rpc_entrypoint::entry()
-{
- Native_connection_state cs;
- Ipc_server srv(cs, _snd_buf, _rcv_buf);
- _ipc_server = &srv;
- _cap = srv;
- _cap_valid.unlock();
-
- /*
- * Now, the capability of the server activation is initialized
- * an can be passed around. However, the processing of capability
- * invocations should not happen until activation-using server
- * is completely initialized. Thus, we wait until the activation
- * gets explicitly unblocked by calling 'Rpc_entrypoint::activate()'.
- */
- _delay_start.lock();
-
- while (!_exit_handler.exit) {
-
- Rpc_opcode opcode(0);
-
- srv.reply_wait();
- srv.extract(opcode);
-
- /* set default return value */
- srv.ret(Rpc_exception_code(Rpc_exception_code::INVALID_OBJECT));
-
- /* atomically lookup and lock referenced object */
- apply(srv.badge(), [&] (Rpc_object_base *curr_obj) {
- if (!curr_obj) return;
-
- /* dispatch request */
- try { srv.ret(curr_obj->dispatch(opcode, srv, srv)); }
- catch (Blocking_canceled) { }
- });
- }
-
- /* answer exit call, thereby wake up '~Rpc_entrypoint' */
- srv.reply();
-
- /* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
- _delay_exit.lock();
-}
diff --git a/repos/base-hw/src/base/signal/signal.cc b/repos/base-hw/src/base/signal/signal.cc
index 4767eccfb1..47bbee3836 100644
--- a/repos/base-hw/src/base/signal/signal.cc
+++ b/repos/base-hw/src/base/signal/signal.cc
@@ -124,7 +124,7 @@ void Signal_receiver::block_for_signal()
return;
}
/* read signal data */
- const void * const utcb = Thread_base::myself()->utcb()->base();
+ const void * const utcb = Thread_base::myself()->utcb()->data();
Signal::Data * const data = (Signal::Data *)utcb;
Signal_context * const context = data->context;
{
diff --git a/repos/base-hw/src/core/include/kernel/ipc_node.h b/repos/base-hw/src/core/include/kernel/ipc_node.h
index ab28f9baa9..39c96071da 100644
--- a/repos/base-hw/src/core/include/kernel/ipc_node.h
+++ b/repos/base-hw/src/core/include/kernel/ipc_node.h
@@ -66,7 +66,7 @@ class Kernel::Ipc_node : public Ipc_node_queue::Element
Ipc_node_queue _request_queue;
/* pre-allocation array for obkject identity references */
- void * _obj_id_ref_ptr[Genode::Msgbuf_base::MAX_CAP_ARGS];
+ void * _obj_id_ref_ptr[Genode::Msgbuf_base::MAX_CAPS_PER_MSG];
inline void copy_msg(Ipc_node * const sender);
diff --git a/repos/base-hw/src/core/kernel/thread.cc b/repos/base-hw/src/core/kernel/thread.cc
index 7012e0a187..ff9ecdcc76 100644
--- a/repos/base-hw/src/core/kernel/thread.cc
+++ b/repos/base-hw/src/core/kernel/thread.cc
@@ -70,7 +70,7 @@ void Thread::_await_signal(Signal_receiver * const receiver)
void Thread::_receive_signal(void * const base, size_t const size)
{
assert(_state == AWAITS_SIGNAL);
- Genode::memcpy((void*)utcb()->base(), base, size);
+ Genode::memcpy(utcb()->data(), base, size);
_become_active();
}
diff --git a/repos/base-hw/src/core/rm_session_support.cc b/repos/base-hw/src/core/rm_session_support.cc
index 45c44a0ed0..78723cd147 100644
--- a/repos/base-hw/src/core/rm_session_support.cc
+++ b/repos/base-hw/src/core/rm_session_support.cc
@@ -48,7 +48,7 @@ void Pager_entrypoint::entry()
if (Kernel::await_signal(_cap.dst())) continue;
Untyped_capability cap =
- (*(Pager_object**)Thread_base::myself()->utcb()->base())->cap();
+ (*(Pager_object**)Thread_base::myself()->utcb()->data())->cap();
/*
* Synchronize access and ensure that the object is still managed
diff --git a/repos/base-hw/src/include/base/internal/native_utcb.h b/repos/base-hw/src/include/base/internal/native_utcb.h
index 07ee0b9d76..9ce79a8793 100644
--- a/repos/base-hw/src/include/base/internal/native_utcb.h
+++ b/repos/base-hw/src/include/base/internal/native_utcb.h
@@ -16,6 +16,8 @@
#define _INCLUDE__BASE__INTERNAL__NATIVE_UTCB_H_
/* Genode includes */
+#include
+#include
#include
#include
@@ -47,30 +49,37 @@ class Genode::Native_utcb
{
public:
- enum { MAX_CAP_ARGS = Msgbuf_base::MAX_CAP_ARGS};
+ enum { MAX_CAP_ARGS = Msgbuf_base::MAX_CAPS_PER_MSG};
enum Offsets { THREAD_MYSELF, PARENT, UTCB_DATASPACE };
private:
- Kernel::capid_t _caps[MAX_CAP_ARGS]; /* capability buffer */
+ /*
+ * Note thats the member variables are sorted from the largest to the
+ * smallest size to avoid padding. Otherwise, the dimensioning of
+ * '_data' would not yield a page-sized 'Native_utcb'.
+ */
+
size_t _cap_cnt; /* capability counter */
- size_t _size; /* bytes to transfer */
+ size_t _data_size; /* bytes to transfer */
long _exception_code; /* result code of RPC */
Kernel::capid_t _destination; /* invoked object */
- uint8_t _buf[get_page_size() - sizeof(_caps) -
- sizeof(_cap_cnt) - sizeof(_size) -
- sizeof(_destination) - sizeof(_exception_code)];
+ Kernel::capid_t _caps[MAX_CAP_ARGS]; /* capability buffer */
+ uint8_t _data[get_page_size() - sizeof(_caps) -
+ sizeof(_cap_cnt) - sizeof(_data_size) -
+ sizeof(_destination) - sizeof(_exception_code)];
public:
- Native_utcb& operator= (const Native_utcb &o)
+ Native_utcb& operator= (const Native_utcb &other)
{
_cap_cnt = 0;
- _size = o._size;
- _exception_code = o._exception_code;
- _destination = o._destination;
- memcpy(_buf, o._buf, _size);
+ _data_size = min(sizeof(_data), other._data_size);
+ _exception_code = other._exception_code;
+ _destination = other._destination;
+ memcpy(_data, other._data, _data_size);
+
return *this;
}
@@ -91,7 +100,7 @@ class Genode::Native_utcb
/**
* Return the count of capabilities in the UTCB
*/
- size_t cap_cnt() { return _cap_cnt; }
+ size_t cap_cnt() const { return _cap_cnt; }
/**
* Set the count of capabilities in the UTCB
@@ -101,41 +110,43 @@ class Genode::Native_utcb
/**
* Return the start address of the payload data
*/
- void const * base() const { return &_buf; }
+ void const *data() const { return &_data[0]; }
+ void *data() { return &_data[0]; }
/**
- * Copy data from the message buffer 'snd_msg' to this UTCB
+ * Return maximum number of bytes for message payload
*/
- void copy_from(Msgbuf_base const &snd_msg)
- {
- _size = min(snd_msg.data_size(), sizeof(_buf));
-
- _cap_cnt = snd_msg._snd_cap_cnt;
- for (unsigned i = 0; i < _cap_cnt; i++)
- _caps[i] = snd_msg._caps[i].dst();
-
- memcpy(_buf, snd_msg.buf, min(_size, snd_msg.capacity()));
- }
+ size_t capacity() const { return sizeof(_data); }
/**
- * Copy data from this UTCB to the message buffer 'o'
+ * Return size of message data in bytes
*/
- void copy_to(Msgbuf_base &o)
- {
- o._snd_cap_cnt = _cap_cnt;
- for (unsigned i = 0; i < _cap_cnt; i++) {
- o._caps[i] = _caps[i];
- if (o._caps[i].valid()) Kernel::ack_cap(o._caps[i].dst());
- }
+ size_t data_size() const { return _data_size; }
- memcpy(o.buf, _buf, min(_size, o.capacity()));
+ /**
+ * Define size of message data to be transferred, in bytes
+ */
+ void data_size(size_t data_size)
+ {
+ _data_size = min(data_size, sizeof(_data));
}
/**
* Return the capability id at index 'i'
*/
- Kernel::capid_t cap_get(unsigned i) {
- return (i < _cap_cnt) ? _caps[i] : Kernel::cap_id_invalid(); }
+ Kernel::capid_t cap_get(unsigned i) const
+ {
+ return (i < MAX_CAP_ARGS) ? _caps[i] : Kernel::cap_id_invalid();
+ }
+
+ /**
+ * Set the capability id at index 'i'
+ */
+ void cap_set(unsigned i, Kernel::capid_t cap)
+ {
+ if (i < MAX_CAP_ARGS)
+ _caps[i] = cap;
+ }
/**
* Set the capability id 'cap_id' at the next index
@@ -144,4 +155,7 @@ class Genode::Native_utcb
if (_cap_cnt < MAX_CAP_ARGS) _caps[_cap_cnt++] = cap_id; }
};
+static_assert(sizeof(Genode::Native_utcb) == Genode::get_page_size(),
+ "Native_utcb is not page-sized");
+
#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_UTCB_H_ */
diff --git a/repos/base-linux/include/base/ipc_msgbuf.h b/repos/base-linux/include/base/ipc_msgbuf.h
deleted file mode 100644
index 2a052b4a7d..0000000000
--- a/repos/base-linux/include/base/ipc_msgbuf.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * \brief Linux-specific layout of IPC message buffer
- * \author Norman Feske
- * \date 2006-06-14
- */
-
-/*
- * Copyright (C) 2006-2013 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
-#define _INCLUDE__BASE__IPC_MSGBUF_H_
-
-#include
-
-namespace Genode {
-
- class Ipc_marshaller;
-
- /**
- * IPC message buffer layout
- */
- class Msgbuf_base
- {
- public:
-
- enum { MAX_CAPS_PER_MSG = 8 };
-
- protected:
-
- friend class Ipc_marshaller;
-
- /*
- * Capabilities (file descriptors) to be transferred
- */
- int _caps[MAX_CAPS_PER_MSG];
- Genode::size_t _used_caps = 0;
- Genode::size_t _read_cap_index = 0;
-
- /**
- * Maximum size of plain-data message payload
- */
- Genode::size_t const _capacity;
-
- /**
- * Actual size of plain-data message payload
- */
- Genode::size_t _data_size = 0;
-
- Msgbuf_base(size_t capacity) : _capacity(capacity) { }
-
- struct Headroom { long space[4]; } _headroom;
-
- char _msg_start[]; /* symbol marks start of message buffer data */
-
- /*
- * No member variables are allowed beyond this point!
- */
-
- public:
-
- template
- T &header()
- {
- static_assert(sizeof(T) <= sizeof(Headroom),
- "Header size exceeds message headroom");
- return *reinterpret_cast(_msg_start - sizeof(T));
- }
-
- /**
- * Return size of message buffer
- */
- Genode::size_t capacity() const { return _capacity; };
-
- /**
- * Return pointer of message data payload
- */
- void *data() { return &_msg_start[0]; };
- void const *data() const { return &_msg_start[0]; };
-
- size_t data_size() const { return _data_size; }
-
- void reset_caps() { _used_caps = 0; _read_cap_index = 0; }
-
- bool append_cap(int cap)
- {
- if (_used_caps == MAX_CAPS_PER_MSG)
- return false;
-
- _caps[_used_caps++] = cap;
- return true;
- }
-
- int read_cap()
- {
- if (_read_cap_index == _used_caps)
- return -1;
-
- return _caps[_read_cap_index++];
- }
-
- size_t used_caps() const { return _used_caps; }
-
- int cap(unsigned index) const
- {
- return index < _used_caps ? _caps[index] : -1;
- }
- };
-
-
- /**
- * Pump up IPC message buffer to specified buffer size
- */
- template
- class Msgbuf : public Msgbuf_base
- {
- public:
-
- char buf[BUF_SIZE];
-
- Msgbuf() : Msgbuf_base(BUF_SIZE) { }
- };
-}
-
-
-#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
diff --git a/repos/base-linux/src/base/env/platform_env.cc b/repos/base-linux/src/base/env/platform_env.cc
index 8a9aeadc45..12afea271f 100644
--- a/repos/base-linux/src/base/env/platform_env.cc
+++ b/repos/base-linux/src/base/env/platform_env.cc
@@ -19,7 +19,7 @@
/* base-internal includes */
#include
-#include
+#include
using namespace Genode;
@@ -180,24 +180,25 @@ Platform_env::Platform_env()
namespace Genode {
- Native_connection_state server_socket_pair()
+ Socket_pair server_socket_pair()
{
Linux_native_cpu_client native_cpu(env()->cpu_session()->native_cpu());
- Native_connection_state ncs;
+ Socket_pair socket_pair;
Thread_base *thread = Thread_base::myself();
if (thread) {
- ncs.server_sd = native_cpu.server_sd(thread->cap()).dst().socket;
- ncs.client_sd = native_cpu.client_sd(thread->cap()).dst().socket;
+ socket_pair.server_sd = native_cpu.server_sd(thread->cap()).dst().socket;
+ socket_pair.client_sd = native_cpu.client_sd(thread->cap()).dst().socket;
+ thread->native_thread().socket_pair = socket_pair;
}
- return ncs;
+ return socket_pair;
}
- void destroy_server_socket_pair(Native_connection_state const &ncs)
+ void destroy_server_socket_pair(Socket_pair socket_pair)
{
/* close local file descriptor if it is valid */
- if (ncs.server_sd != -1) lx_close(ncs.server_sd);
- if (ncs.client_sd != -1) lx_close(ncs.client_sd);
+ if (socket_pair.server_sd != -1) lx_close(socket_pair.server_sd);
+ if (socket_pair.client_sd != -1) lx_close(socket_pair.client_sd);
}
}
diff --git a/repos/base-linux/src/base/ipc/ipc.cc b/repos/base-linux/src/base/ipc/ipc.cc
index 69ea157076..4b77b680ec 100644
--- a/repos/base-linux/src/base/ipc/ipc.cc
+++ b/repos/base-linux/src/base/ipc/ipc.cc
@@ -23,13 +23,13 @@
#include
#include
#include
+#include
/* Linux includes */
#include
#include
#include
-
using namespace Genode;
@@ -52,70 +52,20 @@ using namespace Genode;
*/
struct Protocol_header
{
+ /* badge of invoked object (on call) / exception code (on reply) */
unsigned long protocol_word;
+ size_t num_caps;
+
+ /* badges of the transferred capability arguments */
+ unsigned long badges[Msgbuf_base::MAX_CAPS_PER_MSG];
+
+ enum { INVALID_BADGE = ~0UL };
+
void *msg_start() { return &protocol_word; }
};
-
-/*****************************
- ** IPC marshalling support **
- *****************************/
-
-void Ipc_marshaller::insert(Native_capability const &cap)
-{
- if (cap.valid()) {
- insert(cap.local_name());
-
- _snd_msg.append_cap(cap.dst().socket);
- } else {
- insert(-1L);
- }
-}
-
-
-void Ipc_unmarshaller::extract(Native_capability &cap)
-{
- long local_name = 0;
- extract(local_name);
-
- if (local_name == -1) {
-
- /* construct invalid capability */
- cap = Genode::Native_capability();
-
- } else {
-
- /* construct valid capability */
- int const socket = _rcv_msg.read_cap();
- cap = Native_capability(Cap_dst_policy::Dst(socket), local_name);
- }
-}
-
-
-namespace Genode {
-
- /*
- * Helper for obtaining a bound and connected socket pair
- *
- * For core, the implementation is just a wrapper around
- * 'lx_server_socket_pair()'. For all other processes, the implementation
- * requests the socket pair from the Env::CPU session interface using a
- * Linux-specific interface extension.
- */
- Native_connection_state server_socket_pair();
-
- /*
- * Helper to destroy the server socket pair
- *
- * For core, this is a no-op. For all other processes, the server and client
- * sockets are closed.
- */
- void destroy_server_socket_pair(Native_connection_state const &ncs);
-}
-
-
/******************************
** File-descriptor registry **
******************************/
@@ -205,7 +155,7 @@ namespace {
{
public:
- enum { MAX_SDS_PER_MSG = Genode::Msgbuf_base::MAX_CAPS_PER_MSG };
+ enum { MAX_SDS_PER_MSG = Genode::Msgbuf_base::MAX_CAPS_PER_MSG + 1 };
private:
@@ -283,23 +233,51 @@ namespace {
} /* unnamed namespace */
+static void insert_sds_into_message(Message &msg,
+ Protocol_header &header,
+ Genode::Msgbuf_base &snd_msgbuf)
+{
+ for (unsigned i = 0; i < snd_msgbuf.used_caps(); i++) {
+
+ Native_capability const &cap = snd_msgbuf.cap(i);
+
+ if (cap.valid()) {
+ msg.marshal_socket(cap.dst().socket);
+ header.badges[i] = cap.local_name();
+ } else {
+ header.badges[i] = Protocol_header::INVALID_BADGE;
+ }
+
+ }
+ header.num_caps = snd_msgbuf.used_caps();
+}
+
+
/**
* Utility: Extract socket desriptors from SCM message into 'Genode::Msgbuf'
*/
-static void extract_sds_from_message(unsigned start_index, Message const &msg,
+static void extract_sds_from_message(unsigned start_index,
+ Message const &msg,
+ Protocol_header const &header,
Genode::Msgbuf_base &buf)
{
- buf.reset_caps();
+ unsigned sd_cnt = 0;
+ for (unsigned i = 0; i < min(header.num_caps, Msgbuf_base::MAX_CAPS_PER_MSG); i++) {
- /* start at offset 1 to skip the reply channel */
- for (unsigned i = start_index; i < msg.num_sockets(); i++) {
+ unsigned long const badge = header.badges[i];
- int const sd = msg.socket_at_index(i);
+ /* an invalid capabity was transferred */
+ if (badge == Protocol_header::INVALID_BADGE) {
+ buf.insert(Native_capability());
+ continue;
+ }
+
+ int const sd = msg.socket_at_index(start_index + sd_cnt++);
int const id = lookup_tid_by_client_socket(sd);
int const associated_sd = Genode::ep_sd_registry()->try_associate(sd, id);
- buf.append_cap(associated_sd);
+ buf.insert(Native_capability(Cap_dst_policy::Dst(associated_sd), badge));
if ((associated_sd >= 0) && (associated_sd != sd)) {
@@ -313,57 +291,6 @@ static void extract_sds_from_message(unsigned start_index, Message const &msg,
}
-/**
- * Return type of 'lx_wait'
- */
-struct Request
-{
- /**
- * Destination socket for sending the reply of the RPC function
- */
- int reply_socket = 0;
-
- /**
- * Identity of invoked server object
- */
- unsigned long badge = 0;
-};
-
-
-/**
- * for request from client
- *
- * \return socket descriptor of reply capability
- */
-static Request lx_wait(Genode::Native_connection_state &cs,
- Genode::Msgbuf_base &rcv_msgbuf)
-{
- Protocol_header &header = rcv_msgbuf.header();
- Message msg(header.msg_start(), sizeof(Protocol_header) + rcv_msgbuf.capacity());
-
- msg.accept_sockets(Message::MAX_SDS_PER_MSG);
-
- int const ret = lx_recvmsg(cs.server_sd, msg.msg(), 0);
-
- /* system call got interrupted by a signal */
- if (ret == -LX_EINTR)
- throw Genode::Blocking_canceled();
-
- if (ret < 0) {
- PRAW("lx_recvmsg failed with %d in lx_wait(), sd=%d", ret, cs.server_sd);
- throw Genode::Ipc_error();
- }
-
- Request request;
- request.reply_socket = msg.socket_at_index(0);
- request.badge = header.protocol_word;
-
- extract_sds_from_message(1, msg, rcv_msgbuf);
-
- return request;
-}
-
-
/**
* Send reply to client
*/
@@ -377,13 +304,10 @@ static inline void lx_reply(int reply_socket, Rpc_exception_code exception_code,
Message msg(header.msg_start(), sizeof(Protocol_header) + snd_msgbuf.data_size());
- /*
- * Marshall capabilities to be transferred to the client
- */
- for (unsigned i = 0; i < snd_msgbuf.used_caps(); i++)
- msg.marshal_socket(snd_msgbuf.cap(i));
+ /* marshall capabilities to be transferred to the client */
+ insert_sds_into_message(msg, header, snd_msgbuf);
- int ret = lx_sendmsg(reply_socket, msg.msg(), 0);
+ int const ret = lx_sendmsg(reply_socket, msg.msg(), 0);
/* ignore reply send error caused by disappearing client */
if (ret >= 0 || ret == -LX_ECONNREFUSED) {
@@ -392,7 +316,7 @@ static inline void lx_reply(int reply_socket, Rpc_exception_code exception_code,
}
if (ret < 0)
- PRAW("[%d] lx_sendmsg failed with %d in lx_reply()", lx_getpid(), ret);
+ PRAW("[%d] lx_sendmsg failed with %d in lx_reply() reply_socket=%d", lx_gettid(), ret, reply_socket);
}
@@ -448,8 +372,7 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
snd_msg.marshal_socket(reply_channel.remote_socket());
/* marshal capabilities contained in 'snd_msgbuf' */
- for (unsigned i = 0; i < snd_msgbuf.used_caps(); i++)
- snd_msg.marshal_socket(snd_msgbuf.cap(i));
+ insert_sds_into_message(snd_msg, snd_header, snd_msgbuf);
int const send_ret = lx_sendmsg(dst.dst().socket, snd_msg.msg(), 0);
if (send_ret < 0) {
@@ -466,6 +389,7 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
sizeof(Protocol_header) + rcv_msgbuf.capacity());
rcv_msg.accept_sockets(Message::MAX_SDS_PER_MSG);
+ rcv_msgbuf.reset();
int const recv_ret = lx_recvmsg(reply_channel.local_socket(), rcv_msg.msg(), 0);
/* system call got interrupted by a signal */
@@ -477,40 +401,31 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
throw Genode::Ipc_error();
}
- extract_sds_from_message(0, rcv_msg, rcv_msgbuf);
+ extract_sds_from_message(0, rcv_msg, rcv_header, rcv_msgbuf);
return Rpc_exception_code(rcv_header.protocol_word);
}
/****************
- ** Ipc_server **
+ ** IPC server **
****************/
-void Ipc_server::_prepare_next_reply_wait()
+void Genode::ipc_reply(Native_capability caller, Rpc_exception_code exc,
+ Msgbuf_base &snd_msg)
{
- _read_offset = _write_offset = 0;
-
- /* reset capability slots of send message buffer */
- _snd_msg.reset_caps();
+ try { lx_reply(caller.dst().socket, exc, snd_msg); } catch (Ipc_error) { }
}
-void Ipc_server::reply()
-{
- try {
- lx_reply(_caller.dst().socket, _exception_code, _snd_msg); }
- catch (Ipc_error) { }
-
- _prepare_next_reply_wait();
-}
-
-
-void Ipc_server::reply_wait()
+Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller,
+ Rpc_exception_code exc,
+ Msgbuf_base &reply_msg,
+ Msgbuf_base &request_msg)
{
/* when first called, there was no request yet */
- if (_reply_needed)
- lx_reply(_caller.dst().socket, _exception_code, _snd_msg);
+ if (last_caller.valid() && exc.value != Rpc_exception_code::INVALID_OBJECT)
+ lx_reply(last_caller.dst().socket, exc, reply_msg);
/*
* Block infinitely if called from the main thread. This may happen if the
@@ -521,71 +436,86 @@ void Ipc_server::reply_wait()
for (;;) lx_nanosleep(&ts, 0);
}
- try {
- Request const request = lx_wait(_rcv_cs, _rcv_msg);
+ for (;;) {
+
+ Protocol_header &header = request_msg.header();
+ Message msg(header.msg_start(), sizeof(Protocol_header) + request_msg.capacity());
+
+ msg.accept_sockets(Message::MAX_SDS_PER_MSG);
+
+ Native_thread &native_thread = Thread_base::myself()->native_thread();
+
+ request_msg.reset();
+ int const ret = lx_recvmsg(native_thread.socket_pair.server_sd, msg.msg(), 0);
+
+ /* system call got interrupted by a signal */
+ if (ret == -LX_EINTR)
+ continue;
+
+ if (ret < 0) {
+ PRAW("lx_recvmsg failed with %d in ipc_reply_wait, sd=%d",
+ ret, native_thread.socket_pair.server_sd);
+ continue;
+ }
+
+ int const reply_socket = msg.socket_at_index(0);
+ unsigned long const badge = header.protocol_word;
+
+ /* start at offset 1 to skip the reply channel */
+ extract_sds_from_message(1, msg, header, request_msg);
- /* remember reply capability */
- enum { DUMMY_LOCAL_NAME = -1 };
typedef Native_capability::Dst Dst;
- _caller = Native_capability(Dst(request.reply_socket), DUMMY_LOCAL_NAME);
- _badge = request.badge;
-
- _prepare_next_reply_wait();
-
- } catch (Blocking_canceled) { }
-
- _reply_needed = true;
+ return Rpc_request(Native_capability(Dst(reply_socket), ~0UL), badge);
+ }
}
-Ipc_server::Ipc_server(Native_connection_state &cs,
- Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
+Ipc_server::Ipc_server()
:
- Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg),
- Native_capability(Dst(-1), 0),
- _rcv_cs(cs)
+ Native_capability(Dst(-1), 0)
{
- Thread_base *thread = Thread_base::myself();
-
/*
* If 'thread' is 0, the constructor was called by the main thread. By
* definition, main is never an RPC entrypoint. However, the main thread
* may call 'sleep_forever()', which instantiates 'Ipc_server'.
*/
+ if (!Thread_base::myself())
+ return;
- if (thread && thread->native_thread().is_ipc_server) {
+ Native_thread &native_thread = Thread_base::myself()->native_thread();
+
+ if (native_thread.is_ipc_server) {
PRAW("[%d] unexpected multiple instantiation of Ipc_server by one thread",
lx_gettid());
struct Ipc_server_multiple_instance { };
throw Ipc_server_multiple_instance();
}
- if (thread) {
- _rcv_cs = server_socket_pair();
- thread->native_thread().is_ipc_server = true;
- }
+ Socket_pair const socket_pair = server_socket_pair();
+
+ native_thread.socket_pair = socket_pair;
+ native_thread.is_ipc_server = true;
/* override capability initialization */
*static_cast(this) =
- Native_capability(Native_capability::Dst(_rcv_cs.client_sd), 0);
-
- _prepare_next_reply_wait();
+ Native_capability(Native_capability::Dst(socket_pair.client_sd), 0);
}
Ipc_server::~Ipc_server()
{
- Genode::ep_sd_registry()->disassociate(_rcv_cs.client_sd);
+ if (!Thread_base::myself())
+ return;
/*
* Reset thread role to non-server such that we can enter 'sleep_forever'
* without getting a warning.
*/
- Thread_base *thread = Thread_base::myself();
- if (thread)
- thread->native_thread().is_ipc_server = false;
+ Native_thread &native_thread = Thread_base::myself()->native_thread();
- destroy_server_socket_pair(_rcv_cs);
- _rcv_cs.client_sd = -1;
- _rcv_cs.server_sd = -1;
+ Genode::ep_sd_registry()->disassociate(native_thread.socket_pair.client_sd);
+ native_thread.is_ipc_server = false;
+
+ destroy_server_socket_pair(native_thread.socket_pair);
+ native_thread.socket_pair = Socket_pair();
}
diff --git a/repos/base-linux/src/core/include/platform_thread.h b/repos/base-linux/src/core/include/platform_thread.h
index 1a7d46461a..84486d2b0e 100644
--- a/repos/base-linux/src/core/include/platform_thread.h
+++ b/repos/base-linux/src/core/include/platform_thread.h
@@ -21,7 +21,7 @@
#include
/* base-internal includes */
-#include
+#include
/* core includes */
#include
@@ -68,7 +68,7 @@ namespace Genode {
/**
* Unix-domain socket pair bound to the thread
*/
- Native_connection_state _ncs;
+ Socket_pair _socket_pair;
/*
* Dummy pager object that is solely used for storing the
diff --git a/repos/base-linux/src/core/include/server_socket_pair.h b/repos/base-linux/src/core/include/server_socket_pair.h
index 68d18275fe..f0a133ab6b 100644
--- a/repos/base-linux/src/core/include/server_socket_pair.h
+++ b/repos/base-linux/src/core/include/server_socket_pair.h
@@ -21,6 +21,7 @@
/* base-internal includes */
#include
+#include
/* core-local includes */
#include
@@ -43,25 +44,25 @@ struct Uds_addr : sockaddr_un
/**
* Utility: Create named socket pair for given unique ID
*/
-static inline Genode::Native_connection_state create_server_socket_pair(long id)
+static inline Genode::Socket_pair create_server_socket_pair(long id)
{
- Genode::Native_connection_state ncs;
+ Genode::Socket_pair socket_pair;
/*
* Main thread uses 'Ipc_server' for 'sleep_forever()' only. No need for
* binding.
*/
if (id == -1)
- return ncs;
+ return socket_pair;
Uds_addr addr(id);
/*
* Create server-side socket
*/
- ncs.server_sd = lx_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
- if (ncs.server_sd < 0) {
- PRAW("Error: Could not create server-side socket (ret=%d)", ncs.server_sd);
+ socket_pair.server_sd = lx_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ if (socket_pair.server_sd < 0) {
+ PRAW("Error: Could not create server-side socket (ret=%d)", socket_pair.server_sd);
class Server_socket_failed { };
throw Server_socket_failed();
}
@@ -69,7 +70,7 @@ static inline Genode::Native_connection_state create_server_socket_pair(long id)
/* make sure bind succeeds */
lx_unlink(addr.sun_path);
- int const bind_ret = lx_bind(ncs.server_sd, (sockaddr *)&addr, sizeof(addr));
+ int const bind_ret = lx_bind(socket_pair.server_sd, (sockaddr *)&addr, sizeof(addr));
if (bind_ret < 0) {
PRAW("Error: Could not bind server socket (ret=%d)", bind_ret);
class Bind_failed { };
@@ -79,21 +80,21 @@ static inline Genode::Native_connection_state create_server_socket_pair(long id)
/*
* Create client-side socket
*/
- ncs.client_sd = lx_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
- if (ncs.client_sd < 0) {
- PRAW("Error: Could not create client-side socket (ret=%d)", ncs.client_sd);
+ socket_pair.client_sd = lx_socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ if (socket_pair.client_sd < 0) {
+ PRAW("Error: Could not create client-side socket (ret=%d)", socket_pair.client_sd);
class Client_socket_failed { };
throw Client_socket_failed();
}
- int const conn_ret = lx_connect(ncs.client_sd, (sockaddr *)&addr, sizeof(addr));
+ int const conn_ret = lx_connect(socket_pair.client_sd, (sockaddr *)&addr, sizeof(addr));
if (conn_ret < 0) {
PRAW("Error: Could not connect client-side socket (ret=%d)", conn_ret);
class Connect_failed { };
throw Connect_failed();
}
- ncs.client_sd = Genode::ep_sd_registry()->try_associate(ncs.client_sd, id);
+ socket_pair.client_sd = Genode::ep_sd_registry()->try_associate(socket_pair.client_sd, id);
/*
* Wipe Unix domain socket from the file system. It will live as long as
@@ -101,7 +102,7 @@ static inline Genode::Native_connection_state create_server_socket_pair(long id)
*/
lx_unlink(addr.sun_path);
- return ncs;
+ return socket_pair;
}
#endif /* _CORE__INCLUDE__SERVER_SOCKET_PAIR_H_ */
diff --git a/repos/base-linux/src/core/platform.cc b/repos/base-linux/src/core/platform.cc
index dd759c2db5..9467c06d6f 100644
--- a/repos/base-linux/src/core/platform.cc
+++ b/repos/base-linux/src/core/platform.cc
@@ -158,19 +158,19 @@ void Core_parent::exit(int exit_value)
namespace Genode {
- Native_connection_state server_socket_pair()
+ Socket_pair server_socket_pair()
{
return create_server_socket_pair(Thread_base::myself()->native_thread().tid);
}
- void destroy_server_socket_pair(Native_connection_state const &ncs)
+ void destroy_server_socket_pair(Socket_pair socket_pair)
{
/*
* As entrypoints in core are never destructed, this function is only
* called on IPC-client destruction. In this case, it's a no-op in core
* as well as in Genode processes.
*/
- if (ncs.server_sd != -1 || ncs.client_sd != -1)
+ if (socket_pair.server_sd != -1 || socket_pair.client_sd != -1)
PERR("%s called for IPC server which should never happen", __func__);
}
}
diff --git a/repos/base-linux/src/core/platform_thread.cc b/repos/base-linux/src/core/platform_thread.cc
index 060ca43df6..f7fe433a39 100644
--- a/repos/base-linux/src/core/platform_thread.cc
+++ b/repos/base-linux/src/core/platform_thread.cc
@@ -85,13 +85,13 @@ Platform_thread::Platform_thread(size_t, const char *name, unsigned, addr_t)
Platform_thread::~Platform_thread()
{
- ep_sd_registry()->disassociate(_ncs.client_sd);
+ ep_sd_registry()->disassociate(_socket_pair.client_sd);
- if (_ncs.client_sd)
- lx_close(_ncs.client_sd);
+ if (_socket_pair.client_sd)
+ lx_close(_socket_pair.client_sd);
- if (_ncs.server_sd)
- lx_close(_ncs.server_sd);
+ if (_socket_pair.server_sd)
+ lx_close(_socket_pair.server_sd);
_registry()->remove(this);
}
@@ -119,15 +119,15 @@ void Platform_thread::resume()
int Platform_thread::client_sd()
{
/* construct socket pair on first call */
- if (_ncs.client_sd == -1)
- _ncs = create_server_socket_pair(_tid);
+ if (_socket_pair.client_sd == -1)
+ _socket_pair = create_server_socket_pair(_tid);
- return _ncs.client_sd;
+ return _socket_pair.client_sd;
}
int Platform_thread::server_sd()
{
client_sd();
- return _ncs.server_sd;
+ return _socket_pair.server_sd;
}
diff --git a/repos/base-linux/src/include/base/internal/native_connection_state.h b/repos/base-linux/src/include/base/internal/native_connection_state.h
deleted file mode 100644
index 2a7cc7cc40..0000000000
--- a/repos/base-linux/src/include/base/internal/native_connection_state.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * \brief Connection state of incoming RPC request
- * \author Norman Feske
- * \date 2016-03-03
- */
-
-/*
- * Copyright (C) 2016 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__BASE__INTERNAL__NATIVE_CONNECTION_STATE_H_
-#define _INCLUDE__BASE__INTERNAL__NATIVE_CONNECTION_STATE_H_
-
-#include
-
-namespace Genode { struct Native_connection_state; }
-
-
-struct Genode::Native_connection_state
-{
- int server_sd = -1;
- int client_sd = -1;
-};
-
-#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_CONNECTION_STATE_H_ */
diff --git a/repos/base-linux/src/include/base/internal/native_thread.h b/repos/base-linux/src/include/base/internal/native_thread.h
index 5cd901dda6..5f1a3a5ab2 100644
--- a/repos/base-linux/src/include/base/internal/native_thread.h
+++ b/repos/base-linux/src/include/base/internal/native_thread.h
@@ -15,6 +15,7 @@
#define _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_
#include
+#include
namespace Genode { struct Native_thread; }
@@ -45,6 +46,8 @@ struct Genode::Native_thread
*/
Meta_data *meta_data = nullptr;
+ Socket_pair socket_pair;
+
Native_thread() { }
};
diff --git a/repos/base-linux/src/include/base/internal/server_socket_pair.h b/repos/base-linux/src/include/base/internal/server_socket_pair.h
new file mode 100644
index 0000000000..d59f38c413
--- /dev/null
+++ b/repos/base-linux/src/include/base/internal/server_socket_pair.h
@@ -0,0 +1,44 @@
+/*
+ * \brief Socket pair used by RPC entrypoint
+ * \author Norman Feske
+ * \date 2016-03-25
+ */
+
+/*
+ * Copyright (C) 2016 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _INCLUDE__BASE__INTERNAL__SERVER_SOCKET_PAIR_H_
+#define _INCLUDE__BASE__INTERNAL__SERVER_SOCKET_PAIR_H_
+
+namespace Genode {
+
+ struct Socket_pair
+ {
+ int client_sd = -1;
+ int server_sd = -1;
+ };
+
+ /*
+ * Helper for obtaining a bound and connected socket pair
+ *
+ * For core, the implementation is just a wrapper around
+ * 'lx_server_socket_pair()'. For all other processes, the implementation
+ * requests the socket pair from the Env::CPU session interface using a
+ * Linux-specific interface extension.
+ */
+ Socket_pair server_socket_pair();
+
+ /*
+ * Helper to destroy the server socket pair
+ *
+ * For core, this is a no-op. For all other processes, the server and client
+ * sockets are closed.
+ */
+ void destroy_server_socket_pair(Socket_pair);
+}
+
+#endif /* _INCLUDE__BASE__INTERNAL__SERVER_SOCKET_PAIR_H_ */
diff --git a/repos/base-nova/include/base/ipc_msgbuf.h b/repos/base-nova/include/base/ipc_msgbuf.h
deleted file mode 100644
index b09bb5ee7b..0000000000
--- a/repos/base-nova/include/base/ipc_msgbuf.h
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * \brief IPC message buffer layout for NOVA
- * \author Norman Feske
- * \author Alexander Boettcher
- * \date 2009-10-02
- *
- * On NOVA, we use IPC to transmit plain data and for capability delegation
- * and capability translation.
- * Therefore the message buffer contains three categories of payload. The
- * capability-specific part are the members '_snd_pt*' (sending capability
- * selectors) and '_rcv_pt*' (receiving capability selectors).
- */
-
-/*
- * Copyright (C) 2009-2013 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
-#define _INCLUDE__BASE__IPC_MSGBUF_H_
-
-/* NOVA includes */
-#include
-#include
-
-namespace Genode {
-
- class Ipc_marshaller;
-
- class Msgbuf_base
- {
- public:
-
- enum {
- MAX_CAP_ARGS_LOG2 = 2,
- MAX_CAP_ARGS = 1 << MAX_CAP_ARGS_LOG2
- };
-
- protected:
-
- friend class Ipc_marshaller;
-
- size_t const _capacity;
-
- size_t _data_size = 0;
-
- /**
- * Number of portal-capability selectors to send
- */
- size_t _snd_pt_sel_cnt = 0;
-
- /**
- * Portal capability selectors to delegate
- */
- Native_capability _snd_pt_sel[MAX_CAP_ARGS];
-
- /**
- * Base of portal receive window
- */
- addr_t _rcv_pt_base = 0;
-
- struct {
- addr_t sel = 0;
- bool del = 0;
- } _rcv_pt_sel[MAX_CAP_ARGS];
-
- /**
- * Normally the received capabilities start from the beginning of
- * the receive window (_rcv_pt_base), densely packed ascending.
- * However, a receiver may send invalid caps, which will cause
- * capability-selector gaps in the receiver window. Or a
- * misbehaving sender may even intentionally place a cap at the end
- * of the receive window. The position of a cap within the receive
- * window is fundamentally important to correctly maintain the
- * component-local capability-selector reference count.
- *
- * Additionally, the position is also required to decide whether a
- * kernel capability must be revoked during the receive window
- * cleanup/re-usage. '_rcv_pt_cap_free' is used to track this
- * information in order to free up and revoke selectors
- * (message-buffer cleanup).
- *
- * Meanings of the enums:
- * - FREE_INVALID - invalid cap selector, no cap_map entry
- * - FREE_SEL - valid cap selector, invalid kernel capability
- * - UNUSED_CAP - valid selector and cap, not read/used yet
- * - USED_CAP - valid sel and cap, read/used by stream operator
- */
- enum { FREE_INVALID, FREE_SEL, UNUSED_CAP, USED_CAP }
- _rcv_pt_cap_free [MAX_CAP_ARGS];
-
- /**
- * Read counter for unmarshalling portal capability
- * selectors
- */
- unsigned short _rcv_pt_sel_cnt = 0;
- unsigned short _rcv_pt_sel_max = 0;
- unsigned short _rcv_wnd_log2 = 0;
-
- char _msg_start[]; /* symbol marks start of message */
-
- public:
-
- enum { INVALID_INDEX = ~0UL };
-
- /**
- * Constructor
- */
- Msgbuf_base(size_t capacity)
- :
- _capacity(capacity),
- _rcv_pt_base(INVALID_INDEX), _rcv_wnd_log2(MAX_CAP_ARGS_LOG2)
- {
- rcv_reset();
- snd_reset();
- }
-
- ~Msgbuf_base()
- {
- rcv_reset();
- }
-
- /*
- * Begin of actual message buffer
- */
- char buf[];
-
- /**
- * Return size of message buffer
- */
- size_t capacity() const { return _capacity; }
-
- /**
- * Return pointer of message data payload
- */
- void *data() { return &_msg_start[0]; }
- void const *data() const { return &_msg_start[0]; }
-
- unsigned long &word(unsigned i)
- {
- return reinterpret_cast(buf)[i];
- }
-
- size_t data_size() const { return _data_size; }
-
- /**
- * Reset portal capability selector payload
- */
- void snd_reset() {
-
- for (unsigned i = 0; i < MAX_CAP_ARGS; i++) {
- +_snd_pt_sel[i];
- _snd_pt_sel[i] = Native_capability();
- }
-
- _snd_pt_sel_cnt = 0;
- }
-
- /**
- * Append portal capability selector to message buffer
- */
- bool snd_append_pt_sel(Native_capability const &cap)
- {
- if (_snd_pt_sel_cnt >= MAX_CAP_ARGS - 1)
- return false;
-
- _snd_pt_sel[_snd_pt_sel_cnt++ ] = cap;
- return true;
- }
-
- /**
- * Return number of marshalled portal-capability
- * selectors
- */
- size_t snd_pt_sel_cnt() const
- {
- return _snd_pt_sel_cnt;
- }
-
- /**
- * Return portal capability selector
- *
- * \param i index (0 ... 'pt_sel_cnt()' - 1)
- * \return portal-capability range descriptor
- *
- * The returned object could be a null cap. Use
- * is_null method to check for it.
- */
- Nova::Obj_crd snd_pt_sel(addr_t i, bool &trans_map) const
- {
- if (i >= _snd_pt_sel_cnt)
- return Nova::Obj_crd();
-
- trans_map = _snd_pt_sel[i].trans_map();
-
- return Nova::Obj_crd(_snd_pt_sel[i].local_name(), 0,
- _snd_pt_sel[i].dst().rights());
- }
-
- /**
- * Request current portal-receive window
- */
- addr_t rcv_pt_base() const { return _rcv_pt_base; }
-
- /**
- * Set log2 number of capabilities to be received during reply of
- * a IPC call.
- */
- void rcv_wnd(unsigned short const caps_log2)
- {
- if (caps_log2 > MAX_CAP_ARGS_LOG2)
- nova_die();
-
- _rcv_wnd_log2 = caps_log2;
- }
-
- /**
- * Reset portal-capability receive window
- */
- void rcv_reset()
- {
- if (!rcv_invalid()) { rcv_cleanup(false); }
-
- _rcv_pt_sel_cnt = 0;
- _rcv_pt_sel_max = 0;
- _rcv_pt_base = INVALID_INDEX;
- }
-
- /**
- * Return received portal-capability selector
- */
- void rcv_pt_sel(Native_capability &cap)
- {
- if (_rcv_pt_sel_cnt >= _rcv_pt_sel_max) {
- cap = Native_capability();
- return;
- }
-
- /* return only received or translated caps */
- cap = Native_capability(_rcv_pt_sel[_rcv_pt_sel_cnt++].sel);
- }
-
- /**
- * Return true if receive window must be re-initialized
- */
- bool rcv_invalid() const
- {
- return _rcv_pt_base == INVALID_INDEX;
- }
-
- /**
- * Return true if receive window must be re-initialized
- *
- * After reading portal selectors from the message
- * buffer using 'rcv_pt_sel()', we assume that the IDC
- * call populated the current receive window with one
- * or more portal capabilities.
- * To enable the reception of portal capability
- * selectors for the next IDC, we need a fresh receive
- * window.
- *
- * \param keep 'true' - Try to keep receive window if
- * it's clean.
- * 'false' - Free caps of receive window
- * because object is freed
- * afterwards.
- *
- * \result 'true' - receive window must be re-initialized
- * 'false' - portal selectors has been kept
- */
- bool rcv_cleanup(bool keep, unsigned short const new_max = MAX_CAP_ARGS)
- {
- /* mark used mapped capabilities as used to prevent freeing */
- bool reinit = false;
- for (unsigned i = 0; i < _rcv_pt_sel_cnt; i++) {
- if (!_rcv_pt_sel[i].del)
- continue;
-
- /* should never happen */
- if (_rcv_pt_sel[i].sel < rcv_pt_base() ||
- (_rcv_pt_sel[i].sel >= rcv_pt_base() + MAX_CAP_ARGS))
- nova_die();
-
- _rcv_pt_cap_free [_rcv_pt_sel[i].sel - rcv_pt_base()] = USED_CAP;
-
- reinit = true;
- }
-
- /* if old receive window was smaller, we need to re-init */
- for (unsigned i = 0; !reinit && i < new_max; i++)
- if (_rcv_pt_cap_free[i] == FREE_INVALID)
- reinit = true;
-
- _rcv_pt_sel_cnt = 0;
- _rcv_pt_sel_max = 0;
-
- /* we can keep the cap selectors if none was used */
- if (keep && !reinit) {
- for (unsigned i = 0; i < MAX_CAP_ARGS; i++) {
- /* revoke received caps which are unused */
- if (_rcv_pt_cap_free[i] == UNUSED_CAP)
- Nova::revoke(Nova::Obj_crd(rcv_pt_base() + i, 0), true);
-
- /* free rest of indexes if new_max is smaller then last window */
- if (i >= new_max && _rcv_pt_cap_free[i] == FREE_SEL)
- cap_map()->remove(rcv_pt_base() + i, 0, false);
- }
-
- return false;
- }
-
- /* decrease ref count if valid selector */
- for (unsigned i = 0; i < MAX_CAP_ARGS; i++) {
- if (_rcv_pt_cap_free[i] == FREE_INVALID)
- continue;
- cap_map()->remove(rcv_pt_base() + i, 0, _rcv_pt_cap_free[i] != FREE_SEL);
- }
-
- return true;
- }
-
- /**
- * Initialize receive window for portal capability
- * selectors
- *
- * \param utcb - UTCB of designated receiver
- * thread
- * \param rcv_window - If specified - receive exactly
- * one capability at the specified
- * index of rcv_window
- *
- * Depending on the 'rcv_invalid', 'rcv_cleanup(true)'
- * state of the message buffer and the specified
- * rcv_window parameter, this function allocates a
- * fresh receive window and clears 'rcv_invalid'.
- */
- bool prepare_rcv_window(Nova::Utcb *utcb,
- addr_t rcv_window = INVALID_INDEX)
- {
- /* open maximal translate window */
- utcb->crd_xlt = Nova::Obj_crd(0, ~0UL);
-
- /* use receive window if specified */
- if (rcv_window != INVALID_INDEX) {
- /* cleanup if receive window already used */
- if (!rcv_invalid()) rcv_cleanup(false);
-
- _rcv_pt_base = rcv_window;
-
- /* open receive window */
- utcb->crd_rcv = Nova::Obj_crd(rcv_pt_base(), _rcv_wnd_log2);
- return true;
- }
-
- /* allocate receive window if necessary, otherwise use old one */
- if (rcv_invalid() || rcv_cleanup(true, 1U << _rcv_wnd_log2))
- {
- _rcv_pt_base = cap_map()->insert(_rcv_wnd_log2);
-
- if (_rcv_pt_base == INVALID_INDEX) {
- /* no mappings can be received */
- utcb->crd_rcv = Nova::Obj_crd();
- return false;
- }
- }
-
- /* open receive window */
- utcb->crd_rcv = Nova::Obj_crd(rcv_pt_base(), _rcv_wnd_log2);
- return true;
- }
-
- /**
- * Post IPC processing.
- *
- * Remember where and which caps have been received
- * respectively have been translated.
- * The information is required to correctly free
- * cap indexes and to revoke unused received caps.
- *
- * \param utcb UTCB of designated receiver thread
- */
- void post_ipc(Nova::Utcb *utcb, addr_t const rcv_window = INVALID_INDEX)
- {
- using namespace Nova;
-
- unsigned const rcv_items = (utcb->items >> 16) & 0xffffu;
-
- _rcv_pt_sel_max = 0;
- _rcv_pt_sel_cnt = 0;
-
- unsigned short const max = 1U << utcb->crd_rcv.order();
- if (max > MAX_CAP_ARGS)
- nova_die();
-
- for (unsigned short i = 0; i < MAX_CAP_ARGS; i++)
- _rcv_pt_cap_free [i] = (i >= max) ? FREE_INVALID : FREE_SEL;
-
- for (unsigned i = 0; i < rcv_items; i++) {
- Nova::Utcb::Item * item = utcb->get_item(i);
- if (!item)
- break;
-
- Nova::Crd cap(item->crd);
-
- /* track which items we got mapped */
- if (!cap.is_null() && item->is_del()) {
- /* should never happen */
- if (cap.base() < rcv_pt_base() ||
- (cap.base() >= rcv_pt_base() + max))
- nova_die();
- _rcv_pt_cap_free [cap.base() - rcv_pt_base()] = UNUSED_CAP;
- }
-
- if (_rcv_pt_sel_max >= max) continue;
-
- /* track the order of mapped and translated items */
- if (cap.is_null()) {
- _rcv_pt_sel[_rcv_pt_sel_max].sel = INVALID_INDEX;
- _rcv_pt_sel[_rcv_pt_sel_max++].del = false;
- } else {
- _rcv_pt_sel[_rcv_pt_sel_max].sel = cap.base();
- _rcv_pt_sel[_rcv_pt_sel_max++].del = item->is_del();
- }
- }
-
- /*
- * If a specific rcv_window has been specified,
- * (see prepare_rcv_window) then the caller want to take care
- * about freeing the * selector. Make the _rcv_pt_base invalid
- * so that it is not cleanup twice.
- */
- if (rcv_window != INVALID_INDEX)
- _rcv_pt_base = INVALID_INDEX;
-
- utcb->crd_rcv = 0;
- }
- };
-
-
- template
- class Msgbuf : public Msgbuf_base
- {
- public:
-
- char buf[BUF_SIZE];
-
- Msgbuf() : Msgbuf_base(BUF_SIZE) { }
- };
-}
-
-#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
diff --git a/repos/base-nova/include/base/native_types.h b/repos/base-nova/include/base/native_types.h
index 3bad1694d5..246536bbf3 100644
--- a/repos/base-nova/include/base/native_types.h
+++ b/repos/base-nova/include/base/native_types.h
@@ -54,7 +54,6 @@ namespace Genode {
: dst(sel, 0, rights) { }
} _cap;
- bool _trans_map;
addr_t _rcv_window;
enum { INVALID_INDEX = ~0UL };
@@ -80,7 +79,7 @@ namespace Genode {
*/
Native_capability()
- : _cap(), _trans_map(true), _rcv_window(INVALID_INDEX) {}
+ : _cap(), _rcv_window(INVALID_INDEX) {}
explicit
Native_capability(addr_t sel, unsigned rights = 0x1f)
@@ -92,13 +91,12 @@ namespace Genode {
_inc();
}
- _trans_map = true;
- _rcv_window = INVALID_INDEX;
+ _rcv_window = INVALID_INDEX;
}
Native_capability(const Native_capability &o)
- : _cap(o._cap), _trans_map(o._trans_map),
- _rcv_window(o._rcv_window) { if (valid()) _inc(); }
+ : _cap(o._cap), _rcv_window(o._rcv_window)
+ { if (valid()) _inc(); }
~Native_capability() { if (valid()) _dec(); }
@@ -108,10 +106,13 @@ namespace Genode {
bool operator==(const Native_capability &o) const {
return local_name() == o.local_name(); }
- Native_capability operator+ () const
+ /**
+ * Inhibit removal of capability from cap map if it's the last reference
+ */
+ void keep_if_last_reference()
{
- if (valid()) _inc(true);
- return *this;
+ if (valid())
+ _inc(true);
}
/**
@@ -126,7 +127,6 @@ namespace Genode {
if (valid()) _dec();
_cap = o._cap;
- _trans_map = o._trans_map;
_rcv_window = o._rcv_window;
if (valid()) _inc();
@@ -179,17 +179,6 @@ namespace Genode {
{
return Native_capability();
}
-
- /**
- * Invoke map syscall instead of translate_map call
- */
- void solely_map() { _trans_map = false; }
-
- /**
- * Return true if the cap should be tried first to
- * be translated and if this fails it should be mapped.
- */
- bool trans_map() const { return _trans_map; }
};
}
diff --git a/repos/base-nova/include/nova/native_thread.h b/repos/base-nova/include/nova/native_thread.h
index d74ef62315..32aec3fa9f 100644
--- a/repos/base-nova/include/nova/native_thread.h
+++ b/repos/base-nova/include/nova/native_thread.h
@@ -20,6 +20,7 @@
#define _INCLUDE__NOVA__NATIVE_THREAD_H_
#include
+#include
namespace Genode { struct Native_thread; }
@@ -31,6 +32,9 @@ struct Genode::Native_thread
addr_t exc_pt_sel; /* base of event portal window */
bool is_vcpu;
+ /* receive window for capability selectors received at the server side */
+ Receive_window rcv_window;
+
Native_thread() : ec_sel(INVALID_INDEX),
exc_pt_sel(INVALID_INDEX), is_vcpu(false) { }
};
diff --git a/repos/base-nova/include/nova/receive_window.h b/repos/base-nova/include/nova/receive_window.h
new file mode 100644
index 0000000000..3ce7509041
--- /dev/null
+++ b/repos/base-nova/include/nova/receive_window.h
@@ -0,0 +1,338 @@
+/*
+ * \brief Receive window for capability selectors
+ * \author Alexander Boettcher
+ * \author Norman Feske
+ * \date 2016-03-22
+ */
+
+/*
+ * Copyright (C) 2016 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _INCLUDE__NOVA__RECEIVE_WINDOW_H_
+#define _INCLUDE__NOVA__RECEIVE_WINDOW_H_
+
+/* Genode includes */
+#include
+#include
+
+/* NOVA includes */
+#include
+#include
+
+namespace Genode { struct Receive_window; }
+
+
+struct Genode::Receive_window
+{
+ public:
+
+ enum {
+ MAX_CAP_ARGS_LOG2 = 2,
+ MAX_CAP_ARGS = 1UL << MAX_CAP_ARGS_LOG2
+ };
+
+ static_assert(MAX_CAP_ARGS == (size_t)Msgbuf_base::MAX_CAPS_PER_MSG,
+ "Inconsistency between Receive_window and Msgbuf_base");
+
+ private:
+
+ /**
+ * Base of portal receive window
+ */
+ addr_t _rcv_pt_base = 0;
+
+ struct {
+ addr_t sel = 0;
+ bool del = 0;
+ } _rcv_pt_sel[MAX_CAP_ARGS];
+
+ /**
+ * Normally the received capabilities start from the beginning of
+ * the receive window (_rcv_pt_base), densely packed ascending.
+ * However, a receiver may send invalid caps, which will cause
+ * capability-selector gaps in the receiver window. Or a
+ * misbehaving sender may even intentionally place a cap at the end
+ * of the receive window. The position of a cap within the receive
+ * window is fundamentally important to correctly maintain the
+ * component-local capability-selector reference count.
+ *
+ * Additionally, the position is also required to decide whether a
+ * kernel capability must be revoked during the receive window
+ * cleanup/re-usage. '_rcv_pt_cap_free' is used to track this
+ * information in order to free up and revoke selectors
+ * (message-buffer cleanup).
+ *
+ * Meanings of the enums:
+ * - FREE_INVALID - invalid cap selector, no cap_map entry
+ * - FREE_SEL - valid cap selector, invalid kernel capability
+ * - UNUSED_CAP - valid selector and cap, not read/used yet
+ * - USED_CAP - valid sel and cap, read/used by stream operator
+ */
+ enum { FREE_INVALID, FREE_SEL, UNUSED_CAP, USED_CAP }
+ _rcv_pt_cap_free [MAX_CAP_ARGS];
+
+ /**
+ * Read counter for unmarshalling portal capability
+ * selectors
+ */
+ unsigned short _rcv_pt_sel_cnt = 0;
+ unsigned short _rcv_pt_sel_max = 0;
+ unsigned short _rcv_wnd_log2 = 0;
+
+ /**
+ * Reset portal-capability receive window
+ */
+ void _rcv_reset()
+ {
+ if (!rcv_invalid()) { rcv_cleanup(false); }
+
+ _rcv_pt_sel_cnt = 0;
+ _rcv_pt_sel_max = 0;
+ _rcv_pt_base = INVALID_INDEX;
+ }
+
+ public:
+
+ enum { INVALID_INDEX = ~0UL };
+
+ Receive_window()
+ :
+ _rcv_pt_base(INVALID_INDEX), _rcv_wnd_log2(MAX_CAP_ARGS_LOG2)
+ {
+ _rcv_reset();
+ }
+
+ ~Receive_window()
+ {
+ _rcv_reset();
+ }
+
+ /**
+ * Set log2 number of capabilities to be received during reply of
+ * a IPC call.
+ */
+ void rcv_wnd(unsigned short const caps_log2)
+ {
+ if (caps_log2 > MAX_CAP_ARGS_LOG2)
+ nova_die();
+
+ _rcv_wnd_log2 = caps_log2;
+ }
+
+ /**
+ * Return received portal-capability selector
+ */
+ void rcv_pt_sel(Native_capability &cap)
+ {
+ if (_rcv_pt_sel_cnt >= _rcv_pt_sel_max) {
+ cap = Native_capability();
+ return;
+ }
+
+ /* return only received or translated caps */
+ cap = Native_capability(_rcv_pt_sel[_rcv_pt_sel_cnt++].sel);
+ }
+
+ /**
+ * Return true if receive window must be re-initialized
+ */
+ bool rcv_invalid() const
+ {
+ return _rcv_pt_base == INVALID_INDEX;
+ }
+
+ unsigned num_received_caps() const { return _rcv_pt_sel_max; }
+
+ /**
+ * Return true if receive window must be re-initialized
+ *
+ * After reading portal selectors from the message
+ * buffer using 'rcv_pt_sel()', we assume that the IDC
+ * call populated the current receive window with one
+ * or more portal capabilities.
+ * To enable the reception of portal capability
+ * selectors for the next IDC, we need a fresh receive
+ * window.
+ *
+ * \param keep 'true' - Try to keep receive window if
+ * it's clean.
+ * 'false' - Free caps of receive window
+ * because object is freed
+ * afterwards.
+ *
+ * \result 'true' - receive window must be re-initialized
+ * 'false' - portal selectors has been kept
+ */
+ bool rcv_cleanup(bool keep, unsigned short const new_max = MAX_CAP_ARGS)
+ {
+ /* mark used mapped capabilities as used to prevent freeing */
+ bool reinit = false;
+ for (unsigned i = 0; i < _rcv_pt_sel_cnt; i++) {
+ if (!_rcv_pt_sel[i].del)
+ continue;
+
+ /* should never happen */
+ if (_rcv_pt_sel[i].sel < _rcv_pt_base ||
+ (_rcv_pt_sel[i].sel >= _rcv_pt_base + MAX_CAP_ARGS))
+ nova_die();
+
+ _rcv_pt_cap_free [_rcv_pt_sel[i].sel - _rcv_pt_base] = USED_CAP;
+
+ reinit = true;
+ }
+
+ /* if old receive window was smaller, we need to re-init */
+ for (unsigned i = 0; !reinit && i < new_max; i++)
+ if (_rcv_pt_cap_free[i] == FREE_INVALID)
+ reinit = true;
+
+ _rcv_pt_sel_cnt = 0;
+ _rcv_pt_sel_max = 0;
+
+ /* we can keep the cap selectors if none was used */
+ if (keep && !reinit) {
+ for (unsigned i = 0; i < MAX_CAP_ARGS; i++) {
+ /* revoke received caps which are unused */
+ if (_rcv_pt_cap_free[i] == UNUSED_CAP)
+ Nova::revoke(Nova::Obj_crd(_rcv_pt_base + i, 0), true);
+
+ /* free rest of indexes if new_max is smaller then last window */
+ if (i >= new_max && _rcv_pt_cap_free[i] == FREE_SEL)
+ cap_map()->remove(_rcv_pt_base + i, 0, false);
+ }
+
+ return false;
+ }
+
+ /* decrease ref count if valid selector */
+ for (unsigned i = 0; i < MAX_CAP_ARGS; i++) {
+ if (_rcv_pt_cap_free[i] == FREE_INVALID)
+ continue;
+ cap_map()->remove(_rcv_pt_base + i, 0, _rcv_pt_cap_free[i] != FREE_SEL);
+ }
+
+ return true;
+ }
+
+ /**
+ * Initialize receive window for portal capability
+ * selectors
+ *
+ * \param utcb - UTCB of designated receiver
+ * thread
+ * \param rcv_window - If specified - receive exactly
+ * one capability at the specified
+ * index of rcv_window
+ *
+ * Depending on the 'rcv_invalid', 'rcv_cleanup(true)'
+ * state of the message buffer and the specified
+ * rcv_window parameter, this function allocates a
+ * fresh receive window and clears 'rcv_invalid'.
+ */
+ bool prepare_rcv_window(Nova::Utcb &utcb,
+ addr_t rcv_window = INVALID_INDEX)
+ {
+ /* open maximal translate window */
+ utcb.crd_xlt = Nova::Obj_crd(0, ~0UL);
+
+ /* use receive window if specified */
+ if (rcv_window != INVALID_INDEX) {
+ /* cleanup if receive window already used */
+ if (!rcv_invalid()) rcv_cleanup(false);
+
+ _rcv_pt_base = rcv_window;
+
+ /* open receive window */
+ utcb.crd_rcv = Nova::Obj_crd(_rcv_pt_base, _rcv_wnd_log2);
+ return true;
+ }
+
+ /* allocate receive window if necessary, otherwise use old one */
+ if (rcv_invalid() || rcv_cleanup(true, 1U << _rcv_wnd_log2))
+ {
+ _rcv_pt_base = cap_map()->insert(_rcv_wnd_log2);
+
+ if (_rcv_pt_base == INVALID_INDEX) {
+ /* no mappings can be received */
+ utcb.crd_rcv = Nova::Obj_crd();
+ return false;
+ }
+ }
+
+ /* open receive window */
+ utcb.crd_rcv = Nova::Obj_crd(_rcv_pt_base, _rcv_wnd_log2);
+ return true;
+ }
+
+ /**
+ * Post IPC processing.
+ *
+ * Remember where and which caps have been received
+ * respectively have been translated.
+ * The information is required to correctly free
+ * cap indexes and to revoke unused received caps.
+ *
+ * \param utcb UTCB of designated receiver thread
+ */
+ void post_ipc(Nova::Utcb &utcb, addr_t const rcv_window = INVALID_INDEX)
+ {
+ using namespace Nova;
+
+ unsigned const rcv_items = (utcb.items >> 16) & 0xffffu;
+
+ _rcv_pt_sel_max = 0;
+ _rcv_pt_sel_cnt = 0;
+
+ unsigned short const max = 1U << utcb.crd_rcv.order();
+ if (max > MAX_CAP_ARGS)
+ nova_die();
+
+ for (unsigned short i = 0; i < MAX_CAP_ARGS; i++)
+ _rcv_pt_cap_free [i] = (i >= max) ? FREE_INVALID : FREE_SEL;
+
+ for (unsigned i = 0; i < rcv_items; i++) {
+ Nova::Utcb::Item * item = utcb.get_item(i);
+ if (!item)
+ break;
+
+ Nova::Crd cap(item->crd);
+
+ /* track which items we got mapped */
+ if (!cap.is_null() && item->is_del()) {
+ /* should never happen */
+ if (cap.base() < _rcv_pt_base ||
+ (cap.base() >= _rcv_pt_base + max))
+ nova_die();
+ _rcv_pt_cap_free [cap.base() - _rcv_pt_base] = UNUSED_CAP;
+ }
+
+ if (_rcv_pt_sel_max >= max) continue;
+
+ /* track the order of mapped and translated items */
+ if (cap.is_null()) {
+ _rcv_pt_sel[_rcv_pt_sel_max].sel = INVALID_INDEX;
+ _rcv_pt_sel[_rcv_pt_sel_max++].del = false;
+ } else {
+ _rcv_pt_sel[_rcv_pt_sel_max].sel = cap.base();
+ _rcv_pt_sel[_rcv_pt_sel_max++].del = item->is_del();
+ }
+ }
+
+ /*
+ * If a specific rcv_window has been specified,
+ * (see prepare_rcv_window) then the caller want to take care
+ * about freeing the * selector. Make the _rcv_pt_base invalid
+ * so that it is not cleanup twice.
+ */
+ if (rcv_window != INVALID_INDEX)
+ _rcv_pt_base = INVALID_INDEX;
+
+ utcb.crd_rcv = 0;
+ }
+};
+
+#endif /* _INCLUDE__NOVA__RECEIVE_WINDOW_H_ */
diff --git a/repos/base-nova/include/nova/util.h b/repos/base-nova/include/nova/util.h
index d3d61d1ef1..464ab31e11 100644
--- a/repos/base-nova/include/nova/util.h
+++ b/repos/base-nova/include/nova/util.h
@@ -51,7 +51,7 @@ inline void request_event_portal(Genode::Native_capability const &cap,
utcb->crd_rcv = orig_crd;
if (res)
- PERR("request of event (%lu) capability selector failed", event);
+ PERR("request of event (%lu) capability selector failed (res=%u)", event, res);
}
diff --git a/repos/base-nova/include/signal_source/client.h b/repos/base-nova/include/signal_source/client.h
index c96132a4a4..8735552f2c 100644
--- a/repos/base-nova/include/signal_source/client.h
+++ b/repos/base-nova/include/signal_source/client.h
@@ -71,18 +71,29 @@ namespace Genode {
Signal wait_for_signal() override
{
- /*
- * Block on semaphore, will be unblocked if
- * signal is available
- */
using namespace Nova;
- mword_t value = 0;
- mword_t count = 0;
- if (uint8_t res = si_ctrl(_sem.local_name(), SEMAPHORE_DOWN,
- value, count))
- PWRN("signal reception failed - error %u", res);
- return Signal(value, count);
+ mword_t imprint, count;
+ do {
+
+ /*
+ * We set an invalid imprint (0) to detect a spurious
+ * unblock. In this case, NOVA does not block
+ * SEMAPHORE_DOWN nor touch our input values if the
+ * deblocking (chained) semaphore was dequeued before we
+ * intend to block.
+ */
+ imprint = 0;
+ count = 0;
+
+ /* block on semaphore until signal context was submitted */
+ if (uint8_t res = si_ctrl(_sem.local_name(), SEMAPHORE_DOWN,
+ imprint, count))
+ PWRN("signal reception failed - error %u", res);
+
+ } while (imprint == 0);
+
+ return Signal(imprint, count);
}
};
}
diff --git a/repos/base-nova/src/base/ipc/ipc.cc b/repos/base-nova/src/base/ipc/ipc.cc
index c5908b474a..4c331a0a04 100644
--- a/repos/base-nova/src/base/ipc/ipc.cc
+++ b/repos/base-nova/src/base/ipc/ipc.cc
@@ -17,117 +17,9 @@
#include
/* base-internal includes */
-#include
-
-/* NOVA includes */
-#include
+#include
using namespace Genode;
-using namespace Nova;
-
-
-/*****************************
- ** IPC marshalling support **
- *****************************/
-
-void Ipc_marshaller::insert(Native_capability const &cap)
-{
- _snd_msg.snd_append_pt_sel(cap);
-}
-
-
-void Ipc_unmarshaller::extract(Native_capability &cap)
-{
- _rcv_msg.rcv_pt_sel(cap);
-}
-
-
-/***************
- ** Utilities **
- ***************/
-
-/**
- * Copy message registers from UTCB to destination message buffer
- *
- * \return protocol word delivered via the first UTCB message register
- *
- * The caller of this function must ensure that utcb->msg_words is greater
- * than 0.
- */
-static mword_t copy_utcb_to_msgbuf(Nova::Utcb *utcb, Msgbuf_base &rcv_msg)
-{
- size_t num_msg_words = utcb->msg_words();
-
- /*
- * Handle the reception of a malformed message. This should never happen
- * because the utcb->msg_words is checked by the caller of this function.
- */
- if (num_msg_words < 1)
- return 0;
-
- /* the UTCB contains the protocol word followed by the message data */
- mword_t const protocol_word = utcb->msg[0];
- size_t num_data_words = num_msg_words - 1;
-
- if (num_data_words*sizeof(mword_t) > rcv_msg.capacity()) {
- PERR("receive message buffer too small msg size=%zx, buf size=%zd",
- num_data_words*sizeof(mword_t), rcv_msg.capacity());
- num_data_words = rcv_msg.capacity()/sizeof(mword_t);
- }
-
- /* read message payload into destination message buffer */
- mword_t *src = (mword_t *)(void *)(&utcb->msg[1]);
- mword_t *dst = (mword_t *)rcv_msg.data();
- for (unsigned i = 0; i < num_data_words; i++)
- *dst++ = *src++;
-
- return protocol_word;
-}
-
-
-/**
- * Copy message payload to UTCB message registers
- */
-static bool copy_msgbuf_to_utcb(Nova::Utcb *utcb, Msgbuf_base const &snd_msg,
- mword_t protocol_value)
-{
- /* look up address and size of message payload */
- mword_t *msg_buf = (mword_t *)snd_msg.data();
-
- /* size of message payload in machine words */
- size_t const num_data_words = snd_msg.data_size()/sizeof(mword_t);
-
- /* account for protocol value in front of the message */
- size_t num_msg_words = 1 + num_data_words;
-
- enum { NUM_MSG_REGS = 256 };
- if (num_msg_words > NUM_MSG_REGS) {
- PERR("Message does not fit into UTCB message registers\n");
- num_msg_words = NUM_MSG_REGS;
- }
-
- utcb->msg[0] = protocol_value;
-
- /* store message into UTCB message registers */
- mword_t *src = (mword_t *)&msg_buf[0];
- mword_t *dst = (mword_t *)(void *)&utcb->msg[1];
- for (unsigned i = 0; i < num_data_words; i++)
- *dst++ = *src++;
-
- utcb->set_msg_word(num_msg_words);
-
- /* append portal capability selectors */
- 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);
- if (crd.base() == ~0UL) continue;
-
- if (!utcb->append_item(crd, i, false, false, trans_map))
- return false;
- }
-
- return true;
-}
/****************
@@ -138,6 +30,9 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
size_t rcv_caps)
{
+ Receive_window rcv_window;
+ rcv_msg.reset();
+
/* update receive window for capability selectors if needed */
if (rcv_caps != ~0UL) {
@@ -145,10 +40,10 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
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_window.rcv_wnd(log2_max);
}
- Nova::Utcb *utcb = (Nova::Utcb *)Thread_base::myself()->utcb();
+ Nova::Utcb &utcb = *(Nova::Utcb *)Thread_base::myself()->utcb();
/* the protocol value is unused as the badge is delivered by the kernel */
if (!copy_msgbuf_to_utcb(utcb, snd_msg, 0)) {
@@ -157,7 +52,7 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
}
/* if we can't setup receive window, die in order to recognize the issue */
- if (!rcv_msg.prepare_rcv_window(utcb, dst.rcv_window()))
+ if (!rcv_window.prepare_rcv_window(utcb, dst.rcv_window()))
/* printf doesn't work here since for IPC also rcv_prepare* is used */
nova_die();
@@ -165,67 +60,15 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
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);
+ utcb.set_msg_word(0);
return Rpc_exception_code(Rpc_exception_code::INVALID_OBJECT);
}
- rcv_msg.post_ipc(utcb, dst.rcv_window());
+ rcv_window.post_ipc(utcb, dst.rcv_window());
/* handle malformed reply from a server */
- if (utcb->msg_words() < 1)
+ if (utcb.msg_words() < 1)
return Rpc_exception_code(Rpc_exception_code::INVALID_OBJECT);
- return Rpc_exception_code(copy_utcb_to_msgbuf(utcb, rcv_msg));
+ return Rpc_exception_code(copy_utcb_to_msgbuf(utcb, rcv_window, rcv_msg));
}
-
-
-/****************
- ** Ipc_server **
- ****************/
-
-void Ipc_server::reply()
-{
- Nova::Utcb *utcb = (Nova::Utcb *)Thread_base::myself()->utcb();
-
- copy_msgbuf_to_utcb(utcb, _snd_msg, _exception_code.value);
-
- _snd_msg.snd_reset();
-
- Nova::reply(Thread_base::myself()->stack_top());
-}
-
-
-void Ipc_server::reply_wait()
-{
- /*
- * This function is only called by the portal dispatcher of server
- * entrypoint'. When the dispatcher is called, the incoming message already
- * arrived so that we do not need to block. The only remaining thing to do
- * is unmarshalling the arguments.
- */
-
- Nova::Utcb *utcb = (Nova::Utcb *)Thread_base::myself()->utcb();
-
- _rcv_msg.post_ipc(utcb);
-
- /* handle ill-formed message */
- if (utcb->msg_words() < 2) {
- _rcv_msg.word(0) = ~0UL; /* invalid opcode */
- } else {
- copy_utcb_to_msgbuf(utcb, _rcv_msg);
- }
-
- _read_offset = _write_offset = 0;
-}
-
-
-Ipc_server::Ipc_server(Native_connection_state &cs,
- Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
-:
- Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _rcv_cs(cs)
-{
- _read_offset = _write_offset = 0;
-}
-
-
-Ipc_server::~Ipc_server() { }
diff --git a/repos/base-nova/src/base/server/server.cc b/repos/base-nova/src/base/server/server.cc
index d52537ed74..0c9a76b6e2 100644
--- a/repos/base-nova/src/base/server/server.cc
+++ b/repos/base-nova/src/base/server/server.cc
@@ -20,11 +20,12 @@
/* base-internal includes */
#include
-#include
+#include
/* NOVA includes */
#include
#include
+#include
using namespace Genode;
@@ -106,6 +107,14 @@ void Rpc_entrypoint::_dissolve(Rpc_object_base *obj)
}
+static void reply(Nova::Utcb &utcb, Rpc_exception_code exc, Msgbuf_base &snd_msg)
+{
+ copy_msgbuf_to_utcb(utcb, snd_msg, exc.value);
+
+ Nova::reply(Thread_base::myself()->stack_top());
+}
+
+
void Rpc_entrypoint::_activation_entry()
{
/* retrieve portal id from eax/rdi */
@@ -115,32 +124,38 @@ void Rpc_entrypoint::_activation_entry()
addr_t id_pt; asm volatile ("" : "=a" (id_pt));
#endif
- Rpc_entrypoint *ep = static_cast(Thread_base::myself());
+ Rpc_entrypoint &ep = *static_cast(Thread_base::myself());
+ Nova::Utcb &utcb = *(Nova::Utcb *)Thread_base::myself()->utcb();
- /* required to decrease ref count of capability used during last reply */
- ep->_snd_buf.snd_reset();
+ Receive_window &rcv_window = ep.native_thread().rcv_window;
+ rcv_window.post_ipc(utcb);
- /* prepare ipc server object (copying utcb content to message buffer */
- Rpc_opcode opcode(0);
-
- Native_connection_state cs;
- Ipc_server srv(cs, ep->_snd_buf, ep->_rcv_buf);
- srv.reply_wait();
- srv.extract(opcode);
-
- /* set default return value */
- srv.ret(Rpc_exception_code(Rpc_exception_code::INVALID_OBJECT));
-
- /* in case of a portal cleanup call we are done here - just reply */
- 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.reply();
+ /* handle ill-formed message */
+ if (utcb.msg_words() < 2) {
+ ep._rcv_buf.word(0) = ~0UL; /* invalid opcode */
+ } else {
+ copy_utcb_to_msgbuf(utcb, rcv_window, ep._rcv_buf);
}
+ Ipc_unmarshaller unmarshaller(ep._rcv_buf);
+
+ Rpc_opcode opcode(0);
+ unmarshaller.extract(opcode);
+
+ /* default return value */
+ Rpc_exception_code exc = Rpc_exception_code(Rpc_exception_code::INVALID_OBJECT);
+
+ /* in case of a portal cleanup call we are done here - just reply */
+ if (ep._cap.local_name() == id_pt) {
+ if (!rcv_window.prepare_rcv_window(utcb))
+ PWRN("out of capability selectors for handling server requests");
+
+ ep._rcv_buf.reset();
+ reply(utcb, exc, ep._snd_buf);
+ }
{
/* potentially delay start */
- Lock::Guard lock_guard(ep->_delay_start);
+ Lock::Guard lock_guard(ep._delay_start);
}
/* atomically lookup and lock referenced object */
@@ -151,16 +166,27 @@ void Rpc_entrypoint::_activation_entry()
return;
}
+ /*
+ * Inhibit removal of capabilities sent as results of client requests.
+ * This prevents the recursive revocation of NOVA portal caps and,
+ * therefore, permits clients to use result capabilities after server
+ * code dropped all references.
+ */
+ for (unsigned i = 0; i < ep._snd_buf.used_caps(); ++i)
+ ep._snd_buf.cap(i).keep_if_last_reference();
+
/* dispatch request */
- try { srv.ret(obj->dispatch(opcode, srv, srv)); }
+ ep._snd_buf.reset();
+ try { exc = obj->dispatch(opcode, unmarshaller, ep._snd_buf); }
catch (Blocking_canceled) { }
};
- ep->apply(id_pt, lambda);
+ ep.apply(id_pt, lambda);
- if (!ep->_rcv_buf.prepare_rcv_window((Nova::Utcb *)ep->utcb()))
+ if (!rcv_window.prepare_rcv_window(*(Nova::Utcb *)ep.utcb()))
PWRN("out of capability selectors for handling server requests");
- srv.reply();
+ ep._rcv_buf.reset();
+ reply(utcb, exc, ep._snd_buf);
}
@@ -220,8 +246,10 @@ Rpc_entrypoint::Rpc_entrypoint(Pd_session *pd_session, size_t stack_size,
if (!_cap.valid())
throw Cpu_session::Thread_creation_failed();
+ Receive_window &rcv_window = Thread_base::native_thread().rcv_window;
+
/* prepare portal receive window of new thread */
- if (!_rcv_buf.prepare_rcv_window((Nova::Utcb *)&_stack->utcb()))
+ if (!rcv_window.prepare_rcv_window(*(Nova::Utcb *)&_stack->utcb()))
throw Cpu_session::Thread_creation_failed();
if (start_on_construction)
diff --git a/repos/base-nova/src/core/platform.cc b/repos/base-nova/src/core/platform.cc
index 8c3fd9c44a..52ee95b5ca 100644
--- a/repos/base-nova/src/core/platform.cc
+++ b/repos/base-nova/src/core/platform.cc
@@ -33,6 +33,7 @@
/* NOVA includes */
#include
+#include
using namespace Genode;
using namespace Nova;
diff --git a/repos/base-nova/src/include/base/internal/ipc.h b/repos/base-nova/src/include/base/internal/ipc.h
new file mode 100644
index 0000000000..3b046d92d4
--- /dev/null
+++ b/repos/base-nova/src/include/base/internal/ipc.h
@@ -0,0 +1,123 @@
+/*
+ * \brief IPC utility functions
+ * \author Norman Feske
+ * \date 2016-03-08
+ */
+
+/*
+ * Copyright (C) 2016 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _INCLUDE__BASE__INTERNAL__IPC_H_
+#define _INCLUDE__BASE__INTERNAL__IPC_H_
+
+/* NOVA includes */
+#include
+#include
+
+/**
+ * Copy message registers from UTCB to destination message buffer
+ *
+ * \return protocol word delivered via the first UTCB message register
+ *
+ * The caller of this function must ensure that utcb.msg_words is greater
+ * than 0.
+ */
+static inline Nova::mword_t copy_utcb_to_msgbuf(Nova::Utcb &utcb,
+ Genode::Receive_window &rcv_window,
+ Genode::Msgbuf_base &rcv_msg)
+{
+ using namespace Genode;
+ using namespace Nova;
+
+ size_t num_msg_words = utcb.msg_words();
+
+ /*
+ * Handle the reception of a malformed message. This should never happen
+ * because the utcb.msg_words is checked by the caller of this function.
+ */
+ if (num_msg_words < 1)
+ return 0;
+
+ /* the UTCB contains the protocol word followed by the message data */
+ mword_t const protocol_word = utcb.msg[0];
+ size_t num_data_words = num_msg_words - 1;
+
+ if (num_data_words*sizeof(mword_t) > rcv_msg.capacity()) {
+ PERR("receive message buffer too small msg size=%zx, buf size=%zd",
+ num_data_words*sizeof(mword_t), rcv_msg.capacity());
+ num_data_words = rcv_msg.capacity()/sizeof(mword_t);
+ }
+
+ /* read message payload into destination message buffer */
+ mword_t *src = (mword_t *)(void *)(&utcb.msg[1]);
+ mword_t *dst = (mword_t *)rcv_msg.data();
+ for (unsigned i = 0; i < num_data_words; i++)
+ *dst++ = *src++;
+
+ /* extract caps from UTCB */
+ for (unsigned i = 0; i < rcv_window.num_received_caps(); i++) {
+ Native_capability cap;
+ rcv_window.rcv_pt_sel(cap);
+ rcv_msg.insert(cap);
+ }
+
+ return protocol_word;
+}
+
+
+/**
+ * Copy message payload to UTCB message registers
+ */
+static inline bool copy_msgbuf_to_utcb(Nova::Utcb &utcb,
+ Genode::Msgbuf_base const &snd_msg,
+ Nova::mword_t protocol_value)
+{
+ using namespace Genode;
+ using namespace Nova;
+
+ /* look up address and size of message payload */
+ mword_t *msg_buf = (mword_t *)snd_msg.data();
+
+ /* size of message payload in machine words */
+ size_t const num_data_words = snd_msg.data_size()/sizeof(mword_t);
+
+ /* account for protocol value in front of the message */
+ size_t num_msg_words = 1 + num_data_words;
+
+ enum { NUM_MSG_REGS = 256 };
+ if (num_msg_words > NUM_MSG_REGS) {
+ PERR("Message does not fit into UTCB message registers\n");
+ num_msg_words = NUM_MSG_REGS;
+ }
+
+ utcb.msg[0] = protocol_value;
+
+ /* store message into UTCB message registers */
+ mword_t *src = (mword_t *)&msg_buf[0];
+ mword_t *dst = (mword_t *)(void *)&utcb.msg[1];
+ for (unsigned i = 0; i < num_data_words; i++)
+ *dst++ = *src++;
+
+ utcb.set_msg_word(num_msg_words);
+
+ /* append portal capability selectors */
+ for (unsigned i = 0; i < snd_msg.used_caps(); i++) {
+
+ Native_capability const &cap = snd_msg.cap(i);
+ Nova::Obj_crd crd(cap.local_name(), 0, cap.dst().rights());
+
+ if (crd.base() == ~0UL) continue;
+
+ if (!utcb.append_item(crd, i, false, false, true))
+ return false;
+ }
+
+ return true;
+}
+
+
+#endif /* _INCLUDE__BASE__INTERNAL__IPC_H_ */
diff --git a/repos/base-nova/src/test/platform/main.cc b/repos/base-nova/src/test/platform/main.cc
index b953f72cad..4901435136 100644
--- a/repos/base-nova/src/test/platform/main.cc
+++ b/repos/base-nova/src/test/platform/main.cc
@@ -161,6 +161,9 @@ void test_server_oom()
PINF("received %u. cap", i);
}
+ /* XXX this code does does no longer work since the removal of 'solely_map' */
+#if 0
+
/* case that during send we get oom */
for (unsigned i = 0; i < 20000; i++) {
/* be evil and switch translation off - server ever uses a new selector */
@@ -176,6 +179,7 @@ void test_server_oom()
if (i % 5000 == 4999)
PINF("sent %u. cap", i);
}
+#endif
ep.dissolve(&component);
}
diff --git a/repos/base-nova/src/test/platform/server.h b/repos/base-nova/src/test/platform/server.h
index d0b09dd066..5452b6e5de 100644
--- a/repos/base-nova/src/test/platform/server.h
+++ b/repos/base-nova/src/test/platform/server.h
@@ -81,8 +81,13 @@ bool Test::Component::cap_void(Genode::Native_capability got_cap) {
Genode::Native_capability Test::Component::void_cap() {
Genode::Native_capability send_cap = cap();
+
+ /* XXX this code does does no longer work since the removal of 'solely_map' */
+#if 0
/* be evil and switch translation off - client ever uses a new selector */
send_cap.solely_map();
+#endif
+
return send_cap;
}
diff --git a/repos/base-okl4/include/base/ipc_msgbuf.h b/repos/base-okl4/include/base/ipc_msgbuf.h
deleted file mode 100644
index e29d0ff212..0000000000
--- a/repos/base-okl4/include/base/ipc_msgbuf.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * \brief OKL4-specific layout of IPC message buffer
- * \author Norman Feske
- * \date 2009-03-25
- *
- * On OKL4, we do not directly use the a kernel-specific message-buffer layout.
- * The IPC goes through the UTCBs of the sending and receiving threads. Because
- * on Genode, message buffers are decoupled from threads, we need to copy-in
- * and copy-out the message payload between the message buffers and the used
- * UTCBs.
- */
-
-/*
- * Copyright (C) 2009-2013 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
-#define _INCLUDE__BASE__IPC_MSGBUF_H_
-
-#include
-#include
-
-namespace Genode {
-
- class Ipc_marshaller;
-
- /**
- * IPC message buffer layout
- */
- class Msgbuf_base
- {
- protected:
-
- size_t _data_size = 0;
- size_t _capacity;
- char _msg_start[]; /* symbol marks start of message */
-
- Msgbuf_base(size_t capacity) : _capacity(capacity) { }
-
- friend class Ipc_marshaller;
-
- public:
-
- /**
- * Return size of message buffer
- */
- size_t capacity() const { return _capacity; };
-
- /**
- * Return pointer of message data payload
- */
- void *data() { return &_msg_start[0]; };
- void const *data() const { return &_msg_start[0]; };
-
- size_t data_size() const { return _data_size; }
- };
-
-
- /**
- * Instance of IPC message buffer with specified buffer size
- */
- template
- class Msgbuf : public Msgbuf_base
- {
- public:
-
- char buf[BUF_SIZE];
-
- Msgbuf() : Msgbuf_base(BUF_SIZE) { }
- };
-}
-
-#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
diff --git a/repos/base-okl4/lib/mk/base-common.mk b/repos/base-okl4/lib/mk/base-common.mk
index bb85cbe9cc..2920278b0e 100644
--- a/repos/base-okl4/lib/mk/base-common.mk
+++ b/repos/base-okl4/lib/mk/base-common.mk
@@ -7,7 +7,7 @@
LIBS += cxx startup
SRC_CC += cap_copy.cc
-SRC_CC += ipc/ipc.cc ipc/ipc_marshal_cap.cc
+SRC_CC += ipc/ipc.cc
SRC_CC += avl_tree/avl_tree.cc
SRC_CC += allocator/slab.cc
SRC_CC += allocator/allocator_avl.cc
diff --git a/repos/base-okl4/src/base/ipc/ipc.cc b/repos/base-okl4/src/base/ipc/ipc.cc
index d5c2adbfc5..6dcc5457cd 100644
--- a/repos/base-okl4/src/base/ipc/ipc.cc
+++ b/repos/base-okl4/src/base/ipc/ipc.cc
@@ -53,7 +53,9 @@ static void kdb_emergency_print(const char *s)
* The message tag contains the information about the number of message words
* to send. The tag is always supplied in message register 0. Message register
* 1 is used for the local name (when the client calls the server) or the
- * exception code (when the server replies to the client). All subsequent
+ * exception code (when the server replies to the client). Message register
+ * 2 holds the number of transferred capability arguments. It is followed
+ * by a tuple of (thread ID, local name) for each capability. All subsequent
* message registers hold the message payload.
*/
@@ -64,43 +66,79 @@ static void kdb_emergency_print(const char *s)
*/
static L4_Word_t extract_msg_from_utcb(L4_MsgTag_t rcv_tag, Msgbuf_base &rcv_msg)
{
- unsigned num_msg_words = (int)L4_UntypedWords(rcv_tag);
+ rcv_msg.reset();
- if (num_msg_words*sizeof(L4_Word_t) > rcv_msg.capacity()) {
- PERR("receive message buffer too small msg size=%zd, buf size=%zd",
- num_msg_words*sizeof(L4_Word_t), rcv_msg.capacity());
- num_msg_words = rcv_msg.capacity()/sizeof(L4_Word_t);
+ unsigned const num_msg_words = (int)L4_UntypedWords(rcv_tag);
+
+ if (num_msg_words < 3)
+ return Rpc_exception_code::INVALID_OBJECT;
+
+ L4_Word_t protocol_word = 0;
+ L4_StoreMR(1, &protocol_word);
+
+ L4_Word_t num_caps = 0;
+ L4_StoreMR(2, &num_caps);
+
+ /* each capability is represened as two message words (tid, local name) */
+ for (unsigned i = 0; i < num_caps; i++) {
+ L4_Word_t local_name = 0;
+ L4_ThreadId_t tid;
+ L4_StoreMR(3 + 2*i, &tid.raw);
+ L4_StoreMR(3 + 2*i + 1, &local_name);
+ rcv_msg.insert(Native_capability(tid, local_name));
}
- L4_Word_t local_name = 0;
- L4_StoreMR(1, &local_name);
+ unsigned const data_start_idx = 3 + 2*num_caps;
+
+ if (num_msg_words < data_start_idx)
+ return Rpc_exception_code::INVALID_OBJECT;
+
+ unsigned const num_data_words = num_msg_words - data_start_idx;
+
+ if (num_data_words*sizeof(L4_Word_t) > rcv_msg.capacity()) {
+ PERR("receive message buffer too small msg size=%zd, buf size=%zd",
+ num_data_words*sizeof(L4_Word_t), rcv_msg.capacity());
+ return Rpc_exception_code::INVALID_OBJECT;
+ }
/* read message payload into destination message buffer */
- L4_StoreMRs(2, num_msg_words - 2, (L4_Word_t *)rcv_msg.data());
+ L4_StoreMRs(data_start_idx, num_data_words, (L4_Word_t *)rcv_msg.data());
- return local_name;
+ rcv_msg.data_size(sizeof(num_data_words));
+
+ return protocol_word;
}
/**
* Copy message payload to UTCB message registers
*/
-static void copy_msg_to_utcb(Msgbuf_base const &snd_msg, unsigned num_msg_words,
- L4_Word_t local_name)
+static void copy_msg_to_utcb(Msgbuf_base const &snd_msg, L4_Word_t local_name)
{
- num_msg_words += 2;
+ unsigned const num_header_words = 3 + 2*snd_msg.used_caps();
+ unsigned const num_data_words = snd_msg.data_size()/sizeof(L4_Word_t);
+ unsigned const num_msg_words = num_data_words + num_header_words;
if (num_msg_words >= L4_GetMessageRegisters()) {
kdb_emergency_print("Message does not fit into UTCB message registers\n");
- num_msg_words = L4_GetMessageRegisters() - 1;
+ L4_LoadMR(0, 0);
+ return;
}
L4_MsgTag_t snd_tag;
snd_tag.raw = 0;
snd_tag.X.u = num_msg_words;
- L4_LoadMR (0, snd_tag.raw);
- L4_LoadMR (1, local_name);
- L4_LoadMRs(2, num_msg_words - 2, (L4_Word_t *)snd_msg.data());
+
+ L4_LoadMR(0, snd_tag.raw);
+ L4_LoadMR(1, local_name);
+ L4_LoadMR(2, snd_msg.used_caps());
+
+ for (unsigned i = 0; i < snd_msg.used_caps(); i++) {
+ L4_LoadMR(3 + i*2, snd_msg.cap(i).dst().raw);
+ L4_LoadMR(3 + i*2 + 1, snd_msg.cap(i).local_name());
+ }
+
+ L4_LoadMRs(num_header_words, num_data_words, (L4_Word_t *)snd_msg.data());
}
@@ -113,8 +151,7 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
size_t)
{
/* copy call message to the UTCBs message registers */
- copy_msg_to_utcb(snd_msg, snd_msg.data_size()/sizeof(L4_Word_t),
- dst.local_name());
+ copy_msg_to_utcb(snd_msg, dst.local_name());
L4_Accept(L4_UntypedWordsAcceptor);
@@ -136,54 +173,46 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
/****************
- ** Ipc_server **
+ ** IPC server **
****************/
-void Ipc_server::_prepare_next_reply_wait()
-{
- _reply_needed = true;
- _read_offset = _write_offset = 0;
-}
-
-
-void Ipc_server::reply()
+void Genode::ipc_reply(Native_capability caller, Rpc_exception_code exc,
+ Msgbuf_base &snd_msg)
{
/* copy reply to the UTCBs message registers */
- copy_msg_to_utcb(_snd_msg, _write_offset/sizeof(L4_Word_t),
- _exception_code.value);
+ copy_msg_to_utcb(snd_msg, exc.value);
/* perform non-blocking IPC send operation */
- L4_MsgTag_t rcv_tag = L4_Reply(_caller.dst());
+ L4_MsgTag_t rcv_tag = L4_Reply(caller.dst());
if (L4_IpcFailed(rcv_tag))
PERR("ipc error in _reply - gets ignored");
-
- _prepare_next_reply_wait();
}
-void Ipc_server::reply_wait()
+Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller,
+ Rpc_exception_code exc,
+ Msgbuf_base &reply_msg,
+ Msgbuf_base &request_msg)
{
L4_MsgTag_t rcv_tag;
- if (_reply_needed) {
+ Okl4::L4_ThreadId_t caller = L4_nilthread;
+
+ if (last_caller.valid()) {
/* copy reply to the UTCBs message registers */
- copy_msg_to_utcb(_snd_msg, _write_offset/sizeof(L4_Word_t),
- _exception_code.value);
+ copy_msg_to_utcb(reply_msg, exc.value);
- rcv_tag = L4_ReplyWait(_caller.dst(), &_rcv_cs.caller);
+ rcv_tag = L4_ReplyWait(last_caller.dst(), &caller);
} else {
- rcv_tag = L4_Wait(&_rcv_cs.caller);
+ rcv_tag = L4_Wait(&caller);
}
/* copy request message from the UTCBs message registers */
- _badge = extract_msg_from_utcb(rcv_tag, _rcv_msg);
+ unsigned long const badge = extract_msg_from_utcb(rcv_tag, request_msg);
- /* define destination of next reply */
- _caller = Native_capability(_rcv_cs.caller, badge());
-
- _prepare_next_reply_wait();
+ return Rpc_request(Native_capability(caller, 0), badge);
}
@@ -202,14 +231,7 @@ static inline Okl4::L4_ThreadId_t thread_get_my_global_id()
}
-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_get_my_global_id(), 0),
- _rcv_cs(cs)
-{ }
+Ipc_server::Ipc_server() : Native_capability(thread_get_my_global_id(), 0) { }
Ipc_server::~Ipc_server() { }
diff --git a/repos/base-okl4/src/core/pager_object.cc b/repos/base-okl4/src/core/pager_object.cc
new file mode 100644
index 0000000000..bb3adab879
--- /dev/null
+++ b/repos/base-okl4/src/core/pager_object.cc
@@ -0,0 +1,50 @@
+/*
+ * \brief Kernel-specific RM-faulter wake-up mechanism
+ * \author Norman Feske
+ * \date 2016-04-12
+ */
+
+/*
+ * Copyright (C) 2016 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+/* core includes */
+#include
+
+/* OKL4 includes */
+namespace Okl4 { extern "C" {
+#include
+#include
+} }
+
+using namespace Genode;
+
+
+void Pager_object::wake_up()
+{
+ using namespace Okl4;
+
+ /*
+ * Issue IPC to pager, transmitting the pager-object pointer as 'IP'.
+ */
+ L4_Accept(L4_UntypedWordsAcceptor);
+
+ L4_MsgTag_t snd_tag;
+ snd_tag.raw = 0;
+ snd_tag.X.u = 2;
+
+ L4_LoadMR(0, snd_tag.raw);
+ L4_LoadMR(1, 0); /* fault address */
+ L4_LoadMR(2, (unsigned long)this); /* instruction pointer */
+
+ L4_Call(cap().dst());
+}
+
+
+void Pager_object::unresolved_page_fault_occurred()
+{
+ state.unresolved_page_fault = true;
+}
diff --git a/repos/base-okl4/src/core/target.inc b/repos/base-okl4/src/core/target.inc
index a5f40be42d..014c44bda8 100644
--- a/repos/base-okl4/src/core/target.inc
+++ b/repos/base-okl4/src/core/target.inc
@@ -62,7 +62,6 @@ vpath core_rpc_cap_alloc.cc $(GEN_CORE_DIR)
vpath dump_alloc.cc $(GEN_CORE_DIR)
vpath stack_area.cc $(GEN_CORE_DIR)
vpath pager_ep.cc $(GEN_CORE_DIR)
-vpath pager_object.cc $(GEN_CORE_DIR)
vpath %.cc $(REP_DIR)/src/core
vpath core_printf.cc $(BASE_DIR)/src/base/console
diff --git a/repos/base-okl4/src/include/base/internal/native_connection_state.h b/repos/base-okl4/src/include/base/internal/native_connection_state.h
deleted file mode 100644
index 3f1215927e..0000000000
--- a/repos/base-okl4/src/include/base/internal/native_connection_state.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * \brief Connection state
- * \author Norman Feske
- * \date 2016-03-11
- */
-
-/*
- * Copyright (C) 2016 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__BASE__INTERNAL__NATIVE_CONNECTION_STATE_H_
-#define _INCLUDE__BASE__INTERNAL__NATIVE_CONNECTION_STATE_H_
-
-#include
-
-namespace Genode { struct Native_connection_state; }
-
-
-struct Genode::Native_connection_state
-{
- Okl4::L4_ThreadId_t caller;
-};
-
-#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_CONNECTION_STATE_H_ */
diff --git a/repos/base-pistachio/include/base/ipc_msgbuf.h b/repos/base-pistachio/include/base/ipc_msgbuf.h
deleted file mode 100644
index 58049f8850..0000000000
--- a/repos/base-pistachio/include/base/ipc_msgbuf.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * \brief Pistachio-specific layout of IPC message buffer
- * \author Julian Stecklina
- * \date 2007-01-10
- */
-
-/*
- * Copyright (C) 2007-2013 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
-#define _INCLUDE__BASE__IPC_MSGBUF_H_
-
-namespace Genode {
-
- class Ipc_marshaller;
-
- /**
- * IPC message buffer layout
- */
- class Msgbuf_base
- {
- protected:
-
- friend class Ipc_marshaller;
-
- size_t const _capacity;
-
- size_t _data_size = 0;
-
- char _msg_start[]; /* symbol marks start of message */
-
- Msgbuf_base(size_t capacity) : _capacity(capacity) { }
-
- public:
-
- /*
- * Begin of message buffer layout
- */
- Pistachio::L4_Fpage_t rcv_fpage;
-
- /**
- * Return size of message buffer
- */
- size_t capacity() const { return _capacity; };
-
- /**
- * Return pointer of message data payload
- */
- void *data() { return &_msg_start[0]; };
- void const *data() const { return &_msg_start[0]; };
-
- size_t data_size() const { return _data_size; }
- };
-
-
- /**
- * Instance of IPC message buffer with specified buffer size
- */
- template
- class Msgbuf : public Msgbuf_base
- {
- public:
-
- char buf[BUF_SIZE];
-
- Msgbuf() : Msgbuf_base(BUF_SIZE) { }
- };
-}
-
-#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
diff --git a/repos/base-pistachio/lib/mk/base-common.mk b/repos/base-pistachio/lib/mk/base-common.mk
index 58e8e974dc..7717bb8135 100644
--- a/repos/base-pistachio/lib/mk/base-common.mk
+++ b/repos/base-pistachio/lib/mk/base-common.mk
@@ -7,7 +7,7 @@
LIBS += cxx startup syscall
SRC_CC += cap_copy.cc
-SRC_CC += ipc/ipc.cc ipc/ipc_marshal_cap.cc
+SRC_CC += ipc/ipc.cc
SRC_CC += avl_tree/avl_tree.cc
SRC_CC += allocator/slab.cc
SRC_CC += allocator/allocator_avl.cc
diff --git a/repos/base-pistachio/src/base/ipc/ipc.cc b/repos/base-pistachio/src/base/ipc/ipc.cc
index fe7391432f..ae07e5c8b3 100644
--- a/repos/base-pistachio/src/base/ipc/ipc.cc
+++ b/repos/base-pistachio/src/base/ipc/ipc.cc
@@ -68,19 +68,62 @@ static inline void check_ipc_result(L4_MsgTag_t result, L4_Word_t error_code)
throw Genode::Ipc_error();
}
- if (L4_UntypedWords(result) != 1) {
- PERR("Error in thread %08lx. Expected one untyped word (local_name), but got %lu.\n",
+ if (L4_UntypedWords(result) < 2) {
+ PERR("Error in thread %08lx. Expected at leat two untyped words, but got %lu.\n",
L4_Myself().raw, L4_UntypedWords(result));
+ throw Genode::Ipc_error();
+ }
+}
- PERR("This should not happen. Inspect!");
- throw Genode::Ipc_error();
+
+/**
+ * Configure L4 receive buffer according to Genode receive buffer
+ */
+static void extract_caps(L4_Msg_t &msg, Msgbuf_base &rcv_msg)
+{
+ using namespace Pistachio;
+
+ L4_Word_t const num_caps = min((unsigned)Msgbuf_base::MAX_CAPS_PER_MSG,
+ L4_Get(&msg, 1));
+ for (unsigned i = 0; i < num_caps; i++) {
+
+ L4_ThreadId_t tid;
+ tid.raw = L4_Get(&msg, 2 + i*2);
+
+ L4_Word_t const local_name = L4_Get(&msg, 2 + i*2 + 1);
+
+ rcv_msg.insert(Native_capability(tid, local_name));
}
- if (L4_TypedWords(result) != 2) {
- PERR("Error. Expected two typed words (a string item). but got %lu.\n",
- L4_TypedWords(result));
- PERR("This should not happen. Inspect!");
- throw Genode::Ipc_error();
+}
+
+
+/**
+ * Configure L4 message descriptor according to Genode send buffer
+ */
+static void prepare_send(L4_Word_t protocol_value, L4_Msg_t &msg,
+ Msgbuf_base &snd_msg)
+{
+ L4_Clear(&msg);
+ L4_Append(&msg, protocol_value);
+
+ L4_Append(&msg, (L4_Word_t)snd_msg.used_caps());
+
+ for (unsigned i = 0; i < snd_msg.used_caps(); i++) {
+ L4_Append(&msg, (L4_Word_t)snd_msg.cap(i).dst().raw);
+ L4_Append(&msg, (L4_Word_t)snd_msg.cap(i).local_name());
}
+
+ L4_Append(&msg, L4_StringItem(snd_msg.data_size(), snd_msg.data()));
+ L4_Load(&msg);
+}
+
+
+static void prepare_receive(L4_MsgBuffer_t &l4_msgbuf, Msgbuf_base &rcv_msg)
+{
+ L4_Clear(&l4_msgbuf);
+ L4_Append(&l4_msgbuf, L4_StringItem(rcv_msg.capacity(), rcv_msg.data()));
+ L4_Accept(L4_UntypedWordsAcceptor);
+ L4_Accept(L4_StringItemsAcceptor, &l4_msgbuf);
}
@@ -92,23 +135,13 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg,
size_t)
{
- L4_Msg_t msg;
- L4_StringItem_t sitem = L4_StringItem(snd_msg.data_size(), snd_msg.data());
- L4_Word_t const local_name = dst.local_name();
-
+ /* prepare receive message buffer */
L4_MsgBuffer_t msgbuf;
-
- /* prepare message buffer */
- L4_Clear (&msgbuf);
- L4_Append (&msgbuf, L4_StringItem (rcv_msg.capacity(), rcv_msg.data()));
- L4_Accept(L4_UntypedWordsAcceptor);
- L4_Accept(L4_StringItemsAcceptor, &msgbuf);
+ prepare_receive(msgbuf, rcv_msg);
/* prepare sending parameters */
- L4_Clear(&msg);
- L4_Append(&msg, local_name);
- L4_Append(&msg, sitem);
- L4_Load(&msg);
+ L4_Msg_t msg;
+ prepare_send(dst.local_name(), msg, snd_msg);
L4_MsgTag_t result = L4_Call(dst.dst());
@@ -117,67 +150,56 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
check_ipc_result(result, L4_ErrorCode());
+ extract_caps(msg, rcv_msg);
+
return Rpc_exception_code(L4_Get(&msg, 0));
}
/****************
- ** Ipc_server **
+ ** IPC server **
****************/
-void Ipc_server::_prepare_next_reply_wait()
-{
- _reply_needed = true;
- _read_offset = _write_offset = 0;
-}
-
-
-void Ipc_server::reply()
+void Genode::ipc_reply(Native_capability caller, Rpc_exception_code exc,
+ Msgbuf_base &snd_msg)
{
L4_Msg_t msg;
- L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg.data());
- L4_Word_t const local_name = _caller.local_name();
+ prepare_send(exc.value, msg, snd_msg);
- L4_Clear(&msg);
- L4_Append(&msg, local_name);
- L4_Append(&msg, sitem);
- L4_Load(&msg);
-
- L4_MsgTag_t result = L4_Reply(_caller.dst());
+ L4_MsgTag_t result = L4_Reply(caller.dst());
if (L4_IpcFailed(result))
PERR("ipc error in _reply, ignored");
- _prepare_next_reply_wait();
+ snd_msg.reset();
}
-void Ipc_server::reply_wait()
+Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller,
+ Rpc_exception_code exc,
+ Msgbuf_base &reply_msg,
+ Msgbuf_base &request_msg)
{
bool need_to_wait = true;
L4_MsgTag_t request_tag;
- /* prepare request message buffer */
- L4_MsgBuffer_t request_msgbuf;
- L4_Clear(&request_msgbuf);
- L4_Append(&request_msgbuf, L4_StringItem (_rcv_msg.capacity(), _rcv_msg.data()));
- L4_Accept(L4_UntypedWordsAcceptor);
- L4_Accept(L4_StringItemsAcceptor, &request_msgbuf);
+ request_msg.reset();
- if (_reply_needed) {
+ /* prepare receive buffer for request */
+ L4_MsgBuffer_t request_msgbuf;
+ prepare_receive(request_msgbuf, request_msg);
+
+ L4_ThreadId_t caller = L4_nilthread;
+
+ if (last_caller.valid() && exc.value != Rpc_exception_code::INVALID_OBJECT) {
/* prepare reply massage */
- L4_Msg_t reply_msg;
- L4_StringItem_t sitem = L4_StringItem(_write_offset, _snd_msg.data());
-
- L4_Clear(&reply_msg);
- L4_Append(&reply_msg, (L4_Word_t)_exception_code.value);
- L4_Append(&reply_msg, sitem);
- L4_Load(&reply_msg);
+ L4_Msg_t reply_l4_msg;
+ prepare_send(exc.value, reply_l4_msg, reply_msg);
/* send reply and wait for new request message */
- request_tag = L4_Ipc(_caller.dst(), L4_anythread,
- L4_Timeouts(L4_ZeroTime, L4_Never), &_rcv_cs.caller);
+ request_tag = L4_Ipc(last_caller.dst(), L4_anythread,
+ L4_Timeouts(L4_ZeroTime, L4_Never), &caller);
if (!L4_IpcFailed(request_tag))
need_to_wait = false;
@@ -186,7 +208,7 @@ void Ipc_server::reply_wait()
while (need_to_wait) {
/* wait for new request message */
- request_tag = L4_Wait(&_rcv_cs.caller);
+ request_tag = L4_Wait(&caller);
if (!L4_IpcFailed(request_tag))
need_to_wait = false;
@@ -196,26 +218,14 @@ void Ipc_server::reply_wait()
L4_Msg_t msg;
L4_Clear(&msg);
L4_Store(request_tag, &msg);
+ extract_caps(msg, request_msg);
- /* remember badge of invoked object */
- _badge = L4_Get(&msg, 0);
-
- /* define destination of next reply */
- _caller = Native_capability(_rcv_cs.caller, badge());
-
- _prepare_next_reply_wait();
+ unsigned long const badge = L4_Get(&msg, 0);
+ return Rpc_request(Native_capability(caller, 0), badge);
}
-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(Pistachio::L4_Myself(), 0),
- _rcv_cs(cs)
-{
- _read_offset = _write_offset = 0;
-}
+Ipc_server::Ipc_server() : Native_capability(Pistachio::L4_Myself(), 0) { }
Ipc_server::~Ipc_server() { }
diff --git a/repos/base-pistachio/src/core/pager.cc b/repos/base-pistachio/src/core/pager.cc
index c0f79c88ff..cfeb6d2040 100644
--- a/repos/base-pistachio/src/core/pager.cc
+++ b/repos/base-pistachio/src/core/pager.cc
@@ -132,10 +132,7 @@ void Ipc_pager::reply_and_wait_for_fault()
void Ipc_pager::acknowledge_wakeup()
{
- PERR("acknowledge_wakeup called, not yet implemented");
-// /* answer wakeup call from one of core's region-manager sessions */
-// l4_msgdope_t result;
-// l4_ipc_send(_last, L4_IPC_SHORT_MSG, 0, 0, L4_IPC_SEND_TIMEOUT_0, &result);
+ L4_Reply(_last);
}
diff --git a/repos/base-pistachio/src/core/pager_object.cc b/repos/base-pistachio/src/core/pager_object.cc
new file mode 100644
index 0000000000..0165684d55
--- /dev/null
+++ b/repos/base-pistachio/src/core/pager_object.cc
@@ -0,0 +1,50 @@
+/*
+ * \brief Kernel-specific RM-faulter wake-up mechanism
+ * \author Norman Feske
+ * \date 2016-04-12
+ */
+
+/*
+ * Copyright (C) 2016 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+/* core includes */
+#include
+
+/* Pistachio includes */
+namespace Pistachio {
+#include
+#include
+}
+
+using namespace Genode;
+
+
+void Pager_object::wake_up()
+{
+ using namespace Pistachio;
+
+ /*
+ * Issue IPC to pager, transmitting the pager-object pointer as 'IP'.
+ */
+ L4_Accept(L4_UntypedWordsAcceptor);
+
+ L4_MsgTag_t snd_tag;
+ snd_tag.raw = 0;
+ snd_tag.X.u = 2;
+
+ L4_LoadMR(0, snd_tag.raw);
+ L4_LoadMR(1, 0); /* fault address */
+ L4_LoadMR(2, (unsigned long)this); /* instruction pointer */
+
+ L4_Call(cap().dst());
+}
+
+
+void Pager_object::unresolved_page_fault_occurred()
+{
+ state.unresolved_page_fault = true;
+}
diff --git a/repos/base-pistachio/src/core/target.inc b/repos/base-pistachio/src/core/target.inc
index 69fd7d9f60..ef57fe5b6b 100644
--- a/repos/base-pistachio/src/core/target.inc
+++ b/repos/base-pistachio/src/core/target.inc
@@ -61,7 +61,6 @@ vpath dump_alloc.cc $(GEN_CORE_DIR)
vpath core_rpc_cap_alloc.cc $(GEN_CORE_DIR)
vpath stack_area.cc $(GEN_CORE_DIR)
vpath pager_ep.cc $(GEN_CORE_DIR)
-vpath pager_object.cc $(GEN_CORE_DIR)
vpath core_printf.cc $(BASE_DIR)/src/base/console
vpath kip.cc $(REP_DIR)/src/base/kip
vpath %.cc $(REP_DIR)/src/core
diff --git a/repos/base-pistachio/src/include/base/internal/native_connection_state.h b/repos/base-pistachio/src/include/base/internal/native_connection_state.h
deleted file mode 100644
index 1620cb0ed2..0000000000
--- a/repos/base-pistachio/src/include/base/internal/native_connection_state.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * \brief Connection state
- * \author Norman Feske
- * \date 2016-03-11
- */
-
-/*
- * Copyright (C) 2016 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__BASE__INTERNAL__NATIVE_CONNECTION_STATE_H_
-#define _INCLUDE__BASE__INTERNAL__NATIVE_CONNECTION_STATE_H_
-
-/* Pistachio includes */
-namespace Pistachio {
-#include
-}
-
-namespace Genode { struct Native_connection_state; }
-
-
-struct Genode::Native_connection_state
-{
- Pistachio::L4_ThreadId_t caller;
-};
-
-#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_CONNECTION_STATE_H_ */
diff --git a/repos/base-sel4/include/base/ipc_msgbuf.h b/repos/base-sel4/include/base/ipc_msgbuf.h
deleted file mode 100644
index 392f0bc16e..0000000000
--- a/repos/base-sel4/include/base/ipc_msgbuf.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * \brief IPC message buffer layout
- * \author Norman Feske
- * \date 2015-05-10
- */
-
-/*
- * Copyright (C) 2015 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
-#define _INCLUDE__BASE__IPC_MSGBUF_H_
-
-#include
-
-namespace Genode {
-
- class Msgbuf_base;
- template struct Msgbuf;
-
- class Ipc_marshaller;
-}
-
-
-class Genode::Msgbuf_base
-{
- public:
-
- enum { MAX_CAPS_PER_MSG = 3 };
-
- protected:
-
- friend class Ipc_marshaller;
-
- /*
- * Resolve ambiguity if the header is included from a libc-using
- * program.
- */
- typedef Genode::size_t size_t;
-
- /*
- * Capabilities to be transferred
- */
- Native_capability _caps[MAX_CAPS_PER_MSG];
- size_t _used_caps = 0;
- size_t _read_cap_index = 0;
-
- /**
- * Maximum size of plain-data message payload
- */
- size_t const _capacity;
-
- /**
- * Actual size of plain-data message payload
- */
- size_t _data_size = 0;
-
- char _msg_start[]; /* symbol marks start of message buffer data */
-
- /*
- * No member variables are allowed beyond this point!
- */
-
- Msgbuf_base(size_t capacity) : _capacity(capacity) { }
-
- public:
-
- char buf[];
-
- /**
- * Return size of message buffer
- */
- size_t capacity() const { return _capacity; };
-
- void reset_caps()
- {
- for (Genode::size_t i = 0; i < _used_caps; i++)
- _caps[i] = Native_capability();
-
- _used_caps = 0;
- }
-
- void reset_read_cap_index()
- {
- _read_cap_index = 0;
- }
-
- /**
- * Return pointer to start of message-buffer content
- */
- void const *data() const { return &_msg_start[0]; };
- void *data() { return &_msg_start[0]; };
-
- size_t data_size() const { return _data_size; }
-
- /**
- * Exception type
- */
- class Too_many_caps : public Exception { };
-
- /**
- * Called from '_marshal_capability'
- */
- void append_cap(Native_capability const &cap)
- {
- if (_used_caps == MAX_CAPS_PER_MSG)
- throw Too_many_caps();
-
- _caps[_used_caps++] = cap;
- }
-
- /**
- * Called from '_unmarshal_capability'
- */
- Native_capability extract_cap()
- {
- if (_read_cap_index == _used_caps)
- return Native_capability();
-
- return _caps[_read_cap_index++];
- }
-
- /**
- * Return number of marshalled capabilities
- */
- size_t used_caps() const { return _used_caps; }
-
- Native_capability &cap(unsigned index) { return _caps[index]; }
- Native_capability const &cap(unsigned index) const { return _caps[index]; }
-};
-
-
-template
-struct Genode::Msgbuf : Msgbuf_base
-{
- /**
- * Pump up IPC message buffer to specified buffer size
- *
- * XXX remove padding of 16
- */
- char buf[BUF_SIZE + 16];
-
- Msgbuf() : Msgbuf_base(BUF_SIZE) { }
-};
-
-
-#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
diff --git a/repos/base-sel4/src/base/ipc/ipc.cc b/repos/base-sel4/src/base/ipc/ipc.cc
index 8276840394..7ef0b2314d 100644
--- a/repos/base-sel4/src/base/ipc/ipc.cc
+++ b/repos/base-sel4/src/base/ipc/ipc.cc
@@ -63,11 +63,9 @@ static unsigned &rcv_sel()
/**
* Convert Genode::Msgbuf_base content into seL4 message
*
- * \param msg source message buffer
- * \param data_length size of message data in bytes
+ * \param msg source message buffer
*/
-static seL4_MessageInfo_t new_seL4_message(Msgbuf_base const &msg,
- size_t const data_length)
+static seL4_MessageInfo_t new_seL4_message(Msgbuf_base const &msg)
{
/*
* Supply capabilities to kernel IPC message
@@ -107,7 +105,7 @@ static seL4_MessageInfo_t new_seL4_message(Msgbuf_base const &msg,
* Supply data payload
*/
size_t const num_data_mwords =
- align_natural(data_length) / sizeof(umword_t);
+ align_natural(msg.data_size()) / sizeof(umword_t);
umword_t const *src = (umword_t const *)msg.data();
for (size_t i = 0; i < num_data_mwords; i++)
@@ -129,7 +127,7 @@ static void decode_seL4_message(seL4_MessageInfo_t const &msg_info,
/*
* Extract Genode capabilities from seL4 IPC message
*/
- dst_msg.reset_caps();
+ dst_msg.reset();
size_t const num_caps = seL4_GetMR(MR_IDX_NUM_CAPS);
size_t curr_sel4_cap_idx = 0;
@@ -153,7 +151,7 @@ static void decode_seL4_message(seL4_MessageInfo_t const &msg_info,
* Hence it is meaningless as a key.
*/
if (!rpc_obj_key.valid() && seL4_MessageInfo_get_extraCaps(msg_info) == 0) {
- dst_msg.append_cap(Native_capability());
+ dst_msg.insert(Native_capability());
continue;
}
@@ -185,7 +183,7 @@ static void decode_seL4_message(seL4_MessageInfo_t const &msg_info,
Native_capability arg_cap = Capability_space::lookup(rpc_obj_key);
- dst_msg.append_cap(arg_cap);
+ dst_msg.insert(arg_cap);
} else {
@@ -224,14 +222,14 @@ static void decode_seL4_message(seL4_MessageInfo_t const &msg_info,
Capability_space::reset_sel(rcv_sel());
- dst_msg.append_cap(arg_cap);
+ dst_msg.insert(arg_cap);
} else {
Capability_space::Ipc_cap_data const
ipc_cap_data(rpc_obj_key, rcv_sel());
- dst_msg.append_cap(Capability_space::import(ipc_cap_data));
+ dst_msg.insert(Capability_space::import(ipc_cap_data));
/*
* Since we keep using the received selector, we need to
@@ -247,25 +245,21 @@ static void decode_seL4_message(seL4_MessageInfo_t const &msg_info,
* Extract message data payload
*/
+ size_t const num_msg_words = seL4_MessageInfo_get_length(msg_info);
+
+ /* detect malformed message with too small header */
+ if (num_msg_words < MR_IDX_DATA)
+ return;
+
+ /* copy data payload */
+ size_t const max_words = dst_msg.capacity()/sizeof(umword_t);
+ size_t const num_data_words = min(num_msg_words - MR_IDX_DATA, max_words);
+
umword_t *dst = (umword_t *)dst_msg.data();
- for (size_t i = 0; i < seL4_MessageInfo_get_length(msg_info); i++)
+ for (size_t i = 0; i < num_data_words; i++)
*dst++ = seL4_GetMR(MR_IDX_DATA + i);
-}
-
-/*****************************
- ** IPC marshalling support **
- *****************************/
-
-void Ipc_marshaller::insert(Native_capability const &cap)
-{
- _snd_msg.append_cap(cap);
-}
-
-
-void Ipc_unmarshaller::extract(Native_capability &cap)
-{
- cap = _rcv_msg.extract_cap();
+ dst_msg.data_size(num_data_words*sizeof(umword_t));
}
@@ -285,8 +279,7 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
if (!rcv_sel())
rcv_sel() = Capability_space::alloc_rcv_sel();
- seL4_MessageInfo_t const request_msg_info =
- new_seL4_message(snd_msg, snd_msg.data_size());
+ seL4_MessageInfo_t const request_msg_info = new_seL4_message(snd_msg);
unsigned const dst_sel = Capability_space::ipc_cap_data(dst).sel.value();
@@ -300,55 +293,51 @@ Rpc_exception_code Genode::ipc_call(Native_capability dst,
/****************
- ** Ipc_server **
+ ** IPC server **
****************/
-void Ipc_server::reply()
+void Genode::ipc_reply(Native_capability caller, Rpc_exception_code exc,
+ Msgbuf_base &snd_msg)
{
ASSERT(false);
}
-void Ipc_server::reply_wait()
+Genode::Rpc_request Genode::ipc_reply_wait(Reply_capability const &last_caller,
+ Rpc_exception_code exc,
+ Msgbuf_base &reply_msg,
+ Msgbuf_base &request_msg)
{
- if (!_reply_needed) {
+ seL4_Word badge = 0;
- seL4_MessageInfo_t const msg_info =
- seL4_Recv(Thread_base::myself()->native_thread().ep_sel,
- (seL4_Word *)&_badge);
+ if (exc.value == Rpc_exception_code::INVALID_OBJECT) {
- decode_seL4_message(msg_info, _rcv_msg);
+ seL4_MessageInfo_t const request_msg_info =
+ seL4_Recv(Thread_base::myself()->native_thread().ep_sel, &badge);
+
+ decode_seL4_message(request_msg_info, request_msg);
} else {
- seL4_MessageInfo_t const reply_msg_info =
- new_seL4_message(_snd_msg, _write_offset);
+ seL4_MessageInfo_t const reply_msg_info = new_seL4_message(reply_msg);
- seL4_SetMR(MR_IDX_EXC_CODE, _exception_code.value);
+ seL4_SetMR(MR_IDX_EXC_CODE, exc.value);
seL4_MessageInfo_t const request_msg_info =
seL4_ReplyRecv(Thread_base::myself()->native_thread().ep_sel,
- reply_msg_info, (seL4_Word *)&_badge);
+ reply_msg_info, &badge);
- decode_seL4_message(request_msg_info, _rcv_msg);
+ decode_seL4_message(request_msg_info, request_msg);
}
- _reply_needed = true;
- _read_offset = _write_offset = 0;
-
- _rcv_msg.reset_read_cap_index();
- _snd_msg.reset_caps();
+ return Rpc_request(Native_capability(), badge);
}
-Ipc_server::Ipc_server(Native_connection_state &cs,
- Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg)
+Ipc_server::Ipc_server()
:
- Ipc_marshaller(snd_msg), Ipc_unmarshaller(rcv_msg), _rcv_cs(cs)
-{
- *static_cast(this) =
- Native_capability(Capability_space::create_ep_cap(*Thread_base::myself()));
-}
+ Native_capability(Capability_space::create_ep_cap(*Thread_base::myself()))
+{ }
Ipc_server::~Ipc_server() { }
diff --git a/repos/base-sel4/src/base/server/server.cc b/repos/base-sel4/src/base/server/server.cc
deleted file mode 100644
index 3e7cd26fbc..0000000000
--- a/repos/base-sel4/src/base/server/server.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * \brief Default version of platform-specific part of server framework
- * \author Norman Feske
- * \author Stefan Kalkowski
- * \date 2006-05-12
- *
- * This version is suitable for platforms similar to L4. Each platform
- * for which this implementation is not suited contains a platform-
- * specific version in its respective 'base-' repository.
- */
-
-/*
- * Copyright (C) 2006-2013 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-/* Genode includes */
-#include
-
-/* base-internal includes */
-#include
-#include
-
-using namespace Genode;
-
-
-/***********************
- ** Server entrypoint **
- ***********************/
-
-Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
-{
- Untyped_capability new_obj_cap = _alloc_rpc_cap(_pd_session, _cap);
-
- /* add server object to object pool */
- obj->cap(new_obj_cap);
- insert(obj);
-
- /* return capability that uses the object id as badge */
- return new_obj_cap;
-}
-
-
-void Rpc_entrypoint::entry()
-{
- Native_connection_state cs;
- Ipc_server srv(cs, _snd_buf, _rcv_buf);
- _ipc_server = &srv;
- _cap = srv;
- _cap_valid.unlock();
-
- /*
- * Now, the capability of the server activation is initialized
- * an can be passed around. However, the processing of capability
- * invocations should not happen until activation-using server
- * is completely initialized. Thus, we wait until the activation
- * gets explicitly unblocked by calling 'Rpc_entrypoint::activate()'.
- */
- _delay_start.lock();
-
- while (!_exit_handler.exit) {
-
- Rpc_opcode opcode(0);
-
- srv.reply_wait();
- srv.extract(opcode);
-
- /* set default return value */
- srv.ret(Rpc_exception_code(Rpc_exception_code::INVALID_OBJECT));
-
- /* atomically lookup and lock referenced object */
- auto lambda = [&] (Rpc_object_base *obj) {
- if (!obj) return;
-
- /* dispatch request */
- try { srv.ret(obj->dispatch(opcode, srv, srv)); }
- catch (Blocking_canceled) { }
- };
- apply(srv.badge(), lambda);
- }
-
- /* answer exit call, thereby wake up '~Rpc_entrypoint' */
- srv.reply();
-
- /* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
- _delay_exit.lock();
-}
diff --git a/repos/base/include/base/capability.h b/repos/base/include/base/capability.h
index fdf6ee9b05..c22cfe0a87 100644
--- a/repos/base/include/base/capability.h
+++ b/repos/base/include/base/capability.h
@@ -25,8 +25,8 @@ namespace Genode {
/**
* Forward declaration needed for internal interfaces of 'Capability'
*/
- class Ipc_marshaller;
class Ipc_unmarshaller;
+ class Msgbuf_base;
/**
@@ -58,9 +58,9 @@ class Genode::Capability : public Untyped_capability
* Insert RPC arguments into the message buffer
*/
template
- void _marshal_args(Ipc_marshaller &, ATL &args) const;
+ void _marshal_args(Msgbuf_base &, ATL &args) const;
- void _marshal_args(Ipc_marshaller &, Meta::Empty &) const { }
+ void _marshal_args(Msgbuf_base &, Meta::Empty &) const { }
/**
* Unmarshal single RPC argument from the message buffer
diff --git a/repos/base/include/base/ipc.h b/repos/base/include/base/ipc.h
index 18816ad05d..0757b48c79 100644
--- a/repos/base/include/base/ipc.h
+++ b/repos/base/include/base/ipc.h
@@ -14,19 +14,14 @@
#ifndef _INCLUDE__BASE__IPC_H_
#define _INCLUDE__BASE__IPC_H_
-#include
-#include
-#include
-#include
-#include
#include
#include
#include
namespace Genode {
- class Ipc_error;
- class Ipc_marshaller;
+ struct Ipc_error : Exception { };
+
class Ipc_unmarshaller;
/**
@@ -46,84 +41,6 @@ namespace Genode {
}
-/**
- * Exception type
- */
-class Genode::Ipc_error : public Exception { };
-
-
-/**
- * Marshal arguments into send message buffer
- */
-class Genode::Ipc_marshaller : Noncopyable
-{
- protected:
-
- Msgbuf_base &_snd_msg;
- size_t &_write_offset = _snd_msg._data_size;
-
- private:
-
- char *_snd_buf = (char *)_snd_msg.data();
- size_t const _snd_buf_size = _snd_msg.capacity();
-
- public:
-
- /**
- * Write value to send buffer
- */
- template
- void insert(T const &value)
- {
- /* check buffer range */
- if (_write_offset + sizeof(T) >= _snd_buf_size) return;
-
- /* write integer to buffer */
- *reinterpret_cast(&_snd_buf[_write_offset]) = value;
-
- /* increment write pointer to next dword-aligned value */
- _write_offset += align_natural(sizeof(T));
- }
-
- template
- void insert(Rpc_in_buffer const &b)
- {
- size_t const size = b.size();
- insert(size);
- insert(b.base(), size);
- }
-
- /**
- * Write bytes to send buffer
- */
- void insert(char const *src_addr, unsigned num_bytes)
- {
- /* check buffer range */
- if (_write_offset + num_bytes >= _snd_buf_size) return;
-
- /* copy buffer */
- memcpy(&_snd_buf[_write_offset], src_addr, num_bytes);
-
- /* increment write pointer to next dword-aligned value */
- _write_offset += align_natural(num_bytes);
- }
-
- /**
- * Insert capability to message buffer
- */
- void insert(Native_capability const &cap);
-
- template
- void insert(Capability const &typed_cap)
- {
- Native_capability untyped_cap = typed_cap;
- insert(untyped_cap);
- }
-
- Ipc_marshaller(Msgbuf_base &snd_msg) : _snd_msg(snd_msg) { }
-};
-
-
/**
* Unmarshal arguments from receive buffer
*/
@@ -131,8 +48,9 @@ class Genode::Ipc_unmarshaller : Noncopyable
{
protected:
- Msgbuf_base &_rcv_msg;
- unsigned _read_offset = 0;
+ Msgbuf_base &_rcv_msg;
+ unsigned _read_offset = 0;
+ unsigned _read_cap_index = 0;
private:
@@ -141,6 +59,9 @@ class Genode::Ipc_unmarshaller : Noncopyable
public:
+ /**
+ * Obtain typed capability from message buffer
+ */
template
void extract(Capability &typed_cap)
{
@@ -149,6 +70,16 @@ class Genode::Ipc_unmarshaller : Noncopyable
typed_cap = reinterpret_cap_cast(untyped_cap);
}
+ /**
+ * Obtain capability from message buffer
+ */
+ void extract(Native_capability &cap)
+ {
+ cap = _read_cap_index < _rcv_msg.used_caps()
+ ? _rcv_msg.cap(_read_cap_index) : Native_capability();
+ _read_cap_index++;
+ }
+
/**
* Read 'Rpc_in_buffer' from receive buffer
*/
@@ -165,7 +96,7 @@ class Genode::Ipc_unmarshaller : Noncopyable
* Note: The addr of the Rpc_in_buffer_base is a null pointer when this
* condition triggers.
*/
- if (_read_offset + size >= _rcv_buf_size) {
+ if (_read_offset + size > _rcv_buf_size) {
PERR("message buffer overrun");
return;
}
@@ -174,11 +105,6 @@ class Genode::Ipc_unmarshaller : Noncopyable
_read_offset += align_natural(size);
}
- /**
- * Obtain capability from message buffer
- */
- void extract(Native_capability &cap);
-
/**
* Read value of type T from buffer
*/
@@ -186,7 +112,7 @@ class Genode::Ipc_unmarshaller : Noncopyable
void extract(T &value)
{
/* check receive buffer range */
- if (_read_offset + sizeof(T) >= _rcv_buf_size) return;
+ if (_read_offset + sizeof(T) > _rcv_buf_size) return;
/* return value from receive buffer */
value = *reinterpret_cast(&_rcv_buf[_read_offset]);
@@ -195,8 +121,6 @@ class Genode::Ipc_unmarshaller : Noncopyable
_read_offset += align_natural(sizeof(T));
}
- public:
-
Ipc_unmarshaller(Msgbuf_base &rcv_msg) : _rcv_msg(rcv_msg) { }
};
diff --git a/repos/base/include/base/ipc_msgbuf.h b/repos/base/include/base/ipc_msgbuf.h
new file mode 100644
index 0000000000..a8493a4b58
--- /dev/null
+++ b/repos/base/include/base/ipc_msgbuf.h
@@ -0,0 +1,244 @@
+/*
+ * \brief IPC message buffer layout
+ * \author Norman Feske
+ * \date 2015-05-10
+ */
+
+/*
+ * Copyright (C) 2015 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+#ifndef _INCLUDE__BASE__IPC_MSGBUF_H_
+#define _INCLUDE__BASE__IPC_MSGBUF_H_
+
+#include
+#include
+#include
+#include
+#include
+
+namespace Genode {
+
+ class Msgbuf_base;
+ template class Msgbuf;
+}
+
+
+class Genode::Msgbuf_base : Noncopyable
+{
+ public:
+
+ enum { MAX_CAPS_PER_MSG = 4 };
+
+ private:
+
+ /*
+ * Resolve ambiguity if the header is included from a libc-using
+ * program.
+ */
+ typedef Genode::size_t size_t;
+
+ /*
+ * Capabilities to be transferred
+ */
+ Native_capability _caps[MAX_CAPS_PER_MSG];
+
+ /**
+ * Number of marshalled capabilities
+ */
+ size_t _used_caps = 0;
+
+ /**
+ * Pointer to buffer for data payload
+ */
+ char * const _data;
+
+ /**
+ * Maximum size of plain-data message payload
+ */
+ size_t const _capacity;
+
+ /**
+ * Actual size of plain-data message payload
+ */
+ size_t _data_size = 0;
+
+ char *_data_last() { return &_data[_data_size]; }
+
+ void _clear(size_t const num_bytes)
+ {
+ size_t const num_words = min(num_bytes, _capacity)/sizeof(long);
+ for (unsigned i = 0; i < num_words; i++)
+ word(i) = 0;
+ }
+
+ protected:
+
+ struct Headroom { long space[16]; };
+
+ Msgbuf_base(char *buf, size_t capacity)
+ :
+ _data(buf), _capacity(capacity)
+ {
+ _clear(capacity);
+ }
+
+ public:
+
+ /**
+ * Return reference to platform-specific header in front of the message
+ */
+ template
+ T &header()
+ {
+ static_assert(sizeof(T) <= sizeof(Headroom),
+ "Header size exceeds message headroom");
+ return *reinterpret_cast(_data - sizeof(T));
+ }
+
+ /**
+ * Return reference to the message word at the specified index
+ */
+ unsigned long &word(unsigned i)
+ {
+ return reinterpret_cast(_data)[i];
+ }
+
+ /**
+ * Return size of message buffer
+ */
+ size_t capacity() const { return _capacity; }
+
+ /**
+ * Reset message buffer
+ *
+ * This function is used at the server side for reusing the same
+ * message buffer for subsequent requests.
+ */
+ void reset()
+ {
+ for (Genode::size_t i = 0; i < _used_caps; i++)
+ _caps[i] = Native_capability();
+
+ _clear(_data_size);
+
+ _used_caps = 0;
+ _data_size = 0;
+ }
+
+ /**
+ * Return pointer to start of message-buffer content
+ */
+ void const *data() const { return _data; }
+ void *data() { return _data; }
+
+ /**
+ * Return size of marshalled data payload in bytes
+ */
+ size_t data_size() const { return _data_size; }
+
+ void data_size(size_t data_size) { _data_size = data_size; }
+
+ /**
+ * Exception type
+ */
+ class Too_many_caps : public Exception { };
+
+ /**
+ * Return number of marshalled capabilities
+ */
+ size_t used_caps() const { return _used_caps; }
+
+ void used_caps(size_t used_caps) { _used_caps = used_caps; }
+
+ Native_capability &cap(unsigned i) { return _caps[i]; }
+ Native_capability const &cap(unsigned i) const { return _caps[i]; }
+
+ /**
+ * Append value to message buffer
+ */
+ template
+ void insert(T const &value)
+ {
+ /* check buffer range */
+ if (_data_size + sizeof(T) > _capacity) return;
+
+ /* write value to buffer */
+ *reinterpret_cast(_data_last()) = value;
+
+ /* increment write pointer to next dword-aligned value */
+ _data_size += align_natural(sizeof(T));
+ }
+
+ /**
+ * Insert content of 'Rpc_in_buffer' into message buffer
+ */
+ template
+ void insert(Rpc_in_buffer const &b)
+ {
+ size_t const size = b.size();
+ insert(size);
+ insert(b.base(), size);
+ }
+
+ /**
+ * Write bytes to message buffer
+ */
+ void insert(char const *src_addr, unsigned num_bytes)
+ {
+ /* check buffer range */
+ if (_data_size + num_bytes > _capacity) return;
+
+ /* copy buffer */
+ memcpy(_data_last(), src_addr, num_bytes);
+
+ /* increment write pointer to next dword-aligned value */
+ _data_size += align_natural(num_bytes);
+ }
+
+ /**
+ * Insert capability to message buffer
+ */
+ void insert(Native_capability const &cap)
+ {
+ if (_used_caps == MAX_CAPS_PER_MSG)
+ throw Too_many_caps();
+
+ _caps[_used_caps++] = cap;
+ }
+
+ /**
+ * Insert typed capability into message buffer
+ */
+ template
+ void insert(Capability const &typed_cap)
+ {
+ Native_capability untyped_cap = typed_cap;
+ insert(untyped_cap);
+ }
+};
+
+
+template
+struct Genode::Msgbuf : Msgbuf_base
+{
+ /**
+ * Headroom in front of the actual message payload
+ *
+ * This space is used on some platforms to prepend the message with a
+ * protocol header.
+ */
+ Headroom headroom;
+
+ /**
+ * Buffer for data payload
+ */
+ char buf[BUF_SIZE];
+
+ Msgbuf() : Msgbuf_base(buf, BUF_SIZE) { }
+};
+
+#endif /* _INCLUDE__BASE__IPC_MSGBUF_H_ */
diff --git a/repos/base/include/base/rpc_client.h b/repos/base/include/base/rpc_client.h
index d03f2ce0d6..bac73ec9ff 100644
--- a/repos/base/include/base/rpc_client.h
+++ b/repos/base/include/base/rpc_client.h
@@ -58,12 +58,12 @@ namespace Genode {
template
template
void Capability::
- _marshal_args(Ipc_marshaller &marshaller, ATL &args) const
+ _marshal_args(Msgbuf_base &msg, ATL &args) const
{
if (Trait::Rpc_direction::Type::IN)
- marshaller.insert(args.get());
+ msg.insert(args.get());
- _marshal_args(marshaller, args._2);
+ _marshal_args(msg, args._2);
}
@@ -129,9 +129,8 @@ namespace Genode {
Rpc_opcode opcode(static_cast(Meta::Index_of::Value));
/* marshal opcode and RPC input arguments */
- Ipc_marshaller marshaller(call_buf);
- marshaller.insert(opcode);
- _marshal_args(marshaller, args);
+ call_buf.insert(opcode);
+ _marshal_args(call_buf, args);
{
Trace::Rpc_call trace_event(IF::name(), call_buf);
diff --git a/repos/base/include/base/rpc_server.h b/repos/base/include/base/rpc_server.h
index 9f1a1fddb9..51d2a354f2 100644
--- a/repos/base/include/base/rpc_server.h
+++ b/repos/base/include/base/rpc_server.h
@@ -74,7 +74,7 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
void _read_args(Ipc_unmarshaller &, Meta::Empty) { }
template
- void _write_results(Ipc_marshaller &msg, ARG_LIST &args)
+ void _write_results(Msgbuf_base &msg, ARG_LIST &args)
{
if (Trait::Rpc_direction::Type::OUT)
msg.insert(args._1);
@@ -82,7 +82,7 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
_write_results(msg, args._2);
}
- void _write_results(Ipc_marshaller &, Meta::Empty) { }
+ void _write_results(Msgbuf_base &, Meta::Empty) { }
template
Rpc_exception_code _do_serve(typename RPC_FUNCTION::Server_args &args,
@@ -111,7 +111,7 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
template
Rpc_exception_code _do_dispatch(Rpc_opcode opcode,
- Ipc_unmarshaller &in, Ipc_marshaller &out,
+ Ipc_unmarshaller &in, Msgbuf_base &out,
Meta::Overload_selector)
{
using namespace Meta;
@@ -158,7 +158,7 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
}
Rpc_exception_code _do_dispatch(Rpc_opcode opcode,
- Ipc_unmarshaller &, Ipc_marshaller &,
+ Ipc_unmarshaller &, Msgbuf_base &,
Meta::Overload_selector)
{
PERR("invalid opcode %ld\n", opcode.value);
@@ -169,7 +169,7 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
* Handle corner case of having an RPC interface with no RPC functions
*/
Rpc_exception_code _do_dispatch(Rpc_opcode opcode,
- Ipc_unmarshaller &, Ipc_marshaller &,
+ Ipc_unmarshaller &, Msgbuf_base &,
Meta::Overload_selector >)
{
return Rpc_exception_code(Rpc_exception_code::SUCCESS);
@@ -185,7 +185,7 @@ class Genode::Rpc_dispatcher : public RPC_INTERFACE
public:
Rpc_exception_code dispatch(Rpc_opcode opcode,
- Ipc_unmarshaller &in, Ipc_marshaller &out)
+ Ipc_unmarshaller &in, Msgbuf_base &out)
{
return _do_dispatch(opcode, in, out,
Meta::Overload_selector());
@@ -207,7 +207,7 @@ class Genode::Rpc_object_base : public Object_pool::Entry
* \param out outgoing message for storing method results
*/
virtual Rpc_exception_code
- dispatch(Rpc_opcode op, Ipc_unmarshaller &in, Ipc_marshaller &out) = 0;
+ dispatch(Rpc_opcode op, Ipc_unmarshaller &in, Msgbuf_base &out) = 0;
};
@@ -225,7 +225,7 @@ struct Genode::Rpc_object : Rpc_object_base, Rpc_dispatcher::dispatch(opcode, in, out);
}
@@ -287,13 +287,13 @@ class Genode::Rpc_entrypoint : Thread_base, public Object_pool
protected:
- Ipc_server *_ipc_server;
- Lock _cap_valid; /* thread startup synchronization */
- Lock _delay_start; /* delay start of request dispatching */
- Lock _delay_exit; /* delay destructor until server settled */
- Pd_session &_pd_session; /* for creating capabilities */
- Exit_handler _exit_handler;
- Capability _exit_cap;
+ Native_capability _caller;
+ Lock _cap_valid; /* thread startup synchronization */
+ Lock _delay_start; /* delay start of request dispatching */
+ Lock _delay_exit; /* delay destructor until server settled */
+ Pd_session &_pd_session; /* for creating capabilities */
+ Exit_handler _exit_handler;
+ Capability _exit_cap;
/**
* Access to kernel-specific part of the PD session interface
@@ -402,7 +402,7 @@ class Genode::Rpc_entrypoint : Thread_base, public Object_pool
* Typically, a capability obtained via this method is used as
* argument of 'intermediate_reply'.
*/
- Untyped_capability reply_dst();
+ Untyped_capability reply_dst() { return _caller; }
/**
* Prevent reply of current request
@@ -417,7 +417,7 @@ class Genode::Rpc_entrypoint : Thread_base, public Object_pool
* request. At a later time, the server may chose to unblock the
* client via the 'intermedate_reply' method.
*/
- void omit_reply();
+ void omit_reply() { _caller = Native_capability(); }
/**
* Send a reply out of the normal call-reply order
diff --git a/repos/base/run/rm_fault.run b/repos/base/run/rm_fault.run
index 919da24db9..335cec2d46 100644
--- a/repos/base/run/rm_fault.run
+++ b/repos/base/run/rm_fault.run
@@ -1,4 +1,4 @@
-if {[have_spec linux] || [have_spec pistachio]} {
+if {[have_spec linux]} {
puts "Platform does not support managed dataspaces"; exit }
build "core init test/rm_fault"
@@ -30,4 +30,4 @@ build_boot_image "core init test-rm_fault"
append qemu_args "-nographic -m 64"
-run_genode_until {child "test-rm_fault" exited with exit value 0.*} 10
+run_genode_until {child "test-rm_fault" exited with exit value 0.*} 300
diff --git a/repos/base/src/base/ipc/ipc_marshal_cap.cc b/repos/base/src/base/ipc/ipc_marshal_cap.cc
deleted file mode 100644
index f3292a2ccf..0000000000
--- a/repos/base/src/base/ipc/ipc_marshal_cap.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * \brief Marshalling/unmarshalling of plain-data capabilities
- * \author Norman Feske
- * \date 2013-02-13
- */
-
-/*
- * Copyright (C) 2013 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#include
-
-using namespace Genode;
-
-
-/**
- * Marshalling of capabilities as plain data representation
- */
-void Ipc_marshaller::insert(Native_capability const &cap)
-{
- insert((char const *)&cap, sizeof(Native_capability));
-}
-
-
-/**
- * Unmarshalling of capabilities as plain data representation
- */
-void Ipc_unmarshaller::extract(Native_capability &cap)
-{
- struct Raw { char buf[sizeof(Native_capability)]; } raw;
- extract(raw);
- (Raw &)(cap) = raw;
-}
diff --git a/repos/base/src/base/server/common.cc b/repos/base/src/base/server/common.cc
index 213de0c715..eb81d656d2 100644
--- a/repos/base/src/base/server/common.cc
+++ b/repos/base/src/base/server/common.cc
@@ -43,35 +43,12 @@ void Rpc_entrypoint::_block_until_cap_valid()
}
-Untyped_capability Rpc_entrypoint::reply_dst()
-{
- 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->caller(Untyped_capability());
-}
-
-
void Rpc_entrypoint::reply_signal_info(Untyped_capability reply_cap,
unsigned long imprint, unsigned long cnt)
{
- if (!_ipc_server) return;
-
- /* backup reply capability of current request */
- Untyped_capability last_reply_cap = _ipc_server->caller();
-
- /* direct ipc server to the specified reply destination */
- _ipc_server->ret(Rpc_exception_code(Rpc_exception_code::SUCCESS));
- _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->caller(last_reply_cap);
+ Msgbuf snd_buf;
+ snd_buf.insert(Signal_source::Signal(imprint, cnt));
+ ipc_reply(reply_cap, Rpc_exception_code(Rpc_exception_code::SUCCESS), snd_buf);
}
diff --git a/repos/base/src/base/server/server.cc b/repos/base/src/base/server/server.cc
index 60a77ac892..5138c5d445 100644
--- a/repos/base/src/base/server/server.cc
+++ b/repos/base/src/base/server/server.cc
@@ -2,22 +2,18 @@
* \brief Default version of platform-specific part of RPC framework
* \author Norman Feske
* \date 2006-05-12
- *
- * This version is suitable for platforms similar to L4. Each platform
- * for which this implementation is not suited contains a platform-
- * specific version in its respective 'base-' repository.
*/
/*
- * Copyright (C) 2006-2013 Genode Labs GmbH
+ * Copyright (C) 2006-2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
+#include
#include
-#include
#include
/* base-internal includes */
@@ -32,8 +28,7 @@ using namespace Genode;
Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
{
- Untyped_capability ep_cap = Native_capability(_cap.dst(), 0);
- Untyped_capability new_obj_cap = _alloc_rpc_cap(_pd_session, ep_cap);
+ Untyped_capability new_obj_cap = _alloc_rpc_cap(_pd_session, _cap);
/* add server object to object pool */
obj->cap(new_obj_cap);
@@ -46,11 +41,7 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj)
void Rpc_entrypoint::entry()
{
- using Pool = Object_pool;
-
- Native_connection_state cs;
- Ipc_server srv(cs, _snd_buf, _rcv_buf);
- _ipc_server = &srv;
+ Ipc_server srv;
_cap = srv;
_cap_valid.unlock();
@@ -63,27 +54,32 @@ void Rpc_entrypoint::entry()
*/
_delay_start.lock();
+ Rpc_exception_code exc = Rpc_exception_code(Rpc_exception_code::INVALID_OBJECT);
+
while (!_exit_handler.exit) {
- Rpc_opcode opcode(0);
+ Rpc_request const request = ipc_reply_wait(_caller, exc, _snd_buf, _rcv_buf);
+ _caller = request.caller;
- srv.reply_wait();
- srv.extract(opcode);
+ Ipc_unmarshaller unmarshaller(_rcv_buf);
+ Rpc_opcode opcode(0);
+ unmarshaller.extract(opcode);
/* set default return value */
- srv.ret(Rpc_exception_code(Rpc_exception_code::INVALID_OBJECT));
+ exc = Rpc_exception_code(Rpc_exception_code::INVALID_OBJECT);
+ _snd_buf.reset();
- Pool::apply(srv.badge(), [&] (Rpc_object_base *obj)
+ apply(request.badge, [&] (Rpc_object_base *obj)
{
if (!obj) { return;}
- try {
- srv.ret(obj->dispatch(opcode, srv, srv));
- } catch(Blocking_canceled&) { }
+ try { exc = obj->dispatch(opcode, unmarshaller, _snd_buf); }
+ catch(Blocking_canceled&) { }
});
}
/* answer exit call, thereby wake up '~Rpc_entrypoint' */
- srv.reply();
+ Msgbuf<16> snd_buf;
+ ipc_reply(_caller, Rpc_exception_code(Rpc_exception_code::SUCCESS), snd_buf);
/* defer the destruction of 'Ipc_server' until '~Rpc_entrypoint' is ready */
_delay_exit.lock();
diff --git a/repos/base/src/base/signal/signal.cc b/repos/base/src/base/signal/signal.cc
index 00b3c8e57d..03bd61ffa2 100644
--- a/repos/base/src/base/signal/signal.cc
+++ b/repos/base/src/base/signal/signal.cc
@@ -15,6 +15,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -278,6 +279,11 @@ void Signal_receiver::dispatch_signals(Signal_source *signal_source)
/* look up context as pointed to by the signal imprint */
Signal_context *context = (Signal_context *)(source_signal.imprint());
+ if (!context) {
+ PERR("received null signal imprint, stop signal handling");
+ sleep_forever();
+ }
+
if (!signal_context_registry()->test_and_lock(context)) {
PWRN("encountered dead signal context");
continue;
diff --git a/repos/base/src/core/pager_object.cc b/repos/base/src/core/pager_object.cc
index ac59dd8f44..ce8678f876 100644
--- a/repos/base/src/core/pager_object.cc
+++ b/repos/base/src/core/pager_object.cc
@@ -11,6 +11,9 @@
* under the terms of the GNU General Public License version 2.
*/
+/* Genode includes */
+#include
+
/* core includes */
#include
@@ -19,11 +22,7 @@ using namespace Genode;
void Pager_object::wake_up()
{
- /* notify pager to wake up faulter */
- Msgbuf<16> snd, rcv;
- Ipc_marshaller marshaller(snd);
- marshaller.insert(this);
- ipc_call(cap(), snd, rcv, 0);
+ PWRN("user-level page fault handling is not supported on this platform");
}
diff --git a/repos/base/src/include/base/internal/ipc_server.h b/repos/base/src/include/base/internal/ipc_server.h
index 11128421c9..c97945d1ce 100644
--- a/repos/base/src/include/base/internal/ipc_server.h
+++ b/repos/base/src/include/base/internal/ipc_server.h
@@ -18,73 +18,43 @@
#include
#include
-/* base-internal includes */
-#include
-
namespace Genode {
- class Native_connection_state;
- class Ipc_server;
+ struct Ipc_server;
+
+ /**
+ * Send reply to caller
+ */
+ void ipc_reply(Native_capability caller, Rpc_exception_code,
+ Msgbuf_base &snd_msg);
+
+ typedef Native_capability Reply_capability;
+
+ struct Rpc_request
+ {
+ Reply_capability caller;
+ unsigned long badge = ~0;
+
+ Rpc_request() { }
+
+ Rpc_request(Reply_capability caller, unsigned long badge)
+ : caller(caller), badge(badge) { }
+ };
+
+ /**
+ * Send result of previous RPC request and wait for new one
+ */
+ Rpc_request ipc_reply_wait(Reply_capability const &caller,
+ Rpc_exception_code reply_exc,
+ Msgbuf_base &reply_msg,
+ Msgbuf_base &request_msg);
}
-class Genode::Ipc_server : public Ipc_marshaller, public Ipc_unmarshaller,
- public Native_capability
+struct Genode::Ipc_server : Native_capability
{
- private:
-
- bool _reply_needed = false; /* false for the first reply_wait */
-
- Native_capability _caller;
-
- Native_connection_state &_rcv_cs;
-
- void _prepare_next_reply_wait();
-
- unsigned long _badge = 0;
-
- Rpc_exception_code _exception_code { 0 };
-
- public:
-
- /**
- * Constructor
- */
- Ipc_server(Native_connection_state &,
- Msgbuf_base &snd_msg, Msgbuf_base &rcv_msg);
-
- ~Ipc_server();
-
- /**
- * 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(Rpc_exception_code code) { _exception_code = code; }
-
- /**
- * Read badge that was supplied with the message
- */
- unsigned long badge() const { return _badge; }
-
- /**
- * Set reply destination
- */
- void caller(Native_capability const &caller)
- {
- _caller = caller;
- _reply_needed = caller.valid();
- }
-
- Native_capability caller() const { return _caller; }
+ Ipc_server();
+ ~Ipc_server();
};
#endif /* _INCLUDE__BASE__INTERNAL__IPC_SERVER_H_ */
diff --git a/repos/base/src/include/base/internal/native_connection_state.h b/repos/base/src/include/base/internal/native_connection_state.h
deleted file mode 100644
index 9f3e877102..0000000000
--- a/repos/base/src/include/base/internal/native_connection_state.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * \brief Dummy connection state
- * \author Norman Feske
- * \date 2016-03-03
- */
-
-/*
- * Copyright (C) 2016 Genode Labs GmbH
- *
- * This file is part of the Genode OS framework, which is distributed
- * under the terms of the GNU General Public License version 2.
- */
-
-#ifndef _INCLUDE__BASE__INTERNAL__NATIVE_CONNECTION_STATE_H_
-#define _INCLUDE__BASE__INTERNAL__NATIVE_CONNECTION_STATE_H_
-
-#include
-
-namespace Genode { struct Native_connection_state { }; }
-
-#endif /* _INCLUDE__BASE__INTERNAL__NATIVE_CONNECTION_STATE_H_ */