L4Re - L4 Runtime Environment
event_buffer
1 // vi:set ft=cpp: -*- Mode: C++ -*-
2 /*
3  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
4  * Alexander Warg <warg@os.inf.tu-dresden.de>
5  * economic rights: Technische Universit├Ąt Dresden (Germany)
6  *
7  * This file is part of TUD:OS and distributed under the terms of the
8  * GNU General Public License 2.
9  * Please see the COPYING-GPL-2 file for details.
10  *
11  * As a special exception, you may use this file as part of a free software
12  * library without restriction. Specifically, if other files instantiate
13  * templates or use macros or inline functions from this file, or you compile
14  * this file and link it with other files to produce an executable, this
15  * file does not by itself cause the resulting executable to be covered by
16  * the GNU General Public License. This exception does not however
17  * invalidate any other reasons why the executable file might be covered by
18  * the GNU General Public License.
19  */
20 
21 #pragma once
22 
23 #include <l4/re/event>
24 #include <l4/re/event-sys.h>
25 #include <l4/re/rm>
26 
27 #include <cstring>
28 
29 namespace L4Re { namespace Util {
30 
31 /**
32  * \brief Event_buffer utility class.
33  * \ingroup api_l4re_util
34  */
35 template< typename PAYLOAD >
36 class Event_buffer_t : public L4Re::Event_buffer_t<PAYLOAD>
37 {
38 private:
39  void *_buf;
40 public:
41  /**
42  * \brief Return the buffer.
43  *
44  * \return Pointer to the event buffer.
45  */
46  void *buf() const throw() { return _buf; }
47 
48  /**
49  * \brief Attach event buffer from address space.
50  *
51  * \param ds Dataspace of the event buffer.
52  * \param rm Region manager to attach buffer to.
53  *
54  * \return 0 on success, negative error code otherwise.
55  */
56  long attach(L4::Cap<L4Re::Dataspace> ds, L4::Cap<L4Re::Rm> rm) throw()
57  {
58  l4_addr_t sz = ds->size();
59  _buf = 0;
60 
61  long r = rm->attach(&_buf, sz, L4Re::Rm::Search_addr,
62  L4::Ipc::make_cap_rw(ds));
63  if (r < 0)
64  return r;
65 
66  *(L4Re::Event_buffer_t<PAYLOAD>*)this = L4Re::Event_buffer_t<PAYLOAD>(_buf, sz);
67  return 0;
68  }
69 
70  /**
71  * \brief Detach event buffer from address space.
72  *
73  * \param rm Region manager to detach buffer from.
74  *
75  * \return 0 on success, negative error code otherwise.
76  */
77  long detach(L4::Cap<L4Re::Rm> rm) throw()
78  {
79  L4::Cap<L4Re::Dataspace> ds;
80  if (_buf)
81  return rm->detach(_buf, &ds);
82  return 0;
83  }
84 
85 };
86 
87 /**
88  * \brief An event buffer consumer.
89  * \ingroup api_l4re_util
90  */
91 template< typename PAYLOAD >
92 class Event_buffer_consumer_t : public Event_buffer_t<PAYLOAD>
93 {
94 public:
95 
96  /**
97  * \brief Call function on every available event.
98  *
99  * \param cb Function callback.
100  * \param data Data to pass as an argument to the callback.
101  */
102  template< typename CB, typename D >
103  void foreach_available_event(CB const &cb, D data = D())
104  {
105  typename Event_buffer_t<PAYLOAD>::Event *e;
106  while ((e = Event_buffer_t<PAYLOAD>::next()))
107  {
108  cb(e, data);
109  e->free();
110  }
111  }
112 
113  /**
114  * \brief Continuously wait for events and process them.
115  *
116  * \param irq Event signal to wait for.
117  * \param thread Thread capability of the thread calling this function.
118  * \param cb Callback function that is called for each received event.
119  * \param data Data to pass as an argument to the processing callback.
120  *
121  * \note This function never returns.
122  */
123  template< typename CB, typename D >
124  void process(L4::Cap<L4::Irq> irq,
125  L4::Cap<L4::Thread> thread,
126  CB const &cb, D data = D())
127  {
128 
129  if (l4_error(irq->bind_thread(thread, 0)))
130  return;
131 
132  while (1)
133  {
134  long r;
135  r = l4_ipc_error(l4_irq_receive(irq.cap(), L4_IPC_NEVER),
136  l4_utcb());
137  if (r)
138  continue;
139 
140  foreach_available_event(cb, data);
141  }
142  }
143 };
144 
145 typedef Event_buffer_t<Default_event_payload> Event_buffer;
146 typedef Event_buffer_consumer_t<Default_event_payload> Event_buffer_consumer;
147 
148 }}