L4Re - L4 Runtime Environment
event
Go to the documentation of this file.
1 // vi:set ft=cpp: -*- Mode: C++ -*-
2 /**
3  * \file
4  */
5 /*
6  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
7  * Alexander Warg <warg@os.inf.tu-dresden.de>
8  * economic rights: Technische Universit├Ąt Dresden (Germany)
9  *
10  * This file is part of TUD:OS and distributed under the terms of the
11  * GNU General Public License 2.
12  * Please see the COPYING-GPL-2 file for details.
13  *
14  * As a special exception, you may use this file as part of a free software
15  * library without restriction. Specifically, if other files instantiate
16  * templates or use macros or inline functions from this file, or you compile
17  * this file and link it with other files to produce an executable, this
18  * file does not by itself cause the resulting executable to be covered by
19  * the GNU General Public License. This exception does not however
20  * invalidate any other reasons why the executable file might be covered by
21  * the GNU General Public License.
22  */
23 #pragma once
24 
25 #include <l4/re/cap_alloc>
26 #include <l4/re/util/cap_alloc>
27 #include <l4/re/util/unique_cap>
28 #include <l4/re/env>
29 #include <l4/re/rm>
30 #include <l4/re/util/event_buffer>
31 #include <l4/sys/factory>
32 #include <l4/cxx/type_traits>
33 
34 namespace L4Re { namespace Util {
35 
36 /**
37  * Convenience wrapper for getting access to an event object.
38  *
39  * After calling init() the class supplies the event-buffer and the
40  * associated IRQ object.
41  */
42 template< typename PAYLOAD >
43 class Event_t
44 {
45 public:
46  /**
47  * Modes of operation.
48  */
49  enum Mode
50  {
51  Mode_irq, ///< Create an IRQ and attach, to get notifications.
52  Mode_polling, ///< Do not use an IRQ.
53  };
54 
55  /**
56  * Initialise an event object.
57  *
58  * \tparam IRQ_TYPE Type used for handling notifications from the event
59  * provider. This must be derived from L4::Triggerable.
60  *
61  * \param event Capability to event.
62  * \param env Pointer to L4Re-Environment
63  * \param ca Pointer to capability allocator.
64  *
65  * \retval 0 Success
66  * \retval -L4_ENOMEM No memory to allocate required capabilities.
67  * \retval <0 Other IPC errors.
68  */
69  template<typename IRQ_TYPE>
70  int init(L4::Cap<L4Re::Event> event,
71  L4Re::Env const *env = L4Re::Env::env(),
72  L4Re::Cap_alloc *ca = L4Re::Cap_alloc::get_cap_alloc(L4Re::Util::cap_alloc))
73  {
74  Unique_cap<L4Re::Dataspace> ev_ds(ca->alloc<L4Re::Dataspace>());
75  if (!ev_ds.is_valid())
76  return -L4_ENOMEM;
77 
78  int r;
79 
80  Unique_del_cap<IRQ_TYPE> ev_irq(ca->alloc<IRQ_TYPE>());
81  if (!ev_irq.is_valid())
82  return -L4_ENOMEM;
83 
84  if ((r = l4_error(env->factory()->create(ev_irq.get()))))
85  return r;
86 
87  if ((r = l4_error(event->bind(0, ev_irq.get()))))
88  return r;
89 
90  if ((r = event->get_buffer(ev_ds.get())))
91  return r;
92 
93  long sz = ev_ds->size();
94  if (sz < 0)
95  return sz;
96 
97  Rm::Unique_region<void*> buf;
98 
99  if ((r = env->rm()->attach(&buf, sz, L4Re::Rm::Search_addr,
100  L4::Ipc::make_cap_rw(ev_ds.get()))))
101  return r;
102 
103  _ev_buffer = L4Re::Event_buffer_t<PAYLOAD>(buf.get(), sz);
104  _ev_ds = cxx::move(ev_ds);
105  _ev_irq = cxx::move(ev_irq);
106  _buf = cxx::move(buf);
107 
108  return 0;
109  }
110 
111  /**
112  * Initialise an event object in polling mode.
113  *
114  * \param event Capability to event.
115  * \param env Pointer to L4Re-Environment
116  * \param ca Pointer to capability allocator.
117  *
118  * \retval 0 Success
119  * \retval -L4_ENOMEM No memory to allocate required capabilities.
120  * \retval <0 Other IPC errors.
121  */
122  int init_poll(L4::Cap<L4Re::Event> event,
123  L4Re::Env const *env = L4Re::Env::env(),
124  L4Re::Cap_alloc *ca = L4Re::Cap_alloc::get_cap_alloc(L4Re::Util::cap_alloc))
125  {
126  Unique_cap<L4Re::Dataspace> ev_ds(ca->alloc<L4Re::Dataspace>());
127  if (!ev_ds.is_valid())
128  return -L4_ENOMEM;
129 
130  int r;
131 
132  if ((r = event->get_buffer(ev_ds.get())))
133  return r;
134 
135  long sz = ev_ds->size();
136  if (sz < 0)
137  return sz;
138 
139  Rm::Unique_region<void*> buf;
140 
141  if ((r = env->rm()->attach(&buf, sz, L4Re::Rm::Search_addr,
142  L4::Ipc::make_cap_rw(ev_ds.get()))))
143  return r;
144 
145  _ev_buffer = L4Re::Event_buffer_t<PAYLOAD>(buf.get(), sz);
146  _ev_ds = cxx::move(ev_ds);
147  _buf = cxx::move(buf);
148 
149  return 0;
150  }
151 
152  /**
153  * Get event buffer.
154  *
155  * \return Event buffer object.
156  */
157  L4Re::Event_buffer_t<PAYLOAD> &buffer() { return _ev_buffer; }
158 
159  /**
160  * Get event IRQ.
161  *
162  * \return Event IRQ.
163  */
164  L4::Cap<L4::Triggerable> irq() const { return _ev_irq.get(); }
165 
166 private:
167  Unique_cap<L4Re::Dataspace> _ev_ds;
168  Unique_del_cap<L4::Triggerable> _ev_irq;
169  L4Re::Event_buffer_t<PAYLOAD> _ev_buffer;
170  Rm::Unique_region<void*> _buf;
171 };
172 
173 typedef Event_t<Default_event_payload> Event;
174 
175 }}