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 bool 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 class Istream_copy : public Istream
811 Istream_copy(Istream const &o) : Istream(o), _mrs(*l4_utcb_mr_u(o.utcb()))
813 // do some reverse mr to utcb trickery
814 _utcb = (l4_utcb_t*)((l4_addr_t)&_mrs - (l4_addr_t)l4_utcb_mr_u((l4_utcb_t*)0));
815 _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
820 template< typename T >
822 T read(Istream &s) { T t; s >> t; return t; }
826 * \brief Output stream for IPC marshalling.
829 * Ipc::Ostream is part of the dynamic IPC marshalling infrastructure, as well
830 * as Ipc::Istream and Ipc::Iostream.
832 * Ipc::Ostream is an output stream supporting insertion of values into an
833 * IPC message buffer. A IPC message can be marshalled using the
834 * usual insertion operator <<, see \link ipc_stream IPC stream operators
837 * There exist some special wrapper classes to insert arrays (see
838 * Ipc_buf_cp_out) and indirect strings (see Msg_out_buffer and
844 * \brief Create an IPC output stream using the given message buffer \a msg.
846 Ostream(l4_utcb_t *utcb)
847 : _tag(), _utcb(utcb),
848 _current_msg(reinterpret_cast<char *>(l4_utcb_mr_u(_utcb)->mr)),
849 _pos(0), _current_item(0)
853 * \brief Reset the stream to empty, same state as a newly created stream.
859 _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
863 * \name Get/Put functions.
865 * These functions are basically used to implement the insertion operators
866 * (<<) and should not be called directly.
868 * See \link ipc_stream IPC stream operators \endlink.
873 * \brief Put an array with \a size elements of type \a T into the stream.
874 * \param buf A pointer to the array to insert into the buffer.
875 * \param size The number of elements in the array.
877 template< typename T >
878 void put(T *buf, unsigned long size)
881 _pos = cxx::Type_traits<T>::align(_pos);
882 if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
885 __builtin_memcpy(_current_msg + _pos, buf, size);
890 * \brief Insert an element of type \a T into the stream.
891 * \param v The element to insert.
893 template< typename T >
896 _pos = cxx::Type_traits<T>::align(_pos);
897 if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
900 *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
905 int put(Varg const &va)
908 put(va.data(), va.length());
913 template< typename T >
914 int put(Varg_t<T> const &va)
915 { return put(static_cast<Varg const &>(va)); }
918 * \brief Extract the L4 message tag from the stream.
919 * \return the extracted L4 message tag.
921 l4_msgtag_t tag() const { return _tag; }
924 * \brief Extract a reference to the L4 message tag from the stream.
925 * \return A reference to the L4 message tag.
927 l4_msgtag_t &tag() { return _tag; }
933 * \brief Put a send item into the stream's message buffer.
935 inline bool put_snd_item(Snd_item const &);
939 * \name IPC operations.
944 * \brief Send the message via IPC to the given receiver.
945 * \param dst The destination for the message.
947 inline l4_msgtag_t send(l4_cap_idx_t dst, long proto = 0, unsigned flags = 0);
952 * \brief Return utcb pointer.
954 inline l4_utcb_t *utcb() const { return _utcb; }
957 * \brief Get the currently used bytes in the stream.
959 unsigned long tell() const
961 register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
962 w -= _current_item * 2;
963 _tag = l4_msgtag(0, w, _current_item, 0);
967 l4_msgtag_t prepare_ipc(long proto = 0, unsigned flags = 0)
969 register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
970 w -= _current_item * 2;
971 return l4_msgtag(proto, w, _current_item, flags);
979 unsigned char _current_item;
984 * \brief Input/Output stream for IPC [un]marshalling.
987 * The Ipc::Iostream is part of the AW Env IPC framework as well as
988 * Ipc::Istream and Ipc::Ostream.
989 * In particular an Ipc::Iostream is a combination of an Ipc::Istream and an
990 * Ipc::Ostream. It can use either a single message buffer for receiving and
991 * sending messages or a pair of a receive and a send buffer. The stream also
992 * supports combined IPC operations such as call() and reply_and_wait(), which
993 * can be used to implement RPC functionality.
995 class Iostream : public Istream, public Ostream
1000 * \brief Create an IPC IO stream with a single message buffer.
1001 * \param msg The message buffer used as backing store.
1003 * The created IO stream uses the same message buffer for sending and
1004 * receiving IPC messages.
1006 explicit Iostream(l4_utcb_t *utcb)
1007 : Istream(utcb), Ostream(utcb)
1012 * \brief Reset the stream to its initial state.
1014 * Input as well as the output stream are reset.
1024 * \name Get/Put functions.
1026 * These functions are basically used to implement the insertion operators
1027 * (<<) and should not be called directly.
1029 * See \link ipc_stream IPC stream operators \endlink.
1040 * \name IPC operations.
1045 * \brief Do an IPC call using the message in the output stream and
1046 * receiving to the input stream.
1047 * \param dst The destination L4 UID (thread) to call.
1048 * \return the result dope of the IPC operation.
1050 * This is a combined IPC operation consisting of a send and a receive
1051 * to/from the given destination \a dst.
1053 * A call is usually used by clients for RPCs to a server.
1056 inline l4_msgtag_t call(l4_cap_idx_t dst);
1057 inline l4_msgtag_t call(l4_cap_idx_t dst, long label);
1060 * \brief Do an IPC reply and wait.
1061 * \param src_dst Input: the destination for the send operation. <br>
1062 * Output: the source of the received message.
1063 * \return the result dope of the IPC operation.
1065 * This is a combined IPC operation consisting of a send operation and
1066 * an open wait for any message.
1068 * A reply and wait is usually used by servers that reply to a client
1069 * and wait for the next request by any other client.
1071 inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst, long proto = 0)
1072 { return reply_and_wait(src_dst, L4_IPC_SEND_TIMEOUT_0, proto); }
1074 inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1076 { return send_and_wait(dest, src, L4_IPC_SEND_TIMEOUT_0, proto); }
1079 * \brief Do an IPC reply and wait.
1080 * \param src_dst Input: the destination for the send operation. <br>
1081 * Output: the source of the received message.
1082 * \param timeout Timeout used for IPC.
1083 * \return the result dope of the IPC operation.
1085 * This is a combined IPC operation consisting of a send operation and
1086 * an open wait for any message.
1088 * A reply and wait is usually used by servers that reply to a client
1089 * and wait for the next request by any other client.
1091 inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst,
1092 l4_timeout_t timeout, long proto = 0);
1093 inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1094 l4_timeout_t timeout, long proto = 0);
1095 inline l4_msgtag_t reply(l4_timeout_t timeout, long proto = 0);
1096 inline l4_msgtag_t reply(long proto = 0)
1097 { return reply(L4_IPC_SEND_TIMEOUT_0, proto); }
1104 Ostream::put_snd_item(Snd_item const &v)
1107 _pos = cxx::Type_traits<Snd_item>::align(_pos);
1108 if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
1111 *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
1119 Istream::put(Buf_item const &item)
1121 if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 3)
1124 l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1126 reinterpret_cast<Buf_item&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1133 Istream::put(Small_buf const &item)
1135 if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 2)
1138 l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1140 reinterpret_cast<Small_buf&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1147 Ostream::send(l4_cap_idx_t dst, long proto, unsigned flags)
1149 l4_msgtag_t tag = prepare_ipc(proto, L4_MSGTAG_FLAGS & flags);
1150 return l4_ipc_send(dst, _utcb, tag, L4_IPC_NEVER);
1154 Iostream::call(l4_cap_idx_t dst)
1156 l4_msgtag_t tag = prepare_ipc();
1157 tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER);
1158 Istream::tag() = tag;
1164 Iostream::call(l4_cap_idx_t dst, long label)
1166 l4_msgtag_t tag = prepare_ipc(label);
1167 tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER);
1168 Istream::tag() = tag;
1175 Iostream::reply_and_wait(l4_umword_t *src_dst, l4_timeout_t timeout, long proto)
1177 l4_msgtag_t tag = prepare_ipc(proto);
1178 tag = l4_ipc_reply_and_wait(Ostream::_utcb, tag, src_dst, timeout);
1179 Istream::tag() = tag;
1186 Iostream::send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1187 l4_timeout_t timeout, long proto)
1189 l4_msgtag_t tag = prepare_ipc(proto);
1190 tag = l4_ipc_send_and_wait(dest, Ostream::_utcb, tag, src, timeout);
1191 Istream::tag() = tag;
1197 Iostream::reply(l4_timeout_t timeout, long proto)
1199 l4_msgtag_t tag = prepare_ipc(proto);
1200 tag = l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, Ostream::_utcb, tag, timeout);
1201 Istream::tag() = tag;
1207 Istream::wait(l4_umword_t *src, l4_timeout_t timeout)
1210 res = l4_ipc_wait(_utcb, src, timeout);
1218 Istream::receive(l4_cap_idx_t src, l4_timeout_t timeout)
1221 res = l4_ipc_receive(src, _utcb, timeout);
1232 * \brief Extract one element of type \a T from the stream \a s.
1233 * \ingroup ipc_stream
1234 * \param s The stream to extract from.
1235 * \param v Output: extracted value.
1236 * \return the stream \a s.
1238 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, bool &v) { s.get(v); return s; }
1239 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, int &v) { s.get(v); return s; }
1240 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long int &v) { s.get(v); return s; }
1241 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long long int &v) { s.get(v); return s; }
1242 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned int &v) { s.get(v); return s; }
1243 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long int &v) { s.get(v); return s; }
1244 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long long int &v) { s.get(v); return s; }
1245 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, short int &v) { s.get(v); return s; }
1246 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned short int &v) { s.get(v); return s; }
1247 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, char &v) { s.get(v); return s; }
1248 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned char &v) { s.get(v); return s; }
1249 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, signed char &v) { s.get(v); return s; }
1250 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Buf_item const &v) { s.put(v); return s; }
1251 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Small_buf const &v) { s.put(v); return s; }
1252 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Snd_item &v)
1256 v = L4::Ipc::Snd_item(b,d);
1259 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Varg &v)
1260 { s.get(&v); return s; }
1264 * \brief Extract the L4 message tag from the stream \a s.
1265 * \ingroup ipc_stream
1266 * \param s The stream to extract from.
1267 * \param v Output: the extracted tag.
1268 * \return the stream \a s.
1271 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, l4_msgtag_t &v)
1278 * \brief Extract an array of \a T elements from the stream \a s.
1279 * \ingroup ipc_stream
1281 * This operator actually does not copy out the data in the array, but
1282 * returns a pointer into the message buffer itself. This means that the
1283 * data is only valid as long as there is no new data inserted into the stream.
1285 * See Ipc_buf_in, Ipc_bufcp_in, and Ipc_buf_cp_out.
1287 * \param s The stream to extract from.
1288 * \param v Output: pointer to the extracted array (ipc_buf_in()).
1289 * \return the stream \a s.
1291 template< typename T >
1293 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1294 L4::Ipc::Buf_in<T> const &v)
1299 s.get(L4::Ipc::Msg_ptr<T>(v.buf()), si);
1304 * \brief Extract an element of type \a T from the stream \a s.
1305 * \ingroup ipc_stream
1307 * This operator actually does not copy out the data, but
1308 * returns a pointer into the message buffer itself. This means that the
1309 * data is only valid as long as there is no new data inserted into the stream.
1313 * \param s The stream to extract from.
1314 * \param v Output: pointer to the extracted element.
1315 * \return the stream \a s.
1317 template< typename T >
1319 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1320 L4::Ipc::Msg_ptr<T> const &v)
1327 * \brief Extract an array of \a T elements from the stream \a s.
1328 * \ingroup ipc_stream
1330 * This operator does a copy out of the data into the given buffer.
1332 * See Ipc_buf_in, Ipc_bufcp_in, and Ipc_buf_cp_out.
1334 * \param s The stream to extract from.
1335 * \param v buffer description to copy the array to (ipc_buf_cp_out()).
1336 * \return the stream \a s.
1338 template< typename T >
1340 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1341 L4::Ipc::Buf_cp_in<T> const &v)
1344 s.get(v.buf(), v.size());
1350 * \brief Insert an element to type \a T into the stream \a s.
1351 * \ingroup ipc_stream
1353 * \param s The stream to insert the element \a v.
1354 * \param v The element to insert.
1355 * \return the stream \a s.
1357 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, bool v) { s.put(v); return s; }
1358 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, int v) { s.put(v); return s; }
1359 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long int v) { s.put(v); return s; }
1360 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long long int v) { s.put(v); return s; }
1361 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned int v) { s.put(v); return s; }
1362 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long int v) { s.put(v); return s; }
1363 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long long int v) { s.put(v); return s; }
1364 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, short int v) { s.put(v); return s; }
1365 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned short int v) { s.put(v); return s; }
1366 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char v) { s.put(v); return s; }
1367 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned char v) { s.put(v); return s; }
1368 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, signed char v) { s.put(v); return s; }
1369 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Snd_item const &v) { s.put_snd_item(v); return s; }
1370 template< typename T >
1371 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Cap<T> const &v)
1372 { s << L4::Ipc::Snd_fpage(v.fpage()); return s; }
1374 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg const &v)
1375 { s.put(v); return s; }
1376 template< typename T >
1377 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg_t<T> const &v)
1378 { s.put(v); return s; }
1381 * \brief Insert the L4 message tag into the stream \a s.
1382 * \ingroup ipc_stream
1384 * \note Only one message tag can be inserted into a stream. Multiple
1385 * insertions simply overwrite previous insertions.
1386 * \param s The stream to insert the tag \a v.
1387 * \param v The L4 message tag to insert.
1388 * \return the stream \a s.
1391 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, l4_msgtag_t const &v)
1398 * \brief Insert an array with elements of type \a T into the stream \a s.
1399 * \ingroup ipc_stream
1401 * \param s The stream to insert the array \a v.
1402 * \param v The array to insert (see ipc_buf_cp_out()).
1403 * \return the stream \a s.
1405 template< typename T >
1407 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s,
1408 L4::Ipc::Buf_cp_out<T> const &v)
1411 s.put(v.buf(), v.size());
1416 * \brief Insert a zero terminated character string into the stream \a s.
1417 * \ingroup ipc_stream
1419 * \param s The stream to insert the string \a v.
1420 * \param v The string to insert.
1421 * \return the stream \a s.
1423 * This operator produces basically the same content as the array insertion,
1424 * however the length of the array is calculated using <c> strlen(\a v) + 1
1425 * </c>. The string is copied into the message including the trailing zero.
1428 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char const *v)
1430 unsigned long l = __builtin_strlen(v) + 1;
1437 #ifdef L4_CXX_IPC_BACKWARD_COMPAT
1440 template< typename T > class Ipc_buf_cp_out : public Ipc::Buf_cp_out<T> {};
1441 template< typename T > class Ipc_buf_cp_in : public Ipc::Buf_cp_in<T> {};
1442 template< typename T > class Ipc_buf_in : public Ipc::Buf_in<T> {};
1443 template< typename T > class Msg_ptr : public Ipc::Msg_ptr<T> {};
1445 template< typename T >
1446 Ipc::Buf_cp_out<T> ipc_buf_cp_out(T *v, unsigned long size)
1447 { return Ipc::Buf_cp_out<T>(v,size); }
1449 template< typename T >
1450 Ipc::Buf_cp_in<T> ipc_buf_cp_in(T *v, unsigned long &size)
1451 { return Ipc::Buf_cp_in<T>(v,size); }
1453 template< typename T >
1454 Ipc::Buf_in<T> ipc_buf_in(T *&v, unsigned long &size)
1455 { return Ipc::Buf_in<T>(v, size); }
1457 template< typename T >
1458 Ipc::Msg_ptr<T> msg_ptr(T *&p)
1459 { return Ipc::Msg_ptr<T>(p); }
1461 typedef Ipc::Istream Ipc_istream;
1462 typedef Ipc::Ostream Ipc_ostream;
1463 typedef Ipc::Iostream Ipc_iostream;
1464 typedef Ipc::Snd_fpage Snd_fpage;
1465 typedef Ipc::Rcv_fpage Rcv_fpage;
1466 typedef Ipc::Small_buf Small_buf;