]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/cxx/lib/ipc/include/ipc_stream
update
[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 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)
11  *
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.
15  *
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.
24  */
25
26 #pragma once
27
28 #include <l4/sys/ipc.h>
29 #include <l4/sys/capability>
30 #include <l4/cxx/type_traits>
31
32 #define L4_CXX_IPC_BACKWARD_COMPAT 1
33
34 namespace L4 {
35
36 typedef int Opcode;
37
38 namespace Ipc {
39
40 class Ostream;
41 class Istream;
42
43 /**
44  * \brief Abstraction for inserting an array into an Ipc::Ostream.
45  * \ingroup ipc_fw
46  *
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.
51  *
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.
55  *
56  * You should use buf_cp_out() to create instances of Buf_cp_out.
57  *
58  * The counterpart is either Buf_cp_in (buf_cp_in()) or Buf_in (buf_in()).
59  */
60 template< typename T >
61 class Buf_cp_out
62 {
63 public:
64   /**
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.
68    */
69   Buf_cp_out(T *v, unsigned long size) : _v(v), _s(size) {}
70
71   /**
72    * \brief Get the number of elements in the array.
73    * \note This function is usually used by the Ipc::Ostream itself.
74    */
75   unsigned long size() const { return _s; }
76
77   /**
78    * \brief Get the pointer to the array.
79    * \note This function is usually used by the Ipc::Ostream itself.
80    */
81   T *buf() const { return _v; }
82
83 private:
84   friend class Ostream;
85   T *_v;
86   unsigned long _s;
87 };
88
89 /**
90  * \brief Create an instance of Buf_cp_out for the given values.
91  * \ingroup ipc_fw
92  *
93  * This function makes it more convenient to insert arrays into an
94  * Ipc::Ostream (\see Buf_cp_out.)
95  *
96  * \param v Pointer to the array that shall be inserted into an Ipc::Ostream.
97  * \param size Number of elements in the array.
98  */
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); }
102
103
104 /**
105  * \brief Abstraction for extracting array from an Ipc::Istream.
106  * \ingroup ipc_fw
107  *
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.
113  *
114  * \see buf_cp_in(), Buf_in, buf_in(), Buf_cp_out, and buf_cp_out().
115  */
116 template< typename T >
117 class Buf_cp_in
118 {
119 public:
120   /**
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.
125    */
126   Buf_cp_in(T *v, unsigned long &size) : _v(v), _s(&size) {}
127
128   unsigned long &size() const { return *_s; }
129   T *buf() const { return _v; }
130 private:
131   friend class Istream;
132   T *_v;
133   unsigned long *_s;
134 };
135
136 /**
137  * \brief Create an Buf_cp_in for the given values.
138  * \ingroup ipc_fw
139  *
140  * This function makes it more convenient to extract arrays from an
141  * Ipc::Istream (\see Buf_cp_in.)
142  *
143  * \param v Pointer to the array that shall receive the values from the
144  *          Ipc::Istream.
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.
147  *
148  * \see buf_in() and buf_cp_out().
149  */
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); }
153
154
155 /**
156  * \brief Pointer to an element of type T in an Ipc::Istream.
157  * \ingroup ipc_fw
158  *
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
164  * in the message.
165  *
166  * See msg_ptr().
167  */
168 template< typename T >
169 class Msg_ptr
170 {
171 private:
172   T **_p;
173 public:
174   /**
175    * \brief Create a Msg_ptr object that set pointer p to point into the
176    *        message buffer.
177    * \param p The pointer that is adjusted to point into the message buffer.
178    */
179   explicit Msg_ptr(T *&p) : _p(&p) {}
180   void set(T *p) const { *_p = p; }
181 };
182
183 /**
184  * \brief Create an Msg_ptr to adjust the given pointer.
185  * \ingroup ipc_fw
186  *
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.
190  * (See Msg_ptr.)
191  */
192 template< typename T >
193 Msg_ptr<T> msg_ptr(T *&p)
194 { return Msg_ptr<T>(p); }
195
196
197 /**
198  * \brief Abstraction to extract an array from an Ipc::Istream.
199  * \ingroup ipc_fw
200  *
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.
204  *
205  * The mechanism is comparable to that of Msg_ptr, however it handles arrays
206  * inserted with Buf_cp_out.
207  *
208  * See buf_in(), Buf_cp_out, buf_cp_out(), Buf_cp_in, and buf_cp_in().
209  */
210 template< typename T >
211 class Buf_in
212 {
213 public:
214   /**
215    * \brief Create an Buf_in to adjust a pointer to the array and the size
216    *        of the array.
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.
219    */
220   Buf_in(T *&v, unsigned long &size) : _v(&v), _s(&size) {}
221
222   void set_size(unsigned long s) const { *_s = s; }
223   T *&buf() const { return *_v; }
224 private:
225   friend class Istream;
226   T **_v;
227   unsigned long *_s;
228 };
229
230 /**
231  * \brief Create an Buf_in for the given values.
232  * \ingroup ipc_fw
233  *
234  * This function makes it more convenient to extract arrays from an
235  * Ipc::Istream (See Buf_in.)
236  *
237  * \param v Output: pointer to the array within the Ipc::Istream.
238  * \param size Output: the number of elements found in the stream.
239  *
240  * See buf_cp_in() and buf_cp_out().
241  */
242 template< typename T >
243 Buf_in<T> buf_in(T *&v, unsigned long &size)
244 { return Buf_in<T>(v, size); }
245
246
247
248 /**
249  * \brief A receive item for receiving a single capability.
250  *
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.
255  */
256 class Small_buf
257 {
258 public:
259   explicit Small_buf(L4::Cap<L4::Kobject> cap, unsigned long flags = 0)
260   : _data(cap.cap() | L4_RCV_ITEM_SINGLE_CAP | flags) {}
261
262   explicit Small_buf(l4_cap_idx_t idx, unsigned long flags = 0)
263   : _data(idx | L4_RCV_ITEM_SINGLE_CAP | flags) {}
264 private:
265   l4_umword_t _data;
266 };
267
268 class Snd_item
269 {
270 public:
271   Snd_item(l4_umword_t base, l4_umword_t data) : _base(base), _data(data) {}
272
273 protected:
274   l4_umword_t _base;
275   l4_umword_t _data;
276 };
277
278 class Buf_item
279 {
280 public:
281   Buf_item(l4_umword_t base, l4_umword_t data) : _base(base), _data(data) {}
282
283 protected:
284   l4_umword_t _base;
285   l4_umword_t _data;
286 };
287
288 template< typename T >
289 class Gen_fpage : public T
290 {
291 public:
292   enum Type
293   {
294     Special = L4_FPAGE_SPECIAL << 4,
295     Memory  = L4_FPAGE_MEMORY << 4,
296     Io      = L4_FPAGE_IO << 4,
297     Obj     = L4_FPAGE_OBJ << 4
298   };
299
300   enum Map_type
301   {
302     Map   = L4_MAP_ITEM_MAP,
303     Grant = L4_MAP_ITEM_GRANT,
304   };
305
306   enum Cacheopt
307   {
308     None     = 0,
309     Cached   = L4_FPAGE_CACHEABLE << 4,
310     Buffered = L4_FPAGE_BUFFERABLE << 4,
311     Uncached = L4_FPAGE_UNCACHEABLE << 4
312   };
313
314   enum Continue
315   {
316     Single   = 0,
317     Last     = 0,
318     More     = L4_ITEM_CONT,
319     Compound = L4_ITEM_CONT,
320   };
321
322 private:
323   Gen_fpage(Type type, l4_addr_t base, int order,
324             unsigned char rights,
325             l4_addr_t snd_base,
326             Map_type map_type,
327             Cacheopt cache, Continue cont)
328   : T(L4_ITEM_MAP | (snd_base & (~0UL << 10)) | l4_umword_t(map_type) | l4_umword_t(cache)
329       | l4_umword_t(cont),
330       base | l4_umword_t(type) | rights | (l4_umword_t(order) << 6))
331   {}
332
333 public:
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)
339     | l4_umword_t(cont),
340     fp.raw)
341   {}
342
343   Gen_fpage(L4::Cap<void> cap, unsigned rights)
344   : T(L4_ITEM_MAP | Map | (rights & 0xf0), cap.fpage(rights).raw)
345   {}
346
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); }
366
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)); }
373
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
380   // receiving thread)
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; }
388 };
389
390
391 typedef Gen_fpage<Snd_item> Snd_fpage;
392 typedef Gen_fpage<Buf_item> Rcv_fpage;
393
394 #ifdef L4_CXX_IPC_SUPPORT_STRINGS
395 template <typename T, typename B>
396 class Gen_string : public T
397 {
398 public:
399   Gen_string() : T(0,0) {}
400   Gen_string(B buf, unsigned long size)
401   : T(size << 10, l4_umword_t(buf))
402   {}
403
404   unsigned long len() const { return T::_base >> 10; }
405 };
406
407 typedef Gen_string<Snd_item, void const *> Snd_string;
408 typedef Gen_string<Buf_item, void *> Rcv_string;
409 #endif
410
411
412 template< typename T, template <typename X> class B > struct Generic_va_type : public B<T>
413 {
414   enum { Id = B<T>::Id };
415   typedef B<T> ID;
416   typedef T const &Ret_value;
417   typedef T Value;
418
419   static Ret_value value(void const *d)
420   { return *reinterpret_cast<Value const *>(d); }
421
422   static void const *addr_of(Value const &v) { return &v; }
423
424   static unsigned size(void const *) { return sizeof(T); }
425
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; }
429 };
430
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 }; };
437
438 template< typename T > struct Va_type;
439
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> {};
443
444 template<> struct Va_type<void>
445 {
446   typedef void Ret_value;
447   typedef void Value;
448
449   static void const *addr_of(void) { return 0; }
450
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; }
454 };
455
456 template<> struct Va_type<char const *>
457 {
458   typedef char const *Ret_value;
459   typedef char const *Value;
460
461   static void const *addr_of(Value v) { return v; }
462
463   static L4_varg_type id() { return L4_VARG_TYPE_STRING; }
464   static unsigned size(void const *s)
465   {
466     char const *_s = reinterpret_cast<char const *>(s);
467     int l = 1;
468     while (*_s)
469       {
470         ++_s; ++l;
471       }
472     return l;
473   }
474
475   static Ret_value value(void const *d) { return (char const *)d; }
476 };
477
478
479 class Varg
480 {
481 private:
482   l4_umword_t _tag;
483   char const *_d;
484
485 public:
486
487   typedef l4_umword_t Tag;
488
489   L4_varg_type type() const { return (L4_varg_type)(_tag & 0xff); }
490   int length() const { return _tag >> 16; }
491
492   void tag(Tag tag) { _tag = tag; }
493   Tag tag() const { return _tag; }
494   void data(char const *d) { _d = d; }
495
496   char const *data() const { return _d; }
497   char const *&data() { return _d; }
498
499   Varg() : _tag(0), _d(0) {}
500
501   Varg(L4_varg_type t, void const  *v, int len)
502   : _tag(t | ((l4_mword_t)len << 16)), _d((char const *)v)
503   {}
504
505   template< typename V >
506   typename Va_type<V>::Ret_value value() const
507   { return Va_type<V>::value(_d); }
508
509
510   template< typename T >
511   bool is_of() const { return Va_type<T>::id() == type(); }
512
513   bool is_nil() const { return is_of<void>(); }
514
515   bool is_of_int() const
516   { return (type() & ~L4_VARG_TYPE_SIGN) == L4_VARG_TYPE_UMWORD; }
517
518   template< typename T >
519   bool get_value(typename Va_type<T>::Value *v) const
520   {
521     if (!is_of<T>())
522       return false;
523
524     *v = Va_type<T>::value(_d);
525     return true;
526   }
527
528   template< typename T >
529   void set_value(void const *d)
530   {
531     typedef Va_type<T> Vt;
532     _tag = Vt::id() | (Vt::size(d) << 16);
533     _d = (char const *)d;
534   }
535
536 };
537
538 template<typename T>
539 class Varg_t : public Varg
540 {
541 public:
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)); }
545
546 private:
547   Value _data;
548 };
549
550 namespace Utcb_stream_check
551 {
552   static bool check_utcb_data_offset(unsigned sz)
553   { return sz > sizeof(l4_umword_t) * L4_UTCB_GENERIC_DATA_SIZE; }
554 }
555
556
557 /**
558  * \brief Input stream for IPC unmarshalling.
559  * \ingroup ipc_fw
560  *
561  * Ipc::Istream is part of the dynamic IPC marshalling infrastructure, as well
562  * as Ipc::Ostream and Ipc::Iostream.
563  *
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 (>>).
567  *
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
570  * Msg_io_buffer).
571  */
572 class Istream
573 {
574 public:
575   /**
576    * \brief Create an input stream for the given message buffer.
577    *
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.
583    *
584    * \param msg The message buffer to receive IPC messages.
585    */
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)
590   {}
591
592   /**
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.
595    */
596   void reset()
597   {
598     _pos = 0;
599     _current_buf = 0;
600     _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
601   }
602
603   /**
604    * \brief Check whether a value of type T can be obtained from the stream.
605    */
606   template< typename T >
607   bool has_more()
608   {
609     unsigned apos = cxx::Type_traits<T>::align(_pos);
610     return apos + sizeof(T) <= _tag.words() * sizeof(l4_umword_t);
611   }
612
613   /**
614    * \name Get/Put Functions.
615    * These functions are basically used to implement the extraction operators
616    * (>>) and should not be called directly.
617    *
618    * See \link ipc_stream IPC stream operators \endlink.
619    */
620   //@{
621
622   /**
623    * \brief Copy out an array of type \a T with \a size elements.
624    *
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.
627    *
628    * See \link ipc_stream IPC stream operators \endlink.
629    */
630   template< typename T >
631   void get(T *buf, unsigned long size)
632   {
633     size *= sizeof(T);
634     _pos = cxx::Type_traits<T>::align(_pos);
635     if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
636       return;
637
638     __builtin_memcpy(buf, _current_msg + _pos, size);
639     _pos += size;
640   }
641
642
643   /**
644    * \brief Skip size elements of type T in the stream.
645    * \param size number of elements to skip.
646    */
647   template< typename T >
648   void skip(unsigned long size)
649   {
650     size *= sizeof(T);
651     _pos = cxx::Type_traits<T>::align(_pos);
652     if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
653       return;
654     _pos += size;
655   }
656
657   /**
658    * \brief Read one size elements of type T from the stream and return
659    *        a pointer.
660    *
661    * In contrast to a normal get, this version does actually not copy the data
662    * but returns a pointer to the data.
663    *
664    * \param buf a Msg_ptr that is actually set to point to the element in the
665    *            stream.
666    * \param size number of elements to extract (default is 1).
667    *
668    * See \link ipc_stream IPC stream operators \endlink.
669    */
670   template< typename T >
671   void get(Msg_ptr<T> const &buf, unsigned long size = 1)
672   {
673     size *= sizeof(T);
674     _pos = cxx::Type_traits<T>::align(_pos);
675     if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
676       return;
677
678     buf.set(reinterpret_cast<T*>(_current_msg + _pos));
679     _pos += size;
680   }
681
682
683   /**
684    * \brief Extract a single element of type T from the stream.
685    * \param v Output: the element.
686    *
687    * See \link ipc_stream IPC stream operators \endlink.
688    */
689   template< typename T >
690   void get(T &v)
691   {
692     _pos = cxx::Type_traits<T>::align(_pos);
693     if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
694       {
695         v = T();
696         return;
697       }
698     v = *(reinterpret_cast<T*>(_current_msg + _pos));
699     _pos += sizeof(T);
700   }
701
702
703   bool get(Ipc::Varg *va)
704   {
705     Ipc::Varg::Tag t;
706     if (!has_more<Ipc::Varg::Tag>())
707       {
708         va->tag(0);
709         return 0;
710       }
711     get(t);
712     va->tag(t);
713     get(msg_ptr(va->data()), va->length());
714
715     return 1;
716   }
717
718   /**
719    * \brief Get the message tag of a received IPC.
720    * \return The L4 message tag for the received IPC.
721    *
722    * This is in particular useful for handling page faults or exceptions.
723    *
724    * See \link ipc_stream IPC stream operators \endlink.
725    */
726   l4_msgtag_t tag() const { return _tag; }
727
728
729   /**
730    * \brief Get the message tag of a received IPC.
731    * \return A reference to the L4 message tag for the received IPC.
732    *
733    * This is in particular useful for handling page faults or exceptions.
734    *
735    * See \link ipc_stream IPC stream operators \endlink.
736    */
737   l4_msgtag_t &tag() { return _tag; }
738
739   //@}
740
741   /**
742    * \internal
743    * \brief Put a receive item into the stream's buffer registers.
744    */
745   inline bool put(Buf_item const &);
746
747   /**
748    * \internal
749    * \brief Put a small receive item into the stream's buffer registers.
750    */
751   inline bool put(Small_buf const &);
752
753
754   /**
755    * \name IPC operations.
756    */
757   //@{
758
759   /**
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).
763    *
764    * This wait is actually known as 'open wait'.
765    */
766   inline l4_msgtag_t wait(l4_umword_t *src)
767   { return wait(src, L4_IPC_NEVER); }
768
769   /**
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).
774    *
775    * This wait is actually known as 'open wait'.
776    */
777   inline l4_msgtag_t wait(l4_umword_t *src, l4_timeout_t timeout);
778
779   /**
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).
783    *
784    * This is commonly known as 'closed wait'.
785    */
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);
789
790   //@}
791
792   /**
793    * \brief Return utcb pointer.
794    */
795   inline l4_utcb_t *utcb() const { return _utcb; }
796
797 protected:
798   l4_msgtag_t _tag;
799   l4_utcb_t *_utcb;
800   char *_current_msg;
801   unsigned _pos;
802   unsigned char _current_buf;
803 };
804
805 class Istream_copy : public Istream
806 {
807 private:
808   l4_msg_regs_t _mrs;
809
810 public:
811   Istream_copy(Istream const &o) : Istream(o), _mrs(*l4_utcb_mr_u(o.utcb()))
812   {
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);
816   }
817
818 };
819
820 template< typename T >
821 inline
822 T read(Istream &s) { T t; s >> t; return t; }
823
824
825 /**
826  * \brief Output stream for IPC marshalling.
827  * \ingroup ipc_fw
828  *
829  * Ipc::Ostream is part of the dynamic IPC marshalling infrastructure, as well
830  * as Ipc::Istream and Ipc::Iostream.
831  *
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
835  * \endlink.
836  *
837  * There exist some special wrapper classes to insert arrays (see
838  * Ipc_buf_cp_out) and indirect strings (see Msg_out_buffer and
839  * Msg_io_buffer). */
840 class Ostream
841 {
842 public:
843   /**
844    * \brief Create an IPC output stream using the given message buffer \a msg.
845    */
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)
850   {}
851
852   /**
853    * \brief Reset the stream to empty, same state as a newly created stream.
854    */
855   void reset()
856   {
857     _pos = 0;
858     _current_item = 0;
859     _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
860   }
861
862   /**
863    * \name Get/Put functions.
864    *
865    * These functions are basically used to implement the insertion operators
866    * (<<) and should not be called directly.
867    *
868    * See \link ipc_stream IPC stream operators \endlink.
869    */
870   //@{
871
872   /**
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.
876    */
877   template< typename T >
878   void put(T *buf, unsigned long size)
879   {
880     size *= sizeof(T);
881     _pos = cxx::Type_traits<T>::align(_pos);
882     if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
883       return;
884
885     __builtin_memcpy(_current_msg + _pos, buf, size);
886     _pos += size;
887   }
888
889   /**
890    * \brief Insert an element of type \a T into the stream.
891    * \param v The element to insert.
892    */
893   template< typename T >
894   void put(T const &v)
895   {
896     _pos = cxx::Type_traits<T>::align(_pos);
897     if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
898       return;
899
900     *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
901     _pos += sizeof(T);
902   }
903
904   int put(Varg const &va)
905   {
906     put(va.tag());
907     put(va.data(), va.length());
908
909     return 0;
910   }
911
912   template< typename T >
913   int put(Varg_t<T> const &va)
914   { return put(static_cast<Varg const &>(va)); }
915
916   /**
917    * \brief Extract the L4 message tag from the stream.
918    * \return the extracted L4 message tag.
919    */
920   l4_msgtag_t tag() const { return _tag; }
921
922   /**
923    * \brief Extract a reference to the L4 message tag from the stream.
924    * \return A reference to the L4 message tag.
925    */
926   l4_msgtag_t &tag() { return _tag; }
927
928   //@}
929
930   /**
931    * \internal
932    * \brief Put a send item into the stream's message buffer.
933    */
934   inline bool put_snd_item(Snd_item const &);
935
936
937   /**
938    * \name IPC operations.
939    */
940   //@{
941
942   /**
943    * \brief Send the message via IPC to the given receiver.
944    * \param dst The destination for the message.
945    */
946   inline l4_msgtag_t send(l4_cap_idx_t dst, long proto = 0, unsigned flags = 0);
947
948   //@}
949
950   /**
951    * \brief Return utcb pointer.
952    */
953   inline l4_utcb_t *utcb() const { return _utcb; }
954 #if 0
955   /**
956    * \brief Get the currently used bytes in the stream.
957    */
958   unsigned long tell() const
959   {
960     register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
961     w -= _current_item * 2;
962     _tag = l4_msgtag(0, w, _current_item, 0);
963   }
964 #endif
965 public:
966   l4_msgtag_t prepare_ipc(long proto = 0, unsigned flags = 0)
967   {
968     register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
969     w -= _current_item * 2;
970     return l4_msgtag(proto, w, _current_item, flags);
971   }
972
973 protected:
974   l4_msgtag_t _tag;
975   l4_utcb_t *_utcb;
976   char *_current_msg;
977   unsigned _pos;
978   unsigned char _current_item;
979 };
980
981
982 /**
983  * \brief Input/Output stream for IPC [un]marshalling.
984  * \ingroup ipc_fw
985  *
986  * The Ipc::Iostream is part of the AW Env IPC framework as well as
987  * Ipc::Istream and Ipc::Ostream.
988  * In particular an Ipc::Iostream is a combination of an Ipc::Istream and an
989  * Ipc::Ostream. It can use either a single message buffer for receiving and
990  * sending messages or a pair of a receive and a send buffer. The stream also
991  * supports combined IPC operations such as call() and reply_and_wait(), which
992  * can be used to implement RPC functionality.
993  */
994 class Iostream : public Istream, public Ostream
995 {
996 public:
997
998   /**
999    * \brief Create an IPC IO stream with a single message buffer.
1000    * \param msg The message buffer used as backing store.
1001    *
1002    * The created IO stream uses the same message buffer for sending and
1003    * receiving IPC messages.
1004    */
1005   explicit Iostream(l4_utcb_t *utcb)
1006   : Istream(utcb), Ostream(utcb)
1007   {}
1008
1009
1010   /**
1011    * \brief Reset the stream to its initial state.
1012    *
1013    * Input as well as the output stream are reset.
1014    */
1015   void reset()
1016   {
1017     Istream::reset();
1018     Ostream::reset();
1019   }
1020
1021
1022   /**
1023    * \name Get/Put functions.
1024    *
1025    * These functions are basically used to implement the insertion operators
1026    * (<<) and should not be called directly.
1027    *
1028    * See \link ipc_stream IPC stream operators \endlink.
1029    */
1030   //@{
1031
1032   using Istream::get;
1033   using Istream::put;
1034   using Ostream::put;
1035
1036   //@}
1037
1038   /**
1039    * \name IPC operations.
1040    */
1041   //@{
1042
1043   /**
1044    * \brief Do an IPC call using the message in the output stream and
1045    *        receiving to the input stream.
1046    * \param dst The destination L4 UID (thread) to call.
1047    * \return the result dope of the IPC operation.
1048    *
1049    * This is a combined IPC operation consisting of a send and a receive
1050    * to/from the given destination \a dst.
1051    *
1052    * A call is usually used by clients for RPCs to a server.
1053    *
1054    */
1055   inline l4_msgtag_t call(l4_cap_idx_t dst);
1056   inline l4_msgtag_t call(l4_cap_idx_t dst, long label);
1057
1058   /**
1059    * \brief Do an IPC reply and wait.
1060    * \param src_dst Input: the destination for the send operation. <br>
1061    *                Output: the source of the received message.
1062    * \return the result dope of the IPC operation.
1063    *
1064    * This is a combined IPC operation consisting of a send operation and
1065    * an open wait for any message.
1066    *
1067    * A reply and wait is usually used by servers that reply to a client
1068    * and wait for the next request by any other client.
1069    */
1070   inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst, long proto = 0)
1071   { return reply_and_wait(src_dst, L4_IPC_SEND_TIMEOUT_0, proto); }
1072
1073   inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1074                                    long proto = 0)
1075   { return send_and_wait(dest, src, L4_IPC_SEND_TIMEOUT_0, proto); }
1076
1077   /**
1078    * \brief Do an IPC reply and wait.
1079    * \param src_dst Input: the destination for the send operation. <br>
1080    *                Output: the source of the received message.
1081    * \param timeout Timeout used for IPC.
1082    * \return the result dope of the IPC operation.
1083    *
1084    * This is a combined IPC operation consisting of a send operation and
1085    * an open wait for any message.
1086    *
1087    * A reply and wait is usually used by servers that reply to a client
1088    * and wait for the next request by any other client.
1089    */
1090   inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst,
1091                                     l4_timeout_t timeout, long proto = 0);
1092   inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1093                                    l4_timeout_t timeout, long proto = 0);
1094   inline l4_msgtag_t reply(l4_timeout_t timeout, long proto = 0);
1095   inline l4_msgtag_t reply(long proto = 0)
1096   { return reply(L4_IPC_SEND_TIMEOUT_0, proto); }
1097
1098   //@}
1099 };
1100
1101
1102 inline bool
1103 Ostream::put_snd_item(Snd_item const &v)
1104 {
1105   typedef Snd_item T;
1106   _pos = cxx::Type_traits<Snd_item>::align(_pos);
1107   if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
1108     return false;
1109
1110   *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
1111   _pos += sizeof(T);
1112   ++_current_item;
1113   return true;
1114 }
1115
1116
1117 inline bool
1118 Istream::put(Buf_item const &item)
1119 {
1120   if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 3)
1121     return false;
1122
1123   l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1124
1125   reinterpret_cast<Buf_item&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1126   _current_buf += 2;
1127   return true;
1128 }
1129
1130
1131 inline bool
1132 Istream::put(Small_buf const &item)
1133 {
1134   if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 2)
1135     return false;
1136
1137   l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1138
1139   reinterpret_cast<Small_buf&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1140   _current_buf += 1;
1141   return true;
1142 }
1143
1144
1145 inline l4_msgtag_t
1146 Ostream::send(l4_cap_idx_t dst, long proto, unsigned flags)
1147 {
1148   l4_msgtag_t tag = prepare_ipc(proto, L4_MSGTAG_FLAGS & flags);
1149   return l4_ipc_send(dst, _utcb, tag, L4_IPC_NEVER);
1150 }
1151
1152 inline l4_msgtag_t
1153 Iostream::call(l4_cap_idx_t dst)
1154 {
1155   l4_msgtag_t tag = prepare_ipc();
1156   tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER);
1157   Istream::tag() = tag;
1158   Istream::_pos = 0;
1159   return tag;
1160 }
1161
1162 inline l4_msgtag_t
1163 Iostream::call(l4_cap_idx_t dst, long label)
1164 {
1165   l4_msgtag_t tag = prepare_ipc(label);
1166   tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER);
1167   Istream::tag() = tag;
1168   Istream::_pos = 0;
1169   return tag;
1170 }
1171
1172
1173 inline l4_msgtag_t
1174 Iostream::reply_and_wait(l4_umword_t *src_dst, l4_timeout_t timeout, long proto)
1175 {
1176   l4_msgtag_t tag = prepare_ipc(proto);
1177   tag = l4_ipc_reply_and_wait(Ostream::_utcb, tag, src_dst, timeout);
1178   Istream::tag() = tag;
1179   Istream::_pos = 0;
1180   return tag;
1181 }
1182
1183
1184 inline l4_msgtag_t
1185 Iostream::send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1186                         l4_timeout_t timeout, long proto)
1187 {
1188   l4_msgtag_t tag = prepare_ipc(proto);
1189   tag = l4_ipc_send_and_wait(dest, Ostream::_utcb, tag, src, timeout);
1190   Istream::tag() = tag;
1191   Istream::_pos = 0;
1192   return tag;
1193 }
1194
1195 inline l4_msgtag_t
1196 Iostream::reply(l4_timeout_t timeout, long proto)
1197 {
1198   l4_msgtag_t tag = prepare_ipc(proto);
1199   tag = l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, Ostream::_utcb, tag, timeout);
1200   Istream::tag() = tag;
1201   Istream::_pos = 0;
1202   return tag;
1203 }
1204
1205 inline l4_msgtag_t
1206 Istream::wait(l4_umword_t *src, l4_timeout_t timeout)
1207 {
1208   l4_msgtag_t res;
1209   res = l4_ipc_wait(_utcb, src, timeout);
1210   tag() = res;
1211   _pos = 0;
1212   return res;
1213 }
1214
1215
1216 inline l4_msgtag_t
1217 Istream::receive(l4_cap_idx_t src, l4_timeout_t timeout)
1218 {
1219   l4_msgtag_t res;
1220   res = l4_ipc_receive(src, _utcb, timeout);
1221   tag() = res;
1222   _pos = 0;
1223   return res;
1224 }
1225
1226 };
1227
1228 } // namespace Ipc
1229
1230 /**
1231  * \brief Extract one element of type \a T from the stream \a s.
1232  * \ingroup ipc_stream
1233  * \param s The stream to extract from.
1234  * \param v Output: extracted value.
1235  * \return the stream \a s.
1236  */
1237 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, bool &v) { s.get(v); return s; }
1238 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, int &v) { s.get(v); return s; }
1239 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long int &v) { s.get(v); return s; }
1240 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long long int &v) { s.get(v); return s; }
1241 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned int &v) { s.get(v); return s; }
1242 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long int &v) { s.get(v); return s; }
1243 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long long int &v) { s.get(v); return s; }
1244 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, short int &v) { s.get(v); return s; }
1245 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned short int &v) { s.get(v); return s; }
1246 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, char &v) { s.get(v); return s; }
1247 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned char &v) { s.get(v); return s; }
1248 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, signed char &v) { s.get(v); return s; }
1249 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Buf_item const &v) { s.put(v); return s; }
1250 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Small_buf const &v) { s.put(v); return s; }
1251 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Snd_item &v)
1252 {
1253   l4_umword_t b, d;
1254   s >> b >> d;
1255   v = L4::Ipc::Snd_item(b,d);
1256   return s;
1257 }
1258 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Varg &v)
1259 { s.get(&v); return s; }
1260
1261
1262 /**
1263  * \brief Extract the L4 message tag from the stream \a s.
1264  * \ingroup ipc_stream
1265  * \param s The stream to extract from.
1266  * \param v Output: the extracted tag.
1267  * \return the stream \a s.
1268  */
1269 inline
1270 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, l4_msgtag_t &v)
1271 {
1272   v = s.tag();
1273   return s;
1274 }
1275
1276 /**
1277  * \brief Extract an array of \a T elements from the stream \a s.
1278  * \ingroup ipc_stream
1279  *
1280  * This operator actually does not copy out the data in the array, but
1281  * returns a pointer into the message buffer itself. This means that the
1282  * data is only valid as long as there is no new data inserted into the stream.
1283  *
1284  * See Ipc_buf_in, Ipc_bufcp_in, and Ipc_buf_cp_out.
1285  *
1286  * \param s The stream to extract from.
1287  * \param v Output: pointer to the extracted array (ipc_buf_in()).
1288  * \return the stream \a s.
1289  */
1290 template< typename T >
1291 inline
1292 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1293     L4::Ipc::Buf_in<T> const &v)
1294 {
1295   unsigned long si;
1296   s.get(si);
1297   v.set_size(si);
1298   s.get(L4::Ipc::Msg_ptr<T>(v.buf()), si);
1299   return s;
1300 }
1301
1302 /**
1303  * \brief Extract an element of type \a T from the stream \a s.
1304  * \ingroup ipc_stream
1305  *
1306  * This operator actually does not copy out the data, but
1307  * returns a pointer into the message buffer itself. This means that the
1308  * data is only valid as long as there is no new data inserted into the stream.
1309  *
1310  * See Msg_ptr.
1311  *
1312  * \param s The stream to extract from.
1313  * \param v Output: pointer to the extracted element.
1314  * \return the stream \a s.
1315  */
1316 template< typename T >
1317 inline
1318 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1319     L4::Ipc::Msg_ptr<T> const &v)
1320 {
1321   s.get(v);
1322   return s;
1323 }
1324
1325 /**
1326  * \brief Extract an array of \a T elements from the stream \a s.
1327  * \ingroup ipc_stream
1328  *
1329  * This operator does a copy out of the data into the given buffer.
1330  *
1331  * See Ipc_buf_in, Ipc_bufcp_in, and Ipc_buf_cp_out.
1332  *
1333  * \param s The stream to extract from.
1334  * \param v buffer description to copy the array to (ipc_buf_cp_out()).
1335  * \return the stream \a s.
1336  */
1337 template< typename T >
1338 inline
1339 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1340     L4::Ipc::Buf_cp_in<T> const &v)
1341 {
1342   s.get(v.size());
1343   s.get(v.buf(), v.size());
1344   return s;
1345 }
1346
1347
1348 /**
1349  * \brief Insert an element to type \a T into the stream \a s.
1350  * \ingroup ipc_stream
1351  *
1352  * \param s The stream to insert the element \a v.
1353  * \param v The element to insert.
1354  * \return the stream \a s.
1355  */
1356 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, bool v) { s.put(v); return s; }
1357 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, int v) { s.put(v); return s; }
1358 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long int v) { s.put(v); return s; }
1359 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long long int v) { s.put(v); return s; }
1360 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned int v) { s.put(v); return s; }
1361 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long int v) { s.put(v); return s; }
1362 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long long int v) { s.put(v); return s; }
1363 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, short int v) { s.put(v); return s; }
1364 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned short int v) { s.put(v); return s; }
1365 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char v) { s.put(v); return s; }
1366 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned char v) { s.put(v); return s; }
1367 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, signed char v) { s.put(v); return s; }
1368 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Snd_item const &v) { s.put_snd_item(v); return s; }
1369 template< typename T >
1370 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Cap<T> const &v)
1371 { s << L4::Ipc::Snd_fpage(v.fpage()); return s; }
1372
1373 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg const &v)
1374 { s.put(v); return s; }
1375 template< typename T >
1376 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg_t<T> const &v)
1377 { s.put(v); return s; }
1378
1379 /**
1380  * \brief Insert the L4 message tag into the stream \a s.
1381  * \ingroup ipc_stream
1382  *
1383  * \note Only one message tag can be inserted into a stream. Multiple
1384  *       insertions simply overwrite previous insertions.
1385  * \param s The stream to insert the tag \a v.
1386  * \param v The L4 message tag to insert.
1387  * \return the stream \a s.
1388  */
1389 inline
1390 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, l4_msgtag_t const &v)
1391 {
1392   s.tag() = v;
1393   return s;
1394 }
1395
1396 /**
1397  * \brief Insert an array with elements of type \a T into the stream \a s.
1398  * \ingroup ipc_stream
1399  *
1400  * \param s The stream to insert the array \a v.
1401  * \param v The array to insert (see ipc_buf_cp_out()).
1402  * \return the stream \a s.
1403  */
1404 template< typename T >
1405 inline
1406 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s,
1407     L4::Ipc::Buf_cp_out<T> const &v)
1408 {
1409   s.put(v.size());
1410   s.put(v.buf(), v.size());
1411   return s;
1412 }
1413
1414 /**
1415  * \brief Insert a zero terminated character string into the stream \a s.
1416  * \ingroup ipc_stream
1417  *
1418  * \param s The stream to insert the string \a v.
1419  * \param v The string to insert.
1420  * \return the stream \a s.
1421  *
1422  * This operator produces basically the same content as the array insertion,
1423  * however the length of the array is calculated using <c> strlen(\a v) + 1
1424  * </c>. The string is copied into the message including the trailing zero.
1425  */
1426 inline
1427 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char const *v)
1428 {
1429   unsigned long l = __builtin_strlen(v) + 1;
1430   s.put(l);
1431   s.put(v, l);
1432   return s;
1433 }
1434
1435
1436 #ifdef L4_CXX_IPC_BACKWARD_COMPAT
1437 namespace L4 {
1438
1439 template< typename T > class Ipc_buf_cp_out : public Ipc::Buf_cp_out<T> {};
1440 template< typename T > class Ipc_buf_cp_in : public Ipc::Buf_cp_in<T> {};
1441 template< typename T > class Ipc_buf_in : public Ipc::Buf_in<T> {};
1442 template< typename T > class Msg_ptr : public Ipc::Msg_ptr<T> {};
1443
1444 template< typename T >
1445 Ipc::Buf_cp_out<T> ipc_buf_cp_out(T *v, unsigned long size)
1446 { return Ipc::Buf_cp_out<T>(v,size); }
1447
1448 template< typename T >
1449 Ipc::Buf_cp_in<T> ipc_buf_cp_in(T *v, unsigned long &size)
1450 { return Ipc::Buf_cp_in<T>(v,size); }
1451
1452 template< typename T >
1453 Ipc::Buf_in<T> ipc_buf_in(T *&v, unsigned long &size)
1454 { return Ipc::Buf_in<T>(v, size); }
1455
1456 template< typename T >
1457 Ipc::Msg_ptr<T> msg_ptr(T *&p)
1458 { return Ipc::Msg_ptr<T>(p); }
1459
1460 typedef Ipc::Istream Ipc_istream;
1461 typedef Ipc::Ostream Ipc_ostream;
1462 typedef Ipc::Iostream Ipc_iostream;
1463 typedef Ipc::Snd_fpage Snd_fpage;
1464 typedef Ipc::Rcv_fpage Rcv_fpage;
1465 typedef Ipc::Small_buf Small_buf;
1466
1467 }
1468 #endif
1469