7 * (c) 2008-2009 Technische Universität Dresden
8 * This file is part of TUD:OS and distributed under the terms of the
9 * GNU General Public License 2.
10 * Please see the COPYING-GPL-2 file for details.
12 * As a special exception, you may use this file as part of a free software
13 * library without restriction. Specifically, if other files instantiate
14 * templates or use macros or inline functions from this file, or you compile
15 * this file and link it with other files to produce an executable, this
16 * file does not by itself cause the resulting executable to be covered by
17 * the GNU General Public License. This exception does not however
18 * invalidate any other reasons why the executable file might be covered by
19 * the GNU General Public License.
24 #include <l4/sys/ipc.h>
25 #include <l4/sys/capability>
26 #include <l4/cxx/type_traits>
28 #define L4_CXX_IPC_BACKWARD_COMPAT 1
40 * \brief Abstraction for inserting an array into an Ipc::Ostream.
43 * An object of Buf_cp_out can be used to insert an array of arbitrary values,
44 * that can be inserted into an Ipc::Ostream individually.
45 * The array is therefore copied to the message buffer, in contrast to
46 * data handled with Msg_out_buffer or Msg_io_buffer.
48 * On insertion into the Ipc::Ostream exactly the given number of elements
49 * of type T are copied to the message buffer, this means the source buffer
50 * is no longer referenced after insertion into the stream.
52 * You should use buf_cp_out() to create instances of Buf_cp_out.
54 * The counterpart is either Buf_cp_in (buf_cp_in()) or Buf_in (buf_in()).
56 template< typename T >
61 * \brief Create a buffer object for the given array.
62 * \param v The pointer to the array with size elements of type T.
63 * \param size the number of elements in the array.
65 Buf_cp_out(T *v, unsigned long size) : _v(v), _s(size) {}
68 * \brief Get the number of elements in the array.
69 * \note This function is usually used by the Ipc::Ostream itself.
71 unsigned long size() const { return _s; }
74 * \brief Get the pointer to the array.
75 * \note This function is usually used by the Ipc::Ostream itself.
77 T *buf() const { return _v; }
86 * \brief Create an instance of Buf_cp_out for the given values.
89 * This function makes it more convenient to insert arrays into an
90 * Ipc::Ostream (\see Buf_cp_out.)
92 * \param v Pointer to the array that shall be inserted into an Ipc::Ostream.
93 * \param size Number of elements in the array.
95 template< typename T >
96 Buf_cp_out<T> buf_cp_out(T *v, unsigned long size)
97 { return Buf_cp_out<T>(v,size); }
101 * \brief Abstraction for extracting array from an Ipc::Istream.
104 * An instance of Buf_cp_in can be used to extract an array from
105 * an Ipc::Istream. This is the counterpart to the Buf_cp_out abstraction.
106 * The data from the received message is thereby copied to the given buffer
107 * and size is set to the number of elements found in the stream.
108 * To avoid the copy operation Buf_in may be used instead.
110 * \see buf_cp_in(), Buf_in, buf_in(), Buf_cp_out, and buf_cp_out().
112 template< typename T >
117 * \brief Create a buffer for extracting an array from an Ipc::Istream.
118 * \param v The buffer for array (copy in).
119 * \param size Input: the number of elements the array can take at most<br>
120 * Output: the number of elements found in the stream.
122 Buf_cp_in(T *v, unsigned long &size) : _v(v), _s(&size) {}
124 unsigned long &size() const { return *_s; }
125 T *buf() const { return _v; }
127 friend class Istream;
133 * \brief Create an Buf_cp_in for the given values.
136 * This function makes it more convenient to extract arrays from an
137 * Ipc::Istream (\see Buf_cp_in.)
139 * \param v Pointer to the array that shall receive the values from the
141 * \param size Input: the number of elements the array can take at most<br>
142 * Output: the number of elements found in the stream.
144 * \see buf_in() and buf_cp_out().
146 template< typename T >
147 Buf_cp_in<T> buf_cp_in(T *v, unsigned long &size)
148 { return Buf_cp_in<T>(v,size); }
152 * \brief Pointer to an element of type T in an Ipc::Istream.
155 * This wrapper can be used to extract an element of type T from an
156 * Ipc::Istream, whereas the data is not copied out, but a pointer into
157 * the message buffer itself is returned. With is mechanism it is possible
158 * to avoid an extra copy of large data structures from a received IPC
159 * message, instead the returned pointer gives direct access to the data
164 template< typename T >
171 * \brief Create a Msg_ptr object that set pointer p to point into the
173 * \param p The pointer that is adjusted to point into the message buffer.
175 explicit Msg_ptr(T *&p) : _p(&p) {}
176 void set(T *p) const { *_p = p; }
180 * \brief Create an Msg_ptr to adjust the given pointer.
183 * This function makes it more convenient to extract pointers to data in the
184 * message buffer itself from an Ipc::Istream.
185 * This may be used to avoid copy out of large data structures.
188 template< typename T >
189 Msg_ptr<T> msg_ptr(T *&p)
190 { return Msg_ptr<T>(p); }
194 * \brief Abstraction to extract an array from an Ipc::Istream.
197 * This wrapper provides a possibility to extract an array from an
198 * Ipc::Istream, without extra copy overhead. In contrast to Buf_cp_in
199 * the data is not copied to a buffer, but a pointer to the array is returned.
201 * The mechanism is comparable to that of Msg_ptr, however it handles arrays
202 * inserted with Buf_cp_out.
204 * See buf_in(), Buf_cp_out, buf_cp_out(), Buf_cp_in, and buf_cp_in().
206 template< typename T >
211 * \brief Create an Buf_in to adjust a pointer to the array and the size
213 * \param v The pointer to adjust to the first element of the array.
214 * \param size The number of elements found in the stream.
216 Buf_in(T *&v, unsigned long &size) : _v(&v), _s(&size) {}
218 void set_size(unsigned long s) const { *_s = s; }
219 T *&buf() const { return *_v; }
221 friend class Istream;
227 * \brief Create an Buf_in for the given values.
230 * This function makes it more convenient to extract arrays from an
231 * Ipc::Istream (See Buf_in.)
233 * \param v Output: pointer to the array within the Ipc::Istream.
234 * \param size Output: the number of elements found in the stream.
236 * See buf_cp_in() and buf_cp_out().
238 template< typename T >
239 Buf_in<T> buf_in(T *&v, unsigned long &size)
240 { return Buf_in<T>(v, size); }
245 * \brief A receive item for receiving a single capability.
247 * This class is the main abstraction for receiving capabilities
248 * via Ipc::Istream. To receive a capability an instance of Small_buf
249 * that refers to an empty capability slot must be inserted into the
250 * Ipc::Istream before the receive operation.
255 explicit Small_buf(L4::Cap<L4::Kobject> cap, unsigned long flags = 0)
256 : _data(cap.cap() | L4_RCV_ITEM_SINGLE_CAP | flags) {}
258 explicit Small_buf(l4_cap_idx_t idx, unsigned long flags = 0)
259 : _data(idx | L4_RCV_ITEM_SINGLE_CAP | flags) {}
267 Snd_item(l4_umword_t base, l4_umword_t data) : _base(base), _data(data) {}
277 Buf_item(l4_umword_t base, l4_umword_t data) : _base(base), _data(data) {}
284 template< typename T >
285 class Gen_fpage : public T
290 Special = L4_FPAGE_SPECIAL << 4,
291 Memory = L4_FPAGE_MEMORY << 4,
292 Io = L4_FPAGE_IO << 4,
293 Obj = L4_FPAGE_OBJ << 4
298 Map = L4_MAP_ITEM_MAP,
299 Grant = L4_MAP_ITEM_GRANT,
305 Cached = L4_FPAGE_CACHEABLE << 4,
306 Buffered = L4_FPAGE_BUFFERABLE << 4,
307 Uncached = L4_FPAGE_UNCACHEABLE << 4
315 Compound = L4_ITEM_CONT,
319 Gen_fpage(Type type, l4_addr_t base, int order,
320 unsigned char rights,
323 Cacheopt cache, Continue cont)
324 : T(L4_ITEM_MAP | (snd_base & (~0UL << 10)) | l4_umword_t(map_type) | l4_umword_t(cache)
326 base | l4_umword_t(type) | rights | (l4_umword_t(order) << 6))
330 Gen_fpage() : T(0, 0) {}
331 Gen_fpage(l4_fpage_t const &fp, l4_addr_t snd_base = 0,
332 Map_type map_type = Map,
333 Cacheopt cache = None, Continue cont = Last)
334 : T(L4_ITEM_MAP | (snd_base & (~0UL << 10)) | l4_umword_t(map_type) | l4_umword_t(cache)
339 Gen_fpage(L4::Cap<void> cap, unsigned rights)
340 : T(L4_ITEM_MAP | Map | (rights & 0xf0), cap.fpage(rights).raw)
343 static Gen_fpage<T> obj(l4_addr_t base, int order,
344 unsigned char rights,
345 l4_addr_t snd_base = 0,
346 Map_type map_type = Map,
347 Continue cont = Last)
348 { return Gen_fpage<T>(Obj, base << 12, order, rights, snd_base, map_type, None, cont); }
349 static Gen_fpage<T> mem(l4_addr_t base, int order,
350 unsigned char rights,
351 l4_addr_t snd_base = 0,
352 Map_type map_type = Map,
353 Cacheopt cache = None, Continue cont = Last)
354 { return Gen_fpage<T>(Memory, base, order, rights, snd_base,
355 map_type, cache, cont); }
356 static Gen_fpage<T> io(l4_addr_t base, int order,
357 unsigned char rights,
358 l4_addr_t snd_base = 0,
359 Map_type map_type = Map,
360 Continue cont = Last)
361 { return Gen_fpage<T>(Io, base << 12, order, rights, snd_base, map_type, None, cont); }
363 unsigned order() const { return (T::_data >> 6) & 0x3f; }
364 unsigned snd_order() const { return (T::_data >> 6) & 0x3f; }
365 unsigned rcv_order() const { return (T::_base >> 6) & 0x3f; }
366 l4_addr_t base() const { return T::_data & (~0UL << 12); }
367 l4_addr_t snd_base() const { return T::_base & (~0UL << 10); }
368 void snd_base(l4_addr_t b) { T::_base = (T::_base & ~(~0UL << 10)) | (b & (~0UL << 10)); }
370 bool is_valid() const { return T::_base & L4_ITEM_MAP; }
371 // A cap has been mapped
372 bool cap_received() const { return (T::_base & 0x3e) == 0x38; }
373 // the label out of an IPC gate has been received, L4_RCV_ITEM_LOCAL_ID
374 // must be specified, and the IPC gate must be local to the receiver
375 // (i.e., the target thread of the IPC gate is in the same task as the
377 bool id_received() const { return (T::_base & 0x3e) == 0x3c; }
378 // Sender and receiver are in the same task, set only iff
379 // L4_RCV_ITEM_LOCAL_ID has been specified by the receiver, the value
380 // delivered is the cap-index (in the task)
381 bool local_id_received() const { return (T::_base & 0x3e) == 0x3e; }
382 l4_umword_t data() const { return T::_data; }
383 l4_umword_t base_x() const { return T::_base; }
387 typedef Gen_fpage<Snd_item> Snd_fpage;
388 typedef Gen_fpage<Buf_item> Rcv_fpage;
390 #ifdef L4_CXX_IPC_SUPPORT_STRINGS
391 template <typename T, typename B>
392 class Gen_string : public T
395 Gen_string() : T(0,0) {}
396 Gen_string(B buf, unsigned long size)
397 : T(size << 10, l4_umword_t(buf))
400 unsigned long len() const { return T::_base >> 10; }
403 typedef Gen_string<Snd_item, void const *> Snd_string;
404 typedef Gen_string<Buf_item, void *> Rcv_string;
408 template< typename T, template <typename X> class B > struct Generic_va_type : public B<T>
410 enum { Id = B<T>::Id };
412 typedef T const &Ret_value;
415 static Ret_value value(void const *d)
416 { return *reinterpret_cast<Value const *>(d); }
418 static void const *addr_of(Value const &v) { return &v; }
420 static unsigned size(void const *) { return sizeof(T); }
422 static L4_varg_type unsigned_id() { return (L4_varg_type)(Id & ~L4_VARG_TYPE_SIGN); }
423 static L4_varg_type signed_id() { return (L4_varg_type)(Id | L4_VARG_TYPE_SIGN); }
424 static L4_varg_type id() { return (L4_varg_type)Id; }
427 template< typename T > struct Va_type_id;
428 template<> struct Va_type_id<l4_umword_t> { enum { Id = L4_VARG_TYPE_UMWORD }; };
429 template<> struct Va_type_id<l4_mword_t> { enum { Id = L4_VARG_TYPE_MWORD }; };
430 template<> struct Va_type_id<l4_fpage_t> { enum { Id = L4_VARG_TYPE_FPAGE }; };
431 template<> struct Va_type_id<void> { enum { Id = L4_VARG_TYPE_NIL }; };
432 template<> struct Va_type_id<char const *> { enum { Id = L4_VARG_TYPE_STRING }; };
434 template< typename T > struct Va_type;
436 template<> struct Va_type<l4_umword_t> : public Generic_va_type<l4_umword_t, Va_type_id> {};
437 template<> struct Va_type<l4_mword_t> : public Generic_va_type<l4_mword_t, Va_type_id> {};
438 template<> struct Va_type<l4_fpage_t> : public Generic_va_type<l4_fpage_t, Va_type_id> {};
440 template<> struct Va_type<void>
442 typedef void Ret_value;
445 static void const *addr_of(void) { return 0; }
447 static void value(void const *) {}
448 static L4_varg_type id() { return L4_VARG_TYPE_NIL; }
449 static unsigned size(void const *) { return 0; }
452 template<> struct Va_type<char const *>
454 typedef char const *Ret_value;
455 typedef char const *Value;
457 static void const *addr_of(Value v) { return v; }
459 static L4_varg_type id() { return L4_VARG_TYPE_STRING; }
460 static unsigned size(void const *s)
462 char const *_s = reinterpret_cast<char const *>(s);
471 static Ret_value value(void const *d) { return (char const *)d; }
483 typedef l4_umword_t Tag;
485 L4_varg_type type() const { return (L4_varg_type)(_tag & 0xff); }
486 int length() const { return _tag >> 16; }
488 void tag(Tag tag) { _tag = tag; }
489 Tag tag() const { return _tag; }
490 void data(char const *d) { _d = d; }
492 char const *data() const { return _d; }
493 char const *&data() { return _d; }
495 Varg() : _tag(0), _d(0) {}
497 Varg(L4_varg_type t, void const *v, int len)
498 : _tag(t | ((l4_mword_t)len << 16)), _d((char const *)v)
501 template< typename V >
502 typename Va_type<V>::Ret_value value() const
503 { return Va_type<V>::value(_d); }
506 template< typename T >
507 bool is_of() const { return Va_type<T>::id() == type(); }
509 bool is_nil() const { return is_of<void>(); }
511 bool is_of_int() const
512 { return (type() & ~L4_VARG_TYPE_SIGN) == L4_VARG_TYPE_UMWORD; }
514 template< typename T >
515 bool get_value(typename Va_type<T>::Value *v) const
520 *v = Va_type<T>::value(_d);
524 template< typename T >
525 void set_value(void const *d)
527 typedef Va_type<T> Vt;
528 _tag = Vt::id() | (Vt::size(d) << 16);
529 _d = (char const *)d;
535 class Varg_t : public Varg
538 typedef typename Va_type<T>::Value Value;
539 explicit Varg_t(Value v) : Varg()
540 { _data = v; set_value<T>(Va_type<T>::addr_of(_data)); }
548 * \brief Input stream for IPC unmarshalling.
551 * Ipc::Istream is part of the dynamic IPC marshalling infrastructure, as well
552 * as Ipc::Ostream and Ipc::Iostream.
554 * Ipc::Istream is an input stream supporting extraction of values from an
555 * IPC message buffer. A received IPC message can be unmarshalled using the
556 * usual extraction operator (>>).
558 * There exist some special wrapper classes to extract arrays (see
559 * Ipc_buf_cp_in and Ipc_buf_in) and indirect strings (see Msg_in_buffer and
566 * \brief Create an input stream for the given message buffer.
568 * The given message buffer is used for IPC operations wait()/receive()
569 * and received data can be extracted using the >> operator afterwards.
570 * In the case of indirect message parts a buffer of type Msg_in_buffer
571 * must be inserted into the stream before the IPC operation and contains
572 * received data afterwards.
574 * \param msg The message buffer to receive IPC messages.
576 Istream(l4_utcb_t *utcb)
577 : _tag(), _utcb(utcb),
578 _current_msg(reinterpret_cast<char*>(l4_utcb_mr_u(utcb)->mr)),
579 _pos(0), _current_buf(0)
583 * \brief Reset the stream to empty, and ready for receive()/wait().
584 * The stream is reset to the same state as on its creation.
590 _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
594 * \brief Check whether a value of type T can be obtained from the stream.
596 template< typename T >
599 unsigned apos = cxx::Type_traits<T>::align(_pos);
600 return apos + sizeof(T) <= _tag.words() * sizeof(l4_umword_t);
604 * \name Get/Put Functions.
605 * These functions are basically used to implement the extraction operators
606 * (>>) and should not be called directly.
608 * See \link ipc_stream IPC stream operators \endlink.
613 * \brief Copy out an array of type \a T with \a size elements.
615 * \param buf Pointer to a buffer for size elements of type T.
616 * \param size number of elements of type T to copy out.
618 * See \link ipc_stream IPC stream operators \endlink.
620 template< typename T >
621 void get(T *buf, unsigned long size)
624 _pos = cxx::Type_traits<T>::align(_pos);
625 if ((_pos + size) / sizeof(l4_umword_t) > L4_UTCB_GENERIC_DATA_SIZE)
628 __builtin_memcpy(buf, _current_msg + _pos, size);
634 * \brief Skip size elements of type T in the stream.
635 * \param size number of elements to skip.
637 template< typename T >
638 void skip(unsigned long size)
641 _pos = cxx::Type_traits<T>::align(_pos);
642 if ((_pos + size) / sizeof(l4_umword_t) > L4_UTCB_GENERIC_DATA_SIZE)
648 * \brief Read one size elements of type T from the stream and return
651 * In contrast to a normal get, this version does actually not copy the data
652 * but returns a pointer to the data.
654 * \param buf a Msg_ptr that is actually set to point to the element in the
656 * \param size number of elements to extract (default is 1).
658 * See \link ipc_stream IPC stream operators \endlink.
660 template< typename T >
661 void get(Msg_ptr<T> const &buf, unsigned long size = 1)
664 _pos = cxx::Type_traits<T>::align(_pos);
665 if ((_pos + size) / sizeof(l4_umword_t) > L4_UTCB_GENERIC_DATA_SIZE)
668 buf.set(reinterpret_cast<T*>(_current_msg + _pos));
674 * \brief Extract a single element of type T from the stream.
675 * \param v Output: the element.
677 * See \link ipc_stream IPC stream operators \endlink.
679 template< typename T >
682 _pos = cxx::Type_traits<T>::align(_pos);
683 if ((_pos + sizeof(T)) > L4_UTCB_GENERIC_DATA_SIZE * sizeof(l4_umword_t))
688 v = *(reinterpret_cast<T*>(_current_msg + _pos));
693 int get(Ipc::Varg *va)
696 if (!has_more<Ipc::Varg::Tag>())
703 get(msg_ptr(va->data()), va->length());
709 * \brief Get the message tag of a received IPC.
710 * \return The L4 message tag for the received IPC.
712 * This is in particular useful for handling page faults or exceptions.
714 * See \link ipc_stream IPC stream operators \endlink.
716 l4_msgtag_t tag() const { return _tag; }
720 * \brief Get the message tag of a received IPC.
721 * \return A reference to the L4 message tag for the received IPC.
723 * This is in particular useful for handling page faults or exceptions.
725 * See \link ipc_stream IPC stream operators \endlink.
727 l4_msgtag_t &tag() { return _tag; }
733 * \brief Put a receive item into the stream's buffer registers.
735 inline bool put(Buf_item const &);
739 * \brief Put a small receive item into the stream's buffer registers.
741 inline bool put(Small_buf const &);
745 * \name IPC operations.
750 * \brief Wait for an incoming message from any sender.
751 * \param src contains the sender after a successful IPC operation.
752 * \return The IPC result dope (l4_msgtag_t).
754 * This wait is actually known as 'open wait'.
756 inline l4_msgtag_t wait(l4_umword_t *src)
757 { return wait(src, L4_IPC_NEVER); }
760 * \brief Wait for an incoming message from any sender.
761 * \param src contains the sender after a successful IPC operation.
762 * \param timeout Timeout used for IPC.
763 * \return The IPC result dope (l4_msgtag_t).
765 * This wait is actually known as 'open wait'.
767 inline l4_msgtag_t wait(l4_umword_t *src, l4_timeout_t timeout);
770 * \brief Wait for a message from the specified sender.
771 * \param src The sender id to receive from.
772 * \return The IPC result dope (l4_msgtag_t).
774 * This is commonly known as 'closed wait'.
776 inline l4_msgtag_t receive(l4_cap_idx_t src)
777 { return receive(src, L4_IPC_NEVER); }
778 inline l4_msgtag_t receive(l4_cap_idx_t src, l4_timeout_t timeout);
783 * \brief Return utcb pointer.
785 inline l4_utcb_t *utcb() const { return _utcb; }
792 unsigned char _current_buf;
795 template< typename T >
797 T read(Istream &s) { T t; s >> t; return t; }
801 * \brief Output stream for IPC marshalling.
804 * Ipc::Ostream is part of the dynamic IPC marshalling infrastructure, as well
805 * as Ipc::Istream and Ipc::Iostream.
807 * Ipc::Ostream is an output stream supporting insertion of values into an
808 * IPC message buffer. A IPC message can be marshalled using the
809 * usual insertion operator <<, see \link ipc_stream IPC stream operators
812 * There exist some special wrapper classes to insert arrays (see
813 * Ipc_buf_cp_out) and indirect strings (see Msg_out_buffer and
819 * \brief Create an IPC output stream using the given message buffer \a msg.
821 Ostream(l4_utcb_t *utcb)
822 : _tag(), _utcb(utcb),
823 _current_msg(reinterpret_cast<char *>(l4_utcb_mr_u(_utcb)->mr)),
824 _pos(0), _current_item(0)
828 * \brief Reset the stream to empty, same state as a newly created stream.
834 _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
838 * \name Get/Put functions.
840 * These functions are basically used to implement the insertion operators
841 * (<<) and should not be called directly.
843 * See \link ipc_stream IPC stream operators \endlink.
848 * \brief Put an array with \a size elements of type \a T into the stream.
849 * \param buf A pointer to the array to insert into the buffer.
850 * \param size The number of elements in the array.
852 template< typename T >
853 void put(T *buf, unsigned long size)
856 _pos = cxx::Type_traits<T>::align(_pos);
857 if ((_pos + size) / sizeof(l4_umword_t) > L4_UTCB_GENERIC_DATA_SIZE)
860 __builtin_memcpy(_current_msg + _pos, buf, size);
865 * \brief Insert an element of type \a T into the stream.
866 * \param v The element to insert.
868 template< typename T >
871 _pos = cxx::Type_traits<T>::align(_pos);
872 if ((_pos + sizeof(T)) / sizeof(l4_umword_t) > L4_UTCB_GENERIC_DATA_SIZE)
875 *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
879 int put(Varg const &va)
882 put(va.data(), va.length());
887 template< typename T >
888 int put(Varg_t<T> const &va)
889 { return put(static_cast<Varg const &>(va)); }
892 * \brief Extract the L4 message tag from the stream.
893 * \return the extracted L4 message tag.
895 l4_msgtag_t tag() const { return _tag; }
898 * \brief Extract a reference to the L4 message tag from the stream.
899 * \return A reference to the L4 message tag.
901 l4_msgtag_t &tag() { return _tag; }
907 * \brief Put a send item into the stream's message buffer.
909 inline bool put_snd_item(Snd_item const &);
913 * \name IPC operations.
918 * \brief Send the message via IPC to the given receiver.
919 * \param dst The destination for the message.
921 inline l4_msgtag_t send(l4_cap_idx_t dst, long proto = 0, unsigned flags = 0);
926 * \brief Return utcb pointer.
928 inline l4_utcb_t *utcb() const { return _utcb; }
931 * \brief Get the currently used bytes in the stream.
933 unsigned long tell() const
935 register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
936 w -= _current_item * 2;
937 _tag = l4_msgtag(0, w, _current_item, 0);
943 register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
944 w -= _current_item * 2;
945 _tag = l4_msgtag(0, w, _current_item, 0);
952 unsigned char _current_item;
957 * \brief Input/Output stream for IPC [un]marshalling.
960 * The Ipc::Iostream is part of the AW Env IPC framework as well as
961 * Ipc::Istream and Ipc::Ostream.
962 * In particular an Ipc::Iostream is a combination of an Ipc::Istream and an
963 * Ipc::Ostream. It can use either a single message buffer for receiving and
964 * sending messages or a pair of a receive and a send buffer. The stream also
965 * supports combined IPC operations such as call() and reply_and_wait(), which
966 * can be used to implement RPC functionality.
968 class Iostream : public Istream, public Ostream
973 * \brief Create an IPC IO stream with a single message buffer.
974 * \param msg The message buffer used as backing store.
976 * The created IO stream uses the same message buffer for sending and
977 * receiving IPC messages.
979 explicit Iostream(l4_utcb_t *utcb)
980 : Istream(utcb), Ostream(utcb)
985 * \brief Reset the stream to its initial state.
987 * Input as well as the output stream are reset.
997 * \name Get/Put functions.
999 * These functions are basically used to implement the insertion operators
1000 * (<<) and should not be called directly.
1002 * See \link ipc_stream IPC stream operators \endlink.
1013 * \name IPC operations.
1018 * \brief Do an IPC call using the message in the output stream and
1019 * receiving to the input stream.
1020 * \param dst The destination L4 UID (thread) to call.
1021 * \return the result dope of the IPC operation.
1023 * This is a combined IPC operation consisting of a send and a receive
1024 * to/from the given destination \a dst.
1026 * A call is usually used by clients for RPCs to a server.
1029 inline l4_msgtag_t call(l4_cap_idx_t dst);
1030 inline l4_msgtag_t call(l4_cap_idx_t dst, long label);
1033 * \brief Do an IPC reply and wait.
1034 * \param src_dst Input: the destination for the send operation. <br>
1035 * Output: the source of the received message.
1036 * \return the result dope of the IPC operation.
1038 * This is a combined IPC operation consisting of a send operation and
1039 * an open wait for any message.
1041 * A reply and wait is usually used by servers that reply to a client
1042 * and wait for the next request by any other client.
1044 inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst, long proto = 0)
1045 { return reply_and_wait(src_dst, L4_IPC_SEND_TIMEOUT_0, proto); }
1047 inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1049 { return send_and_wait(dest, src, L4_IPC_SEND_TIMEOUT_0, proto); }
1052 * \brief Do an IPC reply and wait.
1053 * \param src_dst Input: the destination for the send operation. <br>
1054 * Output: the source of the received message.
1055 * \param timeout Timeout used for IPC.
1056 * \return the result dope of the IPC operation.
1058 * This is a combined IPC operation consisting of a send operation and
1059 * an open wait for any message.
1061 * A reply and wait is usually used by servers that reply to a client
1062 * and wait for the next request by any other client.
1064 inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst,
1065 l4_timeout_t timeout, long proto = 0);
1066 inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1067 l4_timeout_t timeout, long proto = 0);
1068 inline l4_msgtag_t reply(l4_timeout_t timeout, long proto);
1069 inline l4_msgtag_t reply(long proto)
1070 { return reply(L4_IPC_SEND_TIMEOUT_0, proto); }
1078 Ostream::put_snd_item(Snd_item const &v)
1081 _pos = cxx::Type_traits<Snd_item>::align(_pos);
1082 if ((_pos + sizeof(T)) / sizeof(l4_umword_t) >= L4_UTCB_GENERIC_DATA_SIZE)
1085 *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
1093 Istream::put(Buf_item const &item)
1095 if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 3)
1098 l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1100 reinterpret_cast<Buf_item&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1107 Istream::put(Small_buf const &item)
1109 if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 2)
1112 l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1114 reinterpret_cast<Small_buf&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1121 Ostream::send(l4_cap_idx_t dst, long proto, unsigned flags)
1124 //unsigned long *b = reinterpret_cast<unsigned long*>(_msg->_msg);
1126 _tag.raw |= (L4_MSGTAG_FLAGS & flags);
1127 return l4_ipc_send(dst, _utcb, _tag, L4_IPC_NEVER);
1131 Iostream::call(l4_cap_idx_t dst)
1135 res = l4_ipc_call(dst, Ostream::_utcb, Ostream::_tag, L4_IPC_NEVER);
1136 Istream::tag() = res;
1142 Iostream::call(l4_cap_idx_t dst, long label)
1146 Ostream::_tag.label(label);
1147 res = l4_ipc_call(dst, Ostream::_utcb, Ostream::_tag, L4_IPC_NEVER);
1148 Istream::tag() = res;
1155 Iostream::reply_and_wait(l4_umword_t *src_dst, l4_timeout_t timeout, long proto)
1159 Ostream::_tag.label(proto);
1160 res = l4_ipc_reply_and_wait(Ostream::_utcb, Ostream::_tag, src_dst, timeout);
1161 Istream::tag() = res;
1168 Iostream::send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1169 l4_timeout_t timeout, long proto)
1173 Ostream::_tag.label(proto);
1174 res = l4_ipc_send_and_wait(dest, Ostream::_utcb, Ostream::_tag, src, timeout);
1175 Istream::tag() = res;
1181 Iostream::reply(l4_timeout_t timeout, long proto)
1185 Ostream::_tag.label(proto);
1186 res = l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, Ostream::_utcb, Ostream::_tag, timeout);
1187 Istream::tag() = res;
1193 Istream::wait(l4_umword_t *src, l4_timeout_t timeout)
1196 res = l4_ipc_wait(_utcb, src, timeout);
1204 Istream::receive(l4_cap_idx_t src, l4_timeout_t timeout)
1207 res = l4_ipc_receive(src, _utcb, timeout);
1218 * \brief Extract one element of type \a T from the stream \a s.
1219 * \ingroup ipc_stream
1220 * \param s The stream to extract from.
1221 * \param v Output: extracted value.
1222 * \return the stream \a s.
1224 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, bool &v) { s.get(v); return s; }
1225 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, int &v) { s.get(v); return s; }
1226 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long int &v) { s.get(v); return s; }
1227 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long long int &v) { s.get(v); return s; }
1228 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned int &v) { s.get(v); return s; }
1229 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long int &v) { s.get(v); return s; }
1230 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long long int &v) { s.get(v); return s; }
1231 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, short int &v) { s.get(v); return s; }
1232 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned short int &v) { s.get(v); return s; }
1233 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, char &v) { s.get(v); return s; }
1234 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned char &v) { s.get(v); return s; }
1235 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, signed char &v) { s.get(v); return s; }
1236 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Buf_item const &v) { s.put(v); return s; }
1237 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Small_buf const &v) { s.put(v); return s; }
1238 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Snd_item &v)
1242 v = L4::Ipc::Snd_item(b,d);
1245 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Varg &v)
1246 { s.get(&v); return s; }
1250 * \brief Extract the L4 message tag from the stream \a s.
1251 * \ingroup ipc_stream
1252 * \param s The stream to extract from.
1253 * \param v Output: the extracted tag.
1254 * \return the stream \a s.
1257 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, l4_msgtag_t &v)
1264 * \brief Extract an array of \a T elements from the stream \a s.
1265 * \ingroup ipc_stream
1267 * This operator actually does not copy out the data in the array, but
1268 * returns a pointer into the message buffer itself. This means that the
1269 * data is only valid as long as there is no new data inserted into the stream.
1271 * See Ipc_buf_in, Ipc_bufcp_in, and Ipc_buf_cp_out.
1273 * \param s The stream to extract from.
1274 * \param v Output: pointer to the extracted array (ipc_buf_in()).
1275 * \return the stream \a s.
1277 template< typename T >
1279 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1280 L4::Ipc::Buf_in<T> const &v)
1285 s.get(L4::Ipc::Msg_ptr<T>(v.buf()), si);
1290 * \brief Extract an element of type \a T from the stream \a s.
1291 * \ingroup ipc_stream
1293 * This operator actually does not copy out the data, but
1294 * returns a pointer into the message buffer itself. This means that the
1295 * data is only valid as long as there is no new data inserted into the stream.
1299 * \param s The stream to extract from.
1300 * \param v Output: pointer to the extracted element.
1301 * \return the stream \a s.
1303 template< typename T >
1305 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1306 L4::Ipc::Msg_ptr<T> const &v)
1313 * \brief Extract an array of \a T elements from the stream \a s.
1314 * \ingroup ipc_stream
1316 * This operator does a copy out of the data into the given buffer.
1318 * See Ipc_buf_in, Ipc_bufcp_in, and Ipc_buf_cp_out.
1320 * \param s The stream to extract from.
1321 * \param v buffer description to copy the array to (ipc_buf_cp_out()).
1322 * \return the stream \a s.
1324 template< typename T >
1326 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1327 L4::Ipc::Buf_cp_in<T> const &v)
1330 s.get(v.buf(), v.size());
1336 * \brief Insert an element to type \a T into the stream \a s.
1337 * \ingroup ipc_stream
1339 * \param s The stream to insert the element \a v.
1340 * \param v The element to insert.
1341 * \return the stream \a s.
1343 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, bool v) { s.put(v); return s; }
1344 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, int v) { s.put(v); return s; }
1345 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long int v) { s.put(v); return s; }
1346 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long long int v) { s.put(v); return s; }
1347 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned int v) { s.put(v); return s; }
1348 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long int v) { s.put(v); return s; }
1349 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long long int v) { s.put(v); return s; }
1350 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, short int v) { s.put(v); return s; }
1351 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned short int v) { s.put(v); return s; }
1352 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char v) { s.put(v); return s; }
1353 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned char v) { s.put(v); return s; }
1354 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, signed char v) { s.put(v); return s; }
1355 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Snd_item const &v) { s.put_snd_item(v); return s; }
1356 template< typename T >
1357 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Cap<T> const &v)
1358 { s << L4::Ipc::Snd_fpage(v.fpage()); return s; }
1360 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg const &v)
1361 { s.put(v); return s; }
1362 template< typename T >
1363 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg_t<T> const &v)
1364 { s.put(v); return s; }
1367 * \brief Insert the L4 message tag into the stream \a s.
1368 * \ingroup ipc_stream
1370 * \note Only one message tag can be inserted into a stream. Multiple
1371 * insertions simply overwrite previous insertions.
1372 * \param s The stream to insert the tag \a v.
1373 * \param v The L4 message tag to insert.
1374 * \return the stream \a s.
1377 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, l4_msgtag_t const &v)
1384 * \brief Insert an array with elements of type \a T into the stream \a s.
1385 * \ingroup ipc_stream
1387 * \param s The stream to insert the array \a v.
1388 * \param v The array to insert (see ipc_buf_cp_out()).
1389 * \return the stream \a s.
1391 template< typename T >
1393 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s,
1394 L4::Ipc::Buf_cp_out<T> const &v)
1397 s.put(v.buf(), v.size());
1402 * \brief Insert a zero terminated character string into the stream \a s.
1403 * \ingroup ipc_stream
1405 * \param s The stream to insert the string \a v.
1406 * \param v The string to insert.
1407 * \return the stream \a s.
1409 * This operator produces basically the same content as the array insertion,
1410 * however the length of the array is calculated using <c> strlen(\a v) + 1
1411 * </c>. The string is copied into the message including the trailing zero.
1414 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char const *v)
1416 unsigned long l = __builtin_strlen(v) + 1;
1423 #ifdef L4_CXX_IPC_BACKWARD_COMPAT
1426 template< typename T > class Ipc_buf_cp_out : public Ipc::Buf_cp_out<T> {};
1427 template< typename T > class Ipc_buf_cp_in : public Ipc::Buf_cp_in<T> {};
1428 template< typename T > class Ipc_buf_in : public Ipc::Buf_in<T> {};
1429 template< typename T > class Msg_ptr : public Ipc::Msg_ptr<T> {};
1431 template< typename T >
1432 Ipc::Buf_cp_out<T> ipc_buf_cp_out(T *v, unsigned long size)
1433 { return Ipc::Buf_cp_out<T>(v,size); }
1435 template< typename T >
1436 Ipc::Buf_cp_in<T> ipc_buf_cp_in(T *v, unsigned long &size)
1437 { return Ipc::Buf_cp_in<T>(v,size); }
1439 template< typename T >
1440 Ipc::Buf_in<T> ipc_buf_in(T *&v, unsigned long &size)
1441 { return Ipc::Buf_in<T>(v, size); }
1443 template< typename T >
1444 Ipc::Msg_ptr<T> msg_ptr(T *&p)
1445 { return Ipc::Msg_ptr<T>(p); }
1447 typedef Ipc::Istream Ipc_istream;
1448 typedef Ipc::Ostream Ipc_ostream;
1449 typedef Ipc::Iostream Ipc_iostream;
1450 typedef Ipc::Snd_fpage Snd_fpage;
1451 typedef Ipc::Rcv_fpage Rcv_fpage;
1452 typedef Ipc::Small_buf Small_buf;