]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/plr/include/measurements.h
update
[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         };
45
46         struct __attribute__((packed))
47         SensorHead {
48                 l4_uint64_t   tsc;   // TSC: stop
49                 l4_uint32_t   vcpu;  // vcpu ptr
50                 unsigned char type;  // event type
51         };
52
53
54         struct __attribute__((packed))
55         PagefaultEvent
56         {
57                 char rw;
58                 l4_addr_t address;
59                 l4_addr_t localbase;
60                 l4_addr_t remotebase;
61         };
62
63         struct __attribute__((packed))
64         TrapEvent
65         {
66                 char        start;
67                 l4_addr_t   trapaddr;
68                 l4_uint32_t trapno;
69         };
70
71
72         struct __attribute__((packed))
73         SyscallEvent
74         {
75                 l4_addr_t   eip;
76                 l4_uint32_t label;
77         };
78
79
80         struct __attribute__((packed))
81         FooEvent
82         {
83                 unsigned start;
84         };
85
86
87         struct __attribute__((packed))
88         GenericEvent
89         {
90                 struct SensorHead header;
91                 union {
92                         struct PagefaultEvent pf;
93                         struct SyscallEvent sys;
94                         struct FooEvent     foo;
95                         struct TrapEvent    trap;
96                         char         pad[19];
97                 } data;
98         };
99
100
101         /*
102          * Event buffer
103          * 
104          * An event buffer holds events of the GenericEvent type. The class does not
105          * allocate memory. Instead the underlying buffer needs to be specified using
106          * the set_buffer() function.
107          * 
108          * Once the buffer is valid, users obtain an element using the next() method
109          * and fill it appropriately.
110          * 
111          * The buffer is managed as a ring buffer and may overflow, in which case the
112          * oldest elements get overwritten. The index variable is increased monotonically,
113          * so users may determine whether the buffer has already overflown by checking
114          * if index > size. If so, (index mod size) points to the oldest element.
115          *
116          * The whole buffer can be dumped using the dump() method. This will produce a UU-encoded
117          * version of the zipped buffer content.
118          */
119         struct __attribute__((packed))
120         EventBuf
121         {
122                 struct GenericEvent*  buffer;
123                 unsigned       index;
124                 unsigned       size;
125                 unsigned       sharedTSC;
126                 l4_uint64_t   *timestamp;
127                 char _end[];
128
129 #ifdef __cplusplus
130
131                 /**
132                  * Create event buffer
133                  *
134                  * sharableTSC -> allow the TSC value to be located in a way that we can share
135                  *                this value among different address spaces (e.g., have replicas
136                  *                log events themselves using this TSC). This requires the timestamp
137                  *                value to be placed on a dedicated page.
138                  */
139                 EventBuf(bool sharableTSC = false)
140                         : buffer(0), index(0), size(0), sharedTSC(sharableTSC ? 1 : 0)
141                 {
142                   static_assert(sizeof(SensorHead) == 13, "Sensor head not 13 bytes large!");
143                   static_assert(sizeof(GenericEvent) == 32, "GenericEvent larger than 24 bytes!");
144                   //static_assert((l4_umword_t)((EventBuf const *)0)->_end < sizeof(GenericEvent), "head too large?");
145
146                   if (!sharableTSC) {
147                         timestamp = new l4_uint64_t();
148                   }
149
150                   static unsigned char dummyBuffer[32];
151                   set_buffer(dummyBuffer, 32);
152                 }
153
154
155                 ~EventBuf()
156                 {
157                         enter_kdebug("~EventBuf");
158                         if (!sharedTSC) {
159                                 delete timestamp;
160                         }
161                 }
162
163
164                 void set_buffer(unsigned char *buf, unsigned size_in_bytes)
165                 {
166                         buffer = reinterpret_cast<GenericEvent*>(buf);
167                         size   = size_in_bytes / sizeof(GenericEvent);
168                 }
169
170
171                 void set_tsc_buffer(l4_uint64_t *buf)
172                 {
173                         timestamp = buf;
174                 }
175
176
177                 static void launchTimerThread(l4_addr_t timerAddress, unsigned CPU);
178
179                 l4_uint64_t getTime(bool local=false)
180                 {
181                         if (local) {
182                                 return l4_rdtsc();
183                         } else {
184                                 return *timestamp;
185                         }
186                 }
187
188                 /*
189                  * Get the next buffer entry.
190                  *
191                  * Safe against concurrent calls by using atomic increment on the
192                  * counter.  Concurrent accesses may lead to events not being properly
193                  * ordered, though.
194                  */
195                 GenericEvent* next()
196                 {
197                         unsigned val = l4util_inc32_res(&index) - 1;
198                         val %= size;
199                         return &buffer[val];
200                 }
201
202
203                 unsigned oldest() const
204                 {
205                         if (index < size) {
206                                 return 0;
207                         }
208                         else {
209                                 return index % size;
210                         }
211                 }
212 #endif /* C++ */
213         };
214
215 #ifdef __cplusplus
216 }
217
218 extern "C"
219 {
220 #endif
221         l4_uint64_t evbuf_get_time(void *eb, unsigned local);
222         struct GenericEvent* evbuf_next(void *eb);
223 #ifdef __cplusplus
224 }
225 #endif