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 unsigned long get(T *buf, unsigned long elems)
633 unsigned long size = elems * sizeof(T);
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);
645 * \brief Skip size elements of type T in the stream.
646 * \param size number of elements to skip.
648 template< typename T >
649 void skip(unsigned long size)
652 _pos = cxx::Type_traits<T>::align(_pos);
653 if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
659 * \brief Read one size elements of type T from the stream and return
662 * In contrast to a normal get, this version does actually not copy the data
663 * but returns a pointer to the data.
665 * \param buf a Msg_ptr that is actually set to point to the element in the
667 * \param size number of elements to extract (default is 1).
669 * See \link ipc_stream IPC stream operators \endlink.
671 template< typename T >
672 unsigned long get(Msg_ptr<T> const &buf, unsigned long size = 1)
675 _pos = cxx::Type_traits<T>::align(_pos);
676 if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
679 buf.set(reinterpret_cast<T*>(_current_msg + _pos));
686 * \brief Extract a single element of type T from the stream.
687 * \param v Output: the element.
689 * See \link ipc_stream IPC stream operators \endlink.
691 template< typename T >
694 _pos = cxx::Type_traits<T>::align(_pos);
695 if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
700 v = *(reinterpret_cast<T*>(_current_msg + _pos));
705 bool get(Ipc::Varg *va)
708 if (!has_more<Ipc::Varg::Tag>())
715 get(msg_ptr(va->data()), va->length());
721 * \brief Get the message tag of a received IPC.
722 * \return The L4 message tag for the received IPC.
724 * This is in particular useful for handling page faults or exceptions.
726 * See \link ipc_stream IPC stream operators \endlink.
728 l4_msgtag_t tag() const { return _tag; }
732 * \brief Get the message tag of a received IPC.
733 * \return A reference to the L4 message tag for the received IPC.
735 * This is in particular useful for handling page faults or exceptions.
737 * See \link ipc_stream IPC stream operators \endlink.
739 l4_msgtag_t &tag() { return _tag; }
745 * \brief Put a receive item into the stream's buffer registers.
747 inline bool put(Buf_item const &);
751 * \brief Put a small receive item into the stream's buffer registers.
753 inline bool put(Small_buf const &);
757 * \name IPC operations.
762 * \brief Wait for an incoming message from any sender.
763 * \param src contains the sender after a successful IPC operation.
764 * \return The IPC result dope (l4_msgtag_t).
766 * This wait is actually known as 'open wait'.
768 inline l4_msgtag_t wait(l4_umword_t *src)
769 { return wait(src, L4_IPC_NEVER); }
772 * \brief Wait for an incoming message from any sender.
773 * \param src contains the sender after a successful IPC operation.
774 * \param timeout Timeout used for IPC.
775 * \return The IPC result dope (l4_msgtag_t).
777 * This wait is actually known as 'open wait'.
779 inline l4_msgtag_t wait(l4_umword_t *src, l4_timeout_t timeout);
782 * \brief Wait for a message from the specified sender.
783 * \param src The sender id to receive from.
784 * \return The IPC result dope (l4_msgtag_t).
786 * This is commonly known as 'closed wait'.
788 inline l4_msgtag_t receive(l4_cap_idx_t src)
789 { return receive(src, L4_IPC_NEVER); }
790 inline l4_msgtag_t receive(l4_cap_idx_t src, l4_timeout_t timeout);
795 * \brief Return utcb pointer.
797 inline l4_utcb_t *utcb() const { return _utcb; }
804 unsigned char _current_buf;
807 class Istream_copy : public Istream
813 Istream_copy(Istream const &o) : Istream(o), _mrs(*l4_utcb_mr_u(o.utcb()))
815 // do some reverse mr to utcb trickery
816 _utcb = (l4_utcb_t*)((l4_addr_t)&_mrs - (l4_addr_t)l4_utcb_mr_u((l4_utcb_t*)0));
817 _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
822 template< typename T >
824 T read(Istream &s) { T t; s >> t; return t; }
828 * \brief Output stream for IPC marshalling.
831 * Ipc::Ostream is part of the dynamic IPC marshalling infrastructure, as well
832 * as Ipc::Istream and Ipc::Iostream.
834 * Ipc::Ostream is an output stream supporting insertion of values into an
835 * IPC message buffer. A IPC message can be marshalled using the
836 * usual insertion operator <<, see \link ipc_stream IPC stream operators
839 * There exist some special wrapper classes to insert arrays (see
840 * Ipc::Buf_cp_out) and indirect strings (see Msg_out_buffer and
846 * \brief Create an IPC output stream using the given message buffer \a msg.
848 Ostream(l4_utcb_t *utcb)
849 : _tag(), _utcb(utcb),
850 _current_msg(reinterpret_cast<char *>(l4_utcb_mr_u(_utcb)->mr)),
851 _pos(0), _current_item(0)
855 * \brief Reset the stream to empty, same state as a newly created stream.
861 _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
865 * \name Get/Put functions.
867 * These functions are basically used to implement the insertion operators
868 * (<<) and should not be called directly.
870 * See \link ipc_stream IPC stream operators \endlink.
875 * \brief Put an array with \a size elements of type \a T into the stream.
876 * \param buf A pointer to the array to insert into the buffer.
877 * \param size The number of elements in the array.
879 template< typename T >
880 void put(T *buf, unsigned long size)
883 _pos = cxx::Type_traits<T>::align(_pos);
884 if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
887 __builtin_memcpy(_current_msg + _pos, buf, size);
892 * \brief Insert an element of type \a T into the stream.
893 * \param v The element to insert.
895 template< typename T >
898 _pos = cxx::Type_traits<T>::align(_pos);
899 if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
902 *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
907 int put(Varg const &va)
910 put(va.data(), va.length());
915 template< typename T >
916 int put(Varg_t<T> const &va)
917 { return put(static_cast<Varg const &>(va)); }
920 * \brief Extract the L4 message tag from the stream.
921 * \return the extracted L4 message tag.
923 l4_msgtag_t tag() const { return _tag; }
926 * \brief Extract a reference to the L4 message tag from the stream.
927 * \return A reference to the L4 message tag.
929 l4_msgtag_t &tag() { return _tag; }
935 * \brief Put a send item into the stream's message buffer.
937 inline bool put_snd_item(Snd_item const &);
941 * \name IPC operations.
946 * \brief Send the message via IPC to the given receiver.
947 * \param dst The destination for the message.
949 inline l4_msgtag_t send(l4_cap_idx_t dst, long proto = 0, unsigned flags = 0);
954 * \brief Return utcb pointer.
956 inline l4_utcb_t *utcb() const { return _utcb; }
959 * \brief Get the currently used bytes in the stream.
961 unsigned long tell() const
963 register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
964 w -= _current_item * 2;
965 _tag = l4_msgtag(0, w, _current_item, 0);
969 l4_msgtag_t prepare_ipc(long proto = 0, unsigned flags = 0)
971 register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
972 w -= _current_item * 2;
973 return l4_msgtag(proto, w, _current_item, flags);
981 unsigned char _current_item;
986 * \brief Input/Output stream for IPC [un]marshalling.
989 * The Ipc::Iostream is part of the AW Env IPC framework as well as
990 * Ipc::Istream and Ipc::Ostream.
991 * In particular an Ipc::Iostream is a combination of an Ipc::Istream and an
992 * Ipc::Ostream. It can use either a single message buffer for receiving and
993 * sending messages or a pair of a receive and a send buffer. The stream also
994 * supports combined IPC operations such as call() and reply_and_wait(), which
995 * can be used to implement RPC functionality.
997 class Iostream : public Istream, public Ostream
1002 * \brief Create an IPC IO stream with a single message buffer.
1003 * \param msg The message buffer used as backing store.
1005 * The created IO stream uses the same message buffer for sending and
1006 * receiving IPC messages.
1008 explicit Iostream(l4_utcb_t *utcb)
1009 : Istream(utcb), Ostream(utcb)
1014 * \brief Reset the stream to its initial state.
1016 * Input as well as the output stream are reset.
1026 * \name Get/Put functions.
1028 * These functions are basically used to implement the insertion operators
1029 * (<<) and should not be called directly.
1031 * See \link ipc_stream IPC stream operators \endlink.
1042 * \name IPC operations.
1047 * \brief Do an IPC call using the message in the output stream and
1048 * receiving to the input stream.
1049 * \param dst The destination L4 UID (thread) to call.
1050 * \return the result dope of the IPC operation.
1052 * This is a combined IPC operation consisting of a send and a receive
1053 * to/from the given destination \a dst.
1055 * A call is usually used by clients for RPCs to a server.
1058 inline l4_msgtag_t call(l4_cap_idx_t dst);
1059 inline l4_msgtag_t call(l4_cap_idx_t dst, long label);
1062 * \brief Do an IPC reply and wait.
1063 * \param src_dst Input: the destination for the send operation. <br>
1064 * Output: the source of the received message.
1065 * \return the result dope of the IPC operation.
1067 * This is a combined IPC operation consisting of a send operation and
1068 * an open wait for any message.
1070 * A reply and wait is usually used by servers that reply to a client
1071 * and wait for the next request by any other client.
1073 inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst, long proto = 0)
1074 { return reply_and_wait(src_dst, L4_IPC_SEND_TIMEOUT_0, proto); }
1076 inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1078 { return send_and_wait(dest, src, L4_IPC_SEND_TIMEOUT_0, proto); }
1081 * \brief Do an IPC reply and wait.
1082 * \param src_dst Input: the destination for the send operation. <br>
1083 * Output: the source of the received message.
1084 * \param timeout Timeout used for IPC.
1085 * \return the result dope of the IPC operation.
1087 * This is a combined IPC operation consisting of a send operation and
1088 * an open wait for any message.
1090 * A reply and wait is usually used by servers that reply to a client
1091 * and wait for the next request by any other client.
1093 inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst,
1094 l4_timeout_t timeout, long proto = 0);
1095 inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1096 l4_timeout_t timeout, long proto = 0);
1097 inline l4_msgtag_t reply(l4_timeout_t timeout, long proto = 0);
1098 inline l4_msgtag_t reply(long proto = 0)
1099 { return reply(L4_IPC_SEND_TIMEOUT_0, proto); }
1106 Ostream::put_snd_item(Snd_item const &v)
1109 _pos = cxx::Type_traits<Snd_item>::align(_pos);
1110 if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
1113 *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
1121 Istream::put(Buf_item const &item)
1123 if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 3)
1126 l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1128 reinterpret_cast<Buf_item&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1135 Istream::put(Small_buf const &item)
1137 if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 2)
1140 l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1142 reinterpret_cast<Small_buf&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1149 Ostream::send(l4_cap_idx_t dst, long proto, unsigned flags)
1151 l4_msgtag_t tag = prepare_ipc(proto, L4_MSGTAG_FLAGS & flags);
1152 return l4_ipc_send(dst, _utcb, tag, L4_IPC_NEVER);
1156 Iostream::call(l4_cap_idx_t dst)
1158 l4_msgtag_t tag = prepare_ipc();
1159 tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER);
1160 Istream::tag() = tag;
1166 Iostream::call(l4_cap_idx_t dst, long label)
1168 l4_msgtag_t tag = prepare_ipc(label);
1169 tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER);
1170 Istream::tag() = tag;
1177 Iostream::reply_and_wait(l4_umword_t *src_dst, l4_timeout_t timeout, long proto)
1179 l4_msgtag_t tag = prepare_ipc(proto);
1180 tag = l4_ipc_reply_and_wait(Ostream::_utcb, tag, src_dst, timeout);
1181 Istream::tag() = tag;
1188 Iostream::send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1189 l4_timeout_t timeout, long proto)
1191 l4_msgtag_t tag = prepare_ipc(proto);
1192 tag = l4_ipc_send_and_wait(dest, Ostream::_utcb, tag, src, timeout);
1193 Istream::tag() = tag;
1199 Iostream::reply(l4_timeout_t timeout, long proto)
1201 l4_msgtag_t tag = prepare_ipc(proto);
1202 tag = l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, Ostream::_utcb, tag, timeout);
1203 Istream::tag() = tag;
1209 Istream::wait(l4_umword_t *src, l4_timeout_t timeout)
1212 res = l4_ipc_wait(_utcb, src, timeout);
1220 Istream::receive(l4_cap_idx_t src, l4_timeout_t timeout)
1223 res = l4_ipc_receive(src, _utcb, timeout);
1234 * \brief Extract one element of type \a T from the stream \a s.
1235 * \ingroup ipc_stream
1236 * \param s The stream to extract from.
1237 * \param v Output: extracted value.
1238 * \return the stream \a s.
1240 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, bool &v) { s.get(v); return s; }
1241 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, int &v) { s.get(v); return s; }
1242 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long int &v) { s.get(v); return s; }
1243 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long long int &v) { s.get(v); return s; }
1244 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned int &v) { s.get(v); return s; }
1245 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long int &v) { s.get(v); return s; }
1246 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long long int &v) { s.get(v); return s; }
1247 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, short int &v) { s.get(v); return s; }
1248 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned short int &v) { s.get(v); return s; }
1249 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, char &v) { s.get(v); return s; }
1250 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned char &v) { s.get(v); return s; }
1251 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, signed char &v) { s.get(v); return s; }
1252 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Buf_item const &v) { s.put(v); return s; }
1253 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Small_buf const &v) { s.put(v); return s; }
1254 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Snd_item &v)
1258 v = L4::Ipc::Snd_item(b,d);
1261 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Varg &v)
1262 { s.get(&v); return s; }
1266 * \brief Extract the L4 message tag from the stream \a s.
1267 * \ingroup ipc_stream
1268 * \param s The stream to extract from.
1269 * \param v Output: the extracted tag.
1270 * \return the stream \a s.
1273 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, l4_msgtag_t &v)
1280 * \brief Extract an array of \a T elements from the stream \a s.
1281 * \ingroup ipc_stream
1283 * This operator actually does not copy out the data in the array, but
1284 * returns a pointer into the message buffer itself. This means that the
1285 * data is only valid as long as there is no new data inserted into the stream.
1287 * See Ipc::Buf_in, Ipc::Buf_cp_in, and Ipc::Buf_cp_out.
1289 * \param s The stream to extract from.
1290 * \param v Output: pointer to the extracted array (ipc_buf_in()).
1291 * \return the stream \a s.
1293 template< typename T >
1295 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1296 L4::Ipc::Buf_in<T> const &v)
1300 v.set_size(s.get(L4::Ipc::Msg_ptr<T>(v.buf()), si));
1305 * \brief Extract an element of type \a T from the stream \a s.
1306 * \ingroup ipc_stream
1308 * This operator actually does not copy out the data, but
1309 * returns a pointer into the message buffer itself. This means that the
1310 * data is only valid as long as there is no new data inserted into the stream.
1314 * \param s The stream to extract from.
1315 * \param v Output: pointer to the extracted element.
1316 * \return the stream \a s.
1318 template< typename T >
1320 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1321 L4::Ipc::Msg_ptr<T> const &v)
1328 * \brief Extract an array of \a T elements from the stream \a s.
1329 * \ingroup ipc_stream
1331 * This operator does a copy out of the data into the given buffer.
1333 * See Ipc::Buf_in, Ipc::Buf_cp_in, and Ipc::Buf_cp_out.
1335 * \param s The stream to extract from.
1336 * \param v buffer description to copy the array to (Ipc::Buf_cp_out()).
1337 * \return the stream \a s.
1339 template< typename T >
1341 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1342 L4::Ipc::Buf_cp_in<T> const &v)
1346 v.size() = s.get(v.buf(), sz);
1352 * \brief Insert an element to type \a T into the stream \a s.
1353 * \ingroup ipc_stream
1355 * \param s The stream to insert the element \a v.
1356 * \param v The element to insert.
1357 * \return the stream \a s.
1359 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, bool v) { s.put(v); return s; }
1360 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, int v) { s.put(v); return s; }
1361 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long int v) { s.put(v); return s; }
1362 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long long int v) { s.put(v); return s; }
1363 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned int v) { s.put(v); return s; }
1364 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long int v) { s.put(v); return s; }
1365 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long long int v) { s.put(v); return s; }
1366 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, short int v) { s.put(v); return s; }
1367 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned short int v) { s.put(v); return s; }
1368 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char v) { s.put(v); return s; }
1369 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned char v) { s.put(v); return s; }
1370 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, signed char v) { s.put(v); return s; }
1371 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Snd_item const &v) { s.put_snd_item(v); return s; }
1372 template< typename T >
1373 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Cap<T> const &v)
1374 { s << L4::Ipc::Snd_fpage(v.fpage()); return s; }
1376 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg const &v)
1377 { s.put(v); return s; }
1378 template< typename T >
1379 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg_t<T> const &v)
1380 { s.put(v); return s; }
1383 * \brief Insert the L4 message tag into the stream \a s.
1384 * \ingroup ipc_stream
1386 * \note Only one message tag can be inserted into a stream. Multiple
1387 * insertions simply overwrite previous insertions.
1388 * \param s The stream to insert the tag \a v.
1389 * \param v The L4 message tag to insert.
1390 * \return the stream \a s.
1393 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, l4_msgtag_t const &v)
1400 * \brief Insert an array with elements of type \a T into the stream \a s.
1401 * \ingroup ipc_stream
1403 * \param s The stream to insert the array \a v.
1404 * \param v The array to insert (see Ipc::Buf_cp_out()).
1405 * \return the stream \a s.
1407 template< typename T >
1409 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s,
1410 L4::Ipc::Buf_cp_out<T> const &v)
1413 s.put(v.buf(), v.size());
1418 * \brief Insert a zero terminated character string into the stream \a s.
1419 * \ingroup ipc_stream
1421 * \param s The stream to insert the string \a v.
1422 * \param v The string to insert.
1423 * \return the stream \a s.
1425 * This operator produces basically the same content as the array insertion,
1426 * however the length of the array is calculated using <c> strlen(\a v) + 1
1427 * </c>. The string is copied into the message including the trailing zero.
1430 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char const *v)
1432 unsigned long l = __builtin_strlen(v) + 1;
1439 #ifdef L4_CXX_IPC_BACKWARD_COMPAT
1443 template< typename T > class Ipc_buf_cp_out : public Ipc::Buf_cp_out<T> {};
1444 template< typename T > class Ipc_buf_cp_in : public Ipc::Buf_cp_in<T> {};
1445 template< typename T > class Ipc_buf_in : public Ipc::Buf_in<T> {};
1446 template< typename T > class Msg_ptr : public Ipc::Msg_ptr<T> {};
1449 template< typename T >
1450 Ipc::Buf_cp_out<T> ipc_buf_cp_out(T *v, unsigned long size)
1451 L4_DEPRECATED("Use L4::Ipc::Buf_cp_out<type>() now");
1453 template< typename T >
1454 Ipc::Buf_cp_out<T> ipc_buf_cp_out(T *v, unsigned long size)
1455 { return Ipc::Buf_cp_out<T>(v,size); }
1458 template< typename T >
1459 Ipc::Buf_cp_in<T> ipc_buf_cp_in(T *v, unsigned long &size)
1460 L4_DEPRECATED("Use L4::Ipc::Buf_cp_in<type>() now");
1462 template< typename T >
1463 Ipc::Buf_cp_in<T> ipc_buf_cp_in(T *v, unsigned long &size)
1464 { return Ipc::Buf_cp_in<T>(v,size); }
1467 template< typename T >
1468 Ipc::Buf_in<T> ipc_buf_in(T *&v, unsigned long &size)
1469 L4_DEPRECATED("Use L4::Ipc::Buf_in<type>() now");
1471 template< typename T >
1472 Ipc::Buf_in<T> ipc_buf_in(T *&v, unsigned long &size)
1473 { return Ipc::Buf_in<T>(v, size); }
1476 template< typename T >
1477 Ipc::Msg_ptr<T> msg_ptr(T *&p)
1478 L4_DEPRECATED("Use L4::Ipc::Msg_ptr<type>() now");
1480 template< typename T >
1481 Ipc::Msg_ptr<T> msg_ptr(T *&p)
1482 { return Ipc::Msg_ptr<T>(p); }
1484 typedef Ipc::Istream Ipc_istream L4_DEPRECATED("Use L4::Ipc::Istream now");
1485 typedef Ipc::Ostream Ipc_ostream L4_DEPRECATED("Use L4::Ipc::Ostream now");;
1486 typedef Ipc::Iostream Ipc_iostream L4_DEPRECATED("Use L4::Ipc::Iostream now");;
1487 typedef Ipc::Snd_fpage Snd_fpage L4_DEPRECATED("Use L4::Ipc::Snd_fpage now");;
1488 typedef Ipc::Rcv_fpage Rcv_fpage L4_DEPRECATED("Use L4::Ipc::Rcv_fpage now");;
1489 typedef Ipc::Small_buf Small_buf L4_DEPRECATED("Use L4::Ipc::Small_buf now");;