]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/plr/include/measurements.h
update: sync
[l4.git] / l4 / pkg / plr / include / measurements.h
1 #pragma once
2
3 /*
4  * measurements.h --
5  *
6  *     Event logging infrastructure
7  *
8  * (c) 2012-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
9  *     economic rights: Technische Universität Dresden (Germany)
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
15 #include <cassert>
16 #include <climits>
17 //#include <utility>
18
19 #include <l4/util/atomic.h>
20 #include <l4/util/rdtsc.h>
21 #include <l4/sys/kdebug.h>
22
23 /*
24  * Namespace containing classes regarding measurements and
25  * sensors etc.
26  *
27  * XXX: C compatibility! Don't use C++ features except inside __cplusplus parts -> I want to
28  *      use this header file from C files, too
29  */
30 #ifdef __cplusplus
31 namespace Measurements
32 {
33 #endif
34
35         enum EventTypes {
36                 Invalid = 0,
37                 Syscall = 1,
38                 Pagefault = 2,
39                 Swifi = 3,
40                 Foo = 4,
41                 Trap = 5,
42                 Thread_start = 6,
43                 Thread_stop  = 7,
44                 Locking = 8,
45                 SHMLocking = 9,
46         };
47
48         struct __attribute__((packed))
49         SensorHead {
50                 l4_uint64_t   tsc;   // TSC: stop
51                 l4_uint32_t   vcpu;  // vcpu ptr
52                 unsigned char type;  // event type
53         };
54
55
56         struct __attribute__((packed))
57         PagefaultEvent
58         {
59                 char rw;
60                 l4_addr_t address;
61                 l4_addr_t localbase;
62                 l4_addr_t remotebase;
63         };
64
65         struct __attribute__((packed))
66         TrapEvent
67         {
68                 char        start;
69                 l4_addr_t   trapaddr;
70                 l4_uint32_t trapno;
71         };
72
73
74         struct __attribute__((packed))
75         SyscallEvent
76         {
77                 l4_addr_t   eip;
78                 l4_uint32_t label;
79         };
80
81
82         struct __attribute__((packed))
83         FooEvent
84         {
85                 unsigned start;
86         };
87
88
89         struct __attribute__((packed))
90         LockEvent
91         {
92                 enum LockEvents {
93                         lock,
94                         unlock,
95                         mtx_lock,
96                         mtx_unlock
97                 };
98                 unsigned eventType;
99         };
100
101
102         struct __attribute__((packed))
103         SHMLockEvent
104         {
105                 unsigned lockid;
106                 unsigned epoch;
107                 unsigned owner; // current owner
108                 unsigned type; // 1 -> init
109                                    // 2 -> lock_enter
110                                            // 3 -> lock_exit
111                                    // 4 -> unlock_enter
112                                            // 5 -> unlock_exit
113         };
114
115
116         struct __attribute__((packed))
117         BarnesEvent
118         {
119                 unsigned nodeptr;
120                 unsigned seqnum;
121         };
122
123
124         struct __attribute__((packed))
125         GenericEvent
126         {
127                 struct SensorHead header;
128                 union {
129                         struct PagefaultEvent pf;
130                         struct SyscallEvent sys;
131                         struct FooEvent     foo;
132                         struct TrapEvent    trap;
133                         struct LockEvent    lock;
134                         struct SHMLockEvent shml;
135                         struct BarnesEvent  barnes;
136                         char         pad[19];
137                 } data;
138         };
139
140
141         /*
142          * Event buffer
143          * 
144          * An event buffer holds events of the GenericEvent type. The class does not
145          * allocate memory. Instead the underlying buffer needs to be specified using
146          * the set_buffer() function.
147          * 
148          * Once the buffer is valid, users obtain an element using the next() method
149          * and fill it appropriately.
150          * 
151          * The buffer is managed as a ring buffer and may overflow, in which case the
152          * oldest elements get overwritten. The index variable is increased monotonically,
153          * so users may determine whether the buffer has already overflown by checking
154          * if index > size. If so, (index mod size) points to the oldest element.
155          *
156          * The whole buffer can be dumped using the dump() method. This will produce a UU-encoded
157          * version of the zipped buffer content.
158          */
159         struct __attribute__((packed))
160         EventBuf
161         {
162                 struct GenericEvent*  buffer;
163                 unsigned       index;
164                 unsigned       size;
165                 unsigned       sharedTSC;
166                 l4_uint64_t   *timestamp;
167                 char _end[];
168
169 #ifdef __cplusplus
170
171                 /**
172                  * Create event buffer
173                  *
174                  * sharableTSC -> allow the TSC value to be located in a way that we can share
175                  *                this value among different address spaces (e.g., have replicas
176                  *                log events themselves using this TSC). This requires the timestamp
177                  *                value to be placed on a dedicated page.
178                  */
179                 EventBuf(bool sharableTSC = false)
180                         : buffer(0), index(0), size(0), sharedTSC(sharableTSC ? 1 : 0)
181                 {
182                   static_assert(sizeof(SensorHead) == 13, "Sensor head not 13 bytes large!");
183                   static_assert(sizeof(GenericEvent) == 32, "GenericEvent larger than 24 bytes!");
184                   //static_assert((l4_umword_t)((EventBuf const *)0)->_end < sizeof(GenericEvent), "head too large?");
185
186                   if (!sharableTSC) {
187                         timestamp = new l4_uint64_t();
188                   }
189
190                   static unsigned char dummyBuffer[32];
191                   set_buffer(dummyBuffer, 32);
192                 }
193
194
195                 ~EventBuf()
196                 {
197                         enter_kdebug("~EventBuf");
198                         if (!sharedTSC) {
199                                 delete timestamp;
200                         }
201                 }
202
203
204                 void set_buffer(unsigned char *buf, unsigned size_in_bytes)
205                 {
206                         buffer = reinterpret_cast<GenericEvent*>(buf);
207                         size   = size_in_bytes / sizeof(GenericEvent);
208                 }
209
210
211                 void set_tsc_buffer(l4_uint64_t *buf)
212                 {
213                         timestamp = buf;
214                 }
215
216
217                 static void launchTimerThread(l4_addr_t timerAddress, unsigned CPU);
218
219                 l4_uint64_t getTime(bool local=false)
220                 {
221                         if (local) {
222                                 return l4_rdtsc();
223                         } else {
224                                 return *timestamp;
225                         }
226                 }
227
228                 /*
229                  * Get the next buffer entry.
230                  *
231                  * Safe against concurrent calls by using atomic increment on the
232                  * counter.  Concurrent accesses may lead to events not being properly
233                  * ordered, though.
234                  */
235                 GenericEvent* next()
236                 {
237                         unsigned val = l4util_inc32_res(&index) - 1;
238                         val %= size;
239                         return &buffer[val];
240                 }
241
242
243                 unsigned oldest() const
244                 {
245                         if (index < size) {
246                                 return 0;
247                         }
248                         else {
249                                 return index % size;
250                         }
251                 }
252 #endif /* C++ */
253         };
254
255 #ifdef __cplusplus
256 }
257
258 extern "C"
259 {
260 #endif
261         void *evbuf_get_address(void);
262         l4_uint64_t evbuf_get_time(void *eb, unsigned is_local);
263         struct GenericEvent* evbuf_next(void *eb);
264 #ifdef __cplusplus
265 }
266 #endif