]> rtime.felk.cvut.cz Git - l4.git/blobdiff - l4/pkg/cxx/lib/ipc/include/ipc_stream
update
[l4.git] / l4 / pkg / cxx / lib / ipc / include / ipc_stream
index 4eed5a3de3b327a60f5841b5ca9f903226b40023..4d77b896b7644b519326c3771bf4f104367b7d9b 100644 (file)
@@ -4,7 +4,11 @@
  * \brief IPC stream
  */
 /*
- * (c) 2008-2009 Technische Universität Dresden
+ * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *               Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
+ *     economic rights: Technische Universität Dresden (Germany)
+ *
  * This file is part of TUD:OS and distributed under the terms of the
  * GNU General Public License 2.
  * Please see the COPYING-GPL-2 file for details.
@@ -85,7 +89,7 @@ private:
 /**
  * \brief Create an instance of Buf_cp_out for the given values.
  * \ingroup ipc_fw
- * 
+ *
  * This function makes it more convenient to insert arrays into an
  * Ipc::Ostream (\see Buf_cp_out.)
  *
@@ -132,7 +136,7 @@ private:
 /**
  * \brief Create an Buf_cp_in for the given values.
  * \ingroup ipc_fw
- * 
+ *
  * This function makes it more convenient to extract arrays from an
  * Ipc::Istream (\see Buf_cp_in.)
  *
@@ -179,7 +183,7 @@ public:
 /**
  * \brief Create an Msg_ptr to adjust the given pointer.
  * \ingroup ipc_fw
- * 
+ *
  * This function makes it more convenient to extract pointers to data in the
  * message buffer itself from an Ipc::Istream.
  * This may be used to avoid copy out of large data structures.
@@ -207,7 +211,7 @@ template< typename T >
 class Buf_in
 {
 public:
-  /** 
+  /**
    * \brief Create an Buf_in to adjust a pointer to the array and the size
    *        of the array.
    * \param v The pointer to adjust to the first element of the array.
@@ -226,7 +230,7 @@ private:
 /**
  * \brief Create an Buf_in for the given values.
  * \ingroup ipc_fw
- * 
+ *
  * This function makes it more convenient to extract arrays from an
  * Ipc::Istream (See Buf_in.)
  *
@@ -543,6 +547,12 @@ private:
   Value _data;
 };
 
+namespace Utcb_stream_check
+{
+  static bool check_utcb_data_offset(unsigned sz)
+  { return sz > sizeof(l4_umword_t) * L4_UTCB_GENERIC_DATA_SIZE; }
+}
+
 
 /**
  * \brief Input stream for IPC unmarshalling.
@@ -564,7 +574,7 @@ class Istream
 public:
   /**
    * \brief Create an input stream for the given message buffer.
-   * 
+   *
    * The given message buffer is used for IPC operations wait()/receive()
    * and received data can be extracted using the >> operator afterwards.
    * In the case of indirect message parts a buffer of type Msg_in_buffer
@@ -622,7 +632,7 @@ public:
   {
     size *= sizeof(T);
     _pos = cxx::Type_traits<T>::align(_pos);
-    if ((_pos + size) / sizeof(l4_umword_t) > L4_UTCB_GENERIC_DATA_SIZE)
+    if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
       return;
 
     __builtin_memcpy(buf, _current_msg + _pos, size);
@@ -639,13 +649,13 @@ public:
   {
     size *= sizeof(T);
     _pos = cxx::Type_traits<T>::align(_pos);
-    if ((_pos + size) / sizeof(l4_umword_t) > L4_UTCB_GENERIC_DATA_SIZE)
+    if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
       return;
     _pos += size;
   }
 
   /**
-   * \brief Read one size elements of type T from the stream and return 
+   * \brief Read one size elements of type T from the stream and return
    *        a pointer.
    *
    * In contrast to a normal get, this version does actually not copy the data
@@ -662,10 +672,10 @@ public:
   {
     size *= sizeof(T);
     _pos = cxx::Type_traits<T>::align(_pos);
-    if ((_pos + size) / sizeof(l4_umword_t) > L4_UTCB_GENERIC_DATA_SIZE)
+    if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
       return;
 
-    buf.set(reinterpret_cast<T*>(_current_msg + _pos)); 
+    buf.set(reinterpret_cast<T*>(_current_msg + _pos));
     _pos += size;
   }
 
@@ -679,8 +689,8 @@ public:
   template< typename T >
   void get(T &v)
   {
-    _pos = cxx::Type_traits<T>::align(_pos); 
-    if ((_pos + sizeof(T)) > L4_UTCB_GENERIC_DATA_SIZE * sizeof(l4_umword_t))
+    _pos = cxx::Type_traits<T>::align(_pos);
+    if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
       {
        v = T();
         return;
@@ -733,7 +743,7 @@ public:
    * \brief Put a receive item into the stream's buffer registers.
    */
   inline bool put(Buf_item const &);
