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 34namespace 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 */ 42template< typename PAYLOAD > 43class Event_t 44{ 45public: 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, 100 L4Re::Rm::F::Search_addr | L4Re::Rm::F::RW, 101 L4::Ipc::make_cap_rw(ev_ds.get())))) 102 return r; 103 104 _ev_buffer = L4Re::Event_buffer_t<PAYLOAD>(buf.get(), sz); 105 _ev_ds = cxx::move(ev_ds); 106 _ev_irq = cxx::move(ev_irq); 107 _buf = cxx::move(buf); 108 109 return 0; 110 } 111 112 /** 113 * Initialise an event object in polling mode. 114 * 115 * \param event Capability to event. 116 * \param env Pointer to L4Re-Environment 117 * \param ca Pointer to capability allocator. 118 * 119 * \retval 0 Success 120 * \retval -L4_ENOMEM No memory to allocate required capabilities. 121 * \retval <0 Other IPC errors. 122 */ 123 int init_poll(L4::Cap<L4Re::Event> event, 124 L4Re::Env const *env = L4Re::Env::env(), 125 L4Re::Cap_alloc *ca = L4Re::Cap_alloc::get_cap_alloc(L4Re::Util::cap_alloc)) 126 { 127 Unique_cap<L4Re::Dataspace> ev_ds(ca->alloc<L4Re::Dataspace>()); 128 if (!ev_ds.is_valid()) 129 return -L4_ENOMEM; 130 131 int r; 132 133 if ((r = event->get_buffer(ev_ds.get()))) 134 return r; 135 136 long sz = ev_ds->size(); 137 if (sz < 0) 138 return sz; 139 140 Rm::Unique_region<void*> buf; 141 142 if ((r = env->rm()->attach(&buf, sz, 143 L4Re::Rm::F::Search_addr | L4Re::Rm::F::RW, 144 L4::Ipc::make_cap_rw(ev_ds.get())))) 145 return r; 146 147 _ev_buffer = L4Re::Event_buffer_t<PAYLOAD>(buf.get(), sz); 148 _ev_ds = cxx::move(ev_ds); 149 _buf = cxx::move(buf); 150 151 return 0; 152 } 153 154 /** 155 * Get event buffer. 156 * 157 * \return Event buffer object. 158 */ 159 L4Re::Event_buffer_t<PAYLOAD> &buffer() { return _ev_buffer; } 160 161 /** 162 * Get event IRQ. 163 * 164 * \return Event IRQ. 165 */ 166 L4::Cap<L4::Triggerable> irq() const { return _ev_irq.get(); } 167 168private: 169 Unique_cap<L4Re::Dataspace> _ev_ds; 170 Unique_del_cap<L4::Triggerable> _ev_irq; 171 L4Re::Event_buffer_t<PAYLOAD> _ev_buffer; 172 Rm::Unique_region<void*> _buf; 173}; 174 175typedef Event_t<Default_event_payload> Event; 176 177}} 178