L4Re - L4 Runtime Environment
ipc_timeout_queue
1 // vim:set ft=cpp: -*- Mode: C++ -*-
2 /*
3  * (c) 2014 Steffen Liebergeld <steffen.liebergeld@kernkonzept.com>
4  *
5  * This file is licensed under the terms of the GNU General Public License 2.
6  * Please see the COPYING-GPL-2 file for details.
7  *
8  * As a special exception, you may use this file as part of a free software
9  * library without restriction. Specifically, if other files instantiate
10  * templates or use macros or inline functions from this file, or you compile
11  * this file and link it with other files to produce an executable, this file
12  * does not by itself cause the resulting executable to be covered by the GNU
13  * General Public License. This exception does not however invalidate any other
14  * reasons why the executable file might be covered by the GNU General Public
15  * License.
16  */
17 #pragma once
18 
19 #include <l4/cxx/hlist>
20 #include <l4/sys/cxx/ipc_server_loop>
21 
22 namespace L4 { namespace Ipc_svr {
23 
28 class Timeout : public cxx::H_list_item
29 {
30  friend class Timeout_queue;
31 public:
33  Timeout() : _timeout(0) {}
34 
36  virtual ~Timeout() = 0;
37 
43  virtual void expired() = 0;
44 
52  { return _timeout; }
53 
54 private:
55  l4_kernel_clock_t _timeout;
56 };
57 
58 inline Timeout::~Timeout() {}
59 
65 {
66 public:
69 
75  {
76  if (auto e = _timeouts.front())
77  return e->timeout();
78 
79  return 0;
80  }
81 
91  {
92  l4_kernel_clock_t next = next_timeout();
93  return (next != 0) && (next <= now);
94  }
95 
101  {
102  while (!_timeouts.empty())
103  {
104  Queue::Iterator top = _timeouts.begin();
105  if ((*top)->_timeout > now)
106  return;
107 
108  Timeout *t = *top;
109  top = _timeouts.erase(top);
110  t->expired();
111  }
112  }
113 
120  void add(Timeout *timeout, l4_kernel_clock_t time)
121  {
122  timeout->_timeout = time;
123  Queue::Iterator i = _timeouts.begin();
124  while (i != _timeouts.end() && (*i)->timeout() < time)
125  ++i;
126 
127  _timeouts.insert_before(timeout, i);
128  }
129 
135  void remove(Timeout *timeout)
136  {
137  _timeouts.remove(timeout);
138  }
139 
140 private:
141  typedef cxx::H_list<Timeout> Queue;
142  Queue _timeouts;
143 };
144 
158 template< typename HOOKS, typename BR_MAN = Br_manager_no_buffers >
159 class Timeout_queue_hooks : public BR_MAN
160 {
161  l4_kernel_clock_t _now()
162  { return static_cast<HOOKS*>(this)->now(); }
163 
164  unsigned _timeout_br()
165  { return this->first_free_br(); }
166 
167 public:
170  {
171  l4_kernel_clock_t t = queue.next_timeout();
172  if (t)
173  return l4_timeout(L4_IPC_TIMEOUT_0, l4_timeout_abs(t, _timeout_br()));
174  return L4_IPC_SEND_TIMEOUT_0;
175  }
176 
179  {
180  // we must handle the timer only when called after a possible reply
181  // otherwise we probably destroy the reply message.
182  if (mode == L4::Ipc_svr::Reply_separate)
183  {
184  l4_kernel_clock_t now = _now();
185  if (queue.timeout_expired(now))
186  queue.handle_expired_timeouts(now);
187  }
188 
189  BR_MAN::setup_wait(utcb, mode);
190  }
191 
194  {
195  // split up reply and wait when a timeout has expired
196  if (queue.timeout_expired(_now()))
199  }
200 
212  {
213  queue.add(timeout, time);
214  return 0;
215  }
216 
225  {
226  queue.remove(timeout);
227  return 0;
228  }
229 
231 };
232 
233 }}
l4_timeout_t l4_timeout(l4_timeout_s snd, l4_timeout_s rcv) L4_NOTHROW
Combine send and receive timeout in a timeout.
Definition: __timeout.h:221
Reply_mode
Reply mode for server loop.
Definition: ipc_server_loop:50
Server shall call reply and wait separately.
Definition: ipc_server_loop:53
L4::Ipc_svr::Reply_mode before_reply(l4_msgtag_t, l4_utcb_t *)
server loop hook
void handle_expired_timeouts(l4_kernel_clock_t now)
run the callbacks of expired timeouts
Timeout queue to be used in l4re server loop.
L4 low-level kernel interface.
L4::Ipc_svr::Timeout Timeout
Provide a local definition of Timeout for backward compat.
void setup_wait(l4_utcb_t *utcb, L4::Ipc_svr::Reply_mode mode)
setup_wait() for the server loop
l4_kernel_clock_t timeout() const
return absolute timeout of this callback.
struct l4_utcb_t l4_utcb_t
Opaque type for the UTCB.
Definition: utcb.h:67
Callback interface for Timeout_queue.
Timeout pair.
Definition: __timeout.h:57
l4_timeout_s l4_timeout_abs(l4_kernel_clock_t pint, int br) L4_NOTHROW
Set an absolute timeout.
Definition: utcb.h:383
l4_kernel_clock_t next_timeout() const
Get the time for the next timeout.
bool timeout_expired(l4_kernel_clock_t now) const
Determine if a timeout has happened.
virtual ~Timeout()=0
Destroy a timeout.
Basic element type for a double-linked H_list.
Definition: hlist:33
l4_uint64_t l4_kernel_clock_t
Kernel clock type.
Definition: l4int.h:65
Timeout_queue queue
Use this timeout queue.
virtual void expired()=0
callback function to be called when timeout happened
int add_timeout(Timeout *timeout, l4_kernel_clock_t time)
Add a timout to the queue for time time.
l4_timeout_t timeout()
get the time for the next timeout
int remove_timeout(Timeout *timeout)
Remove timeout from the queue.
#define L4_IPC_SEND_TIMEOUT_0
0 send timeout
Definition: __timeout.h:82
Timeout()
Make a timeout.
void add(Timeout *timeout, l4_kernel_clock_t time)
Add a timeout to the queue.
#define L4_IPC_TIMEOUT_0
Timeout constants.
Definition: __timeout.h:77
Message tag data structure.
Definition: types.h:159
Loop hooks mixin for integrating a timeout queue into the server loop.
Server shall use a compound reply and wait (fast).
Definition: ipc_server_loop:52