-  
+
   /**
    * \internal
    * \brief Put a small receive item into the stream's buffer registers.
@@ -854,7 +864,7 @@ public:
   {
     size *= sizeof(T);
     _pos = cxx::Type_traits<T>::align(_pos);
-    if ((_pos + size) / sizeof(l4_umword_t) > L4_UTCB_GENERIC_DATA_SIZE)
+    if (Utcb_stream_check::check_utcb_data_offset(_pos + size))
       return;
 
     __builtin_memcpy(_current_msg + _pos, buf, size);
@@ -869,7 +879,7 @@ public:
   void put(T const &v)
   {
     _pos = cxx::Type_traits<T>::align(_pos);
-    if ((_pos + sizeof(T)) / sizeof(l4_umword_t) > L4_UTCB_GENERIC_DATA_SIZE)
+    if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
       return;
 
     *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
@@ -937,14 +947,15 @@ public:
     _tag = l4_msgtag(0, w, _current_item, 0);
   }
 #endif
-protected:
-  void pre_ipc()
+public:
+  l4_msgtag_t prepare_ipc(long proto = 0, unsigned flags = 0)
   {
     register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t);
     w -= _current_item * 2;
-    _tag = l4_msgtag(0, w, _current_item, 0);
+    return l4_msgtag(proto, w, _current_item, flags);
   }
 
+protected:
   l4_msgtag_t _tag;
   l4_utcb_t *_utcb;
   char *_current_msg;
@@ -1065,12 +1076,11 @@ public:
                                     l4_timeout_t timeout, long proto = 0);
   inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
                                    l4_timeout_t timeout, long proto = 0);
-  inline l4_msgtag_t reply(l4_timeout_t timeout, long proto);
-  inline l4_msgtag_t reply(long proto)
+  inline l4_msgtag_t reply(l4_timeout_t timeout, long proto = 0);
+  inline l4_msgtag_t reply(long proto = 0)
   { return reply(L4_IPC_SEND_TIMEOUT_0, proto); }
 
   //@}
-
 };
 
 
@@ -1079,7 +1089,7 @@ Ostream::put_snd_item(Snd_item const &v)
 {
   typedef Snd_item T;
   _pos = cxx::Type_traits<Snd_item>::align(_pos);
-  if ((_pos + sizeof(T)) / sizeof(l4_umword_t) >= L4_UTCB_GENERIC_DATA_SIZE)
+  if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T)))
     return false;
 
   *(reinterpret_cast<T*>(_current_msg + _pos)) = v;
@@ -1120,47 +1130,39 @@ Istream::put(Small_buf const &item)
 inline l4_msgtag_t
 Ostream::send(l4_cap_idx_t dst, long proto, unsigned flags)
 {
-  pre_ipc();
-  //unsigned long *b = reinterpret_cast<unsigned long*>(_msg->_msg);
-  _tag.label(proto);
-  _tag.raw |= (L4_MSGTAG_FLAGS & flags);
-  return l4_ipc_send(dst, _utcb, _tag, L4_IPC_NEVER);
+  l4_msgtag_t tag = prepare_ipc(proto, L4_MSGTAG_FLAGS & flags);
+  return l4_ipc_send(dst, _utcb, tag, L4_IPC_NEVER);
 }
 
 inline l4_msgtag_t
 Iostream::call(l4_cap_idx_t dst)
 {
-  pre_ipc();
-  l4_msgtag_t res;
-  res = l4_ipc_call(dst, Ostream::_utcb, Ostream::_tag, L4_IPC_NEVER);
-  Istream::tag() = res;
+  l4_msgtag_t tag = prepare_ipc();
+  tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER);
+  Istream::tag() = tag;
   Istream::_pos = 0;
-  return res;
+  return tag;
 }
 
 inline l4_msgtag_t
 Iostream::call(l4_cap_idx_t dst, long label)
 {
-  pre_ipc();
-  l4_msgtag_t res;
-  Ostream::_tag.label(label);
-  res = l4_ipc_call(dst, Ostream::_utcb, Ostream::_tag, L4_IPC_NEVER);
-  Istream::tag() = res;
+  l4_msgtag_t tag = prepare_ipc(label);
+  tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER);
+  Istream::tag() = tag;
   Istream::_pos = 0;
-  return res;
+  return tag;
 }
 
 
 inline l4_msgtag_t
 Iostream::reply_and_wait(l4_umword_t *src_dst, l4_timeout_t timeout, long proto)
 {
-  pre_ipc();
-  l4_msgtag_t res;
-  Ostream::_tag.label(proto);
-  res = l4_ipc_reply_and_wait(Ostream::_utcb, Ostream::_tag, src_dst, timeout);
-  Istream::tag() = res;
+  l4_msgtag_t tag = prepare_ipc(proto);
+  tag = l4_ipc_reply_and_wait(Ostream::_utcb, tag, src_dst, timeout);
+  Istream::tag() = tag;
   Istream::_pos = 0;
-  return res;
+  return tag;
 }
 
 
@@ -1168,25 +1170,21 @@ inline l4_msgtag_t
 Iostream::send_and_wait(l4_cap_idx_t dest, l4_umword_t *src,
                         l4_timeout_t timeout, long proto)
 {
-  pre_ipc();
-  l4_msgtag_t res;
-  Ostream::_tag.label(proto);
-  res = l4_ipc_send_and_wait(dest, Ostream::_utcb, Ostream::_tag, src, timeout);
-  Istream::tag() = res;
+  l4_msgtag_t tag = prepare_ipc(proto);
+  tag = l4_ipc_send_and_wait(dest, Ostream::_utcb, tag, src, timeout);
+  Istream::tag() = tag;
   Istream::_pos = 0;
-  return res;
+  return tag;
 }
 
 inline l4_msgtag_t
 Iostream::reply(l4_timeout_t timeout, long proto)
 {
-  pre_ipc();
-  l4_msgtag_t res;
-  Ostream::_tag.label(proto);
-  res = l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, Ostream::_utcb, Ostream::_tag, timeout);
-  Istream::tag() = res;
+  l4_msgtag_t tag = prepare_ipc(proto);
+  tag = l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, Ostream::_utcb, tag, timeout);
+  Istream::tag() = tag;
   Istream::_pos = 0;
-  return res;
+  return tag;
 }
 
 inline l4_msgtag_t