diff --git a/base-codezero/lib/mk/ipc.mk b/base-codezero/lib/mk/ipc.mk index 302770253..9a85fb2e4 100644 --- a/base-codezero/lib/mk/ipc.mk +++ b/base-codezero/lib/mk/ipc.mk @@ -1,5 +1,6 @@ -SRC_CC = ipc.cc pager.cc +SRC_CC = ipc.cc pager.cc ipc_marshal_cap.cc INC_DIR += $(REP_DIR)/include/codezero/dummies LIBS = cap_copy -vpath %.cc $(REP_DIR)/src/base/ipc +vpath %.cc $(REP_DIR)/src/base/ipc +vpath ipc_marshal_cap.cc $(BASE_DIR)/src/base/ipc diff --git a/base-fiasco/lib/mk/ipc.mk b/base-fiasco/lib/mk/ipc.mk index aac0969d0..282f5ab24 100644 --- a/base-fiasco/lib/mk/ipc.mk +++ b/base-fiasco/lib/mk/ipc.mk @@ -1,4 +1,5 @@ -SRC_CC = ipc.cc pager.cc +SRC_CC = ipc.cc pager.cc ipc_marshal_cap.cc LIBS = cap_copy -vpath %.cc $(REP_DIR)/src/base/ipc +vpath %.cc $(REP_DIR)/src/base/ipc +vpath ipc_marshal_cap.cc $(BASE_DIR)/src/base/ipc diff --git a/base-foc/include/base/ipc.h b/base-foc/include/base/ipc.h deleted file mode 100644 index 1f9312f14..000000000 --- a/base-foc/include/base/ipc.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * \brief Fiasco.OC-specific supplements to the IPC framework - * \author Norman Feske - * \author Stefan Kalkowski - * \date 2010-01-27 - */ - -/* - * 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_H_ -#define _INCLUDE__BASE__IPC_H_ - -#include -#include - - -inline void Genode::Ipc_ostream::_marshal_capability(Genode::Native_capability const &cap) -{ - using namespace Fiasco; - - /* first transfer local capability value */ - _write_to_buf(cap.local()); - - /* if it's a local capability we're done */ - if (cap.local()) - return; - - if (cap.valid()) { - if (!l4_msgtag_label(l4_task_cap_valid(L4_BASE_TASK_CAP, cap.dst()))) { - _write_to_buf(0); - return; - } - } - - /* transfer capability id */ - _write_to_buf(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"); -} - - -inline void Genode::Ipc_istream::_unmarshal_capability(Genode::Native_capability &cap) -{ - using namespace Fiasco; - - long value = 0; - - /* get local capability pointer from message buffer */ - _read_from_buf(value); - - /* if it's a local capability, the pointer is marshalled in the id */ - if (value) { - cap = Capability::local_cap((Native_capability*)value); - return; - } - - /* extract capability id from message buffer */ - _read_from_buf(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())); -} - -#endif /* _INCLUDE__BASE__IPC_H_ */ diff --git a/base-foc/src/base/ipc/ipc.cc b/base-foc/src/base/ipc/ipc.cc index f33b7b989..e693d6367 100644 --- a/base-foc/src/base/ipc/ipc.cc +++ b/base-foc/src/base/ipc/ipc.cc @@ -25,6 +25,7 @@ #include #include #include +#include /* base-foc/src/base/lock */ #include /* for 'thread_get_my_native_id()' */ @@ -42,6 +43,66 @@ using namespace Genode; using namespace Fiasco; +/***************************** + ** IPC marshalling support ** + *****************************/ + +void Ipc_ostream::_marshal_capability(Native_capability const &cap) +{ + /* first transfer local capability value */ + _write_to_buf(cap.local()); + + /* if it's a local capability we're done */ + if (cap.local()) + return; + + if (cap.valid()) { + if (!l4_msgtag_label(l4_task_cap_valid(L4_BASE_TASK_CAP, cap.dst()))) { + _write_to_buf(0); + return; + } + } + + /* transfer capability id */ + _write_to_buf(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_istream::_unmarshal_capability(Native_capability &cap) +{ + long value = 0; + + /* get local capability pointer from message buffer */ + _read_from_buf(value); + + /* if it's a local capability, the pointer is marshalled in the id */ + if (value) { + cap = Capability::local_cap((Native_capability*)value); + return; + } + + /* extract capability id from message buffer */ + _read_from_buf(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 ** ***************/ diff --git a/base-host/lib/mk/ipc.mk b/base-host/lib/mk/ipc.mk index 6e3e9b51a..52ec507d5 100644 --- a/base-host/lib/mk/ipc.mk +++ b/base-host/lib/mk/ipc.mk @@ -1,4 +1,5 @@ -SRC_CC = ipc.cc +SRC_CC = ipc.cc ipc_marshal_cap.cc LIBS = cap_copy -vpath ipc.cc $(REP_DIR)/src/base/ipc +vpath ipc.cc $(REP_DIR)/src/base/ipc +vpath ipc_marshal_cap.cc $(BASE_DIR)/src/base/ipc diff --git a/base-hw/lib/mk/raw_ipc.mk b/base-hw/lib/mk/raw_ipc.mk index d9a9b3214..3b85980e7 100644 --- a/base-hw/lib/mk/raw_ipc.mk +++ b/base-hw/lib/mk/raw_ipc.mk @@ -1,12 +1,13 @@ # -# \brief Interprocess communication without thread implementations +# \brief Inter-process communication without thread implementations # \author Martin Stein # \date 2012-04-16 # # add C++ source files -SRC_CC += ipc.cc +SRC_CC += ipc.cc ipc_marshal_cap.cc # declare source paths -vpath ipc.cc $(REP_DIR)/src/base +vpath ipc.cc $(REP_DIR)/src/base +vpath ipc_marshal_cap.cc $(BASE_DIR)/src/base/ipc diff --git a/base-linux/include/base/ipc.h b/base-linux/include/base/ipc.h deleted file mode 100644 index 269c9cbed..000000000 --- a/base-linux/include/base/ipc.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * \brief Linux-specific supplements to the IPC framework - * \author Norman Feske - * \date 2012-07-26 - */ - -/* - * Copyright (C) 2012-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_H_ -#define _INCLUDE__BASE__IPC_H_ - -#include - - -inline void Genode::Ipc_ostream::_marshal_capability(Genode::Native_capability const &cap) -{ - if (cap.valid()) { - _write_to_buf(cap.local_name()); - - _snd_msg->append_cap(cap.dst().socket); - } else { - _write_to_buf(-1L); - } -} - - -inline void Genode::Ipc_istream::_unmarshal_capability(Genode::Native_capability &cap) -{ - long local_name = 0; - _read_from_buf(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); - } -} - -#endif /* _INCLUDE__BASE__IPC_H_ */ diff --git a/base-linux/src/base/ipc/ipc.cc b/base-linux/src/base/ipc/ipc.cc index 0d2d25f8f..f967db7cb 100644 --- a/base-linux/src/base/ipc/ipc.cc +++ b/base-linux/src/base/ipc/ipc.cc @@ -46,6 +46,41 @@ using namespace Genode; +/***************************** + ** IPC marshalling support ** + *****************************/ + +void Ipc_ostream::_marshal_capability(Native_capability const &cap) +{ + if (cap.valid()) { + _write_to_buf(cap.local_name()); + + _snd_msg->append_cap(cap.dst().socket); + } else { + _write_to_buf(-1L); + } +} + + +void Ipc_istream::_unmarshal_capability(Native_capability &cap) +{ + long local_name = 0; + _read_from_buf(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 { /* diff --git a/base-mb/lib/mk/ipc.mk b/base-mb/lib/mk/ipc.mk index 50249b5a6..46a5dcd7f 100755 --- a/base-mb/lib/mk/ipc.mk +++ b/base-mb/lib/mk/ipc.mk @@ -1,6 +1,7 @@ -SRC_CC = ipc.cc +SRC_CC = ipc.cc ipc_marshal_cap.cc SRC_CC += pager.cc LIBS += thread_context cap_copy -vpath ipc.cc $(REP_DIR)/src/base/ipc -vpath pager.cc $(REP_DIR)/src/base/ipc +vpath ipc.cc $(REP_DIR)/src/base/ipc +vpath pager.cc $(REP_DIR)/src/base/ipc +vpath ipc_marshal_cap.cc $(BASE_DIR)/src/base/ipc diff --git a/base-nova/include/base/ipc.h b/base-nova/include/base/ipc.h deleted file mode 100644 index 5ada0551e..000000000 --- a/base-nova/include/base/ipc.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * \brief NOVA-specific supplements to the IPC framework - * \author Norman Feske - * \date 2010-01-27 - */ - -/* - * 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_H_ -#define _INCLUDE__BASE__IPC_H_ - -#include - - -inline void -Genode::Ipc_ostream::_marshal_capability(Genode::Native_capability const &cap) -{ - if (cap.valid()) - _snd_msg->snd_append_pt_sel(cap.local_name(), - cap.dst().rights(), - cap.trans_map()); -} - - -inline void -Genode::Ipc_istream::_unmarshal_capability(Genode::Native_capability &cap) -{ - addr_t pt_sel = _rcv_msg->rcv_pt_sel(); - cap = Native_capability(pt_sel); -} - -#endif /* _INCLUDE__BASE__IPC_H_ */ diff --git a/base-nova/src/base/ipc/ipc.cc b/base-nova/src/base/ipc/ipc.cc index 077184c82..e56d45fff 100644 --- a/base-nova/src/base/ipc/ipc.cc +++ b/base-nova/src/base/ipc/ipc.cc @@ -24,6 +24,26 @@ using namespace Genode; using namespace Nova; +/***************************** + ** IPC marshalling support ** + *****************************/ + +void Ipc_ostream::_marshal_capability(Native_capability const &cap) +{ + if (cap.valid()) + _snd_msg->snd_append_pt_sel(cap.local_name(), + cap.dst().rights(), + cap.trans_map()); +} + + +void Ipc_istream::_unmarshal_capability(Native_capability &cap) +{ + addr_t pt_sel = _rcv_msg->rcv_pt_sel(); + cap = Native_capability(pt_sel); +} + + /*************** ** Utilities ** ***************/ diff --git a/base-okl4/lib/mk/ipc.mk b/base-okl4/lib/mk/ipc.mk index aac0969d0..282f5ab24 100644 --- a/base-okl4/lib/mk/ipc.mk +++ b/base-okl4/lib/mk/ipc.mk @@ -1,4 +1,5 @@ -SRC_CC = ipc.cc pager.cc +SRC_CC = ipc.cc pager.cc ipc_marshal_cap.cc LIBS = cap_copy -vpath %.cc $(REP_DIR)/src/base/ipc +vpath %.cc $(REP_DIR)/src/base/ipc +vpath ipc_marshal_cap.cc $(BASE_DIR)/src/base/ipc diff --git a/base-pistachio/lib/mk/ipc.mk b/base-pistachio/lib/mk/ipc.mk index cc39f1793..6ba207822 100644 --- a/base-pistachio/lib/mk/ipc.mk +++ b/base-pistachio/lib/mk/ipc.mk @@ -1,7 +1,8 @@ -SRC_CC = ipc.cc pager.cc +SRC_CC = ipc.cc pager.cc ipc_marshal_cap.cc LIBS = cap_copy # disable warning about array boundaries, caused by L4 headers CC_WARN = -Wall -Wno-array-bounds -vpath %.cc $(REP_DIR)/src/base/ipc +vpath %.cc $(REP_DIR)/src/base/ipc +vpath ipc_marshal_cap.cc $(BASE_DIR)/src/base/ipc diff --git a/base/include/base/ipc.h b/base/include/base/ipc.h index fe5c61971..7a06d34a7 100644 --- a/base/include/base/ipc.h +++ b/base/include/base/ipc.h @@ -1,41 +1,632 @@ /* * \brief Generic IPC infrastructure * \author Norman Feske - * \date 2009-10-02 + * \date 2006-06-12 * - * This file is used for platforms that only use the generic IPC API. A platform - * may extend the generic API with platform-specific marshalling operators by - * providing a custom version of 'ipc.h' in its 'base-' repository. + * Most of the marshalling and unmarshallung code is generic for IPC + * implementations among different platforms. In addition to the generic + * marshalling items, platform-specific marshalling items can be realized + * via specialized stream operators defined in the platform-specific + * 'base/ipc.h'. Hence, this header file is never to be included directly. + * It should only be included by a platform-specific 'base/ipc.h' file. */ /* - * Copyright (C) 2009-2013 Genode Labs GmbH + * 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_H_ -#define _INCLUDE__BASE__IPC_H_ +#ifndef _INCLUDE__BASE__IPC_GENERIC_H_ +#define _INCLUDE__BASE__IPC_GENERIC_H_ -#include +#include +#include +#include +#include +#include +#include +#include +#include -/** - * Marshalling of capabilities as plain data representation - */ -inline void -Genode::Ipc_ostream::_marshal_capability(Genode::Native_capability const &cap) -{ - _write_to_buf(cap); +namespace Genode { + + enum Ipc_ostream_send { IPC_SEND }; + enum Ipc_istream_wait { IPC_WAIT }; + enum Ipc_client_call { IPC_CALL }; + enum Ipc_server_reply { IPC_REPLY }; + enum Ipc_server_reply_wait { IPC_REPLY_WAIT }; + + + /********************* + ** Exception types ** + *********************/ + + class Ipc_error : public Exception { }; + + + /** + * Marshal arguments into send message buffer + */ + class Ipc_marshaller + { + protected: + + char *_sndbuf; + size_t _sndbuf_size; + unsigned _write_offset; + + protected: + + /** + * Write value to send buffer + */ + template + void _write_to_buf(T const &value) + { + /* check buffer range */ + if (_write_offset + sizeof(T) >= _sndbuf_size) return; + + /* write integer to buffer */ + *reinterpret_cast(&_sndbuf[_write_offset]) = value; + + /* increment write pointer to next dword-aligned value */ + _write_offset += align_natural(sizeof(T)); + } + + /** + * Write bytes to send buffer + */ + void _write_to_buf(char const *src_addr, unsigned num_bytes) + { + /* check buffer range */ + if (_write_offset + num_bytes >= _sndbuf_size) return; + + /* copy buffer */ + memcpy(&_sndbuf[_write_offset], src_addr, num_bytes); + + /* increment write pointer to next dword-aligned value */ + _write_offset += align_natural(num_bytes); + } + + /** + * Write 'Rpc_in_buffer' to send buffer + */ + void _write_buffer_to_buf(Rpc_in_buffer_base const &b) + { + size_t size = b.size(); + _write_to_buf(size); + _write_to_buf(b.base(), size); + } + + /** + * Write array to send buffer + */ + template + void _write_to_buf(T const (&array)[N]) + { + /* check buffer range */ + if (_write_offset + sizeof(array) >= _sndbuf_size) + PERR("send buffer overrun"); + + memcpy(&_sndbuf[_write_offset], array, sizeof(array)); + _write_offset += align_natural(sizeof(array)); + } + + public: + + Ipc_marshaller(char *sndbuf, size_t sndbuf_size) + : _sndbuf(sndbuf), _sndbuf_size(sndbuf_size), _write_offset(0) { } + }; + + + /** + * Unmarshal arguments from receive buffer + */ + class Ipc_unmarshaller + { + protected: + + char *_rcvbuf; + size_t _rcvbuf_size; + unsigned _read_offset; + + protected: + + /** + * Read value of type T from buffer + */ + template + void _read_from_buf(T &value) + { + /* check receive buffer range */ + if (_read_offset + sizeof(T) >= _rcvbuf_size) return; + + /* return value from receive buffer */ + value = *reinterpret_cast(&_rcvbuf[_read_offset]); + + /* increment read pointer to next dword-aligned value */ + _read_offset += align_natural(sizeof(T)); + } + + /** + * Read 'Rpc_in_buffer' from receive buffer + */ + void _read_bytebuf_from_buf(Rpc_in_buffer_base &b) + { + size_t size = 0; + _read_from_buf(size); + b = Rpc_in_buffer_base(0, 0); + + /* + * Check receive buffer range + * + * Note: The addr of the Rpc_in_buffer_base is a null pointer when this + * condition triggers. + */ + if (_read_offset + size >= _rcvbuf_size) { + PERR("message buffer overrun"); + return; + } + + b = Rpc_in_buffer_base(&_rcvbuf[_read_offset], size); + _read_offset += align_natural(size); + } + + /** + * Read array from receive buffer + */ + template + void _read_from_buf(T (&array)[N]) + { + if (_read_offset + sizeof(array) >= _rcvbuf_size) { + PERR("receive buffer overrun"); + return; + } + + memcpy(array, &_rcvbuf[_read_offset], sizeof(array)); + _read_offset += align_natural(sizeof(array)); + } + + /** + * Read long value at specified byte index of receive buffer + */ + long _long_at_idx(int idx) { return *(long *)(&_rcvbuf[idx]); } + + public: + + Ipc_unmarshaller(char *rcvbuf, size_t rcvbuf_size) + : _rcvbuf(rcvbuf), _rcvbuf_size(rcvbuf_size), _read_offset(0) { } + }; + + + /** + * Stream for sending information via a capability to an endpoint + */ + class Ipc_ostream : public Ipc_marshaller + { + protected: + + Msgbuf_base *_snd_msg; /* send message buffer */ + Native_capability _dst; + + /** + * Reset marshaller and write badge at the beginning of the message + */ + void _prepare_next_send(); + + /** + * Send message in _snd_msg to _dst + */ + void _send(); + + /** + * Insert capability to message buffer + */ + void _marshal_capability(Native_capability const &cap); + + public: + + /** + * Constructor + */ + Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg); + + /** + * Return true if Ipc_ostream is ready for send + */ + bool ready_for_send() const { return _dst.valid(); } + + /** + * Insert value into send buffer + */ + template + Ipc_ostream &operator << (T const &value) + { + _write_to_buf(value); + return *this; + } + + /** + * Insert byte buffer to send buffer + */ + Ipc_ostream &operator << (Rpc_in_buffer_base const &b) + { + _write_buffer_to_buf(b); + return *this; + } + + /** + * Insert capability to send buffer + */ + Ipc_ostream &operator << (Native_capability const &cap) + { + _marshal_capability(cap); + return *this; + } + + /** + * Insert typed capability to send buffer + */ + template + Ipc_ostream &operator << (Capability const &typed_cap) + { + _marshal_capability(typed_cap); + return *this; + } + + /** + * Issue the sending of the message buffer + */ + Ipc_ostream &operator << (Ipc_ostream_send) + { + _send(); + return *this; + } + + /** + * Return current 'IPC_SEND' destination + * + * This function is typically needed by a server than sends replies + * in a different order as the incoming calls. + */ + Native_capability dst() const { return _dst; } + + /** + * Set destination for the next 'IPC_SEND' + */ + void dst(Native_capability const &dst) { _dst = dst; } + }; + + + /** + * Stream for receiving information + */ + class Ipc_istream : public Ipc_unmarshaller, public Native_capability + { + private: + + /** + * Prevent 'Ipc_istream' objects from being copied + * + * Copying an 'Ipc_istream' object would result in a duplicated + * (and possibly inconsistent) connection state both the original + * and the copied object. + */ + Ipc_istream(const Ipc_istream &); + + protected: + + Msgbuf_base *_rcv_msg; + Native_connection_state _rcv_cs; + + /** + * Obtain capability from message buffer + */ + void _unmarshal_capability(Native_capability &cap); + + protected: + + /** + * Reset unmarshaller + */ + void _prepare_next_receive(); + + /** + * Wait for incoming message to be received in _rcv_msg + */ + void _wait(); + + public: + + explicit Ipc_istream(Msgbuf_base *rcv_msg); + + ~Ipc_istream(); + + /** + * Read badge that was supplied with the message + */ + long badge() { return _long_at_idx(0); } + + /** + * Block for an incoming message filling the receive buffer + */ + Ipc_istream &operator >> (Ipc_istream_wait) + { + _wait(); + return *this; + } + + /** + * Read values from receive buffer + */ + template + Ipc_istream &operator >> (T &value) + { + _read_from_buf(value); + return *this; + } + + /** + * Read byte buffer from receive buffer + */ + Ipc_istream &operator >> (Rpc_in_buffer_base &b) + { + _read_bytebuf_from_buf(b); + return *this; + } + + /** + * Read byte buffer from receive buffer + */ + template + Ipc_istream &operator >> (Rpc_in_buffer &b) + { + _read_bytebuf_from_buf(b); + return *this; + } + + /** + * Read capability from receive buffer + */ + Ipc_istream &operator >> (Native_capability &cap) + { + _unmarshal_capability(cap); + return *this; + } + + /** + * Read typed capability from receive buffer + */ + template + Ipc_istream &operator >> (Capability &typed_cap) + { + _unmarshal_capability(typed_cap); + return *this; + } + }; + + + class Ipc_client: public Ipc_istream, public Ipc_ostream + { + protected: + + int _result; /* result of most recent call */ + + void _prepare_next_call(); + + /** + * Send RPC message and wait for result + */ + void _call(); + + /** + * Set return value if call to server failed + */ + void ret(int retval) + { + *reinterpret_cast(&_rcvbuf[sizeof(umword_t)]) = retval; + } + + public: + + /** + * Constructor + */ + Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg, + Msgbuf_base *rcv_msg); + + /** + * Operator that issues an IPC call + * + * \throw Ipc_error + * \throw Blocking_canceled + */ + Ipc_client &operator << (Ipc_client_call) + { + _call(); + _read_from_buf(_result); + if (_result == ERR_INVALID_OBJECT) { + PERR("tried to call an invalid object"); + throw Ipc_error(); + } + return *this; + } + + template + Ipc_client &operator << (T const &value) + { + _write_to_buf(value); + return *this; + } + + Ipc_client &operator << (Rpc_in_buffer_base const &b) + { + _write_buffer_to_buf(b); + return *this; + } + + template + Ipc_client &operator << (Rpc_in_buffer const &b) + { + _write_buffer_to_buf(b); + return *this; + } + + Ipc_client &operator << (Native_capability const &cap) + { + _marshal_capability(cap); + return *this; + } + + template + Ipc_client &operator << (Capability const &typed_cap) + { + _marshal_capability(typed_cap); + return *this; + } + + Ipc_client &operator >> (Native_capability &cap) + { + _unmarshal_capability(cap); + return *this; + } + + template + Ipc_client &operator >> (Capability &typed_cap) + { + _unmarshal_capability(typed_cap); + return *this; + } + + template + Ipc_client &operator >> (T &value) + { + _read_from_buf(value); + return *this; + } + + Ipc_client &operator >> (Rpc_in_buffer_base &b) + { + _read_bytebuf_from_buf(b); + return *this; + } + + int result() const { return _result; } + }; + + + class Ipc_server : public Ipc_istream, public Ipc_ostream + { + protected: + + bool _reply_needed; /* false for the first reply_wait */ + + void _prepare_next_reply_wait(); + + /** + * Wait for incoming call + * + * In constrast to 'Ipc_istream::_wait()', this function stores the + * next reply destination from into 'dst' of the 'Ipc_ostream'. + */ + void _wait(); + + /** + * Send reply to destination + * + * In contrast to 'Ipc_ostream::_send()', this function prepares + * the 'Ipc_server' to send another subsequent reply without the + * calling '_wait()' in between. This is needed when a server + * answers calls out of order. + */ + void _reply(); + + /** + * Send result of previous RPC request and wait for new one + */ + void _reply_wait(); + + public: + + /** + * Constructor + */ + Ipc_server(Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg); + + /** + * Set return value of server call + */ + void ret(int retval) + { + *reinterpret_cast(&_sndbuf[sizeof(umword_t)]) = retval; + } + + /** + * Set reply destination + */ + void dst(Native_capability const &reply_dst) + { + Ipc_ostream::dst(reply_dst); + _reply_needed = reply_dst.valid(); + } + + using Ipc_ostream::dst; + + /** + * Block for an incoming message filling the receive buffer + */ + Ipc_server &operator >> (Ipc_istream_wait) + { + _wait(); + return *this; + } + + /** + * Issue the sending of the message buffer + */ + Ipc_server &operator << (Ipc_server_reply) + { + _reply(); + return *this; + } + + /** + * Reply current request and wait for a new one + */ + Ipc_server &operator >> (Ipc_server_reply_wait) + { + _reply_wait(); + return *this; + } + + /** + * Write value to send buffer + * + * This operator is only used by test programs + */ + template + Ipc_server &operator << (T const &value) + { + _write_to_buf(value); + return *this; + } + + /** + * Read value from receive buffer + * + * This operator should only be used by the server framework for + * reading the function offset. The server-side processing of the + * payload is done using 'Ipc_istream' and 'Ipc_ostream'. + */ + template + Ipc_server &operator >> (T &value) + { + _read_from_buf(value); + return *this; + } + }; } -/** - * Unmarshalling of capabilities as plain data representation - */ -inline void -Genode::Ipc_istream::_unmarshal_capability(Genode::Native_capability &cap) -{ - _read_from_buf(cap); -} - -#endif /* _INCLUDE__BASE__IPC_H_ */ +#endif /* _INCLUDE__BASE__IPC_GENERIC_H_ */ diff --git a/base/include/base/ipc_generic.h b/base/include/base/ipc_generic.h deleted file mode 100644 index 7a06d34a7..000000000 --- a/base/include/base/ipc_generic.h +++ /dev/null @@ -1,632 +0,0 @@ -/* - * \brief Generic IPC infrastructure - * \author Norman Feske - * \date 2006-06-12 - * - * Most of the marshalling and unmarshallung code is generic for IPC - * implementations among different platforms. In addition to the generic - * marshalling items, platform-specific marshalling items can be realized - * via specialized stream operators defined in the platform-specific - * 'base/ipc.h'. Hence, this header file is never to be included directly. - * It should only be included by a platform-specific 'base/ipc.h' file. - */ - -/* - * 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_GENERIC_H_ -#define _INCLUDE__BASE__IPC_GENERIC_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Genode { - - enum Ipc_ostream_send { IPC_SEND }; - enum Ipc_istream_wait { IPC_WAIT }; - enum Ipc_client_call { IPC_CALL }; - enum Ipc_server_reply { IPC_REPLY }; - enum Ipc_server_reply_wait { IPC_REPLY_WAIT }; - - - /********************* - ** Exception types ** - *********************/ - - class Ipc_error : public Exception { }; - - - /** - * Marshal arguments into send message buffer - */ - class Ipc_marshaller - { - protected: - - char *_sndbuf; - size_t _sndbuf_size; - unsigned _write_offset; - - protected: - - /** - * Write value to send buffer - */ - template - void _write_to_buf(T const &value) - { - /* check buffer range */ - if (_write_offset + sizeof(T) >= _sndbuf_size) return; - - /* write integer to buffer */ - *reinterpret_cast(&_sndbuf[_write_offset]) = value; - - /* increment write pointer to next dword-aligned value */ - _write_offset += align_natural(sizeof(T)); - } - - /** - * Write bytes to send buffer - */ - void _write_to_buf(char const *src_addr, unsigned num_bytes) - { - /* check buffer range */ - if (_write_offset + num_bytes >= _sndbuf_size) return; - - /* copy buffer */ - memcpy(&_sndbuf[_write_offset], src_addr, num_bytes); - - /* increment write pointer to next dword-aligned value */ - _write_offset += align_natural(num_bytes); - } - - /** - * Write 'Rpc_in_buffer' to send buffer - */ - void _write_buffer_to_buf(Rpc_in_buffer_base const &b) - { - size_t size = b.size(); - _write_to_buf(size); - _write_to_buf(b.base(), size); - } - - /** - * Write array to send buffer - */ - template - void _write_to_buf(T const (&array)[N]) - { - /* check buffer range */ - if (_write_offset + sizeof(array) >= _sndbuf_size) - PERR("send buffer overrun"); - - memcpy(&_sndbuf[_write_offset], array, sizeof(array)); - _write_offset += align_natural(sizeof(array)); - } - - public: - - Ipc_marshaller(char *sndbuf, size_t sndbuf_size) - : _sndbuf(sndbuf), _sndbuf_size(sndbuf_size), _write_offset(0) { } - }; - - - /** - * Unmarshal arguments from receive buffer - */ - class Ipc_unmarshaller - { - protected: - - char *_rcvbuf; - size_t _rcvbuf_size; - unsigned _read_offset; - - protected: - - /** - * Read value of type T from buffer - */ - template - void _read_from_buf(T &value) - { - /* check receive buffer range */ - if (_read_offset + sizeof(T) >= _rcvbuf_size) return; - - /* return value from receive buffer */ - value = *reinterpret_cast(&_rcvbuf[_read_offset]); - - /* increment read pointer to next dword-aligned value */ - _read_offset += align_natural(sizeof(T)); - } - - /** - * Read 'Rpc_in_buffer' from receive buffer - */ - void _read_bytebuf_from_buf(Rpc_in_buffer_base &b) - { - size_t size = 0; - _read_from_buf(size); - b = Rpc_in_buffer_base(0, 0); - - /* - * Check receive buffer range - * - * Note: The addr of the Rpc_in_buffer_base is a null pointer when this - * condition triggers. - */ - if (_read_offset + size >= _rcvbuf_size) { - PERR("message buffer overrun"); - return; - } - - b = Rpc_in_buffer_base(&_rcvbuf[_read_offset], size); - _read_offset += align_natural(size); - } - - /** - * Read array from receive buffer - */ - template - void _read_from_buf(T (&array)[N]) - { - if (_read_offset + sizeof(array) >= _rcvbuf_size) { - PERR("receive buffer overrun"); - return; - } - - memcpy(array, &_rcvbuf[_read_offset], sizeof(array)); - _read_offset += align_natural(sizeof(array)); - } - - /** - * Read long value at specified byte index of receive buffer - */ - long _long_at_idx(int idx) { return *(long *)(&_rcvbuf[idx]); } - - public: - - Ipc_unmarshaller(char *rcvbuf, size_t rcvbuf_size) - : _rcvbuf(rcvbuf), _rcvbuf_size(rcvbuf_size), _read_offset(0) { } - }; - - - /** - * Stream for sending information via a capability to an endpoint - */ - class Ipc_ostream : public Ipc_marshaller - { - protected: - - Msgbuf_base *_snd_msg; /* send message buffer */ - Native_capability _dst; - - /** - * Reset marshaller and write badge at the beginning of the message - */ - void _prepare_next_send(); - - /** - * Send message in _snd_msg to _dst - */ - void _send(); - - /** - * Insert capability to message buffer - */ - void _marshal_capability(Native_capability const &cap); - - public: - - /** - * Constructor - */ - Ipc_ostream(Native_capability dst, Msgbuf_base *snd_msg); - - /** - * Return true if Ipc_ostream is ready for send - */ - bool ready_for_send() const { return _dst.valid(); } - - /** - * Insert value into send buffer - */ - template - Ipc_ostream &operator << (T const &value) - { - _write_to_buf(value); - return *this; - } - - /** - * Insert byte buffer to send buffer - */ - Ipc_ostream &operator << (Rpc_in_buffer_base const &b) - { - _write_buffer_to_buf(b); - return *this; - } - - /** - * Insert capability to send buffer - */ - Ipc_ostream &operator << (Native_capability const &cap) - { - _marshal_capability(cap); - return *this; - } - - /** - * Insert typed capability to send buffer - */ - template - Ipc_ostream &operator << (Capability const &typed_cap) - { - _marshal_capability(typed_cap); - return *this; - } - - /** - * Issue the sending of the message buffer - */ - Ipc_ostream &operator << (Ipc_ostream_send) - { - _send(); - return *this; - } - - /** - * Return current 'IPC_SEND' destination - * - * This function is typically needed by a server than sends replies - * in a different order as the incoming calls. - */ - Native_capability dst() const { return _dst; } - - /** - * Set destination for the next 'IPC_SEND' - */ - void dst(Native_capability const &dst) { _dst = dst; } - }; - - - /** - * Stream for receiving information - */ - class Ipc_istream : public Ipc_unmarshaller, public Native_capability - { - private: - - /** - * Prevent 'Ipc_istream' objects from being copied - * - * Copying an 'Ipc_istream' object would result in a duplicated - * (and possibly inconsistent) connection state both the original - * and the copied object. - */ - Ipc_istream(const Ipc_istream &); - - protected: - - Msgbuf_base *_rcv_msg; - Native_connection_state _rcv_cs; - - /** - * Obtain capability from message buffer - */ - void _unmarshal_capability(Native_capability &cap); - - protected: - - /** - * Reset unmarshaller - */ - void _prepare_next_receive(); - - /** - * Wait for incoming message to be received in _rcv_msg - */ - void _wait(); - - public: - - explicit Ipc_istream(Msgbuf_base *rcv_msg); - - ~Ipc_istream(); - - /** - * Read badge that was supplied with the message - */ - long badge() { return _long_at_idx(0); } - - /** - * Block for an incoming message filling the receive buffer - */ - Ipc_istream &operator >> (Ipc_istream_wait) - { - _wait(); - return *this; - } - - /** - * Read values from receive buffer - */ - template - Ipc_istream &operator >> (T &value) - { - _read_from_buf(value); - return *this; - } - - /** - * Read byte buffer from receive buffer - */ - Ipc_istream &operator >> (Rpc_in_buffer_base &b) - { - _read_bytebuf_from_buf(b); - return *this; - } - - /** - * Read byte buffer from receive buffer - */ - template - Ipc_istream &operator >> (Rpc_in_buffer &b) - { - _read_bytebuf_from_buf(b); - return *this; - } - - /** - * Read capability from receive buffer - */ - Ipc_istream &operator >> (Native_capability &cap) - { - _unmarshal_capability(cap); - return *this; - } - - /** - * Read typed capability from receive buffer - */ - template - Ipc_istream &operator >> (Capability &typed_cap) - { - _unmarshal_capability(typed_cap); - return *this; - } - }; - - - class Ipc_client: public Ipc_istream, public Ipc_ostream - { - protected: - - int _result; /* result of most recent call */ - - void _prepare_next_call(); - - /** - * Send RPC message and wait for result - */ - void _call(); - - /** - * Set return value if call to server failed - */ - void ret(int retval) - { - *reinterpret_cast(&_rcvbuf[sizeof(umword_t)]) = retval; - } - - public: - - /** - * Constructor - */ - Ipc_client(Native_capability const &srv, Msgbuf_base *snd_msg, - Msgbuf_base *rcv_msg); - - /** - * Operator that issues an IPC call - * - * \throw Ipc_error - * \throw Blocking_canceled - */ - Ipc_client &operator << (Ipc_client_call) - { - _call(); - _read_from_buf(_result); - if (_result == ERR_INVALID_OBJECT) { - PERR("tried to call an invalid object"); - throw Ipc_error(); - } - return *this; - } - - template - Ipc_client &operator << (T const &value) - { - _write_to_buf(value); - return *this; - } - - Ipc_client &operator << (Rpc_in_buffer_base const &b) - { - _write_buffer_to_buf(b); - return *this; - } - - template - Ipc_client &operator << (Rpc_in_buffer const &b) - { - _write_buffer_to_buf(b); - return *this; - } - - Ipc_client &operator << (Native_capability const &cap) - { - _marshal_capability(cap); - return *this; - } - - template - Ipc_client &operator << (Capability const &typed_cap) - { - _marshal_capability(typed_cap); - return *this; - } - - Ipc_client &operator >> (Native_capability &cap) - { - _unmarshal_capability(cap); - return *this; - } - - template - Ipc_client &operator >> (Capability &typed_cap) - { - _unmarshal_capability(typed_cap); - return *this; - } - - template - Ipc_client &operator >> (T &value) - { - _read_from_buf(value); - return *this; - } - - Ipc_client &operator >> (Rpc_in_buffer_base &b) - { - _read_bytebuf_from_buf(b); - return *this; - } - - int result() const { return _result; } - }; - - - class Ipc_server : public Ipc_istream, public Ipc_ostream - { - protected: - - bool _reply_needed; /* false for the first reply_wait */ - - void _prepare_next_reply_wait(); - - /** - * Wait for incoming call - * - * In constrast to 'Ipc_istream::_wait()', this function stores the - * next reply destination from into 'dst' of the 'Ipc_ostream'. - */ - void _wait(); - - /** - * Send reply to destination - * - * In contrast to 'Ipc_ostream::_send()', this function prepares - * the 'Ipc_server' to send another subsequent reply without the - * calling '_wait()' in between. This is needed when a server - * answers calls out of order. - */ - void _reply(); - - /** - * Send result of previous RPC request and wait for new one - */ - void _reply_wait(); - - public: - - /** - * Constructor - */ - Ipc_server(Msgbuf_base *snd_msg, Msgbuf_base *rcv_msg); - - /** - * Set return value of server call - */ - void ret(int retval) - { - *reinterpret_cast(&_sndbuf[sizeof(umword_t)]) = retval; - } - - /** - * Set reply destination - */ - void dst(Native_capability const &reply_dst) - { - Ipc_ostream::dst(reply_dst); - _reply_needed = reply_dst.valid(); - } - - using Ipc_ostream::dst; - - /** - * Block for an incoming message filling the receive buffer - */ - Ipc_server &operator >> (Ipc_istream_wait) - { - _wait(); - return *this; - } - - /** - * Issue the sending of the message buffer - */ - Ipc_server &operator << (Ipc_server_reply) - { - _reply(); - return *this; - } - - /** - * Reply current request and wait for a new one - */ - Ipc_server &operator >> (Ipc_server_reply_wait) - { - _reply_wait(); - return *this; - } - - /** - * Write value to send buffer - * - * This operator is only used by test programs - */ - template - Ipc_server &operator << (T const &value) - { - _write_to_buf(value); - return *this; - } - - /** - * Read value from receive buffer - * - * This operator should only be used by the server framework for - * reading the function offset. The server-side processing of the - * payload is done using 'Ipc_istream' and 'Ipc_ostream'. - */ - template - Ipc_server &operator >> (T &value) - { - _read_from_buf(value); - return *this; - } - }; -} - -#endif /* _INCLUDE__BASE__IPC_GENERIC_H_ */ diff --git a/base/src/base/ipc/ipc_marshal_cap.cc b/base/src/base/ipc/ipc_marshal_cap.cc new file mode 100644 index 000000000..3d62b3b03 --- /dev/null +++ b/base/src/base/ipc/ipc_marshal_cap.cc @@ -0,0 +1,34 @@ +/* + * \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_ostream::_marshal_capability(Native_capability const &cap) +{ + _write_to_buf(cap); +} + + +/** + * Unmarshalling of capabilities as plain data representation + */ +void Ipc_istream::_unmarshal_capability(Native_capability &cap) +{ + _read_from_buf(cap); +} diff --git a/qt4/src/lib/qnitpickerviewwidget/qnitpickerviewwidget.cpp b/qt4/src/lib/qnitpickerviewwidget/qnitpickerviewwidget.cpp index 70bdf86dd..5ac234ebf 100644 --- a/qt4/src/lib/qnitpickerviewwidget/qnitpickerviewwidget.cpp +++ b/qt4/src/lib/qnitpickerviewwidget/qnitpickerviewwidget.cpp @@ -4,7 +4,7 @@ * \date 2010-08-26 */ -#include +#include #include