7 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
8 * Alexander Warg <warg@os.inf.tu-dresden.de>,
9 * Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
10 * economic rights: Technische Universität Dresden (Germany)
12 * This file is part of TUD:OS and distributed under the terms of the
13 * GNU General Public License 2.
14 * Please see the COPYING-GPL-2 file for details.
16 * As a special exception, you may use this file as part of a free software
17 * library without restriction. Specifically, if other files instantiate
18 * templates or use macros or inline functions from this file, or you compile
19 * this file and link it with other files to produce an executable, this
20 * file does not by itself cause the resulting executable to be covered by
21 * the GNU General Public License. This exception does not however
22 * invalidate any other reasons why the executable file might be covered by
23 * the GNU General Public License.
28 #include <l4/sys/ipc.h>
29 #include <l4/sys/capability>
30 #include <l4/cxx/type_traits>
32 #define L4_CXX_IPC_BACKWARD_COMPAT 1
44 * \brief Abstraction for inserting an array into an Ipc::Ostream.
47 * An object of Buf_cp_out can be used to insert an array of arbitrary values,
48 * that can be inserted into an Ipc::Ostream individually.
49 * The array is therefore copied to the message buffer, in contrast to
50 * data handled with Msg_out_buffer or Msg_io_buffer.
52 * On insertion into the Ipc::Ostream exactly the given number of elements
53 * of type T are copied to the message buffer, this means the source buffer
54 * is no longer referenced after insertion into the stream.
56 * You should use buf_cp_out() to create instances of Buf_cp_out.
58 * The counterpart is either Buf_cp_in (buf_cp_in()) or Buf_in (buf_in()).
60 template< typename T >
65 * \brief Create a buffer object for the given array.
66 * \param v The pointer to the array with size elements of type T.
67 * \param size the number of elements in the array.
69 Buf_cp_out(T *v, unsigned long size) : _v(v), _s(size) {}
72 * \brief Get the number of elements in the array.
73 * \note This function is usually used by the Ipc::Ostream itself.
75 unsigned long size() const { return _s; }
78 * \brief Get the pointer to the array.
79 * \note This function is usually used by the Ipc::Ostream itself.
81 T *buf() const { return _v; }
90 * \brief Create an instance of Buf_cp_out for the given values.
93 * This function makes it more convenient to insert arrays into an
94 * Ipc::Ostream (\see Buf_cp_out.)
96 * \param v Pointer to the array that shall be inserted into an Ipc::Ostream.
97 * \param size Number of elements in the array.
99 template< typename T >
100 Buf_cp_out<T> buf_cp_out(T *v, unsigned long size)
101 { return Buf_cp_out<T>(v,size); }
105 * \brief Abstraction for extracting array from an Ipc::Istream.
108 * An instance of Buf_cp_in can be used to extract an array from
109 * an Ipc::Istream. This is the counterpart to the Buf_cp_out abstraction.
110 * The data from the received message is thereby copied to the given buffer
111 * and size is set to the number of elements found in the stream.
112 * To avoid the copy operation Buf_in may be used instead.
114 * \see buf_cp_in(), Buf_in, buf_in(), Buf_cp_out, and buf_cp_out().
116 template< typename T >
121 * \brief Create a buffer for extracting an array from an Ipc::Istream.
122 * \param v The buffer for array (copy in).
123 * \param size Input: the number of elements the array can take at most<br>
124 * Output: the number of elements found in the stream.
126 Buf_cp_in(T *v, unsigned long &size) : _v(v), _s(&size) {}
128 unsigned long &size() const { return *_s; }
129 T *buf() const { return _v; }
131 friend class Istream;
137 * \brief Create an Buf_cp_in for the given values.
140 * This function makes it more convenient to extract arrays from an
141 * Ipc::Istream (\see Buf_cp_in.)
143 * \param v Pointer to the array that shall receive the values from the
145 * \param size Input: the number of elements the array can take at most<br>
146 * Output: the number of elements found in the stream.
148 * \see buf_in() and buf_cp_out().
150 template< typename T >
151 Buf_cp_in<T> buf_cp_in(T *v, unsigned long &size)
152 { return Buf_cp_in<T>(v,size); }
156 * \brief Pointer to an element of type T in an Ipc::Istream.
159 * This wrapper can be used to extract an element of type T from an
160 * Ipc::Istream, whereas the data is not copied out, but a pointer into
161 * the message buffer itself is returned. With is mechanism it is possible
162 * to avoid an extra copy of large data structures from a received IPC
163 * message, instead the returned pointer gives direct access to the data
168 template< typename T >
175 * \brief Create a Msg_ptr object that set pointer p to point into the
177 * \param p The pointer that is adjusted to point into the message buffer.
179 explicit Msg_ptr(T *&p) : _p(&p) {}
180 void set(T *p) const { *_p = p; }
184 * \brief Create an Msg_ptr to adjust the given pointer.
187 * This function makes it more convenient to extract pointers to data in the
188 * message buffer itself from an Ipc::Istream.
189 * This may be used to avoid copy out of large data structures.
192 template< typename T >
193 Msg_ptr<T> msg_ptr(T *&p)
194 { return Msg_ptr<T>(p); }
198 * \brief Abstraction to extract an array from an Ipc::Istream.
201 * This wrapper provides a possibility to extract an array from an
202 * Ipc::Istream, without extra copy overhead. In contrast to Buf_cp_in
203 * the data is not copied to a buffer, but a pointer to the array is returned.
205 * The mechanism is comparable to that of Msg_ptr, however it handles arrays
206 * inserted with Buf_cp_out.
208 * See buf_in(), Buf_cp_out, buf_cp_out(), Buf_cp_in, and buf_cp_in().
210 template< typename T >
215 * \brief Create an Buf_in to adjust a pointer to the array and the size
217 * \param v The pointer to adjust to the first element of the array.
218 * \param size The number of elements found in the stream.
220 Buf_in(T *&v, unsigned long &size) : _v(&v), _s(&size) {}
222 void set_size(unsigned long s) const { *_s = s; }
223 T *&buf() const { return *_v; }
225 friend class Istream;
231 * \brief Create an Buf_in for the given values.
234 * This function makes it more convenient to extract arrays from an
235 * Ipc::Istream (See Buf_in.)
237 * \param v Output: pointer to the array within the Ipc::Istream.
238 * \param size Output: the number of elements found in the stream.
240 * See buf_cp_in() and buf_cp_out().
242 template< typename T >
243 Buf_in<T> buf_in(T *&v, unsigned long &size)
244 { return Buf_in<T>(v, size); }
249 * \brief A receive item for receiving a single capability.
251 * This class is the main abstraction for receiving capabilities
252 * via Ipc::Istream. To receive a capability an instance of Small_buf
253 * that refers to an empty capability slot must be inserted into the
254 * Ipc::Istream before the receive operation.
259 explicit Small_buf(L4::Cap<L4::Kobject> cap, unsigned long flags = 0)
260 : _data(cap.cap() | L4_RCV_ITEM_SINGLE_CAP | flags) {}
262 explicit Small_buf(l4_cap_idx_t idx, unsigned long flags = 0)
263 : _data(idx | L4_RCV_ITEM_SINGLE_CAP | flags) {}
271 Snd_item(l4_umword_t base, l4_umword_t data) : _base(base), _data(data) {}
281 Buf_item(l4_umword_t base, l4_umword_t data) : _base(base), _data(data) {}
288 template< typename T >
289 class Gen_fpage : public T
294 Special = L4_FPAGE_SPECIAL << 4,
295 Memory = L4_FPAGE_MEMORY << 4,
296 Io = L4_FPAGE_IO << 4,
297 Obj = L4_FPAGE_OBJ << 4
302 Map = L4_MAP_ITEM_MAP,
303 Grant = L4_MAP_ITEM_GRANT,
309 Cached = L4_FPAGE_CACHEABLE << 4,
310 Buffered = L4_FPAGE_BUFFERABLE << 4,
311 Uncached = L4_FPAGE_UNCACHEABLE << 4
319 Compound = L4_ITEM_CONT,
323 Gen_fpage(Type type, l4_addr_t base, int order,
324 unsigned char rights,
327 Cacheopt cache, Continue cont)
328 : T(L4_ITEM_MAP | (snd_base & (~0UL << 10)) | l4_umword_t(map_type) | l4_umword_t(cache)
330 base | l4_umword_t(type) | rights | (l4_umword_t(order) << 6))
334 Gen_fpage() : T(0, 0) {}
335 Gen_fpage(l4_fpage_t const &fp, l4_addr_t snd_base = 0,
336 Map_type map_type = Map,
337 Cacheopt cache = None, Continue cont = Last)
338 : T(L4_ITEM_MAP | (snd_base & (~0UL << 10)) | l4_umword_t(map_type) | l4_umword_t(cache)
343 Gen_fpage(L4::Cap<void> cap, unsigned rights)
344 : T(L4_ITEM_MAP | Map | (rights & 0xf0), cap.fpage(rights).raw)
347 static Gen_fpage<T> obj(l4_addr_t base, int order,
348 unsigned char rights,
349 l4_addr_t snd_base = 0,
350 Map_type map_type = Map,
351 Continue cont = Last)
352 { return Gen_fpage<T>(Obj, base << 12, order, rights, snd_base, map_type, None, cont); }
353 static Gen_fpage<T> mem(l4_addr_t base, int order,
354 unsigned char rights,
355 l4_addr_t snd_base = 0,
356 Map_type map_type = Map,
357 Cacheopt cache = None, Continue cont = Last)
358 { return Gen_fpage<T>(Memory, base, order, rights, snd_base,
359 map_type, cache, cont); }
360 static Gen_fpage<T> io(l4_addr_t base, int order,
361 unsigned char rights,
362 l4_addr_t snd_base = 0,
363 Map_type map_type = Map,
364 Continue cont = Last)
365 { return Gen_fpage<T>(Io, base << 12, order, rights, snd_base, map_type, None, cont); }
367 unsigned order() const { return (T::_data >> 6) & 0x3f; }
368 unsigned snd_order() const { return (T::_data >> 6) & 0x3f; }
369 unsigned rcv_order() const { return (T::_base >> 6) & 0x3f; }
370 l4_addr_t base() const { return T::_data & (~0UL << 12); }
371 l4_addr_t snd_base() const { return T::_base & (~0UL << 10); }
372 void snd_base(l4_addr_t b) { T::_base = (T::_base & ~(~0UL << 10)) | (b & (~0UL << 10)); }
374 bool is_valid() const { return T::_base & L4_ITEM_MAP; }
375 // A cap has been mapped
376 bool cap_received() const { return (T::_base & 0x3e) == 0x38; }
377 // the label out of an IPC gate has been received, L4_RCV_ITEM_LOCAL_ID
378 // must be specified, and the IPC gate must be local to the receiver
379 // (i.e., the target thread of the IPC gate is in the same task as the
381 bool id_received() const { return (T::_base & 0x3e) == 0x3c; }
382 // Sender and receiver are in the same task, set only iff
383 // L4_RCV_ITEM_LOCAL_ID has been specified by the receiver, the value
384 // delivered is the cap-index (in the task)
385 bool local_id_received() const { return (T::_base & 0x3e) == 0x3e; }
386 l4_umword_t data() const { return T::_data; }
387 l4_umword_t base_x() const { return T::_base; }
391 typedef Gen_fpage<Snd_item> Snd_fpage;
392 typedef Gen_fpage<Buf_item> Rcv_fpage;
394 #ifdef L4_CXX_IPC_SUPPORT_STRINGS
395 template <typename T, typename B>
396 class Gen_string : public T
399 Gen_string() : T(0,0) {}
400 Gen_string(B buf, unsigned long size)
401 : T(size << 10, l4_umword_t(buf))
404 unsigned long len() const { return T::_base >> 10; }
407 typedef Gen_string<Snd_item, void const *> Snd_string;
408 typedef Gen_string<Buf_item, void *> Rcv_string;
412 template< typename T, template <typename X> class B > struct Generic_va_type : public B<T>
414 enum { Id = B<T>::Id };
416 typedef T const &Ret_value;
419 static Ret_value value(void const *d)
420 { return *reinterpret_cast<Value const *>(d); }
422 static void const *addr_of(Value const &v) { return &v; }
424 static unsigned size(void const *) { return sizeof(T); }
426 static L4_varg_type unsigned_id() { return (L4_varg_type)(Id & ~L4_VARG_TYPE_SIGN); }
427 static L4_varg_type signed_id() { return (L4_varg_type)(Id | L4_VARG_TYPE_SIGN); }
428 static L4_varg_type id() { return (L4_varg_type)Id; }
431 template< typename T > struct Va_type_id;
432 template<> struct Va_type_id<l4_umword_t> { enum { Id = L4_VARG_TYPE_UMWORD }; };
433 template<> struct Va_type_id<l4_mword_t> { enum { Id = L4_VARG_TYPE_MWORD }; };
434 template<> struct Va_type_id<l4_fpage_t> { enum { Id = L4_VARG_TYPE_FPAGE }; };
435 template<> struct Va_type_id<void> { enum { Id = L4_VARG_TYPE_NIL }; };
436 template<> struct Va_type_id<char const *> { enum { Id = L4_VARG_TYPE_STRING }; };
438 template< typename T > struct Va_type;
440 template<> struct Va_type<l4_umword_t> : public Generic_va_type<l4_umword_t, Va_type_id> {};
441 template<> struct Va_type<l4_mword_t> : public Generic_va_type<l4_mword_t, Va_type_id> {};
442 template<> struct Va_type<l4_fpage_t> : public Generic_va_type<l4_fpage_t, Va_type_id> {};
444 template<> struct Va_type<void>
446 typedef void Ret_value;
449 static void const *addr_of(void) { return 0; }
451 static void value(void const *) {}
452 static L4_varg_type id() { return L4_VARG_TYPE_NIL; }
453 static unsigned size(void const *) { return 0; }
456 template<> struct Va_type<char const *>
458 typedef char const *Ret_value;
459 typedef char const *Value;
461 static void const *addr_of(Value v) { return v; }
463 static L4_varg_type id() { return L4_VARG_TYPE_STRING; }
464 static unsigned size(void const *s)
466 char const *_s = reinterpret_cast<char const *>(s);
475 static Ret_value value(void const *d) { return (char const *)d; }
487 typedef l4_umword_t Tag;
489 L4_varg_type type() const { return (L4_varg_type)(_tag & 0xff); }
490 int length() const { return _tag >> 16; }
492 void tag(Tag tag) { _tag = tag; }
493 Tag tag() const { return _tag; }
494 void data(char const *d) { _d = d; }
496 char const *data() const { return _d; }
497 char const *&data() { return _d; }
499 Varg() : _tag(0), _d(0) {}
501 Varg(L4_varg_type t, void const *v, int len)
502 : _tag(t | ((l4_mword_t)len << 16)), _d((char const *)v)
505 template< typename V >
506 typename Va_type<V>::Ret_value value() const
507 { return Va_type<V>::value(_d); }
510 template< typename T >
511 bool is_of() const { return Va_type<T>::id() == type(); }
513 bool is_nil() const { return is_of<void>(); }
515 bool is_of_int() const
516 { return (type() & ~L4_VARG_TYPE_SIGN) == L4_VARG_TYPE_UMWORD; }
518 template< typename T >
519 bool get_value(typename Va_type<T>::Value *v) const
524 *v = Va_type<T>::value(_d);
528 template< typename T >
529 void set_value(void const *d)
531 typedef Va_type<T> Vt;
532 _tag = Vt::id() | (Vt::size(d) << 16);
533 _d = (char const *)d;
539 class Varg_t : public Varg
542 typedef typename Va_type<T>::Value Value;
543 explicit Varg_t(Value v) : Varg()
544 { _data = v; set_value<T>(Va_type<T>::addr_of(_data)); }
550 namespace Utcb_stream_check
552 static bool check_utcb_data_offset(unsigned sz)
553 { return sz > sizeof(l4_umword_t) * L4_UTCB_GENERIC_DATA_SIZE; }
558 * \brief Input stream for IPC unmarshalling.
561 * Ipc::Istream is part of the dynamic IPC marshalling infrastructure, as well
562 * as Ipc::Ostream and Ipc::Iostream.
564 * Ipc::Istream is an input stream supporting extraction of values from an
565 * IPC message buffer. A received IPC message can be unmarshalled using the
566 * usual extraction operator (>>).
568 * There exist some special wrapper classes to extract arrays (see
569 * Ipc_buf_cp_in and Ipc_buf_in) and indirect strings (see Msg_in_buffer and
576 * \brief Create an input stream for the given message buffer.
578 * The given message buffer is used for IPC operations wait()/receive()
579 * and received data can be extracted using the >> operator afterwards.
580 * In the case of indirect message parts a buffer of type Msg_in_buffer
581 * must be inserted into the stream before the IPC operation and contains
582 * received data afterwards.
584 * \param msg The message buffer to receive IPC messages.
586 Istream(l4_utcb_t *utcb)
587 : _tag(), _utcb(utcb),
588 _current_msg(reinterpret_cast<char*>(l4_utcb_mr_u(utcb)->mr)),
589 _pos(0), _current_buf(0)
593 * \brief Reset the stream to empty, and ready for receive()/wait().
594 * The stream is reset to the same state as on its creation.
600 _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
604 * \brief Check whether a value of type T can be obtained from the stream.
606 template< typename T >
609 unsigned apos = cxx::Type_traits<T>::align(_pos);
610 return apos + sizeof(T) <= _tag.words() * sizeof(l4_umword_t);
614 * \name Get/Put Functions.
615 * These functions are basically used to implement the extraction operators
616 * (>>) and should not be called directly.
618 * See \link ipc_stream IPC stream operators \endlink.
623 * \brief Copy out an array of type \a T with \a size elements.
625 * \param buf Pointer to a buffer for size elements of type T.
626 * \param size number of elements of type T to copy out.
628 * See \link ipc_stream IPC stream operators \endlink.
630 template< typename T >
631 void get(T *buf, unsigned long size)
634 _pos = cxx::Type_traits<T>::align(_pos);
635 if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
638 __builtin_memcpy(buf, _current_msg + _pos, size);
644 * \brief Skip size elements of type T in the stream.
645 * \param size number of elements to skip.
647 template< typename T >
648 void skip(unsigned long size)
651 _pos = cxx::Type_traits<T>::align(_pos);
652 if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
658 * \brief Read one size elements of type T from the stream and return
661 * In contrast to a normal get, this version does actually not copy the data
662 * but returns a pointer to the data.
664 * \param buf a Msg_ptr that is actually set to point to the element in the
666 * \param size number of elements to extract (default is 1).
668 * See \link ipc_stream IPC stream operators \endlink.
670 template< typename T >
671 void get(Msg_ptr<T> const &buf, unsigned long size = 1)
674 _pos = cxx::Type_traits<T>::align(_pos);
675 if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
678 buf.set(reinterpret_cast<T*>(_current_msg + _pos));
684 * \brief Extract a single element of type T from the stream.
685 * \param v Output: the element.
687 * See \link ipc_stream IPC stream operators \endlink.
689 template< typename T >
692 _pos = cxx::Type_traits<T>::align(_pos);
693 if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
698 v = *(reinterpret_cast<T*>(_current_msg + _pos));
703 int get(Ipc::Varg *va)
706 if (!has_more<Ipc::Varg::Tag>())
713 get(msg_ptr(va->data()), va->length());
719 * \brief Get the message tag of a received IPC.
720 * \return The L4 message tag for the received IPC.
722 * This is in particular useful for handling page faults or exceptions.
724 * See \link ipc_stream IPC stream operators \endlink.
726 l4_msgtag_t tag() const { return _tag; }
730 * \brief Get the message tag of a received IPC.
731 * \return A reference to the L4 message tag for the received IPC.
733 * This is in particular useful for handling page faults or exceptions.
735 * See \link ipc_stream IPC stream operators \endlink.
737 l4_msgtag_t &tag() { return _tag; }
743 * \brief Put a receive item into the stream's buffer registers.
745 inline bool put(Buf_item const &);
749 * \brief Put a small receive item into the stream's buffer registers.
751 inline bool put(Small_buf const &);
755 * \name IPC operations.
760 * \brief Wait for an incoming message from any sender.
761 * \param src contains the sender after a successful IPC operation.
762 * \return The IPC result dope (l4_msgtag_t).
764 * This wait is actually known as 'open wait'.
766 inline l4_msgtag_t wait(l4_umword_t *src)
767 { return wait(src, L4_IPC_NEVER); }
770 * \brief Wait for an incoming message from any sender.
771 * \param src contains the sender after a successful IPC operation.
772 * \param timeout Timeout used for IPC.
773 * \return The IPC result dope (l4_msgtag_t).
775 * This wait is actually known as 'open wait'.
777 inline l4_msgtag_t wait(l4_umword_t *src, l4_timeout_t timeout);
780 * \brief Wait for a message from the specified sender.
781 * \param src The sender id to receive from.
782 * \return The IPC result dope (l4_msgtag_t).
784 * This is commonly known as 'closed wait'.
786 inline l4_msgtag_t receive(l4_cap_idx_t src)
787 { return receive(src, L4_IPC_NEVER); }
788 inline l4_msgtag_t receive(l4_cap_idx_t src, l4_timeout_t timeout);
793 * \brief Return utcb pointer.
795 inline l4_utcb_t *utcb() const { return _utcb; }
802 unsigned char _current_buf;
805 template< typename T >
807 T read(Istream &s) { T t; s >> t; return t; }
811 * \brief Output stream for IPC marshalling.
814 * Ipc::Ostream is part of the dynamic IPC marshalling infrastructure, as well
815 * as Ipc::Istream and Ipc::Iostream.
817 * Ipc::Ostream is an output stream supporting insertion of values into an
818 * IPC message buffer. A IPC message can be marshalled using the
819 * usual insertion operator <<, see \link ipc_stream IPC stream operators
822 * There exist some special wrapper classes to insert arrays (see
823 * Ipc_buf_cp_out) and indirect strings (see Msg_out_buffer and
829 * \brief Create an IPC output stream using the given message buffer \a msg.
831 Ostream(l4_utcb_t *utcb)
832 : _tag(), _utcb(utcb),
833 _current_msg(reinterpret_cast<char *>(l4_utcb_mr_u(_utcb)->mr)),
834 _pos(0), _current_item(0)
838 * \brief Reset the stream to empty, same state as a newly created stream.
844 _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
848 * \name Get/Put functions.
850 * These functions are basically used to implement the insertion operators
851 * (<<) and should not be called directly.
853 * See \link ipc_stream IPC stream operators \endlink.
858 * \brief Put an array with \a size elements of type \a T into the stream.
859 * \param buf A pointer to the array to insert into the buffer.
860 * \param size The number of elements in the array.
862 template< typename T >
863 void put(T *buf, unsigned long size)
866 _pos = cxx::Type_traits<T>::align(_pos);
867 if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
870 __builtin_memcpy(_current_msg + _pos, buf, size);
875 * \brief Insert an element of type \a T into the stream.
876 * \param v The element to insert.
878 template< typename T >
881 _pos = cxx::Type_traits<T>::align(_pos);
882 if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
885 *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
889 int put(Varg const &va)
892 put(va.data(), va.length());
897 template< typename T >
898 int put(Varg_t<T> const &va)
899 { return put(static_cast<Varg const &>(va)); }
902 * \brief Extract the L4 message tag from the stream.
903 * \return the extracted L4 message tag.
905 l4_msgtag_t tag() const { return _tag; }
908 * \brief Extract a reference to the L4 message tag from the stream.
909 * \return A reference to the L4 message tag.
911 l4_msgtag_t &tag() { return _tag; }
917 * \brief Put a send item into the stream's message buffer.
919 inline bool put_snd_item(Snd_item const &);
923 * \name IPC operations.
928 * \brief Send the message via IPC to the given receiver.
929 * \param dst The destination for the message.
931 inline l4_msgtag_t send(l4_cap_idx_t dst, long proto = 0, unsigned flags = 0);
936 * \brief Return utcb pointer.
938 inline l4_utcb_t *utcb() const { return _utcb; }
941 * \brief Get the currently used bytes in the stream.
943 unsigned long tell() const
945 register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
946 w -= _current_item * 2;
947 _tag = l4_msgtag(0, w, _current_item, 0);
951 l4_msgtag_t prepare_ipc(long proto = 0, unsigned flags = 0)
953 register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
954 w -= _current_item * 2;
955 return l4_msgtag(proto, w, _current_item, flags);
963 unsigned char _current_item;
968 * \brief Input/Output stream for IPC [un]marshalling.
971 * The Ipc::Iostream is part of the AW Env IPC framework as well as
972 * Ipc::Istream and Ipc::Ostream.
973 * In particular an Ipc::Iostream is a combination of an Ipc::Istream and an
974 * Ipc::Ostream. It can use either a single message buffer for receiving and
975 * sending messages or a pair of a receive and a send buffer. The stream also
976 * supports combined IPC operations such as call() and reply_and_wait(), which
977 * can be used to implement RPC functionality.
979 class Iostream : public Istream, public Ostream
984 * \brief Create an IPC IO stream with a single message buffer.
985 * \param msg The message buffer used as backing store.
987 * The created IO stream uses the same message buffer for sending and
988 * receiving IPC messages.
990 explicit Iostream(l4_utcb_t *utcb)
991 : Istream(utcb), Ostream(utcb)
996 * \brief Reset the stream to its initial state.
998 * Input as well as the output stream are reset.
1008 * \name Get/Put functions.
1010 * These functions are basically used to implement the insertion operators
1011 * (<<) and should not be called directly.
1013 * See \link ipc_stream IPC stream operators \endlink.
1024 * \name IPC operations.
1029 * \brief Do an IPC call using the message in the output stream and
1030 * receiving to the input stream.
1031 * \param dst The destination L4 UID (thread) to call.
1032 * \return the result dope of the IPC operation.
1034 * This is a combined IPC operation consisting of a send and a receive
1035 * to/from the given destination \a dst.
1037 * A call is usually used by clients for RPCs to a server.
1040 inline l4_msgtag_t call(l4_cap_idx_t dst);
1041 inline l4_msgtag_t call(l4_cap_idx_t dst, long label);
1044 * \brief Do an IPC reply and wait.
1045 * \param src_dst Input: the destination for the send operation. <br>
1046 * Output: the source of the received message.
1047 * \return the result dope of the IPC operation.
1049 * This is a combined IPC operation consisting of a send operation and
1050 * an open wait for any message.
1052 * A reply and wait is usually used by servers that reply to a client
1053 * and wait for the next request by any other client.
1055 inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst, long proto = 0)
1056 { return reply_and_wait(src_dst, L4_IPC_SEND_TIMEOUT_0, proto); }
1058 inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1060 { return send_and_wait(dest, src, L4_IPC_SEND_TIMEOUT_0, proto); }
1063 * \brief Do an IPC reply and wait.
1064 * \param src_dst Input: the destination for the send operation. <br>
1065 * Output: the source of the received message.
1066 * \param timeout Timeout used for IPC.
1067 * \return the result dope of the IPC operation.
1069 * This is a combined IPC operation consisting of a send operation and
1070 * an open wait for any message.
1072 * A reply and wait is usually used by servers that reply to a client
1073 * and wait for the next request by any other client.
1075 inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst,
1076 l4_timeout_t timeout, long proto = 0);
1077 inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1078 l4_timeout_t timeout, long proto = 0);
1079 inline l4_msgtag_t reply(l4_timeout_t timeout, long proto = 0);
1080 inline l4_msgtag_t reply(long proto = 0)
1081 { return reply(L4_IPC_SEND_TIMEOUT_0, proto); }
1088 Ostream::put_snd_item(Snd_item const &v)
1091 _pos = cxx::Type_traits<Snd_item>::align(_pos);
1092 if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
1095 *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
1103 Istream::put(Buf_item const &item)
1105 if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 3)
1108 l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1110 reinterpret_cast<Buf_item&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1117 Istream::put(Small_buf const &item)
1119 if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 2)
1122 l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1124 reinterpret_cast<Small_buf&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1131 Ostream::send(l4_cap_idx_t dst, long proto, unsigned flags)
1133 l4_msgtag_t tag = prepare_ipc(proto, L4_MSGTAG_FLAGS & flags);
1134 return l4_ipc_send(dst, _utcb, tag, L4_IPC_NEVER);
1138 Iostream::call(l4_cap_idx_t dst)
1140 l4_msgtag_t tag = prepare_ipc();
1141 tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER);
1142 Istream::tag() = tag;
1148 Iostream::call(l4_cap_idx_t dst, long label)
1150 l4_msgtag_t tag = prepare_ipc(label);
1151 tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER);
1152 Istream::tag() = tag;
1159 Iostream::reply_and_wait(l4_umword_t *src_dst, l4_timeout_t timeout, long proto)
1161 l4_msgtag_t tag = prepare_ipc(proto);
1162 tag = l4_ipc_reply_and_wait(Ostream::_utcb, tag, src_dst, timeout);
1163 Istream::tag() = tag;
1170 Iostream::send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1171 l4_timeout_t timeout, long proto)
1173 l4_msgtag_t tag = prepare_ipc(proto);
1174 tag = l4_ipc_send_and_wait(dest, Ostream::_utcb, tag, src, timeout);
1175 Istream::tag() = tag;
1181 Iostream::reply(l4_timeout_t timeout, long proto)
1183 l4_msgtag_t tag = prepare_ipc(proto);
1184 tag = l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, Ostream::_utcb, tag, timeout);
1185 Istream::tag() = tag;
1191 Istream::wait(l4_umword_t *src, l4_timeout_t timeout)
1194 res = l4_ipc_wait(_utcb, src, timeout);
1202 Istream::receive(l4_cap_idx_t src, l4_timeout_t timeout)
1205 res = l4_ipc_receive(src, _utcb, timeout);
1216 * \brief Extract one element of type \a T from the stream \a s.
1217 * \ingroup ipc_stream
1218 * \param s The stream to extract from.
1219 * \param v Output: extracted value.
1220 * \return the stream \a s.
1222 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, bool &v) { s.get(v); return s; }
1223 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, int &v) { s.get(v); return s; }
1224 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long int &v) { s.get(v); return s; }
1225 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long long int &v) { s.get(v); return s; }
1226 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned int &v) { s.get(v); return s; }
1227 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long int &v) { s.get(v); return s; }
1228 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long long int &v) { s.get(v); return s; }
1229 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, short int &v) { s.get(v); return s; }
1230 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned short int &v) { s.get(v); return s; }
1231 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, char &v) { s.get(v); return s; }
1232 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned char &v) { s.get(v); return s; }
1233 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, signed char &v) { s.get(v); return s; }
1234 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Buf_item const &v) { s.put(v); return s; }
1235 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Small_buf const &v) { s.put(v); return s; }
1236 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Snd_item &v)
1240 v = L4::Ipc::Snd_item(b,d);
1243 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Varg &v)
1244 { s.get(&v); return s; }
1248 * \brief Extract the L4 message tag from the stream \a s.
1249 * \ingroup ipc_stream
1250 * \param s The stream to extract from.
1251 * \param v Output: the extracted tag.
1252 * \return the stream \a s.
1255 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, l4_msgtag_t &v)
1262 * \brief Extract an array of \a T elements from the stream \a s.
1263 * \ingroup ipc_stream
1265 * This operator actually does not copy out the data in the array, but
1266 * returns a pointer into the message buffer itself. This means that the
1267 * data is only valid as long as there is no new data inserted into the stream.
1269 * See Ipc_buf_in, Ipc_bufcp_in, and Ipc_buf_cp_out.
1271 * \param s The stream to extract from.
1272 * \param v Output: pointer to the extracted array (ipc_buf_in()).
1273 * \return the stream \a s.
1275 template< typename T >
1277 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1278 L4::Ipc::Buf_in<T> const &v)
1283 s.get(L4::Ipc::Msg_ptr<T>(v.buf()), si);
1288 * \brief Extract an element of type \a T from the stream \a s.
1289 * \ingroup ipc_stream
1291 * This operator actually does not copy out the data, but
1292 * returns a pointer into the message buffer itself. This means that the
1293 * data is only valid as long as there is no new data inserted into the stream.
1297 * \param s The stream to extract from.
1298 * \param v Output: pointer to the extracted element.
1299 * \return the stream \a s.
1301 template< typename T >
1303 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1304 L4::Ipc::Msg_ptr<T> const &v)
1311 * \brief Extract an array of \a T elements from the stream \a s.
1312 * \ingroup ipc_stream
1314 * This operator does a copy out of the data into the given buffer.
1316 * See Ipc_buf_in, Ipc_bufcp_in, and Ipc_buf_cp_out.
1318 * \param s The stream to extract from.
1319 * \param v buffer description to copy the array to (ipc_buf_cp_out()).
1320 * \return the stream \a s.
1322 template< typename T >
1324 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1325 L4::Ipc::Buf_cp_in<T> const &v)
1328 s.get(v.buf(), v.size());
1334 * \brief Insert an element to type \a T into the stream \a s.
1335 * \ingroup ipc_stream
1337 * \param s The stream to insert the element \a v.
1338 * \param v The element to insert.
1339 * \return the stream \a s.
1341 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, bool v) { s.put(v); return s; }
1342 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, int v) { s.put(v); return s; }
1343 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long int v) { s.put(v); return s; }
1344 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long long int v) { s.put(v); return s; }
1345 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned int v) { s.put(v); return s; }
1346 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long int v) { s.put(v); return s; }
1347 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long long int v) { s.put(v); return s; }
1348 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, short int v) { s.put(v); return s; }
1349 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned short int v) { s.put(v); return s; }
1350 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char v) { s.put(v); return s; }
1351 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned char v) { s.put(v); return s; }
1352 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, signed char v) { s.put(v); return s; }
1353 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Snd_item const &v) { s.put_snd_item(v); return s; }
1354 template< typename T >
1355 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Cap<T> const &v)
1356 { s << L4::Ipc::Snd_fpage(v.fpage()); return s; }
1358 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg const &v)
1359 { s.put(v); return s; }
1360 template< typename T >
1361 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg_t<T> const &v)
1362 { s.put(v); return s; }
1365 * \brief Insert the L4 message tag into the stream \a s.
1366 * \ingroup ipc_stream
1368 * \note Only one message tag can be inserted into a stream. Multiple
1369 * insertions simply overwrite previous insertions.
1370 * \param s The stream to insert the tag \a v.
1371 * \param v The L4 message tag to insert.
1372 * \return the stream \a s.
1375 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, l4_msgtag_t const &v)
1382 * \brief Insert an array with elements of type \a T into the stream \a s.
1383 * \ingroup ipc_stream
1385 * \param s The stream to insert the array \a v.
1386 * \param v The array to insert (see ipc_buf_cp_out()).
1387 * \return the stream \a s.
1389 template< typename T >
1391 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s,
1392 L4::Ipc::Buf_cp_out<T> const &v)
1395 s.put(v.buf(), v.size());
1400 * \brief Insert a zero terminated character string into the stream \a s.
1401 * \ingroup ipc_stream
1403 * \param s The stream to insert the string \a v.
1404 * \param v The string to insert.
1405 * \return the stream \a s.
1407 * This operator produces basically the same content as the array insertion,
1408 * however the length of the array is calculated using <c> strlen(\a v) + 1
1409 * </c>. The string is copied into the message including the trailing zero.
1412 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char const *v)
1414 unsigned long l = __builtin_strlen(v) + 1;
1421 #ifdef L4_CXX_IPC_BACKWARD_COMPAT
1424 template< typename T > class Ipc_buf_cp_out : public Ipc::Buf_cp_out<T> {};
1425 template< typename T > class Ipc_buf_cp_in : public Ipc::Buf_cp_in<T> {};
1426 template< typename T > class Ipc_buf_in : public Ipc::Buf_in<T> {};
1427 template< typename T > class Msg_ptr : public Ipc::Msg_ptr<T> {};
1429 template< typename T >
1430 Ipc::Buf_cp_out<T> ipc_buf_cp_out(T *v, unsigned long size)
1431 { return Ipc::Buf_cp_out<T>(v,size); }
1433 template< typename T >
1434 Ipc::Buf_cp_in<T> ipc_buf_cp_in(T *v, unsigned long &size)
1435 { return Ipc::Buf_cp_in<T>(v,size); }
1437 template< typename T >
1438 Ipc::Buf_in<T> ipc_buf_in(T *&v, unsigned long &size)
1439 { return Ipc::Buf_in<T>(v, size); }
1441 template< typename T >
1442 Ipc::Msg_ptr<T> msg_ptr(T *&p)
1443 { return Ipc::Msg_ptr<T>(p); }
1445 typedef Ipc::Istream Ipc_istream;
1446 typedef Ipc::Ostream Ipc_ostream;
1447 typedef Ipc::Iostream Ipc_iostream;
1448 typedef Ipc::Snd_fpage Snd_fpage;
1449 typedef Ipc::Rcv_fpage Rcv_fpage;
1450 typedef Ipc::Small_buf Small_buf;