L4Re - L4 Runtime Environment
ipc_stream
Go to the documentation of this file.
1 // vi:set ft=cpp: -*- Mode: C++ -*-
2 /**
3  * \file
4  * 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/sys/cxx/ipc_types>
31 #include <l4/sys/cxx/ipc_varg>
32 #include <l4/cxx/type_traits>
33 #include <l4/cxx/minmax>
34 
35 #define L4_CXX_IPC_BACKWARD_COMPAT
36 
37 namespace L4 {
38 namespace Ipc {
39 
40 class Ostream;
41 class Istream;
42 
43 namespace Internal {
44 /**
45  * Abstraction for inserting an array into an Ipc::Ostream.
46  * \internal
47  *
48  * An object of Buf_cp_out can be used to insert an array of arbitrary values,
49  * that can be inserted into an Ipc::Ostream individually.
50  * The array is therefore copied to the message buffer, in contrast to
51  * data handled with Msg_out_buffer or Msg_io_buffer.
52  *
53  * On insertion into the Ipc::Ostream exactly the given number of elements
54  * of type T are copied to the message buffer, this means the source buffer
55  * is no longer referenced after insertion into the stream.
56  *
57  * You should use buf_cp_out() to create instances of Buf_cp_out.
58  *
59  * The counterpart is either Buf_cp_in (buf_cp_in()) or Buf_in (buf_in()).
60  */
61 template< typename T >
62 class Buf_cp_out
63 {
64 public:
65  /**
66  * Create a buffer object for the given array.
67  *
68  * \param v The pointer to the array with size elements of type T.
69  * \param size The number of elements in the array.
70  */
71  Buf_cp_out(T const *v, unsigned long size) : _v(v), _s(size) {}
72 
73  /**
74  * Get the number of elements in the array.
75  *
76  * \returns The number of elements in the array.
77  *
78  * \note This function is usually used by the Ipc::Ostream itself.
79  */
80  unsigned long size() const { return _s; }
81 
82  /**
83  * Get the pointer to the array.
84  *
85  * \returns Pointer to the array.
86  *
87  * \note This function is usually used by the Ipc::Ostream itself.
88  */
89  T const *buf() const { return _v; }
90 
91 private:
92  friend class Ostream;
93  T const *_v;
94  unsigned long _s;
95 };
96 }
97 
98 /**
99  * Insert an array into an Ipc::Ostream.
100  *
101  * \param v Pointer to the array that shall be inserted into an
102  * Ipc::Ostream.
103  * \param size Number of elements in the array.
104  *
105  * This function inserts an array (e.g. a string) into an Ipc::Ostream.
106  * The data is copied to the stream. On insertion into the Ipc::Ostream
107  * exactly the given number of elements of type T are copied to the message
108  * buffer, this means the source buffer is no longer referenced after
109  * insertion into the stream.
110  *
111  * \see The counterpart is either buf_cp_in() or buf_in().
112  */
113 template< typename T >
114 Internal::Buf_cp_out<T> buf_cp_out(T const *v, unsigned long size)
115 { return Internal::Buf_cp_out<T>(v, size); }
116 
117 
118 namespace Internal {
119 /**
120  * Abstraction for extracting array from an Ipc::Istream.
121  * \internal
122  *
123  * An instance of Buf_cp_in can be used to extract an array from
124  * an Ipc::Istream. This is the counterpart to the Buf_cp_out abstraction.
125  * The data from the received message is thereby copied to the given buffer
126  * and size is set to the number of elements found in the stream.
127  * To avoid the copy operation Buf_in may be used instead.
128  *
129  * \see buf_cp_in(), Buf_in, buf_in(), Buf_cp_out, and buf_cp_out().
130  */
131 template< typename T >
132 class Buf_cp_in
133 {
134 public:
135  /**
136  * Create a buffer for extracting an array from an Ipc::Istream.
137  *
138  * \param v The buffer for array (copy in).
139  * \param[in,out] size Input: the number of elements the array can take at
140  * most <br>
141  * Output: the number of elements found in the stream.
142  */
143  Buf_cp_in(T *v, unsigned long &size) : _v(v), _s(&size) {}
144 
145  unsigned long &size() const { return *_s; }
146  T *buf() const { return _v; }
147 private:
148  friend class Istream;
149  T *_v;
150  unsigned long *_s;
151 };
152 }
153 
154 /**
155  * Extract an array from an Ipc::Istream.
156  *
157  * \param v Pointer to the array that shall receive the values from
158  * the Ipc::Istream.
159  * \param[in,out] size Input: the number of elements the array can take at
160  * most <br>
161  * Output: the number of elements found in the stream.
162  *
163  * buf_cp_in() can be used to extract an array from an Ipc::Istream. This is
164  * the counterpart buf_cp_out(). The data from the received message is
165  * thereby copied to the given buffer and size is set to the number of
166  * elements found in the stream. To avoid the copy operation buf_in() may be
167  * used instead.
168  *
169  * \see buf_in() and buf_cp_out().
170  */
171 template< typename T >
172 Internal::Buf_cp_in<T> buf_cp_in(T *v, unsigned long &size)
173 { return Internal::Buf_cp_in<T>(v, size); }
174 
175 /**
176  * Abstraction for extracting a zero-terminated string from an Ipc::Istream.
177  *
178  * An instance of Str_cp_in can be used to extract a zero-terminated string
179  * an Ipc::Istream. The data from the received message is thereby copied to the
180  * given buffer and size is set to the number of characters found in the
181  * stream. The string is zero terminated in any circumstances. When the given
182  * buffer is smaller than the received string the last byte in the buffer will
183  * be the zero terminator. In the case the received string is shorter than the
184  * given buffer the zero termination will be placed behind the received data.
185  * This provides a zero-terminated result even in cases where the sender did
186  * not provide proper termination or in cases of too small receiver buffers.
187  *
188  * \see str_cp_in().
189  */
190 template< typename T >
191 class Str_cp_in
192 {
193 public:
194  /**
195  * Create a buffer for extracting an array from an Ipc::Istream.
196  *
197  * \param v The buffer for string.
198  * \param[in,out] size Input: The number of bytes available in `v` <br>
199  * Output: The number of bytes received (including the
200  * terminator).
201  */
202  Str_cp_in(T *v, unsigned long &size) : _v(v), _s(&size) {}
203 
204  unsigned long &size() const { return *_s; }
205  T *buf() const { return _v; }
206 private:
207  friend class Istream;
208  T *_v;
209  unsigned long *_s;
210 };
211 
212 /**
213  * Create a Str_cp_in for the given values.
214  *
215  * \param v Pointer to the array that shall receive the values from
216  * the Ipc::Istream.
217  * \param[in,out] size Input: the number of elements the array can take at
218  * most <br>
219  * Output: the number of elements found in the stream.
220  *
221  * This function makes it more convenient to extract arrays from an
222  * Ipc::Istream (\see Str_cp_in.)
223  */
224 template< typename T >
225 Str_cp_in<T> str_cp_in(T *v, unsigned long &size)
226 { return Str_cp_in<T>(v, size); }
227 
228 /**
229  * Pointer to an element of type T in an Ipc::Istream.
230  *
231  * This wrapper can be used to extract an element of type T from an
232  * Ipc::Istream, whereas the data is not copied out, but a pointer into
233  * the message buffer itself is returned. With is mechanism it is possible
234  * to avoid an extra copy of large data structures from a received IPC
235  * message, instead the returned pointer gives direct access to the data
236  * in the message.
237  *
238  * See msg_ptr().
239  */
240 template< typename T >
241 class Msg_ptr
242 {
243 private:
244  T **_p;
245 public:
246  /**
247  * Create a Msg_ptr object that set pointer p to point into the message
248  * buffer.
249  *
250  * \param p The pointer that is adjusted to point into the message buffer.
251  */
252  explicit Msg_ptr(T *&p) : _p(&p) {}
253  void set(T *p) const { *_p = p; }
254 };
255 
256 /**
257  * Create an Msg_ptr to adjust the given pointer.
258  *
259  * This function makes it more convenient to extract pointers to data in the
260  * message buffer itself from an Ipc::Istream. This may be used to avoid copy
261  * out of large data structures. (See Msg_ptr.)
262  */
263 template< typename T >
264 Msg_ptr<T> msg_ptr(T *&p)
265 { return Msg_ptr<T>(p); }
266 
267 
268 namespace Internal {
269 /**
270  * Abstraction to extract an array from an Ipc::Istream.
271  * \internal
272  *
273  * This wrapper provides a possibility to extract an array from an
274  * Ipc::Istream, without extra copy overhead. In contrast to Buf_cp_in
275  * the data is not copied to a buffer, but a pointer to the array is returned.
276  *
277  * The mechanism is comparable to that of Msg_ptr, however it handles arrays
278  * inserted with Buf_cp_out.
279  *
280  * See buf_in(), Buf_cp_out, buf_cp_out(), Buf_cp_in, and buf_cp_in().
281  */
282 template< typename T >
283 class Buf_in
284 {
285 public:
286  /**
287  * Create a Buf_in to adjust a pointer to the array and the size of the array.
288  *
289  * \param v The pointer to adjust to the first element of the array.
290  * \param[out] size The number of elements found in the stream.
291  */
292  Buf_in(T *&v, unsigned long &size) : _v(&v), _s(&size) {}
293 
294  void set_size(unsigned long s) const { *_s = s; }
295  T *&buf() const { return *_v; }
296 private:
297  friend class Istream;
298  T **_v;
299  unsigned long *_s;
300 };
301 }
302 
303 /**
304  * Return a pointer to stream array data.
305  *
306  * \param[out] v Pointer to the array within the Ipc::Istream.
307  * \param[out] size The number of elements found in the stream.
308  *
309  * This routine provdes a possibility to extract an array from an
310  * Ipc::Istream, without extra copy overhead. In contrast to buf_cp_in()
311  * the data is not copied to a buffer, but a pointer to the array is returned.
312  * The user must make sure the UTCB is not used for other purposes while the
313  * returned pointer is still in use.
314  *
315  * The mechanism is comparable to that of Msg_ptr, however it handles arrays
316  * inserted with buf_cp_out().
317  *
318  * \see buf_cp_in() and buf_cp_out().
319  */
320 template< typename T >
321 Internal::Buf_in<T> buf_in(T *&v, unsigned long &size)
322 { return Internal::Buf_in<T>(v, size); }
323 
324 namespace Utcb_stream_check
325 {
326  static bool check_utcb_data_offset(unsigned sz)
327  { return sz > sizeof(l4_umword_t) * L4_UTCB_GENERIC_DATA_SIZE; }
328 }
329 
330 
331 /**
332  * Input stream for IPC unmarshalling.
333  *
334  * Ipc::Istream is part of the dynamic IPC marshalling infrastructure, as well
335  * as Ipc::Ostream and Ipc::Iostream.
336  *
337  * Ipc::Istream is an input stream supporting extraction of values from an
338  * IPC message buffer. A received IPC message can be unmarshalled using the
339  * usual extraction operator (>>).
340  *
341  * There exist some special wrapper classes to extract arrays (see
342  * Ipc_buf_cp_in and Ipc_buf_in) and indirect strings (see Msg_in_buffer and
343  * Msg_io_buffer).
344  */
345 class Istream
346 {
347 public:
348  /**
349  * Create an input stream for the given message buffer.
350  *
351  * The given message buffer is used for IPC operations wait()/receive()
352  * and received data can be extracted using the >> operator afterwards.
353  * In the case of indirect message parts a buffer of type Msg_in_buffer
354  * must be inserted into the stream before the IPC operation and contains
355  * received data afterwards.
356  *
357  * \param utcb The message buffer to receive IPC messages.
358  */
359  Istream(l4_utcb_t *utcb)
360  : _tag(), _utcb(utcb),
361  _current_msg(reinterpret_cast<char*>(l4_utcb_mr_u(utcb)->mr)),
362  _pos(0), _current_buf(0)
363  {}
364 
365  /**
366  * Reset the stream to empty, and ready for receive()/wait().
367  * The stream is reset to the same state as on its creation.
368  */
369  void reset()
370  {
371  _pos = 0;
372  _current_buf = 0;
373  _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
374  }
375 
376  /**
377  * Check whether a value of type T can be obtained from the stream.
378  */
379  template< typename T >
380  bool has_more(unsigned long count = 1)
381  {
382  auto const max_bytes = L4_UTCB_GENERIC_DATA_SIZE * sizeof(l4_umword_t);
383  unsigned apos = cxx::Type_traits<T>::align(_pos);
384  return (count <= max_bytes / sizeof(T))
385  && (apos + (sizeof(T) * count)
386  <= _tag.words() * sizeof(l4_umword_t));
387  }
388 
389  /**
390  * \name Get/Put Functions.
391  */
392  //@{
393 
394  /**
395  * Copy out an array of type `T` with `size` elements.
396  *
397  * \param buf Pointer to a buffer for size elements of type T.
398  * \param elems Number of elements of type T to copy out.
399  *
400  * See \ref Istream::operator>>()
401  */
402  template< typename T >
403  unsigned long get(T *buf, unsigned long elems)
404  {
405  if (L4_UNLIKELY(!has_more<T>(elems)))
406  return 0;
407 
408  unsigned long size = elems * sizeof(T);
409  _pos = cxx::Type_traits<T>::align(_pos);
410 
411  __builtin_memcpy(buf, _current_msg + _pos, size);
412  _pos += size;
413  return elems;
414  }
415 
416 
417  /**
418  * Skip size elements of type T in the stream.
419  * \param elems Number of elements to skip.
420  */
421  template< typename T >
422  void skip(unsigned long elems)
423  {
424  if (L4_UNLIKELY(!has_more<T>(elems)))
425  return;
426 
427  unsigned long size = elems * sizeof(T);
428  _pos = cxx::Type_traits<T>::align(_pos);
429  _pos += size;
430  }
431 
432  /**
433  * Read one size elements of type T from the stream and return a pointer.
434  *
435  * \param buf A Msg_ptr that is actually set to point to the element in the
436  * stream.
437  * \param elems Number of elements to extract (default is 1).
438  *
439  * In contrast to a normal get, this version does actually not copy the data
440  * but returns a pointer to the data.
441  *
442  * See \ref Istream::operator>>()
443  */
444  template< typename T >
445  unsigned long get(Msg_ptr<T> const &buf, unsigned long elems = 1)
446  {
447  if (L4_UNLIKELY(!has_more<T>(elems)))
448  return 0;
449 
450  unsigned long size = elems * sizeof(T);
451  _pos = cxx::Type_traits<T>::align(_pos);
452 
453  buf.set(reinterpret_cast<T*>(_current_msg + _pos));
454  _pos += size;
455  return elems;
456  }
457 
458 
459  /**
460  * Extract a single element of type T from the stream.
461  *
462  * \param[out] v The element.
463  *
464  * See \ref Istream::operator>>()
465  */
466  template< typename T >
467  bool get(T &v)
468  {
469  if (L4_UNLIKELY(!has_more<T>()))
470  {
471  v = T();
472  return false;
473  }
474 
475  _pos = cxx::Type_traits<T>::align(_pos);
476  v = *(reinterpret_cast<T*>(_current_msg + _pos));
477  _pos += sizeof(T);
478  return true;
479  }
480 
481 
482  bool get(Ipc::Varg *va)
483  {
484  Ipc::Varg::Tag t;
485  if (!has_more<Ipc::Varg::Tag>())
486  {
487  va->tag(0);
488  return 0;
489  }
490  get(t);
491  va->tag(t);
492  char const *d;
493  get(msg_ptr(d), va->length());
494  va->data(d);
495 
496  return 1;
497  }
498 
499  /**
500  * Get the message tag of a received IPC.
501  *
502  * \return The L4 message tag for the received IPC.
503  *
504  * This is in particular useful for handling page faults or exceptions.
505  *
506  * See \ref Istream::operator>>()
507  */
508  l4_msgtag_t tag() const { return _tag; }
509 
510 
511  /**
512  * Get the message tag of a received IPC.
513  *
514  * \return A reference to the L4 message tag for the received IPC.
515  *
516  * This is in particular useful for handling page faults or exceptions.
517  *
518  * See \ref Istream::operator>>()
519  */
520  l4_msgtag_t &tag() { return _tag; }
521 
522  //@}
523 
524  /**
525  * \internal
526  * Put a receive item into the stream's buffer registers.
527  */
528  inline bool put(Buf_item const &);
529 
530  /**
531  * \internal
532  * Put a small receive item into the stream's buffer registers.
533  */
534  inline bool put(Small_buf const &);
535 
536 
537  /**
538  * \name IPC operations.
539  */
540  //@{
541 
542  /**
543  * Wait for an incoming message from any sender.
544  *
545  * \param[out] src Contains the sender after a successful IPC operation.
546  *
547  * \return Syscall return tag.
548  *
549  * This wait is actually known as 'open wait'.
550  */
551  inline l4_msgtag_t wait(l4_umword_t *src)
552  { return wait(src, L4_IPC_NEVER); }
553 
554  /**
555  * Wait for an incoming message from any sender.
556  *
557  * \param[out] src Contains the sender after a successful IPC operation.
558  * \param timeout Timeout used for IPC.
559  *
560  * \return The IPC result dope (l4_msgtag_t).
561  *
562  * This wait is actually known as 'open wait'.
563  */
564  inline l4_msgtag_t wait(l4_umword_t *src, l4_timeout_t timeout);
565 
566  /**
567  * Wait for a message from the specified sender.
568  *
569  * \param src The sender id to receive from.
570  *
571  * \return The IPC result dope (l4_msgtag_t).
572  *
573  * This is commonly known as 'closed wait'.
574  */
575  inline l4_msgtag_t receive(l4_cap_idx_t src)
576  { return receive(src, L4_IPC_NEVER); }
577  inline l4_msgtag_t receive(l4_cap_idx_t src, l4_timeout_t timeout);
578 
579  //@}
580 
581  /**
582  * Return utcb pointer.
583  */
584  inline l4_utcb_t *utcb() const { return _utcb; }
585 
586 protected:
587  l4_msgtag_t _tag;
588  l4_utcb_t *_utcb;
589  char *_current_msg;
590  unsigned _pos;
591  unsigned char _current_buf;
592 };
593 
594 class Istream_copy : public Istream
595 {
596 private:
597  l4_msg_regs_t _mrs;
598 
599 public:
600  Istream_copy(Istream const &o) : Istream(o), _mrs(*l4_utcb_mr_u(o.utcb()))
601  {
602  // do some reverse mr to utcb trickery
603  _utcb = (l4_utcb_t*)((l4_addr_t)&_mrs - (l4_addr_t)l4_utcb_mr_u((l4_utcb_t*)0));
604  _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
605  }
606 
607 };
608 
609 /**
610  * Output stream for IPC marshalling.
611  *
612  * Ipc::Ostream is part of the dynamic IPC marshalling infrastructure, as well
613  * as Ipc::Istream and Ipc::Iostream.
614  *
615  * Ipc::Ostream is an output stream supporting insertion of values into an
616  * IPC message buffer. A IPC message can be marshalled using the
617  * usual insertion operator <<, see \link ipc_stream IPC stream operators
618  * \endlink.
619  *
620  * There exist some special wrapper classes to insert arrays (see
621  * Ipc::Buf_cp_out) and indirect strings (see Msg_out_buffer and
622  * Msg_io_buffer). */
623 class Ostream
624 {
625 public:
626  /**
627  * Create an IPC output stream using the given message buffer `utcb`.
628  */
629  Ostream(l4_utcb_t *utcb)
630  : _tag(), _utcb(utcb),
631  _current_msg(reinterpret_cast<char *>(l4_utcb_mr_u(_utcb)->mr)),
632  _pos(0), _current_item(0)
633  {}
634 
635  /**
636  * Reset the stream to empty, same state as a newly created stream.
637  */
638  void reset()
639  {
640  _pos = 0;
641  _current_item = 0;
642  _current_msg = reinterpret_cast<char*>(l4_utcb_mr_u(_utcb)->mr);
643  }
644 
645  /**
646  * \name Get/Put functions.
647  *
648  * These functions are basically used to implement the insertion operators
649  * (<<) and should not be called directly.
650  */
651  //@{
652 
653  /**
654  * Put an array with `size` elements of type `T` into the stream.
655  *
656  * \param buf A pointer to the array to insert into the buffer.
657  * \param size The number of elements in the array.
658  */
659  template< typename T >
660  bool put(T *buf, unsigned long size)
661  {
662  size *= sizeof(T);
663  _pos = cxx::Type_traits<T>::align(_pos);
664  if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
665  return false;
666 
667  __builtin_memcpy(_current_msg + _pos, buf, size);
668  _pos += size;
669  return true;
670  }
671 
672  /**
673  * Insert an element of type `T` into the stream.
674  *
675  * \param v The element to insert.
676  */
677  template< typename T >
678  bool put(T const &v)
679  {
680  _pos = cxx::Type_traits<T>::align(_pos);
681  if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
682  return false;
683 
684  *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
685  _pos += sizeof(T);
686  return true;
687  }
688 
689  int put(Varg const &va)
690  {
691  put(va.tag());
692  put(va.data(), va.length());
693 
694  return 0;
695  }
696 
697  template< typename T >
698  int put(Varg_t<T> const &va)
699  { return put(static_cast<Varg const &>(va)); }
700 
701  /**
702  * Extract the L4 message tag from the stream.
703  *
704  * \return the extracted L4 message tag.
705  */
706  l4_msgtag_t tag() const { return _tag; }
707 
708  /**
709  * Extract a reference to the L4 message tag from the stream.
710  *
711  * \return A reference to the L4 message tag.
712  */
713  l4_msgtag_t &tag() { return _tag; }
714 
715  //@}
716 
717  /**
718  * \internal
719  * Put a send item into the stream's message buffer.
720  */
721  inline bool put_snd_item(Snd_item const &);
722 
723 
724  /**
725  * \name IPC operations.
726  */
727  //@{
728 
729  /**
730  * Send the message via IPC to the given receiver.
731  *
732  * \param dst The destination for the message.
733  * \param proto Protocol to use.
734  * \param flags Flags to use.
735  *
736  * \return Syscall return tag.
737  */
738  inline l4_msgtag_t send(l4_cap_idx_t dst, long proto = 0, unsigned flags = 0);
739 
740  //@}
741 
742  /**
743  * Return utcb pointer.
744  */
745  inline l4_utcb_t *utcb() const { return _utcb; }
746 #if 0
747  /**
748  * Get the currently used bytes in the stream.
749  */
750  unsigned long tell() const
751  {
752  unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
753  w -= _current_item * 2;
754  _tag = l4_msgtag(0, w, _current_item, 0);
755  }
756 #endif
757 public:
758  l4_msgtag_t prepare_ipc(long proto = 0, unsigned flags = 0)
759  {
760  unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
761  w -= _current_item * 2;
762  return l4_msgtag(proto, w, _current_item, flags);
763  }
764 
765  // XXX: this is a hack for <l4/sys/cxx/ipc_server> adaption
766  void set_ipc_params(l4_msgtag_t tag)
767  {
768  _pos = (tag.words() + tag.items()*2)*sizeof(l4_umword_t);
769  _current_item = tag.items();
770  }
771 protected:
772  l4_msgtag_t _tag;
773  l4_utcb_t *_utcb;
774  char *_current_msg;
775  unsigned _pos;
776  unsigned char _current_item;
777 };
778 
779 
780 /**
781  * Input/Output stream for IPC [un]marshalling.
782  *
783  * The Ipc::Iostream is part of the AW Env IPC framework as well as
784  * Ipc::Istream and Ipc::Ostream.
785  * In particular an Ipc::Iostream is a combination of an Ipc::Istream and an
786  * Ipc::Ostream. It can use either a single message buffer for receiving and
787  * sending messages or a pair of a receive and a send buffer. The stream also
788  * supports combined IPC operations such as call() and reply_and_wait(), which
789  * can be used to implement RPC functionality.
790  */
791 class Iostream : public Istream, public Ostream
792 {
793 public:
794 
795  /**
796  * Create an IPC IO stream with a single message buffer.
797  *
798  * \param utcb The message buffer used as backing store.
799  *
800  * The created IO stream uses the same message buffer for sending and
801  * receiving IPC messages.
802  */
803  explicit Iostream(l4_utcb_t *utcb)
804  : Istream(utcb), Ostream(utcb)
805  {}
806 
807  // disambiguate those functions
808  l4_msgtag_t tag() const { return Istream::tag(); }
809  l4_msgtag_t &tag() { return Istream::tag(); }
810  l4_utcb_t *utcb() const { return Istream::utcb(); }
811 
812  /**
813  * Reset the stream to its initial state.
814  *
815  * Input as well as the output stream are reset.
816  */
817  void reset()
818  {
819  Istream::reset();
820  Ostream::reset();
821  }
822 
823 
824  /**
825  * \name Get/Put functions.
826  *
827  * These functions are basically used to implement the insertion operators
828  * (<<) and should not be called directly.
829  */
830  //@{
831 
832  using Istream::get;
833  using Istream::put;
834  using Ostream::put;
835 
836  //@}
837 
838  /**
839  * \name IPC operations.
840  */
841  //@{
842 
843  /**
844  * Do an IPC call using the message in the output stream and receiving to
845  * the input stream.
846  *
847  * \param dst The destination L4 UID (thread) to call.
848  * \param timeout The IPC timeout for the call.
849  * \param proto The protocol value to use in the message tag.
850  *
851  * \return The result dope of the IPC operation.
852  *
853  * This is a combined IPC operation consisting of a send and a receive
854  * to/from the given destination `dst`.
855  *
856  * A call is usually used by clients for RPCs to a server.
857  */
858  inline l4_msgtag_t call(l4_cap_idx_t dst, l4_timeout_t timeout, long proto = 0);
859  inline l4_msgtag_t call(l4_cap_idx_t dst, long proto = 0);
860 
861  /**
862  * Do an IPC reply and wait.
863  *
864  * \param[in,out] src_dst Input: the destination for the send operation. <br>
865  * Output: the source of the received message.
866  * \param proto Protocol to use.
867  *
868  * \return the result dope of the IPC operation.
869  *
870  * This is a combined IPC operation consisting of a send operation and
871  * an open wait for any message.
872  *
873  * A reply and wait is usually used by servers that reply to a client
874  * and wait for the next request by any other client.
875  */
876  inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst, long proto = 0)
877  { return reply_and_wait(src_dst, L4_IPC_SEND_TIMEOUT_0, proto); }
878 
879  inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
880  long proto = 0)
881  { return send_and_wait(dest, src, L4_IPC_SEND_TIMEOUT_0, proto); }
882 
883  /**
884  * Do an IPC reply and wait.
885  *
886  * \param[in,out] src_dst Input: the destination for the send operation. <br>
887  * Output: the source of the received message.
888  * \param timeout Timeout used for IPC.
889  * \param proto Protocol to use.
890  *
891  * \return the result dope of the IPC operation.
892  *
893  * This is a combined IPC operation consisting of a send operation and
894  * an open wait for any message.
895  *
896  * A reply and wait is usually used by servers that reply to a client
897  * and wait for the next request by any other client.
898  */
899  inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst,
900  l4_timeout_t timeout, long proto = 0);
901  inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
902  l4_timeout_t timeout, long proto = 0);
903  inline l4_msgtag_t reply(l4_timeout_t timeout, long proto = 0);
904  inline l4_msgtag_t reply(long proto = 0)
905  { return reply(L4_IPC_SEND_TIMEOUT_0, proto); }
906 
907  //@}
908 };
909 
910 
911 inline bool
912 Ostream::put_snd_item(Snd_item const &v)
913 {
914  typedef Snd_item T;
915  _pos = cxx::Type_traits<Snd_item>::align(_pos);
916  if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
917  return false;
918 
919  *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
920  _pos += sizeof(T);
921  ++_current_item;
922  return true;
923 }
924 
925 
926 inline bool
927 Istream::put(Buf_item const &item)
928 {
929  if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 3)
930  return false;
931 
932  l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
933 
934  reinterpret_cast<Buf_item&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
935  _current_buf += 2;
936  return true;
937 }
938 
939 
940 inline bool
941 Istream::put(Small_buf const &item)
942 {
943  if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 2)
944  return false;
945 
946  l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK;
947 
948  reinterpret_cast<Small_buf&>(l4_utcb_br_u(_utcb)->br[_current_buf]) = item;
949  _current_buf += 1;
950  return true;
951 }
952 
953 
954 inline l4_msgtag_t
955 Ostream::send(l4_cap_idx_t dst, long proto, unsigned flags)
956 {
957  l4_msgtag_t tag = prepare_ipc(proto, L4_MSGTAG_FLAGS & flags);
958  return l4_ipc_send(dst, _utcb, tag, L4_IPC_NEVER);
959 }
960 
961 inline l4_msgtag_t
962 Iostream::call(l4_cap_idx_t dst, l4_timeout_t timeout, long label)
963 {
964  l4_msgtag_t tag = prepare_ipc(label);
965  tag = l4_ipc_call(dst, Ostream::_utcb, tag, timeout);
966  Istream::tag() = tag;
967  Istream::_pos = 0;
968  return tag;
969 }
970 
971 inline l4_msgtag_t
972 Iostream::call(l4_cap_idx_t dst, long label)
973 { return call(dst, L4_IPC_NEVER, label); }
974 
975 
976 inline l4_msgtag_t
977 Iostream::reply_and_wait(l4_umword_t *src_dst, l4_timeout_t timeout, long proto)
978 {
979  l4_msgtag_t tag = prepare_ipc(proto);
980  tag = l4_ipc_reply_and_wait(Ostream::_utcb, tag, src_dst, timeout);
981  Istream::tag() = tag;
982  Istream::_pos = 0;
983  return tag;
984 }
985 
986 
987 inline l4_msgtag_t
988 Iostream::send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
989  l4_timeout_t timeout, long proto)
990 {
991  l4_msgtag_t tag = prepare_ipc(proto);
992  tag = l4_ipc_send_and_wait(dest, Ostream::_utcb, tag, src, timeout);
993  Istream::tag() = tag;
994  Istream::_pos = 0;
995  return tag;
996 }
997 
998 inline l4_msgtag_t
999 Iostream::reply(l4_timeout_t timeout, long proto)
1000 {
1001  l4_msgtag_t tag = prepare_ipc(proto);
1002  tag = l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, Ostream::_utcb, tag, timeout);
1003  Istream::tag() = tag;
1004  Istream::_pos = 0;
1005  return tag;
1006 }
1007 
1008 inline l4_msgtag_t
1009 Istream::wait(l4_umword_t *src, l4_timeout_t timeout)
1010 {
1011  l4_msgtag_t res;
1012  res = l4_ipc_wait(_utcb, src, timeout);
1013  tag() = res;
1014  _pos = 0;
1015  return res;
1016 }
1017 
1018 
1019 inline l4_msgtag_t
1020 Istream::receive(l4_cap_idx_t src, l4_timeout_t timeout)
1021 {
1022  l4_msgtag_t res;
1023  res = l4_ipc_receive(src, _utcb, timeout);
1024  tag() = res;
1025  _pos = 0;
1026  return res;
1027 }
1028 
1029 } // namespace Ipc
1030 } // namespace L4
1031 
1032 /**
1033  * Extract one element of type `T` from the stream `s`.
1034  *
1035  * \param s The stream to extract from.
1036  * \param[out] v Extracted value.
1037  *
1038  * \return The stream `s`.
1039  */
1040 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, bool &v) { s.get(v); return s; }
1041 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, int &v) { s.get(v); return s; }
1042 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long int &v) { s.get(v); return s; }
1043 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long long int &v) { s.get(v); return s; }
1044 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned int &v) { s.get(v); return s; }
1045 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long int &v) { s.get(v); return s; }
1046 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long long int &v) { s.get(v); return s; }
1047 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, short int &v) { s.get(v); return s; }
1048 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned short int &v) { s.get(v); return s; }
1049 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, char &v) { s.get(v); return s; }
1050 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned char &v) { s.get(v); return s; }
1051 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, signed char &v) { s.get(v); return s; }
1052 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Buf_item const &v) { s.put(v); return s; }
1053 inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Small_buf const &v) { s.put(v); return s; }
1054 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Snd_item &v)
1055 {
1056  l4_umword_t b, d;
1057  s >> b >> d;
1058  v = L4::Ipc::Snd_item(b, d);
1059  return s;
1060 }
1061 inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Varg &v)
1062 { s.get(&v); return s; }
1063 
1064 
1065 /**
1066  * Extract the L4 message tag from the stream `s`.
1067  *
1068  * \param s The stream to extract from.
1069  * \param[out] v The extracted tag.
1070  *
1071  * \return The stream `s`.
1072  */
1073 inline
1074 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, l4_msgtag_t &v)
1075 {
1076  v = s.tag();
1077  return s;
1078 }
1079 
1080 /**
1081  * Extract an array of `T` elements from the stream `s`.
1082  *
1083  * \param s The stream to extract from.
1084  * \param[out] v Pointer to the extracted array (ipc_buf_in()).
1085  *
1086  * \return The stream `s`.
1087  *
1088  * This operator actually does not copy out the data in the array, but
1089  * returns a pointer into the message buffer itself. This means that the
1090  * data is only valid as long as there is no new data inserted into the stream.
1091  *
1092  * \note If array does not fit into transmitted words size will be set to zero.
1093  * Client has to implement check against zero.
1094  *
1095  * See Ipc::Buf_in, Ipc::Buf_cp_in, and Ipc::Buf_cp_out.
1096  */
1097 template< typename T >
1098 inline
1099 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1100  L4::Ipc::Internal::Buf_in<T> const &v)
1101 {
1102  unsigned long si;
1103  if (s.get(si) && s.has_more<T>(si))
1104  v.set_size(s.get(L4::Ipc::Msg_ptr<T>(v.buf()), si));
1105  else
1106  v.set_size(0);
1107  return s;
1108 }
1109 
1110 /**
1111  * Extract an element of type `T` from the stream `s`.
1112  *
1113  * \param s The stream to extract from.
1114  * \param[out] v Pointer to the extracted element.
1115  *
1116  * \return the stream `s`.
1117  *
1118  * This operator actually does not copy out the data, but
1119  * returns a pointer into the message buffer itself. This means that the
1120  * data is only valid as long as there is no new data inserted into the stream.
1121  *
1122  * See Msg_ptr.
1123  */
1124 template< typename T >
1125 inline
1126 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1127  L4::Ipc::Msg_ptr<T> const &v)
1128 {
1129  s.get(v);
1130  return s;
1131 }
1132 
1133 /**
1134  * Extract an array of `T` elements from the stream `s`.
1135  *
1136  * \param s The stream to extract from.
1137  * \param[out] v Buffer description to copy the array to (Ipc::Buf_cp_out()).
1138  *
1139  * \return The stream `s`.
1140  *
1141  * This operator does a copy out of the data into the given buffer.
1142  *
1143  * See Ipc::Buf_in, Ipc::Buf_cp_in, and Ipc::Buf_cp_out.
1144  */
1145 template< typename T >
1146 inline
1147 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1148  L4::Ipc::Internal::Buf_cp_in<T> const &v)
1149 {
1150  unsigned long sz;
1151  s.get(sz);
1152  v.size() = s.get(v.buf(), cxx::min(v.size(), sz));
1153  return s;
1154 }
1155 
1156 /**
1157  * Extract a zero-terminated string from the stream.
1158  *
1159  * \param s The stream to extract from.
1160  * \param[out] v Buffer description to copy the array to (Ipc::Str_cp_out()).
1161  *
1162  * \return the stream `s`.
1163  *
1164  * This operator does a copy out of the data into the given buffer.
1165  */
1166 template< typename T >
1167 inline
1168 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s,
1169  L4::Ipc::Str_cp_in<T> const &v)
1170 {
1171  unsigned long sz;
1172  s.get(sz);
1173  unsigned long rsz = s.get(v.buf(), cxx::min(v.size(), sz));
1174  if (rsz < v.size() && v.buf()[rsz - 1])
1175  ++rsz; // add the zero termination behind the received data
1176 
1177  if (rsz != 0)
1178  v.buf()[rsz - 1] = 0;
1179 
1180  v.size() = rsz;
1181  return s;
1182 }
1183 
1184 
1185 /**
1186  * Insert an element to type `T` into the stream `s`.
1187  *
1188  * \param s The stream to insert the element `v`.
1189  * \param v The element to insert.
1190  *
1191  * \return The stream `s`.
1192  */
1193 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, bool v) { s.put(v); return s; }
1194 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, int v) { s.put(v); return s; }
1195 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long int v) { s.put(v); return s; }
1196 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long long int v) { s.put(v); return s; }
1197 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned int v) { s.put(v); return s; }
1198 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long int v) { s.put(v); return s; }
1199 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long long int v) { s.put(v); return s; }
1200 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, short int v) { s.put(v); return s; }
1201 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned short int v) { s.put(v); return s; }
1202 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char v) { s.put(v); return s; }
1203 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned char v) { s.put(v); return s; }
1204 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, signed char v) { s.put(v); return s; }
1205 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Snd_item const &v) { s.put_snd_item(v); return s; }
1206 template< typename T >
1207 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Cap<T> const &v)
1208 { s << L4::Ipc::Snd_fpage(v.fpage()); return s; }
1209 
1210 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg const &v)
1211 { s.put(v); return s; }
1212 template< typename T >
1213 inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg_t<T> const &v)
1214 { s.put(v); return s; }
1215 
1216 /**
1217  * Insert the L4 message tag into the stream `s`.
1218  *
1219  * \param s The stream to insert the tag `v`.
1220  * \param v The L4 message tag to insert.
1221  *
1222  * \return The stream `s`.
1223  *
1224  * \note Only one message tag can be inserted into a stream. Multiple
1225  * insertions simply overwrite previous insertions.
1226  */
1227 inline
1228 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, l4_msgtag_t const &v)
1229 {
1230  s.tag() = v;
1231  return s;
1232 }
1233 
1234 /**
1235  * Insert an array with elements of type `T` into the stream `s`.
1236  *
1237  * \param s The stream to insert the array `v`.
1238  * \param v The array to insert (see Ipc::Buf_cp_out()).
1239  *
1240  * \return the stream `s`.
1241  */
1242 template< typename T >
1243 inline
1244 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s,
1245  L4::Ipc::Internal::Buf_cp_out<T> const &v)
1246 {
1247  s.put(v.size());
1248  s.put(v.buf(), v.size());
1249  return s;
1250 }
1251 
1252 /**
1253  * Insert a zero terminated character string into the stream `s`.
1254  *
1255  * \param s The stream to insert the string `v`.
1256  * \param v The string to insert.
1257  *
1258  * \return The stream `s`.
1259  *
1260  * This operator produces basically the same content as the array insertion,
1261  * however the length of the array is calculated using `strlen(v) + 1`
1262  * The string is copied into the message including the trailing zero.
1263  */
1264 inline
1265 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char const *v)
1266 {
1267  unsigned long l = __builtin_strlen(v) + 1;
1268  s.put(l);
1269  s.put(v, l);
1270  return s;
1271 }
1272 
1273 
1274 #ifdef L4_CXX_IPC_BACKWARD_COMPAT
1275 namespace L4 {
1276 
1277 #if 0
1278 template< typename T > class Ipc_buf_cp_out : public Ipc::Buf_cp_out<T> {};
1279 template< typename T > class Ipc_buf_cp_in : public Ipc::Buf_cp_in<T> {};
1280 template< typename T > class Ipc_buf_in : public Ipc::Buf_in<T> {};
1281 template< typename T > class Msg_ptr : public Ipc::Msg_ptr<T> {};
1282 #endif
1283 
1284 template< typename T >
1285 Ipc::Internal::Buf_cp_out<T> ipc_buf_cp_out(T *v, unsigned long size)
1286  L4_DEPRECATED("Use L4::Ipc::buf_cp_out() now");
1287 
1288 template< typename T >
1289 Ipc::Internal::Buf_cp_out<T> ipc_buf_cp_out(T *v, unsigned long size)
1290 { return Ipc::Internal::Buf_cp_out<T>(v, size); }
1291 
1292 
1293 template< typename T >
1294 Ipc::Internal::Buf_cp_in<T> ipc_buf_cp_in(T *v, unsigned long &size)
1295  L4_DEPRECATED("Use L4::Ipc::buf_cp_in() now");
1296 
1297 template< typename T >
1298 Ipc::Internal::Buf_cp_in<T> ipc_buf_cp_in(T *v, unsigned long &size)
1299 { return Ipc::Internal::Buf_cp_in<T>(v, size); }
1300 
1301 
1302 template< typename T >
1303 Ipc::Internal::Buf_in<T> ipc_buf_in(T *&v, unsigned long &size)
1304  L4_DEPRECATED("Use L4::Ipc::buf_in() now");
1305 
1306 template< typename T >
1307 Ipc::Internal::Buf_in<T> ipc_buf_in(T *&v, unsigned long &size)
1308 { return Ipc::Internal::Buf_in<T>(v, size); }
1309 
1310 
1311 template< typename T >
1312 Ipc::Msg_ptr<T> msg_ptr(T *&p)
1313  L4_DEPRECATED("Use L4::Ipc::msg_ptr() now");
1314 
1315 template< typename T >
1316 Ipc::Msg_ptr<T> msg_ptr(T *&p)
1317 { return Ipc::Msg_ptr<T>(p); }
1318 
1319 typedef Ipc::Istream Ipc_istream L4_DEPRECATED("Use L4::Ipc::Istream now");
1320 typedef Ipc::Ostream Ipc_ostream L4_DEPRECATED("Use L4::Ipc::Ostream now");;
1321 typedef Ipc::Iostream Ipc_iostream L4_DEPRECATED("Use L4::Ipc::Iostream now");;
1322 typedef Ipc::Snd_fpage Snd_fpage L4_DEPRECATED("Use L4::Ipc::Snd_fpage now");;
1323 typedef Ipc::Rcv_fpage Rcv_fpage L4_DEPRECATED("Use L4::Ipc::Rcv_fpage now");;
1324 typedef Ipc::Small_buf Small_buf L4_DEPRECATED("Use L4::Ipc::Small_buf now");;
1325 
1326 
1327 namespace Ipc {
1328 template< typename T > class Buf_cp_in : public Internal::Buf_cp_in<T>
1329 {
1330 public:
1331  Buf_cp_in(T *v, unsigned long &size) : Internal::Buf_cp_in<T>(v, size) {}
1332 };
1333 
1334 template< typename T >
1335 class Buf_cp_out : public Internal::Buf_cp_out<T>
1336 {
1337 public:
1338  Buf_cp_out(T const *v, unsigned long size) : Internal::Buf_cp_out<T>(v, size) {}
1339 };
1340 
1341 template< typename T >
1342 class Buf_in : public Internal::Buf_in<T>
1343 {
1344 public:
1345  Buf_in(T *&v, unsigned long &size) : Internal::Buf_in<T>(v, size) {}
1346 };
1347 } // namespace Ipc
1348 } // namespace L4
1349 
1350 template< typename T >
1351 inline
1352 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Buf_cp_in<T> const &v)
1353  L4_DEPRECATED("Use L4::Ipc::buf_cp_in() now");
1354 
1355 template< typename T >
1356 inline
1357 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Buf_cp_in<T> const &v)
1358 { return operator>>(s, static_cast<L4::Ipc::Internal::Buf_cp_in<T> >(v)); }
1359 
1360 template< typename T >
1361 inline
1362 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Buf_in<T> const &v)
1363  L4_DEPRECATED("Use L4::Ipc::buf_in() now");
1364 
1365 template< typename T >
1366 inline
1367 L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Buf_in<T> const &v)
1368 { return operator>>(s, static_cast<L4::Ipc::Internal::Buf_in<T> >(v)); }
1369 
1370 template< typename T >
1371 inline
1372 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Buf_cp_out<T> const &v)
1373  L4_DEPRECATED("Use L4::Ipc::buf_cp_out() now");
1374 
1375 template< typename T >
1376 inline
1377 L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Buf_cp_out<T> const &v)
1378 { return operator<<(s, static_cast<L4::Ipc::Internal::Buf_cp_out<T> >(v)); }
1379 #endif
1380 
1381 namespace L4 { namespace Ipc {
1382 /**
1383  * Read a value out of a stream.
1384  *
1385  * \param s An Istream.
1386  * \return The value of type `T`.
1387  *
1388  * The stream position is progressed accordingly.
1389  */
1390 template< typename T >
1391 inline
1392 T read(Istream &s) { T t; s >> t; return t; }
1393 
1394 } // namespace Ipc
1395 } // namespace L4