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 29namespace L4Re { namespace Util { 30 31/** 32 * \brief Event_buffer utility class. 33 * \ingroup api_l4re_util 34 */ 35template< typename PAYLOAD > 36class Event_buffer_t : public L4Re::Event_buffer_t<PAYLOAD> 37{ 38private: 39 void *_buf; 40public: 41 /** 42 * \brief Return the buffer. 43 * 44 * \return Pointer to the event buffer. 45 */ 46 void *buf() const noexcept { 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) noexcept 57 { 58 l4_addr_t sz = ds->size(); 59 _buf = 0; 60 61 long r = rm->attach(&_buf, sz, 62 L4Re::Rm::F::Search_addr | L4Re::Rm::F::RW, 63 L4::Ipc::make_cap_rw(ds)); 64 if (r < 0) 65 return r; 66 67 *(L4Re::Event_buffer_t<PAYLOAD>*)this = L4Re::Event_buffer_t<PAYLOAD>(_buf, sz); 68 return 0; 69 } 70 71 /** 72 * \brief Detach event buffer from address space. 73 * 74 * \param rm Region manager to detach buffer from. 75 * 76 * \return 0 on success, negative error code otherwise. 77 */ 78 long detach(L4::Cap<L4Re::Rm> rm) noexcept 79 { 80 L4::Cap<L4Re::Dataspace> ds; 81 if (_buf) 82 return rm->detach(_buf, &ds); 83 return 0; 84 } 85 86}; 87 88/** 89 * \brief An event buffer consumer. 90 * \ingroup api_l4re_util 91 */ 92template< typename PAYLOAD > 93class Event_buffer_consumer_t : public Event_buffer_t<PAYLOAD> 94{ 95public: 96 97 /** 98 * \brief Call function on every available event. 99 * 100 * \param cb Function callback. 101 * \param data Data to pass as an argument to the callback. 102 */ 103 template< typename CB, typename D > 104 void foreach_available_event(CB const &cb, D data = D()) 105 { 106 typename Event_buffer_t<PAYLOAD>::Event *e; 107 while ((e = Event_buffer_t<PAYLOAD>::next())) 108 { 109 cb(e, data); 110 e->free(); 111 } 112 } 113 114 /** 115 * \brief Continuously wait for events and process them. 116 * 117 * \param irq Event signal to wait for. 118 * \param thread Thread capability of the thread calling this function. 119 * \param cb Callback function that is called for each received event. 120 * \param data Data to pass as an argument to the processing callback. 121 * 122 * \note This function never returns. 123 */ 124 template< typename CB, typename D > 125 void process(L4::Cap<L4::Irq> irq, 126 L4::Cap<L4::Thread> thread, 127 CB const &cb, D data = D()) 128 { 129 130 if (l4_error(irq->bind_thread(thread, 0))) 131 return; 132 133 while (1) 134 { 135 long r; 136 r = l4_ipc_error(l4_irq_receive(irq.cap(), L4_IPC_NEVER), 137 l4_utcb()); 138 if (r) 139 continue; 140 141 foreach_available_event(cb, data); 142 } 143 } 144}; 145 146typedef Event_buffer_t<Default_event_payload> Event_buffer; 147typedef Event_buffer_consumer_t<Default_event_payload> Event_buffer_consumer; 148 149}} 150