]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/cxx/lib/ipc/include/ipc_stream
d1db894b1e9d83d839f7497b90da5f0c108a72d0
[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   unsigned long get(T *buf, unsigned long elems)
632   {
633     unsigned long size = elems * sizeof(T);
634     _pos = cxx::Type_traits<T>::align(_pos);
635     if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
636       return 0;
637
638     __builtin_memcpy(buf, _current_msg + _pos, size);
639     _pos += size;
640     return elems;
641   }
642
643
644   /**
645    * \brief Skip size elements of type T in the stream.
646    * \param size number of elements to skip.
647    */
648   template< typename T >
649   void skip(unsigned long size)
650   {
651     size *= sizeof(T);
652     _pos = cxx::Type_traits<T>::align(_pos);
653     if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
654       return;
655     _pos += size;
656   }
657
658   /**
659    * \brief Read one size elements of type T from the stream and return
660    *        a pointer.
661    *
662    * In contrast to a normal get, this version does actually not copy the data
663    * but returns a pointer to the data.
664    *
665    * \param buf a Msg_ptr that is actually set to point to the element in the
666    *            stream.
667    * \param size number of elements to extract (default is 1).
668    *
669    * See \link ipc_stream IPC stream operators \endlink.
670    */
671   template< typename T >
672   unsigned long get(Msg_ptr<T> const &buf, unsigned long size = 1)
673   {
674     size *= sizeof(T);
675     _pos = cxx::Type_traits<T>::align(_pos);
676     if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
677       return 0;
678
679     buf.set(reinterpret_cast<T*>(_current_msg + _pos));
680     _pos += size;
681     return size;
682   }
683
684
685   /**
686    * \brief Extract a single element of type T from the stream.
687    * \param v Output: the element.
688    *
689    * See \link ipc_stream IPC stream operators \endlink.
690    */
691   template< typename T >
692   void get(T &v)
693   {
694     _pos = cxx::Type_traits<T>::align(_pos);
695     if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
696       {
697         v = T();
698         return;
699       }
700     v = *(reinterpret_cast<T*>(_current_msg + _pos));
701     _pos += sizeof(T);
702   }
703
704
705   bool get(Ipc::Varg *va)
706   {
707     Ipc::Varg::Tag t;
708     if (!has_more<Ipc::Varg::Tag>())
709       {
710         va->tag(0);
711         return 0;
712       }
713     get(t);
714     va->tag(t);
715     get(msg_ptr(va->data()), va->length());
716
717     return 1;
718   }
719
720   /**
721    * \brief Get the message tag of a received IPC.
722    * \return The L4 message tag for the received IPC.
723    *
724    * This is in particular useful for handling page faults or exceptions.
725    *
726    * See \link ipc_stream IPC stream operators \endlink.
727    */
728   l4_msgtag_t tag() const { return _tag; }
729
730
731   /**
732    * \brief Get the message tag of a received IPC.
733    * \return A reference to the L4 message tag for the received IPC.
734    *
735    * This is in particular useful for handling page faults or exceptions.
736    *
737    * See \link ipc_stream IPC stream operators \endlink.
738    */
739   l4_msgtag_t &tag() { return _tag; }
740
741   //@}
742
743   /**
744    * \internal
745    * \brief Put a receive item into the stream's buffer registers.
746    */
747   inline bool put(Buf_item const &);
748
749   /**
750    * \internal
751    * \brief Put a small receive item into the stream's buffer registers.
752    */
753   inline bool put(Small_buf const &);
754
755
756   /**
757    * \name IPC operations.
758    */
759   //@{
760
761   /**
762    * \brief Wait for an incoming message from any sender.
763    * \param src contains the sender after a successful IPC operation.
764    * \return The IPC result dope (l4_msgtag_t).
765    *
766    * This wait is actually known as 'open wait'.
767    */
768   inline l4_msgtag_t wait(l4_umword_t *src)
769   { return wait(src, L4_IPC_NEVER); }
770
771   /**
772    * \brief Wait for an incoming message from any sender.
773    * \param src contains the sender after a successful IPC operation.
774    * \param timeout Timeout used for IPC.
775    * \return The IPC result dope (l4_msgtag_t).
776    *
777    * This wait is actually known as 'open wait'.
778    */
779   inline l4_msgtag_t wait(l4_umword_t *src, l4_timeout_t timeout);
780
781   /**
782    * \brief Wait for a message from the specified sender.
783    * \param src The sender id to receive from.
784    * \return The IPC  result dope (l4_msgtag_t).
785    *
786    * This is commonly known as 'closed wait'.
787    */
788   inline l4_msgtag_t receive(l4_cap_idx_t src)
789   { return receive(src, L4_IPC_NEVER); }
790   inline l4_msgtag_t receive(l4_cap_idx_t src, l4_timeout_t timeout);
791
792   //@}
793
794   /**
795    * \brief Return utcb pointer.
796    */
797   inline l4_utcb_t *utcb() const { return _utcb; }
798
799 protected:
800   l4_msgtag_t _tag;
801   l4_utcb_t *_utcb;
802   char *_current_msg;
803   unsigned _pos;
804   unsigned char _current_buf;
805 };
806
807 class Istream_copy : public Istream
808 {
809 private:
810   l4_msg_regs_t _mrs;
811
812 public:
813   Istream_copy(Istream const &o) : Istream(o), _mrs(*l4_utcb_mr_u(o.utcb()))
814   {
815     // do some reverse mr to utcb trickery
816     _utcb = (l4_utcb_t*)((l4_addr_t)&_mrs - (l4_addr_t)l4_utcb_mr_u((l4_utcb_t*)0));
817     _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
818   }
819
820 };
821
822 template< typename T >
823 inline
824 T read(Istream &s) { T t; s >> t; return t; }
825
826
827 /**
828  * \brief Output stream for IPC marshalling.
829  * \ingroup ipc_fw
830  *
831  * Ipc::Ostream is part of the dynamic IPC marshalling infrastructure, as well
832  * as Ipc::Istream and Ipc::Iostream.
833  *
834  * Ipc::Ostream is an output stream supporting insertion of values into an
835  * IPC message buffer. A IPC message can be marshalled using the
836  * usual insertion operator <<, see \link ipc_stream IPC stream operators
837  * \endlink.
838  *
839  * There exist some special wrapper classes to insert arrays (see
840  * Ipc::Buf_cp_out) and indirect strings (see Msg_out_buffer and
841  * Msg_io_buffer). */
842 class Ostream
843 {
844 public:
845   /**
846    * \brief Create an IPC output stream using the given message buffer \a msg.
847    */
848   Ostream(l4_utcb_t *utcb)
849   : _tag(), _utcb(utcb),
850     _current_msg(reinterpret_cast<char *>(l4_utcb_mr_u(_utcb)->mr)),
851     _pos(0), _current_item(0)
852   {}
853
854   /**
855    * \brief Reset the stream to empty, same state as a newly created stream.
856    */
857   void reset()
858   {
859     _pos = 0;
860     _current_item = 0;
861     _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
862   }
863
864   /**
865    * \name Get/Put functions.
866    *
867    * These functions are basically used to implement the insertion operators
868    * (<<) and should not be called directly.
869    *
870    * See \link ipc_stream IPC stream operators \endlink.
871    */
872   //@{
873
874   /**
875    * \brief Put an array with \a size elements of type \a T into the stream.
876    * \param buf A pointer to the array to insert into the buffer.
877    * \param size The number of elements in the array.
878    */
879   template< typename T >
880   void put(T *buf, unsigned long size)
881   {
882     size *= sizeof(T);
883     _pos = cxx::Type_traits<T>::align(_pos);
884     if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
885       return;
886
887     __builtin_memcpy(_current_msg + _pos, buf, size);
888     _pos += size;
889   }
890
891   /**
892    * \brief Insert an element of type \a T into the stream.
893    * \param v The element to insert.
894    */
895   template< typename T >
896   bool put(T const &v)
897   {
898     _pos = cxx::Type_traits<T>::align(_pos);
899     if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
900       return false;
901
902     *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
903     _pos += sizeof(T);
904     return true;
905   }
906
907   int put(Varg const &va)
908   {
909     put(va.tag());
910     put(va.data(), va.length());
911
912     return 0;
913   }
914
915   template< typename T >
916   int put(Varg_t<T> const &va)
917   { return put(static_cast<Varg const &>(va)); }
918
919   /**
920    * \brief Extract the L4 message tag from the stream.
921    * \return the extracted L4 message tag.
922    */
923   l4_msgtag_t tag() const { return _tag; }
924
925   /**
926    * \brief Extract a reference to the L4 message tag from the stream.
927    * \return A reference to the L4 message tag.
928    */
929   l4_msgtag_t &tag() { return _tag; }
930
931   //@}
932
933   /**
934    * \internal
935    * \brief Put a send item into the stream's message buffer.
936    */
937   inline bool put_snd_item(Snd_item const &);
938
939
940   /**
941    * \name IPC operations.
942    */
943   //@{
944
945   /**
946    * \brief Send the message via IPC to the given receiver.
947    * \param dst The destination for the message.
948    */
949   inline l4_msgtag_t send(l4_cap_idx_t dst, long proto = 0, unsigned flags = 0);
950
951   //@}
952
953   /**
954    * \brief Return utcb pointer.
955    */
956   inline l4_utcb_t *utcb() const { return _utcb; }
957 #if 0
958   /**
959    * \brief Get the currently used bytes in the stream.
960    */
961   unsigned long tell() const
962   {
963     register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
964     w -= _current_item * 2;
965     _tag = l4_msgtag(0, w, _current_item, 0);
966   }
967 #endif
968 public:
969   l4_msgtag_t prepare_ipc(long proto = 0, unsigned flags = 0)
970   {
971     register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
972     w -= _current_item * 2;
973     return l4_msgtag(proto, w, _current_item, flags);
974   }
975
976 protected:
977   l4_msgtag_t _tag;
978   l4_utcb_t *_utcb;
979   char *_current_msg;
980   unsigned _pos;
981   unsigned char _current_item;
982 };
983
984
985 /**
986  * \brief Input/Output stream for IPC [un]marshalling.
987  * \ingroup ipc_fw
988  *
989  * The Ipc::Iostream is part of the AW Env IPC framework as well as
990  * Ipc::Istream and Ipc::Ostream.
991  * In particular an Ipc::Iostream is a combination of an Ipc::Istream and an
992  * Ipc::Ostream. It can use either a single message buffer for receiving and
993  * sending messages or a pair of a receive and a send buffer. The stream also
994  * supports combined IPC operations such as call() and reply_and_wait(), which
995  * can be used to implement RPC functionality.
996  */
997 class Iostream : public Istream, public Ostream
998 {
999 public:
1000
1001   /**
1002    * \brief Create an IPC IO stream with a single message buffer.
1003    * \param msg The message buffer used as backing store.
1004    *
1005    * The created IO stream uses the same message buffer for sending and
1006    * receiving IPC messages.
1007    */
1008   explicit Iostream(l4_utcb_t *utcb)
1009   : Istream(utcb), Ostream(utcb)
1010   {}
1011
1012
1013   /**
1014    * \brief Reset the stream to its initial state.
1015    *
1016    * Input as well as the output stream are reset.
1017    */
1018   void reset()
1019   {
1020     Istream::reset();
1021     Ostream::reset();
1022   }
1023
1024
1025   /**
1026    * \name Get/Put functions.
1027    *
1028    * These functions are basically used to implement the insertion operators
1029    * (<<) and should not be called directly.
1030    *
1031    * See \link ipc_stream IPC stream operators \endlink.
1032    */
1033   //@{
1034
1035   using Istream::get;
1036   using Istream::put;
1037   using Ostream::put;
1038
1039   //@}
1040
1041   /**
1042    * \name IPC operations.
1043    */
1044   //@{
1045
1046   /**
1047    * \brief Do an IPC call using the message in the output stream and
1048    *        receiving to the input stream.
1049    * \param dst The destination L4 UID (thread) to call.
1050    * \return the result dope of the IPC operation.
1051    *
1052    * This is a combined IPC operation consisting of a send and a receive
1053    * to/from the given destination \a dst.
1054    *
1055    * A call is usually used by clients for RPCs to a server.
1056    *
1057    */
1058   inline l4_msgtag_t call(l4_cap_idx_t dst);
1059   inline l4_msgtag_t call(l4_cap_idx_t dst, long label);
1060
1061   /**
1062    * \brief Do an IPC reply and wait.
1063    * \param src_dst Input: the destination for the send operation. <br>
1064    *                Output: the source of the received message.
1065    * \return the result dope of the IPC operation.
1066    *
1067    * This is a combined IPC operation consisting of a send operation and
1068    * an open wait for any message.
1069    *
1070    * A reply and wait is usually used by servers that reply to a client
1071    * and wait for the next request by any other client.
1072    */
1073   inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst, long proto = 0)
1074   { return reply_and_wait(src_dst, L4_IPC_SEND_TIMEOUT_0, proto); }
1075
1076   inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1077                                    long proto = 0)
1078   { return send_and_wait(dest, src, L4_IPC_SEND_TIMEOUT_0, proto); }
1079
1080   /**
1081    * \brief Do an IPC reply and wait.
1082    * \param src_dst Input: the destination for the send operation. <br>
1083    *                Output: the source of the received message.
1084    * \param timeout Timeout used for IPC.
1085    * \return the result dope of the IPC operation.
1086    *
1087    * This is a combined IPC operation consisting of a send operation and
1088    * an open wait for any message.
1089    *
1090    * A reply and wait is usually used by servers that reply to a client
1091    * and wait for the next request by any other client.
1092    */
1093   inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst,
1094                                     l4_timeout_t timeout, long proto = 0);
1095   inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1096                                    l4_timeout_t timeout, long proto = 0);
1097   inline l4_msgtag_t reply(l4_timeout_t timeout, long proto = 0);
1098   inline l4_msgtag_t reply(long proto = 0)
1099   { return reply(L4_IPC_SEND_TIMEOUT_0, proto); }
1100
1101   //@}
1102 };
1103
1104
1105 inline bool
1106 Ostream::put_snd_item(Snd_item const &v)
1107 {
1108   typedef Snd_item T;
1109   _pos = cxx::Type_traits<Snd_item>::align(_pos);
1110   if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
1111     return false;
1112
1113   *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
1114   _pos += sizeof(T);
1115   ++_current_item;
1116   return true;
1117 }
1118
1119
1120 inline bool
1121 Istream::put(Buf_item const &item)
1122 {
1123   if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 3)
1124     return false;
1125
1126   l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1127
1128   reinterpret_cast<Buf_item&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1129   _current_buf += 2;
1130   return true;
1131 }
1132
1133
1134 inline bool
1135 Istream::put(Small_buf const &item)
1136 {
1137   if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 2)
1138     return false;
1139
1140   l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
1141
1142   reinterpret_cast<Small_buf&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
1143   _current_buf += 1;
1144   return true;
1145 }
1146
1147
1148 inline l4_msgtag_t
1149 Ostream::send(l4_cap_idx_t dst, long proto, unsigned flags)
1150 {
1151   l4_msgtag_t tag = prepare_ipc(proto, L4_MSGTAG_FLAGS & flags);
1152   return l4_ipc_send(dst, _utcb, tag, L4_IPC_NEVER);
1153 }
1154
1155 inline l4_msgtag_t
1156 Iostream::call(l4_cap_idx_t dst)
1157 {
1158   l4_msgtag_t tag = prepare_ipc();
1159   tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER);
1160   Istream::tag() = tag;
1161   Istream::_pos = 0;
1162   return tag;
1163 }
1164
1165 inline l4_msgtag_t
1166 Iostream::call(l4_cap_idx_t dst, long label)
1167 {
1168   l4_msgtag_t tag = prepare_ipc(label);
1169   tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER);
1170   Istream::tag() = tag;
1171   Istream::_pos = 0;
1172   return tag;
1173 }
1174
1175
1176 inline l4_msgtag_t
1177 Iostream::reply_and_wait(l4_umword_t *src_dst, l4_timeout_t timeout, long proto)
1178 {
1179   l4_msgtag_t tag = prepare_ipc(proto);
1180   tag = l4_ipc_reply_and_wait(Ostream::_utcb, tag, src_dst, timeout);
1181   Istream::tag() = tag;
1182   Istream::_pos = 0;
1183   return tag;
1184 }
1185
1186
1187 inline l4_msgtag_t
1188 Iostream::send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
1189                         l4_timeout_t timeout, long proto)
1190 {
1191   l4_msgtag_t tag = prepare_ipc(proto);
1192   tag = l4_ipc_send_and_wait(dest, Ostream::_utcb, tag, src, timeout);
1193   Istream::tag() = tag;
1194   Istream::_pos = 0;
1195   return tag;
1196 }
1197
1198 inline l4_msgtag_t
1199 Iostream::reply(l4_timeout_t timeout, long proto)
1200 {
1201   l4_msgtag_t tag = prepare_ipc(proto);
1202   tag = l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, Ostream::_utcb, tag, timeout);
1203   Istream::tag() = tag;
1204   Istream::_pos = 0;
1205   return tag;
1206 }
1207
1208 inline l4_msgtag_t
1209 Istream::wait(l4_umword_t *src, l4_timeout_t timeout)
1210 {
1211   l4_msgtag_t res;
1212   res = l4_ipc_wait(_utcb, src, timeout);
1213   tag() = res;
1214   _pos = 0;
1215   return res;
1216 }
1217
1218
1219 inline l4_msgtag_t
1220 Istream::receive(l4_cap_idx_t src, l4_timeout_t timeout)
1221 {
1222   l4_msgtag_t res;
1223   res = l4_ipc_receive(src, _utcb, timeout);
1224   tag() = res;
1225   _pos = 0;
1226   return res;
1227 }
1228
1229 };
1230
1231 } // namespace Ipc
1232
1233 /**
1234  * \brief Extract one element of type \a T from the stream \a s.
1235  * \ingroup ipc_stream
1236  * \param s The stream to extract from.
1237  * \param v Output: extracted value.
1238  * \return the stream \a s.
1239  */
1240 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, bool &v) { s.get(v); return s; }
1241 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, int &v) { s.get(v); return s; }
1242 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long int &v) { s.get(v); return s; }
1243 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long long int &v) { s.get(v); return s; }
1244 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned int &v) { s.get(v); return s; }
1245 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long int &v) { s.get(v); return s; }
1246 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long long int &v) { s.get(v); return s; }
1247 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, short int &v) { s.get(v); return s; }
1248 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned short int &v) { s.get(v); return s; }
1249 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, char &v) { s.get(v); return s; }
1250 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned char &v) { s.get(v); return s; }
1251 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, signed char &v) { s.get(v); return s; }
1252 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Buf_item const &v) { s.put(v); return s; }
1253 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Small_buf const &v) { s.put(v); return s; }
1254 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Snd_item &v)
1255 {
1256   l4_umword_t b, d;
1257   s >> b >> d;
1258   v = L4::Ipc::Snd_item(b,d);
1259   return s;
1260 }
1261 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Varg &v)
1262 { s.get(&v); return s; }
1263
1264
1265 /**
1266  * \brief Extract the L4 message tag from the stream \a s.
1267  * \ingroup ipc_stream
1268  * \param s The stream to extract from.
1269  * \param v Output: the extracted tag.
1270  * \return the stream \a s.
1271  */
1272 inline
1273 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, l4_msgtag_t &v)
1274 {
1275   v = s.tag();
1276   return s;
1277 }
1278
1279 /**
1280  * \brief Extract an array of \a T elements from the stream \a s.
1281  * \ingroup ipc_stream
1282  *
1283  * This operator actually does not copy out the data in the array, but
1284  * returns a pointer into the message buffer itself. This means that the
1285  * data is only valid as long as there is no new data inserted into the stream.
1286  *
1287  * See Ipc::Buf_in, Ipc::Buf_cp_in, and Ipc::Buf_cp_out.
1288  *
1289  * \param s The stream to extract from.
1290  * \param v Output: pointer to the extracted array (ipc_buf_in()).
1291  * \return the stream \a s.
1292  */
1293 template< typename T >
1294 inline
1295 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1296     L4::Ipc::Buf_in<T> const &v)
1297 {
1298   unsigned long si;
1299   s.get(si);
1300   v.set_size(s.get(L4::Ipc::Msg_ptr<T>(v.buf()), si));
1301   return s;
1302 }
1303
1304 /**
1305  * \brief Extract an element of type \a T from the stream \a s.
1306  * \ingroup ipc_stream
1307  *
1308  * This operator actually does not copy out the data, but
1309  * returns a pointer into the message buffer itself. This means that the
1310  * data is only valid as long as there is no new data inserted into the stream.
1311  *
1312  * See Msg_ptr.
1313  *
1314  * \param s The stream to extract from.
1315  * \param v Output: pointer to the extracted element.
1316  * \return the stream \a s.
1317  */
1318 template< typename T >
1319 inline
1320 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1321     L4::Ipc::Msg_ptr<T> const &v)
1322 {
1323   s.get(v);
1324   return s;
1325 }
1326
1327 /**
1328  * \brief Extract an array of \a T elements from the stream \a s.
1329  * \ingroup ipc_stream
1330  *
1331  * This operator does a copy out of the data into the given buffer.
1332  *
1333  * See Ipc::Buf_in, Ipc::Buf_cp_in, and Ipc::Buf_cp_out.
1334  *
1335  * \param s The stream to extract from.
1336  * \param v buffer description to copy the array to (Ipc::Buf_cp_out()).
1337  * \return the stream \a s.
1338  */
1339 template< typename T >
1340 inline
1341 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1342     L4::Ipc::Buf_cp_in<T> const &v)
1343 {
1344   unsigned long sz;
1345   s.get(sz);
1346   v.size() = s.get(v.buf(), sz);
1347   return s;
1348 }
1349
1350
1351 /**
1352  * \brief Insert an element to type \a T into the stream \a s.
1353  * \ingroup ipc_stream
1354  *
1355  * \param s The stream to insert the element \a v.
1356  * \param v The element to insert.
1357  * \return the stream \a s.
1358  */
1359 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, bool v) { s.put(v); return s; }
1360 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, int v) { s.put(v); return s; }
1361 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long int v) { s.put(v); return s; }
1362 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long long int v) { s.put(v); return s; }
1363 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned int v) { s.put(v); return s; }
1364 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long int v) { s.put(v); return s; }
1365 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long long int v) { s.put(v); return s; }
1366 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, short int v) { s.put(v); return s; }
1367 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned short int v) { s.put(v); return s; }
1368 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char v) { s.put(v); return s; }
1369 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned char v) { s.put(v); return s; }
1370 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, signed char v) { s.put(v); return s; }
1371 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Snd_item const &v) { s.put_snd_item(v); return s; }
1372 template< typename T >
1373 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Cap<T> const &v)
1374 { s << L4::Ipc::Snd_fpage(v.fpage()); return s; }
1375
1376 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg const &v)
1377 { s.put(v); return s; }
1378 template< typename T >
1379 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg_t<T> const &v)
1380 { s.put(v); return s; }
1381
1382 /**
1383  * \brief Insert the L4 message tag into the stream \a s.
1384  * \ingroup ipc_stream
1385  *
1386  * \note Only one message tag can be inserted into a stream. Multiple
1387  *       insertions simply overwrite previous insertions.
1388  * \param s The stream to insert the tag \a v.
1389  * \param v The L4 message tag to insert.
1390  * \return the stream \a s.
1391  */
1392 inline
1393 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, l4_msgtag_t const &v)
1394 {
1395   s.tag() = v;
1396   return s;
1397 }
1398
1399 /**
1400  * \brief Insert an array with elements of type \a T into the stream \a s.
1401  * \ingroup ipc_stream
1402  *
1403  * \param s The stream to insert the array \a v.
1404  * \param v The array to insert (see Ipc::Buf_cp_out()).
1405  * \return the stream \a s.
1406  */
1407 template< typename T >
1408 inline
1409 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s,
1410     L4::Ipc::Buf_cp_out<T> const &v)
1411 {
1412   s.put(v.size());
1413   s.put(v.buf(), v.size());
1414   return s;
1415 }
1416
1417 /**
1418  * \brief Insert a zero terminated character string into the stream \a s.
1419  * \ingroup ipc_stream
1420  *
1421  * \param s The stream to insert the string \a v.
1422  * \param v The string to insert.
1423  * \return the stream \a s.
1424  *
1425  * This operator produces basically the same content as the array insertion,
1426  * however the length of the array is calculated using <c> strlen(\a v) + 1
1427  * </c>. The string is copied into the message including the trailing zero.
1428  */
1429 inline
1430 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char const *v)
1431 {
1432   unsigned long l = __builtin_strlen(v) + 1;
1433   s.put(l);
1434   s.put(v, l);
1435   return s;
1436 }
1437
1438
1439 #ifdef L4_CXX_IPC_BACKWARD_COMPAT
1440 namespace L4 {
1441
1442 #if 0
1443 template< typename T > class Ipc_buf_cp_out : public Ipc::Buf_cp_out<T> {};
1444 template< typename T > class Ipc_buf_cp_in : public Ipc::Buf_cp_in<T> {};
1445 template< typename T > class Ipc_buf_in : public Ipc::Buf_in<T> {};
1446 template< typename T > class Msg_ptr : public Ipc::Msg_ptr<T> {};
1447 #endif
1448
1449 template< typename T >
1450 Ipc::Buf_cp_out<T> ipc_buf_cp_out(T *v, unsigned long size)
1451   L4_DEPRECATED("Use L4::Ipc::Buf_cp_out<type>() now");
1452
1453 template< typename T >
1454 Ipc::Buf_cp_out<T> ipc_buf_cp_out(T *v, unsigned long size)
1455 { return Ipc::Buf_cp_out<T>(v,size); }
1456
1457
1458 template< typename T >
1459 Ipc::Buf_cp_in<T> ipc_buf_cp_in(T *v, unsigned long &size)
1460   L4_DEPRECATED("Use L4::Ipc::Buf_cp_in<type>() now");
1461
1462 template< typename T >
1463 Ipc::Buf_cp_in<T> ipc_buf_cp_in(T *v, unsigned long &size)
1464 { return Ipc::Buf_cp_in<T>(v,size); }
1465
1466
1467 template< typename T >
1468 Ipc::Buf_in<T> ipc_buf_in(T *&v, unsigned long &size)
1469   L4_DEPRECATED("Use L4::Ipc::Buf_in<type>() now");
1470
1471 template< typename T >
1472 Ipc::Buf_in<T> ipc_buf_in(T *&v, unsigned long &size)
1473 { return Ipc::Buf_in<T>(v, size); }
1474
1475
1476 template< typename T >
1477 Ipc::Msg_ptr<T> msg_ptr(T *&p)
1478   L4_DEPRECATED("Use L4::Ipc::Msg_ptr<type>() now");
1479
1480 template< typename T >
1481 Ipc::Msg_ptr<T> msg_ptr(T *&p)
1482 { return Ipc::Msg_ptr<T>(p); }
1483
1484 typedef Ipc::Istream Ipc_istream L4_DEPRECATED("Use L4::Ipc::Istream now");
1485 typedef Ipc::Ostream Ipc_ostream L4_DEPRECATED("Use L4::Ipc::Ostream now");;
1486 typedef Ipc::Iostream Ipc_iostream L4_DEPRECATED("Use L4::Ipc::Iostream now");;
1487 typedef Ipc::Snd_fpage Snd_fpage L4_DEPRECATED("Use L4::Ipc::Snd_fpage now");;
1488 typedef Ipc::Rcv_fpage Rcv_fpage L4_DEPRECATED("Use L4::Ipc::Rcv_fpage now");;
1489 typedef Ipc::Small_buf Small_buf L4_DEPRECATED("Use L4::Ipc::Small_buf now");;
1490
1491 }
1492 #endif
1493