]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/cxx/lib/ipc/include/ipc_stream
4eed5a3de3b327a60f5841b5ca9f903226b40023
[l4.git] / l4 / pkg / cxx / lib / ipc / include / ipc_stream
1 // vi:ft=cpp
2 /**
3  * \file
4  * \brief IPC stream
5  */
6 /*
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.
11  *
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.
20  */
21
22 #pragma once
23
24 #include <l4/sys/ipc.h>
25 #include <l4/sys/capability>
26 #include <l4/cxx/type_traits>
27
28 #define L4_CXX_IPC_BACKWARD_COMPAT 1
29
30 namespace L4 {
31
32 typedef int Opcode;
33
34 namespace Ipc {
35
36 class Ostream;
37 class Istream;
38
39 /**
40  * \brief Abstraction for inserting an array into an Ipc::Ostream.
41  * \ingroup ipc_fw
42  *
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.
47  *
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.
51  *
52  * You should use buf_cp_out() to create instances of Buf_cp_out.
53  *
54  * The counterpart is either Buf_cp_in (buf_cp_in()) or Buf_in (buf_in()).
55  */
56 template< typename T >
57 class Buf_cp_out
58 {
59 public:
60   /**
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.
64    */
65   Buf_cp_out(T *v, unsigned long size) : _v(v), _s(size) {}
66
67   /**
68    * \brief Get the number of elements in the array.
69    * \note This function is usually used by the Ipc::Ostream itself.
70    */
71   unsigned long size() const { return _s; }
72
73   /**
74    * \brief Get the pointer to the array.
75    * \note This function is usually used by the Ipc::Ostream itself.
76    */
77   T *buf() const { return _v; }
78
79 private:
80   friend class Ostream;
81   T *_v;
82   unsigned long _s;
83 };
84
85 /**
86  * \brief Create an instance of Buf_cp_out for the given values.
87  * \ingroup ipc_fw
88  * 
89  * This function makes it more convenient to insert arrays into an
90  * Ipc::Ostream (\see Buf_cp_out.)
91  *
92  * \param v Pointer to the array that shall be inserted into an Ipc::Ostream.
93  * \param size Number of elements in the array.
94  */
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); }
98
99
100 /**
101  * \brief Abstraction for extracting array from an Ipc::Istream.
102  * \ingroup ipc_fw
103  *
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.
109  *
110  * \see buf_cp_in(), Buf_in, buf_in(), Buf_cp_out, and buf_cp_out().
111  */
112 template< typename T >
113 class Buf_cp_in
114 {
115 public:
116   /**
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.
121    */
122   Buf_cp_in(T *v, unsigned long &size) : _v(v), _s(&size) {}
123
124   unsigned long &size() const { return *_s; }
125   T *buf() const { return _v; }
126 private:
127   friend class Istream;
128   T *_v;
129   unsigned long *_s;
130 };
131
132 /**
133  * \brief Create an Buf_cp_in for the given values.
134  * \ingroup ipc_fw
135  * 
136  * This function makes it more convenient to extract arrays from an
137  * Ipc::Istream (\see Buf_cp_in.)
138  *
139  * \param v Pointer to the array that shall receive the values from the
140  *          Ipc::Istream.
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.
143  *
144  * \see buf_in() and buf_cp_out().
145  */
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); }
149
150
151 /**
152  * \brief Pointer to an element of type T in an Ipc::Istream.
153  * \ingroup ipc_fw
154  *
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
160  * in the message.
161  *
162  * See msg_ptr().
163  */
164 template< typename T >
165 class Msg_ptr
166 {
167 private:
168   T **_p;
169 public:
170   /**
171    * \brief Create a Msg_ptr object that set pointer p to point into the
172    *        message buffer.
173    * \param p The pointer that is adjusted to point into the message buffer.
174    */
175   explicit Msg_ptr(T *&p) : _p(&p) {}
176   void set(T *p) const { *_p = p; }
177 };
178
179 /**
180  * \brief Create an Msg_ptr to adjust the given pointer.
181  * \ingroup ipc_fw
182  * 
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.
186  * (See Msg_ptr.)
187  */
188 template< typename T >
189 Msg_ptr<T> msg_ptr(T *&p)
190 { return Msg_ptr<T>(p); }
191
192
193 /**
194  * \brief Abstraction to extract an array from an Ipc::Istream.
195  * \ingroup ipc_fw
196  *
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.
200  *
201  * The mechanism is comparable to that of Msg_ptr, however it handles arrays
202  * inserted with Buf_cp_out.
203  *
204  * See buf_in(), Buf_cp_out, buf_cp_out(), Buf_cp_in, and buf_cp_in().
205  */
206 template< typename T >
207 class Buf_in
208 {
209 public:
210   /** 
211    * \brief Create an Buf_in to adjust a pointer to the array and the size
212    *        of the array.
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.
215    */
216   Buf_in(T *&v, unsigned long &size) : _v(&v), _s(&size) {}
217
218   void set_size(unsigned long s) const { *_s = s; }
219   T *&buf() const { return *_v; }
220 private:
221   friend class Istream;
222   T **_v;
223   unsigned long *_s;
224 };
225
226 /**
227  * \brief Create an Buf_in for the given values.
228  * \ingroup ipc_fw
229  * 
230  * This function makes it more convenient to extract arrays from an
231  * Ipc::Istream (See Buf_in.)
232  *
233  * \param v Output: pointer to the array within the Ipc::Istream.
234  * \param size Output: the number of elements found in the stream.
235  *
236  * See buf_cp_in() and buf_cp_out().
237  */
238 template< typename T >
239 Buf_in<T> buf_in(T *&v, unsigned long &size)
240 { return Buf_in<T>(v, size); }
241
242
243
244 /**
245  * \brief A receive item for receiving a single capability.
246  *
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.
251  */
252 class Small_buf
253 {
254 public:
255   explicit Small_buf(L4::Cap<L4::Kobject> cap, unsigned long flags = 0)
256   : _data(cap.cap() | L4_RCV_ITEM_SINGLE_CAP | flags) {}
257
258   explicit Small_buf(l4_cap_idx_t idx, unsigned long flags = 0)
259   : _data(idx | L4_RCV_ITEM_SINGLE_CAP | flags) {}
260 private:
261   l4_umword_t _data;
262 };
263
264 class Snd_item
265 {
266 public:
267   Snd_item(l4_umword_t base, l4_umword_t data) : _base(base), _data(data) {}
268
269 protected:
270   l4_umword_t _base;
271   l4_umword_t _data;
272 };
273
274 class Buf_item
275 {
276 public:
277   Buf_item(l4_umword_t base, l4_umword_t data) : _base(base), _data(data) {}
278
279 protected:
280   l4_umword_t _base;
281   l4_umword_t _data;
282 };
283
284 template< typename T >
285 class Gen_fpage : public T
286 {
287 public:
288   enum Type
289   {
290     Special = L4_FPAGE_SPECIAL << 4,
291     Memory  = L4_FPAGE_MEMORY << 4,
292     Io      = L4_FPAGE_IO << 4,
293     Obj     = L4_FPAGE_OBJ << 4
294   };
295
296   enum Map_type
297   {
298     Map   = L4_MAP_ITEM_MAP,
299     Grant = L4_MAP_ITEM_GRANT,
300   };
301
302   enum Cacheopt
303   {
304     None     = 0,
305     Cached   = L4_FPAGE_CACHEABLE << 4,
306     Buffered = L4_FPAGE_BUFFERABLE << 4,
307     Uncached = L4_FPAGE_UNCACHEABLE << 4
308   };
309
310   enum Continue
311   {
312     Single   = 0,
313     Last     = 0,
314     More     = L4_ITEM_CONT,
315     Compound = L4_ITEM_CONT,
316   };
317
318 private:
319   Gen_fpage(Type type, l4_addr_t base, int order,
320             unsigned char rights,
321             l4_addr_t snd_base,
322             Map_type map_type,
323             Cacheopt cache, Continue cont)
324   : T(L4_ITEM_MAP | (snd_base & (~0UL << 10)) | l4_umword_t(map_type) | l4_umword_t(cache)
325       | l4_umword_t(cont),
326       base | l4_umword_t(type) | rights | (l4_umword_t(order) << 6))
327   {}
328
329 public:
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)
335     | l4_umword_t(cont),
336     fp.raw)
337   {}
338
339   Gen_fpage(L4::Cap<void> cap, unsigned rights)
340   : T(L4_ITEM_MAP | Map | (rights & 0xf0), cap.fpage(rights).raw)
341   {}
342
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); }
362
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)); }
369
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
376   // receiving thread)
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; }
384 };
385
386
387 typedef Gen_fpage<Snd_item> Snd_fpage;
388 typedef Gen_fpage<Buf_item> Rcv_fpage;
389
390 #ifdef L4_CXX_IPC_SUPPORT_STRINGS
391 template <typename T, typename B>
392 class Gen_string : public T
393 {
394 public:
395   Gen_string() : T(0,0) {}
396   Gen_string(B buf, unsigned long size)
397   : T(size << 10, l4_umword_t(buf))
398   {}
399
400   unsigned long len() const { return T::_base >> 10; }
401 };
402
403 typedef Gen_string<Snd_item, void const *> Snd_string;
404 typedef Gen_string<Buf_item, void *> Rcv_string;
405 #endif
406
407
408 template< typename T, template <typename X> class B > struct Generic_va_type : public B<T>
409 {
410   enum { Id = B<T>::Id };
411   typedef B<T> ID;
412   typedef T const &Ret_value;
413   typedef T Value;
414
415   static Ret_value value(void const *d)
416   { return *reinterpret_cast<Value const *>(d); }
417
418   static void const *addr_of(Value const &v) { return &v; }
419
420   static unsigned size(void const *) { return sizeof(T); }
421
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; }
425 };
426
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 }; };
433
434 template< typename T > struct Va_type;
435
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> {};
439
440 template<> struct Va_type<void>
441 {
442   typedef void Ret_value;
443   typedef void Value;
444
445   static void const *addr_of(void) { return 0; }
446
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; }
450 };
451
452 template<> struct Va_type<char const *>
453 {
454   typedef char const *Ret_value;
455   typedef char const *Value;
456
457   static void const *addr_of(Value v) { return v; }
458
459   static L4_varg_type id() { return L4_VARG_TYPE_STRING; }
460   static unsigned size(void const *s)
461   {
462     char const *_s = reinterpret_cast<char const *>(s);
463     int l = 1;
464     while (*_s)
465       {
466         ++_s; ++l;
467       }
468     return l;
469   }
470
471   static Ret_value value(void const *d) { return (char const *)d; }
472 };
473
474
475 class Varg
476 {
477 private:
478   l4_umword_t _tag;
479   char const *_d;
480
481 public:
482
483   typedef l4_umword_t Tag;
484
485   L4_varg_type type() const { return (L4_varg_type)(_tag & 0xff); }
486   int length() const { return _tag >> 16; }
487
488   void tag(Tag tag) { _tag = tag; }
489   Tag tag() const { return _tag; }
490   void data(char const *d) { _d = d; }
491
492   char const *data() const { return _d; }
493   char const *&data() { return _d; }
494
495   Varg() : _tag(0), _d(0) {}
496
497   Varg(L4_varg_type t, void const  *v, int len)
498   : _tag(t | ((l4_mword_t)len << 16)), _d((char const *)v)
499   {}
500
501   template< typename V >
502   typename Va_type<V>::Ret_value value() const
503   { return Va_type<V>::value(_d); }
504
505
506   template< typename T >
507   bool is_of() const { return Va_type<T>::id() == type(); }
508
509   bool is_nil() const { return is_of<void>(); }
510
511   bool is_of_int() const
512   { return (type() & ~L4_VARG_TYPE_SIGN) == L4_VARG_TYPE_UMWORD; }
513
514   template< typename T >
515   bool get_value(typename Va_type<T>::Value *v) const
516   {
517     if (!is_of<T>())
518       return false;
519
520     *v = Va_type<T>::value(_d);
521     return true;
522   }
523
524   template< typename T >
525   void set_value(void const *d)
526   {
527     typedef Va_type<T> Vt;
528     _tag = Vt::id() | (Vt::size(d) << 16);
529     _d = (char const *)d;
530   }
531
532 };
533
534 template<typename T>
535 class Varg_t : public Varg
536 {
537 public:
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)); }
541
542 private:
543   Value _data;
544 };
545
546
547 /**
548  * \brief Input stream for IPC unmarshalling.
549  * \ingroup ipc_fw
550  *
551  * Ipc::Istream is part of the dynamic IPC marshalling infrastructure, as well
552  * as Ipc::Ostream and Ipc::Iostream.
553  *
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 (>>).
557  *
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
560  * Msg_io_buffer).
561  */
562 class Istream
563 {
564 public:
565   /**
566    * \brief Create an input stream for the given message buffer.
567    * 
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.
573    *
574    * \param msg The message buffer to receive IPC messages.
575    */
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)
580   {}
581
582   /**
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.
585    */
586   void reset()
587   {
588     _pos = 0;
589     _current_buf = 0;
590     _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
591   }
592
593   /**
594    * \brief Check whether a value of type T can be obtained from the stream.
595    */
596   template< typename T >
597   bool has_more()
598   {
599     unsigned apos = cxx::Type_traits<T>::align(_pos);
600     return apos + sizeof(T) <= _tag.words() * sizeof(l4_umword_t);
601   }
602
603   /**
604    * \name Get/Put Functions.
605    * These functions are basically used to implement the extraction operators
606    * (>>) and should not be called directly.
607    *
608    * See \link ipc_stream IPC stream operators \endlink.
609    */
610   //@{
611
612   /**
613    * \brief Copy out an array of type \a T with \a size elements.
614    *
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.
617    *
618    * See \link ipc_stream IPC stream operators \endlink.
619    */
620   template< typename T >
621   void get(T *buf, unsigned long size)
622   {
623     size *= sizeof(T);
624     _pos = cxx::Type_traits<T>::align(_pos);
625     if ((_pos + size) / sizeof(l4_umword_t) > L4_UTCB_GENERIC_DATA_SIZE)
626       return;
627
628     __builtin_memcpy(buf, _current_msg + _pos, size);
629     _pos += size;
630   }
631
632
633   /**
634    * \brief Skip size elements of type T in the stream.
635    * \param size number of elements to skip.
636    */
637   template< typename T >
638   void skip(unsigned long size)
639   {
640     size *= sizeof(T);
641     _pos = cxx::Type_traits<T>::align(_pos);
642     if ((_pos + size) / sizeof(l4_umword_t) > L4_UTCB_GENERIC_DATA_SIZE)
643       return;
644     _pos += size;
645   }
646
647   /**
648    * \brief Read one size elements of type T from the stream and return 
649    *        a pointer.
650    *
651    * In contrast to a normal get, this version does actually not copy the data
652    * but returns a pointer to the data.
653    *
654    * \param buf a Msg_ptr that is actually set to point to the element in the
655    *            stream.
656    * \param size number of elements to extract (default is 1).
657    *
658    * See \link ipc_stream IPC stream operators \endlink.
659    */
660   template< typename T >
661   void get(Msg_ptr<T> const &buf, unsigned long size = 1)
662   {
663     size *= sizeof(T);
664     _pos = cxx::Type_traits<T>::align(_pos);
665     if ((_pos + size) / sizeof(l4_umword_t) > L4_UTCB_GENERIC_DATA_SIZE)
666       return;
667
668     buf.set(reinterpret_cast<T*>(_current_msg + _pos)); 
669     _pos += size;
670   }
671
672
673   /**
674    * \brief Extract a single element of type T from the stream.
675    * \param v Output: the element.
676    *
677    * See \link ipc_stream IPC stream operators \endlink.
678    */
679   template< typename T >
680   void get(T &v)
681   {
682     _pos = cxx::Type_traits<T>::align(_pos); 
683     if ((_pos + sizeof(T)) > L4_UTCB_GENERIC_DATA_SIZE * sizeof(l4_umword_t))
684       {
685         v = T();
686         return;
687       }
688     v = *(reinterpret_cast<T*>(_current_msg + _pos));
689     _pos += sizeof(T);
690   }
691
692
693   int get(Ipc::Varg *va)
694   {
695     Ipc::Varg::Tag t;
696     if (!has_more<Ipc::Varg::Tag>())
697       {
698         va->tag(0);
699         return 0;
700       }
701     get(t);
702     va->tag(t);
703     get(msg_ptr(va->data()), va->length());
704
705     return 0;
706   }
707
708   /**
709    * \brief Get the message tag of a received IPC.
710    * \return The L4 message tag for the received IPC.
711    *
712    * This is in particular useful for handling page faults or exceptions.
713    *
714    * See \link ipc_stream IPC stream operators \endlink.
715    */
716   l4_msgtag_t tag() const { return _tag; }
717
718
719   /**
720    * \brief Get the message tag of a received IPC.
721    * \return A reference to the L4 message tag for the received IPC.
722    *
723    * This is in particular useful for handling page faults or exceptions.
724    *
725    * See \link ipc_stream IPC stream operators \endlink.
726    */
727   l4_msgtag_t &tag() { return _tag; }
728
729   //@}
730
731   /**
732    * \internal
733    * \brief Put a receive item into the stream's buffer registers.
734    */
735   inline bool put(Buf_item const &);
736   
737   /**
738    * \internal
739    * \brief Put a small receive item into the stream's buffer registers.
740    */
741   inline bool put(Small_buf const &);
742
743
744   /**
745    * \name IPC operations.
746    */
747   //@{
748
749   /**
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).
753    *
754    * This wait is actually known as 'open wait'.
755    */
756   inline l4_msgtag_t wait(l4_umword_t *src)
757   { return wait(src, L4_IPC_NEVER); }
758
759   /**
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).
764    *
765    * This wait is actually known as 'open wait'.
766    */
767   inline l4_msgtag_t wait(l4_umword_t *src, l4_timeout_t timeout);
768
769   /**
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).
773    *
774    * This is commonly known as 'closed wait'.
775    */
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);
779
780   //@}
781
782   /**
783    * \brief Return utcb pointer.
784    */
785   inline l4_utcb_t *utcb() const { return _utcb; }
786
787 protected:
788   l4_msgtag_t _tag;
789   l4_utcb_t *_utcb;
790   char *_current_msg;
791   unsigned _pos;
792   unsigned char _current_buf;
793 };
794
795 template< typename T >
796 inline
797 T read(Istream &s) { T t; s >> t; return t; }
798
799
800 /**
801  * \brief Output stream for IPC marshalling.
802  * \ingroup ipc_fw
803  *
804  * Ipc::Ostream is part of the dynamic IPC marshalling infrastructure, as well
805  * as Ipc::Istream and Ipc::Iostream.
806  *
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
810  * \endlink.
811  *
812  * There exist some special wrapper classes to insert arrays (see
813  * Ipc_buf_cp_out) and indirect strings (see Msg_out_buffer and
814  * Msg_io_buffer). */
815 class Ostream
816 {
817 public:
818   /**
819    * \brief Create an IPC output stream using the given message buffer \a msg.
820    */
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)
825   {}
826
827   /**
828    * \brief Reset the stream to empty, same state as a newly created stream.
829    */
830   void reset()
831   {
832     _pos = 0;
833     _current_item = 0;
834     _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
835   }
836
837   /**
838    * \name Get/Put functions.
839    *
840    * These functions are basically used to implement the insertion operators
841    * (<<) and should not be called directly.
842    *
843    * See \link ipc_stream IPC stream operators \endlink.
844    */
845   //@{
846
847   /**
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.
851    */
852   template< typename T >
853   void put(T *buf, unsigned long size)
854   {
855     size *= sizeof(T);
856     _pos = cxx::Type_traits<T>::align(_pos);
857     if ((_pos + size) / sizeof(l4_umword_t) > L4_UTCB_GENERIC_DATA_SIZE)
858       return;
859
860     __builtin_memcpy(_current_msg + _pos, buf, size);
861     _pos += size;
862   }
863
864   /**
865    * \brief Insert an element of type \a T into the stream.
866    * \param v The element to insert.
867    */
868   template< typename T >
869   void put(T const &v)
870   {
871     _pos = cxx::Type_traits<T>::align(_pos);
872     if ((_pos + sizeof(T)) / sizeof(l4_umword_t) > L4_UTCB_GENERIC_DATA_SIZE)
873       return;
874
875     *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
876     _pos += sizeof(T);
877   }
878
879   int put(Varg const &va)
880   {
881     put(va.tag());
882     put(va.data(), va.length());
883
884     return 0;
885   }
886
887   template< typename T >
888   int put(Varg_t<T> const &va)
889   { return put(static_cast<Varg const &>(va)); }
890
891   /**
892    * \brief Extract the L4 message tag from the stream.
893    * \return the extracted L4 message tag.
894    */
895   l4_msgtag_t tag() const { return _tag; }
896
897   /**
898    * \brief Extract a reference to the L4 message tag from the stream.
899    * \return A reference to the L4 message tag.
900    */
901   l4_msgtag_t &tag() { return _tag; }
902
903   //@}
904
905   /**
906    * \internal
907    * \brief Put a send item into the stream's message buffer.
908    */
909   inline bool put_snd_item(Snd_item const &);
910
911
912   /**
913    * \name IPC operations.
914    */
915   //@{
916
917   /**
918    * \brief Send the message via IPC to the given receiver.
919    * \param dst The destination for the message.
920    */
921   inline l4_msgtag_t send(l4_cap_idx_t dst, long proto = 0, unsigned flags = 0);
922
923   //@}
924
925   /**
926    * \brief Return utcb pointer.
927    */
928   inline l4_utcb_t *utcb() const { return _utcb; }
929 #if 0
930   /**
931    * \brief Get the currently used bytes in the stream.
932    */
933   unsigned long tell() const
934   {
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);
938   }
939 #endif
940 protected:
941   void pre_ipc()
942   {
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);
946   }
947
948   l4_msgtag_t _tag;
949   l4_utcb_t *_utcb;
950   char *_current_msg;
951   unsigned _pos;
952   unsigned char _current_item;
953 };
954
955
956 /**
957  * \brief Input/Output stream for IPC [un]marshalling.
958  * \ingroup ipc_fw
959  *
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.
967  */
968 class Iostream : public Istream, public Ostream
969 {
970 public:
971
972   /**
973    * \brief Create an IPC IO stream with a single message buffer.
974    * \param msg The message buffer used as backing store.
975    *
976    * The created IO stream uses the same message buffer for sending and
977    * receiving IPC messages.
978    */
979   explicit Iostream(l4_utcb_t *utcb)
980   : Istream(utcb), Ostream(utcb)
981   {}
982
983
984   /**
985    * \brief Reset the stream to its initial state.
986    *
987    * Input as well as the output stream are reset.
988    */
989   void reset()
990   {
991     Istream::reset();
992     Ostream::reset();
993   }
994
995
996   /**
997    * \name Get/Put functions.
998    *
999    * These functions are basically used to implement the insertion operators
1000    * (<<) and should not be called directly.
1001    *
1002    * See \link ipc_stream IPC stream operators \endlink.
1003    */
1004   //@{
1005
1006   using Istream::get;
1007   using Istream::put;
1008   using Ostream::put;
1009
1010   //@}
1011
1012   /**
1013    * \name IPC operations.
1014    */
1015   //@{
1016
1017   /**
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.
1022    *
1023    * This is a combined IPC operation consisting of a send and a receive
1024    * to/from the given destination \a dst.
1025    *
1026    * A call is usually used by clients for RPCs to a server.
1027    *
1028    */
1029   inline l4_msgtag_t call(l4_cap_idx_t dst);
1030   inline l4_msgtag_t call(l4_cap_idx_t dst, long label);
1031
1032   /**
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.
1037    *
1038    * This is a combined IPC operation consisting of a send operation and
1039    * an open wait for any message.
1040    *
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.
1043    */
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); }
1046
1047   inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1048                                    long proto = 0)
1049   { return send_and_wait(dest, src, L4_IPC_SEND_TIMEOUT_0, proto); }
1050
1051   /**
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.
1057    *
1058    * This is a combined IPC operation consisting of a send operation and
1059    * an open wait for any message.
1060    *
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.
1063    */
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); }
1071
1072   //@}
1073
1074 };
1075
1076
1077 inline bool
1078 Ostream::put_snd_item(Snd_item const &v)
1079 {
1080   typedef Snd_item T;
1081   _pos = cxx::Type_traits<Snd_item>::align(_pos);
1082   if ((_pos + sizeof(T)) / sizeof(l4_umword_t) >= L4_UTCB_GENERIC_DATA_SIZE)
1083     return false;
1084
1085   *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
1086   _pos += sizeof(T);
1087   ++_current_item;
1088   return true;
1089 }
1090
1091
1092 inline bool
1093 Istream::put(Buf_item const &item)
1094 {
1095   if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 3)
1096     return false;
1097
1098   l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1099
1100   reinterpret_cast<Buf_item&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1101   _current_buf += 2;
1102   return true;
1103 }
1104
1105
1106 inline bool
1107 Istream::put(Small_buf const &item)
1108 {
1109   if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 2)
1110     return false;
1111
1112   l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1113
1114   reinterpret_cast<Small_buf&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1115   _current_buf += 1;
1116   return true;
1117 }
1118
1119
1120 inline l4_msgtag_t
1121 Ostream::send(l4_cap_idx_t dst, long proto, unsigned flags)
1122 {
1123   pre_ipc();
1124   //unsigned long *b = reinterpret_cast<unsigned long*>(_msg->_msg);
1125   _tag.label(proto);
1126   _tag.raw |= (L4_MSGTAG_FLAGS & flags);
1127   return l4_ipc_send(dst, _utcb, _tag, L4_IPC_NEVER);
1128 }
1129
1130 inline l4_msgtag_t
1131 Iostream::call(l4_cap_idx_t dst)
1132 {
1133   pre_ipc();
1134   l4_msgtag_t res;
1135   res = l4_ipc_call(dst, Ostream::_utcb, Ostream::_tag, L4_IPC_NEVER);
1136   Istream::tag() = res;
1137   Istream::_pos = 0;
1138   return res;
1139 }
1140
1141 inline l4_msgtag_t
1142 Iostream::call(l4_cap_idx_t dst, long label)
1143 {
1144   pre_ipc();
1145   l4_msgtag_t res;
1146   Ostream::_tag.label(label);
1147   res = l4_ipc_call(dst, Ostream::_utcb, Ostream::_tag, L4_IPC_NEVER);
1148   Istream::tag() = res;
1149   Istream::_pos = 0;
1150   return res;
1151 }
1152
1153
1154 inline l4_msgtag_t
1155 Iostream::reply_and_wait(l4_umword_t *src_dst, l4_timeout_t timeout, long proto)
1156 {
1157   pre_ipc();
1158   l4_msgtag_t res;
1159   Ostream::_tag.label(proto);
1160   res = l4_ipc_reply_and_wait(Ostream::_utcb, Ostream::_tag, src_dst, timeout);
1161   Istream::tag() = res;
1162   Istream::_pos = 0;
1163   return res;
1164 }
1165
1166
1167 inline l4_msgtag_t
1168 Iostream::send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1169                         l4_timeout_t timeout, long proto)
1170 {
1171   pre_ipc();
1172   l4_msgtag_t res;
1173   Ostream::_tag.label(proto);
1174   res = l4_ipc_send_and_wait(dest, Ostream::_utcb, Ostream::_tag, src, timeout);
1175   Istream::tag() = res;
1176   Istream::_pos = 0;
1177   return res;
1178 }
1179
1180 inline l4_msgtag_t
1181 Iostream::reply(l4_timeout_t timeout, long proto)
1182 {
1183   pre_ipc();
1184   l4_msgtag_t res;
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;
1188   Istream::_pos = 0;
1189   return res;
1190 }
1191
1192 inline l4_msgtag_t
1193 Istream::wait(l4_umword_t *src, l4_timeout_t timeout)
1194 {
1195   l4_msgtag_t res;
1196   res = l4_ipc_wait(_utcb, src, timeout);
1197   tag() = res;
1198   _pos = 0;
1199   return res;
1200 }
1201
1202
1203 inline l4_msgtag_t
1204 Istream::receive(l4_cap_idx_t src, l4_timeout_t timeout)
1205 {
1206   l4_msgtag_t res;
1207   res = l4_ipc_receive(src, _utcb, timeout);
1208   tag() = res;
1209   _pos = 0;
1210   return res;
1211 }
1212
1213 };
1214
1215 } // namespace Ipc
1216
1217 /**
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.
1223  */
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)
1239 {
1240   l4_umword_t b, d;
1241   s >> b >> d;
1242   v = L4::Ipc::Snd_item(b,d);
1243   return s;
1244 }
1245 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Varg &v)
1246 { s.get(&v); return s; }
1247
1248
1249 /**
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.
1255  */
1256 inline
1257 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, l4_msgtag_t &v)
1258 {
1259   v = s.tag();
1260   return s;
1261 }
1262
1263 /**
1264  * \brief Extract an array of \a T elements from the stream \a s.
1265  * \ingroup ipc_stream
1266  *
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.
1270  *
1271  * See Ipc_buf_in, Ipc_bufcp_in, and Ipc_buf_cp_out.
1272  *
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.
1276  */
1277 template< typename T >
1278 inline
1279 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1280     L4::Ipc::Buf_in<T> const &v)
1281 {
1282   unsigned long si;
1283   s.get(si);
1284   v.set_size(si);
1285   s.get(L4::Ipc::Msg_ptr<T>(v.buf()), si);
1286   return s;
1287 }
1288
1289 /**
1290  * \brief Extract an element of type \a T from the stream \a s.
1291  * \ingroup ipc_stream
1292  *
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.
1296  *
1297  * See Msg_ptr.
1298  *
1299  * \param s The stream to extract from.
1300  * \param v Output: pointer to the extracted element.
1301  * \return the stream \a s.
1302  */
1303 template< typename T >
1304 inline
1305 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1306     L4::Ipc::Msg_ptr<T> const &v)
1307 {
1308   s.get(v);
1309   return s;
1310 }
1311
1312 /**
1313  * \brief Extract an array of \a T elements from the stream \a s.
1314  * \ingroup ipc_stream
1315  *
1316  * This operator does a copy out of the data into the given buffer.
1317  *
1318  * See Ipc_buf_in, Ipc_bufcp_in, and Ipc_buf_cp_out.
1319  *
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.
1323  */
1324 template< typename T >
1325 inline
1326 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1327     L4::Ipc::Buf_cp_in<T> const &v)
1328 {
1329   s.get(v.size());
1330   s.get(v.buf(), v.size());
1331   return s;
1332 }
1333
1334
1335 /**
1336  * \brief Insert an element to type \a T into the stream \a s.
1337  * \ingroup ipc_stream
1338  *
1339  * \param s The stream to insert the element \a v.
1340  * \param v The element to insert.
1341  * \return the stream \a s.
1342  */
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; }
1359
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; }
1365
1366 /**
1367  * \brief Insert the L4 message tag into the stream \a s.
1368  * \ingroup ipc_stream
1369  *
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.
1375  */
1376 inline
1377 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, l4_msgtag_t const &v)
1378 {
1379   s.tag() = v;
1380   return s;
1381 }
1382
1383 /**
1384  * \brief Insert an array with elements of type \a T into the stream \a s.
1385  * \ingroup ipc_stream
1386  *
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.
1390  */
1391 template< typename T >
1392 inline
1393 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s,
1394     L4::Ipc::Buf_cp_out<T> const &v)
1395 {
1396   s.put(v.size());
1397   s.put(v.buf(), v.size());
1398   return s;
1399 }
1400
1401 /**
1402  * \brief Insert a zero terminated character string into the stream \a s.
1403  * \ingroup ipc_stream
1404  *
1405  * \param s The stream to insert the string \a v.
1406  * \param v The string to insert.
1407  * \return the stream \a s.
1408  *
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.
1412  */
1413 inline
1414 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char const *v)
1415 {
1416   unsigned long l = __builtin_strlen(v) + 1;
1417   s.put(l);
1418   s.put(v, l);
1419   return s;
1420 }
1421
1422
1423 #ifdef L4_CXX_IPC_BACKWARD_COMPAT
1424 namespace L4 {
1425
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> {};
1430
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); }
1434
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); }
1438
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); }
1442
1443 template< typename T >
1444 Ipc::Msg_ptr<T> msg_ptr(T *&p)
1445 { return Ipc::Msg_ptr<T>(p); }
1446
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;
1453
1454 }
1455 #endif
1456