1 /**
2  * \internal
3  * \file
4  * Timeout definitions.
5  */
6 /*
7  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
8  *               Alexander Warg <warg@os.inf.tu-dresden.de>,
9  *               Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
10  *     economic rights: Technische Universität Dresden (Germany)
11  *
12  * This file is part of TUD:OS and distributed under the terms of the
13  * GNU General Public License 2.
14  * Please see the COPYING-GPL-2 file for details.
15  *
16  * As a special exception, you may use this file as part of a free software
17  * library without restriction.  Specifically, if other files instantiate
18  * templates or use macros or inline functions from this file, or you compile
19  * this file and link it with other files to produce an executable, this
20  * file does not by itself cause the resulting executable to be covered by
21  * the GNU General Public License.  This exception does not however
22  * invalidate any other reasons why the executable file might be covered by
23  * the GNU General Public License.
24  */
25 #ifndef L4_SYS_TIMEOUT_H__
26 #define L4_SYS_TIMEOUT_H__
27 
28 #include <l4/sys/l4int.h>
29 
30 /**
31  * \defgroup l4_timeout_api Timeouts
32  * \ingroup l4_ipc_api
33  * All kinds of timeouts and time related functions.
34  */
35 
36 /**
37  * Basic timeout specification.
38  * \ingroup l4_timeout_api
39  *
40  * Basically a floating point number with 10 bits mantissa and
41  * 5 bits exponent (t = m*2^e).
42  *
43  * If bit 15 == 1 the timeout is absolute and the lower 6 bits encode the index
44  * of the UTCB buffer register(s) holding the absolute 64-bit timeout value. On
45  * 32-bit systems, two consecutive UTCB buffer registers are used.
46  */
47 typedef struct l4_timeout_s {
48   l4_uint16_t t;                           /**< timeout value */
49 } __attribute__((packed)) l4_timeout_s;
50 
51 
52 /**
53  * Timeout pair.
54  * \ingroup l4_timeout_api
55  *
56  * For IPC there are usually a send and a receive timeout.
57  * So this structure contains a pair of timeouts.
58  */
59 typedef union l4_timeout_t {
60   l4_uint32_t raw;                 /**< raw value */
61   struct
62   {
63 #ifdef __BIG_ENDIAN__
64     l4_timeout_s snd;              /**< send timeout */
65     l4_timeout_s rcv;              /**< receive timeout */
66 #else
67     l4_timeout_s rcv;              /**< receive timeout */
68     l4_timeout_s snd;              /**< send timeout */
69 #endif
70   } p;                             /**< combined timeout */
71 } l4_timeout_t;
72 
73 
74 /**
75  * Timeout constants.
76  * \ingroup l4_timeout_api
77  */
78 /*@{*/
79 #define L4_IPC_TIMEOUT_0 ((l4_timeout_s){0x0400})           /**< 0 timeout */
80 #define L4_IPC_TIMEOUT_NEVER ((l4_timeout_s){0})            /**< never timeout */
81 #define L4_IPC_NEVER_INITIALIZER {0}                        /**< never timeout, init */
82 #define L4_IPC_NEVER ((l4_timeout_t){0})                    /**< never timeout */
83 #define L4_IPC_RECV_TIMEOUT_0 ((l4_timeout_t){0x00000400})  /**< 0 receive timeout */
84 #define L4_IPC_SEND_TIMEOUT_0 ((l4_timeout_t){0x04000000})  /**< 0 send timeout */
85 #define L4_IPC_BOTH_TIMEOUT_0 ((l4_timeout_t){0x04000400})  /**< 0 receive and send timeout */
86 /*@}*/
87 
88 /**
89  * Get relative timeout consisting of mantissa and exponent.
90  * \ingroup l4_timeout_api
91  *
92  * \param man  Mantissa of timeout
93  * \param exp  Exponent of timeout
94  *
95  * \return timeout value
96  */
97 L4_INLINE
98 l4_timeout_s l4_timeout_rel(unsigned man, unsigned exp) L4_NOTHROW;
99 
100 
101 /**
102  * Convert explicit timeout values to l4_timeout_t type.
103  * \ingroup l4_timeout_api
104  *
105  * \param  snd_man    Mantissa of send timeout.
106  * \param  snd_exp    Exponent of send timeout.
107  * \param  rcv_man    Mantissa of receive timeout.
108  * \param  rcv_exp    Exponent of receive timeout.
109  */
110 L4_INLINE
111 l4_timeout_t l4_ipc_timeout(unsigned snd_man, unsigned snd_exp,
112                             unsigned rcv_man, unsigned rcv_exp) L4_NOTHROW;
113 
114 /**
115  * Combine send and receive timeout in a timeout.
116  * \ingroup l4_timeout_api
117  *
118  * \param  snd    Send timeout
119  * \param  rcv    Receive timeout
120  *
121  * \return L4 timeout
122  */
123 L4_INLINE
124 l4_timeout_t l4_timeout(l4_timeout_s snd, l4_timeout_s rcv) L4_NOTHROW;
125 
126 /**
127  * Set send timeout in given to timeout.
128  * \ingroup l4_timeout_api
129  *
130  * \param  snd    Send timeout
131  * \retval to     L4 timeout
132  */
133 L4_INLINE
134 void l4_snd_timeout(l4_timeout_s snd, l4_timeout_t *to) L4_NOTHROW;
135 
136 /**
137  * Set receive timeout in given to timeout.
138  * \ingroup l4_timeout_api
139  *
140  * \param  rcv    Receive timeout
141  * \retval to     L4 timeout
142  */
143 L4_INLINE
144 void l4_rcv_timeout(l4_timeout_s rcv, l4_timeout_t *to) L4_NOTHROW;
145 
146 /**
147  * Get clock value of out timeout.
148  * \ingroup l4_timeout_api
149  *
150  * \param to     L4 timeout
151  *
152  * \return Clock value
153  */
154 L4_INLINE
155 l4_kernel_clock_t l4_timeout_rel_get(l4_timeout_s to) L4_NOTHROW;
156 
157 
158 /**
159  * Return whether the given timeout is absolute or not.
160  * \ingroup l4_timeout_api
161  *
162  * \param to     L4 timeout
163  *
164  * \return != 0 if absolute, 0 if relative
165  */
166 L4_INLINE
167 unsigned l4_timeout_is_absolute(l4_timeout_s to) L4_NOTHROW;
168 
169 /**
170  * Get clock value for a clock + a timeout.
171  * \ingroup l4_timeout_api
172  *
173  * \param cur    Clock value
174  * \param to     L4 timeout
175  *
176  * \return Clock sum
177  */
178 L4_INLINE
179 l4_kernel_clock_t l4_timeout_get(l4_kernel_clock_t cur, l4_timeout_s to) L4_NOTHROW;
180 
181 
182 /*
183  * Implementation
184  */
185 
186 L4_INLINE
l4_ipc_timeout(unsigned snd_man,unsigned snd_exp,unsigned rcv_man,unsigned rcv_exp)187 l4_timeout_t l4_ipc_timeout(unsigned snd_man, unsigned snd_exp,
188     unsigned rcv_man, unsigned rcv_exp) L4_NOTHROW
189 {
190   l4_timeout_t t;
191   t.p.snd.t = (snd_man & 0x3ff) | ((snd_exp << 10) & 0x7c00);
192   t.p.rcv.t = (rcv_man & 0x3ff) | ((rcv_exp << 10) & 0x7c00);
193   return t;
194 }
195 
196 
197 L4_INLINE
l4_timeout(l4_timeout_s snd,l4_timeout_s rcv)198 l4_timeout_t l4_timeout(l4_timeout_s snd, l4_timeout_s rcv) L4_NOTHROW
199 {
200   l4_timeout_t t;
201   t.p.snd = snd;
202   t.p.rcv = rcv;
203   return t;
204 }
205 
206 
207 L4_INLINE
l4_snd_timeout(l4_timeout_s snd,l4_timeout_t * to)208 void l4_snd_timeout(l4_timeout_s snd, l4_timeout_t *to) L4_NOTHROW
209 {
210   to->p.snd = snd;
211 }
212 
213 
214 L4_INLINE
l4_rcv_timeout(l4_timeout_s rcv,l4_timeout_t * to)215 void l4_rcv_timeout(l4_timeout_s rcv, l4_timeout_t *to) L4_NOTHROW
216 {
217   to->p.rcv = rcv;
218 }
219 
220 
221 L4_INLINE
l4_timeout_rel(unsigned man,unsigned exp)222 l4_timeout_s l4_timeout_rel(unsigned man, unsigned exp) L4_NOTHROW
223 {
224   return (l4_timeout_s){(l4_uint16_t)((man & 0x3ff) | ((exp << 10) & 0x7c00))};
225 }
226 
227 
228 L4_INLINE
l4_timeout_rel_get(l4_timeout_s to)229 l4_kernel_clock_t l4_timeout_rel_get(l4_timeout_s to) L4_NOTHROW
230 {
231   if (to.t == 0)
232     return ~0ULL;
233   return (l4_kernel_clock_t)(to.t & 0x3ff) << ((to.t >> 10) & 0x1f);
234 }
235 
236 
237 L4_INLINE
l4_timeout_is_absolute(l4_timeout_s to)238 unsigned l4_timeout_is_absolute(l4_timeout_s to) L4_NOTHROW
239 {
240   return to.t & 0x8000;
241 }
242 
243 
244 L4_INLINE
l4_timeout_get(l4_kernel_clock_t cur,l4_timeout_s to)245 l4_kernel_clock_t l4_timeout_get(l4_kernel_clock_t cur, l4_timeout_s to) L4_NOTHROW
246 {
247   if (l4_timeout_is_absolute(to))
248     return 0; /* We cannot retrieve the value ... */
249   else
250     return cur + l4_timeout_rel_get(to);
251 }
252 
253 
254 #endif
255