1 /*
2 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3 * Alexander Warg <warg@os.inf.tu-dresden.de>,
4 * Frank Mehnert <fm3@os.inf.tu-dresden.de>,
5 * Michael Hohmuth <hohmuth@os.inf.tu-dresden.de>,
6 * Jork Löser <jork@os.inf.tu-dresden.de>,
7 * Lars Reuther <reuther@os.inf.tu-dresden.de>
8 * economic rights: Technische Universität Dresden (Germany)
9 * This file is part of TUD:OS and distributed under the terms of the
10 * GNU Lesser General Public License 2.1.
11 * Please see the COPYING-LGPL-2.1 file for details.
12 */
13 /*
14 */
15
16 /*****************************************************************************
17 * libl4util/src/micros2l4to.c *
18 * calculate L4 timeout *
19 *****************************************************************************/
20
21 #include <l4/sys/compiler.h> /* for static_assert() */
22 #include <l4/sys/types.h>
23 #include <l4/util/util.h>
24 #include <l4/util/bitops.h>
25
26 L4_CV l4_timeout_s
l4util_micros2l4to(unsigned int mus)27 l4util_micros2l4to(unsigned int mus)
28 {
29 static_assert(sizeof(mus) <= 4,
30 "Verify the correctness of log2(mus) and the number of bits for e!");
31 l4_timeout_s t;
32 if (mus == 0)
33 t = L4_IPC_TIMEOUT_0;
34 else if (mus == ~0U)
35 t = L4_IPC_TIMEOUT_NEVER;
36 else
37 {
38 /* Here it is certain that at least one bit in 'mus' is set. */
39 int e = l4util_log2(mus) - 7;
40 if (e < 0) e = 0;
41 /* Here it is certain that '0 <= e <= 24' and '1 <= 2^e <= 2^24'. */
42
43 unsigned m = mus >> e;
44 /* Here it is certain that '1 <= m <= 255. Consider the following cases:
45 * o 1 <= mus <= 255: e = 0; 2^e = 1; 1 <= mus/1 <= 255
46 * o 256 <= mus <= 511: e = 1; 2^e = 2; 128 <= mus/2 <= 255
47 * o 512 <= mus <= 1023: e = 2; 2^e = 4; 128 <= mus/4 <= 255
48 * o 1024 <= mus <= 2047: e = 3; 2^e = 8; 128 <= mus/8 <= 255
49 * ...
50 * o 2^31 <= mus <= 2^32-1: e = 24; 128 <= mus/2^24 <= 255
51 *
52 * Dividing by (1<<e) ensures that for all mus < 2^32: m < 2^8.
53 *
54 * As we have 10 bits for m we could also use 'e = log2(mus) - 9':
55 * o 1 <= mus <= 1023: e = 0; 2^e = 1; 1 <= mus/1 <= 1023
56 * o 1024 <= mus <= 2047: e = 1; 2^e = 2; 512 <= mus/2 <= 1023
57 * o 2048 <= mus <= 4095: e = 2; 2^e = 4; 512 <= mus/4 <= 1023
58 * ...
59 * o 2^31 <= mus <= 2^32-1: e = 22; 512 <= mus/2^22 <= 1023
60 *
61 * What about sizeof(mus) == 8? 'e = log2(mus) - 7':
62 * o 2^63 <= mus <= 2^64-1: e = 56; 128 <= mus/2^56 <= 255.
63 *
64 * That means that this function would even work for 64-bit values of
65 * 'mus' as long as l4util_log2(mus) works correctly for that range.
66 * But the number of bits available for the exponent is limited:
67 * o bits 0..9 (10 bits) are used for 'm'
68 * o bits 10..14 (5 bits) are used for 'e'
69 * o bit 15 is used to distinguish between absolute timeouts and
70 * relative timeouts (see l4_timeout_is_absolute())
71 *
72 * That means 'e <= 31' and thus it's not possible to encode timeouts
73 * represented by 64-bit values.
74 */
75
76 t.t = (e << 10) | m;
77 }
78 return t;
79 }
80