aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorBjoern Brandenburg <bbb@mpi-sws.org>2016-03-23 18:22:01 -0400
committerBjoern Brandenburg <bbb@mpi-sws.org>2016-03-23 18:22:01 -0400
commitb06db0322429df80ee0fe09d257520f0c5b71901 (patch)
treea13f5669e2334737a611e03057c696ad0c7c13fd /include
parent37aea5e4e06d30267c01ae3d078be34fb07fcfd3 (diff)
Port st-dump and st-job-stats
Include st-dump (formerly 'st_show') and st-job-stats (formerly 'st_job_stats') from https://github.com/brandenburg/sched-trace-tools in this repository.
Diffstat (limited to 'include')
-rw-r--r--include/eheap.h12
-rw-r--r--include/heap.h379
-rw-r--r--include/load.h92
-rw-r--r--include/sched_trace.h149
4 files changed, 632 insertions, 0 deletions
diff --git a/include/eheap.h b/include/eheap.h
new file mode 100644
index 0000000..323fa30
--- /dev/null
+++ b/include/eheap.h
@@ -0,0 +1,12 @@
1#ifndef EHEAP_H
2#define EHEAP_H
3
4#include <limits.h>
5#include "heap.h"
6
7int earlier_event(struct heap_node* _a, struct heap_node* _b);
8
9struct heap* heapify_events(struct st_event_record *ev, unsigned int count);
10
11
12#endif
diff --git a/include/heap.h b/include/heap.h
new file mode 100644
index 0000000..e46b0eb
--- /dev/null
+++ b/include/heap.h
@@ -0,0 +1,379 @@
1/* heap.h -- Binomial Heaps
2 *
3 * Copyright (c) 2008, Bjoern B. Brandenburg <bbb [at] cs.unc.edu>
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of the University of North Carolina nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY COPYRIGHT OWNER AND CONTRIBUTERS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTERS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#ifndef HEAP_H
32#define HEAP_H
33
34#define NOT_IN_HEAP UINT_MAX
35
36struct heap_node {
37 struct heap_node* parent;
38 struct heap_node* next;
39 struct heap_node* child;
40
41 unsigned int degree;
42 void* value;
43 struct heap_node** ref;
44};
45
46struct heap {
47 struct heap_node* head;
48 /* We cache the minimum of the heap.
49 * This speeds up repeated peek operations.
50 */
51 struct heap_node* min;
52};
53
54/* item comparison function:
55 * return 1 if a has higher prio than b, 0 otherwise
56 */
57typedef int (*heap_prio_t)(struct heap_node* a, struct heap_node* b);
58
59static inline void heap_init(struct heap* heap)
60{
61 heap->head = NULL;
62 heap->min = NULL;
63}
64
65static inline void heap_node_init_ref(struct heap_node** _h, void* value)
66{
67 struct heap_node* h = *_h;
68 h->parent = NULL;
69 h->next = NULL;
70 h->child = NULL;
71 h->degree = NOT_IN_HEAP;
72 h->value = value;
73 h->ref = _h;
74}
75
76static inline void heap_node_init(struct heap_node* h, void* value)
77{
78 h->parent = NULL;
79 h->next = NULL;
80 h->child = NULL;
81 h->degree = NOT_IN_HEAP;
82 h->value = value;
83 h->ref = NULL;
84}
85
86static inline void* heap_node_value(struct heap_node* h)
87{
88 return h->value;
89}
90
91static inline int heap_node_in_heap(struct heap_node* h)
92{
93 return h->degree != NOT_IN_HEAP;
94}
95
96static inline int heap_empty(struct heap* heap)
97{
98 return heap->head == NULL && heap->min == NULL;
99}
100
101/* make child a subtree of root */
102static inline void __heap_link(struct heap_node* root,
103 struct heap_node* child)
104{
105 child->parent = root;
106 child->next = root->child;
107 root->child = child;
108 root->degree++;
109}
110
111/* merge root lists */
112static inline struct heap_node* __heap_merge(struct heap_node* a,
113 struct heap_node* b)
114{
115 struct heap_node* head = NULL;
116 struct heap_node** pos = &head;
117
118 while (a && b) {
119 if (a->degree < b->degree) {
120 *pos = a;
121 a = a->next;
122 } else {
123 *pos = b;
124 b = b->next;
125 }
126 pos = &(*pos)->next;
127 }
128 if (a)
129 *pos = a;
130 else
131 *pos = b;
132 return head;
133}
134
135/* reverse a linked list of nodes. also clears parent pointer */
136static inline struct heap_node* __heap_reverse(struct heap_node* h)
137{
138 struct heap_node* tail = NULL;
139 struct heap_node* next;
140
141 if (!h)
142 return h;
143
144 h->parent = NULL;
145 while (h->next) {
146 next = h->next;
147 h->next = tail;
148 tail = h;
149 h = next;
150 h->parent = NULL;
151 }
152 h->next = tail;
153 return h;
154}
155
156static inline void __heap_min(heap_prio_t higher_prio, struct heap* heap,
157 struct heap_node** prev, struct heap_node** node)
158{
159 struct heap_node *_prev, *cur;
160 *prev = NULL;
161
162 if (!heap->head) {
163 *node = NULL;
164 return;
165 }
166
167 *node = heap->head;
168 _prev = heap->head;
169 cur = heap->head->next;
170 while (cur) {
171 if (higher_prio(cur, *node)) {
172 *node = cur;
173 *prev = _prev;
174 }
175 _prev = cur;
176 cur = cur->next;
177 }
178}
179
180static inline void __heap_union(heap_prio_t higher_prio, struct heap* heap,
181 struct heap_node* h2)
182{
183 struct heap_node* h1;
184 struct heap_node *prev, *x, *next;
185 if (!h2)
186 return;
187 h1 = heap->head;
188 if (!h1) {
189 heap->head = h2;
190 return;
191 }
192 h1 = __heap_merge(h1, h2);
193 prev = NULL;
194 x = h1;
195 next = x->next;
196 while (next) {
197 if (x->degree != next->degree ||
198 (next->next && next->next->degree == x->degree)) {
199 /* nothing to do, advance */
200 prev = x;
201 x = next;
202 } else if (higher_prio(x, next)) {
203 /* x becomes the root of next */
204 x->next = next->next;
205 __heap_link(x, next);
206 } else {
207 /* next becomes the root of x */
208 if (prev)
209 prev->next = next;
210 else
211 h1 = next;
212 __heap_link(next, x);
213 x = next;
214 }
215 next = x->next;
216 }
217 heap->head = h1;
218}
219
220static inline struct heap_node* __heap_extract_min(heap_prio_t higher_prio,
221 struct heap* heap)
222{
223 struct heap_node *prev, *node;
224 __heap_min(higher_prio, heap, &prev, &node);
225 if (!node)
226 return NULL;
227 if (prev)
228 prev->next = node->next;
229 else
230 heap->head = node->next;
231 __heap_union(higher_prio, heap, __heap_reverse(node->child));
232 return node;
233}
234
235/* insert (and reinitialize) a node into the heap */
236static inline void heap_insert(heap_prio_t higher_prio, struct heap* heap,
237 struct heap_node* node)
238{
239 struct heap_node *min;
240 node->child = NULL;
241 node->parent = NULL;
242 node->next = NULL;
243 node->degree = 0;
244 if (heap->min && higher_prio(node, heap->min)) {
245 /* swap min cache */
246 min = heap->min;
247 min->child = NULL;
248 min->parent = NULL;
249 min->next = NULL;
250 min->degree = 0;
251 __heap_union(higher_prio, heap, min);
252 heap->min = node;
253 } else
254 __heap_union(higher_prio, heap, node);
255}
256
257static inline void __uncache_min(heap_prio_t higher_prio, struct heap* heap)
258{
259 struct heap_node* min;
260 if (heap->min) {
261 min = heap->min;
262 heap->min = NULL;
263 heap_insert(higher_prio, heap, min);
264 }
265}
266
267/* merge addition into target */
268static inline void heap_union(heap_prio_t higher_prio,
269 struct heap* target, struct heap* addition)
270{
271 /* first insert any cached minima, if necessary */
272 __uncache_min(higher_prio, target);
273 __uncache_min(higher_prio, addition);
274 __heap_union(higher_prio, target, addition->head);
275 /* this is a destructive merge */
276 addition->head = NULL;
277}
278
279static inline struct heap_node* heap_peek(heap_prio_t higher_prio,
280 struct heap* heap)
281{
282 if (!heap->min)
283 heap->min = __heap_extract_min(higher_prio, heap);
284 return heap->min;
285}
286
287static inline struct heap_node* heap_take(heap_prio_t higher_prio,
288 struct heap* heap)
289{
290 struct heap_node *node;
291 if (!heap->min)
292 heap->min = __heap_extract_min(higher_prio, heap);
293 node = heap->min;
294 heap->min = NULL;
295 if (node)
296 node->degree = NOT_IN_HEAP;
297 return node;
298}
299
300static inline void heap_decrease(heap_prio_t higher_prio, struct heap* heap,
301 struct heap_node* node)
302{
303 struct heap_node *parent;
304 struct heap_node** tmp_ref;
305 void* tmp;
306
307 /* node's priority was decreased, we need to update its position */
308 if (!node->ref)
309 return;
310 if (heap->min != node) {
311 /* bubble up */
312 parent = node->parent;
313 while (parent && higher_prio(node, parent)) {
314 /* swap parent and node */
315 tmp = parent->value;
316 parent->value = node->value;
317 node->value = tmp;
318 /* swap references */
319 if (parent->ref)
320 *(parent->ref) = node;
321 *(node->ref) = parent;
322 tmp_ref = parent->ref;
323 parent->ref = node->ref;
324 node->ref = tmp_ref;
325 /* step up */
326 node = parent;
327 parent = node->parent;
328 }
329 }
330}
331
332static inline void heap_delete(heap_prio_t higher_prio, struct heap* heap,
333 struct heap_node* node)
334{
335 struct heap_node *parent, *prev, *pos;
336 struct heap_node** tmp_ref;
337 void* tmp;
338
339 if (!node->ref) /* can only delete if we have a reference */
340 return;
341 if (heap->min != node) {
342 /* bubble up */
343 parent = node->parent;
344 while (parent) {
345 /* swap parent and node */
346 tmp = parent->value;
347 parent->value = node->value;
348 node->value = tmp;
349 /* swap references */
350 if (parent->ref)
351 *(parent->ref) = node;
352 *(node->ref) = parent;
353 tmp_ref = parent->ref;
354 parent->ref = node->ref;
355 node->ref = tmp_ref;
356 /* step up */
357 node = parent;
358 parent = node->parent;
359 }
360 /* now delete:
361 * first find prev */
362 prev = NULL;
363 pos = heap->head;
364 while (pos != node) {
365 prev = pos;
366 pos = pos->next;
367 }
368 /* we have prev, now remove node */
369 if (prev)
370 prev->next = node->next;
371 else
372 heap->head = node->next;
373 __heap_union(higher_prio, heap, __heap_reverse(node->child));
374 } else
375 heap->min = NULL;
376 node->degree = NOT_IN_HEAP;
377}
378
379#endif /* HEAP_H */
diff --git a/include/load.h b/include/load.h
new file mode 100644
index 0000000..c0d10aa
--- /dev/null
+++ b/include/load.h
@@ -0,0 +1,92 @@
1#ifndef LOAD_H
2#define LOAD_H
3
4#include "sched_trace.h"
5
6int map_trace(const char *name, void **start, void **end, size_t *size);
7struct heap* load(char **files, int no_files, unsigned int *count);
8
9struct evlink {
10 struct evlink *next;
11 struct st_event_record* rec;
12};
13
14struct task {
15 int pid;
16 unsigned int no_events;
17 struct st_event_record* name;
18 struct st_event_record* param;
19 struct evlink* events;
20 struct evlink** next;
21};
22
23#define MAX_TASKS 512
24
25extern struct task tasks[MAX_TASKS];
26extern struct evlink* sys_events;
27extern u64 time0;
28extern u32 g_min_task;
29extern u32 g_max_task;
30
31static inline double ns2ms(u64 ns)
32{
33 return ns / 1000000.0;
34}
35
36static inline double ns2ms_adj(u64 ns)
37{
38 return ns2ms(ns - time0);
39}
40
41static inline double evtime(struct st_event_record* rec)
42{
43 return ns2ms_adj(event_time(rec));
44}
45
46
47void crop_events(struct task* t, double min, double max);
48void crop_events_all(double min, double max);
49
50struct task* by_pid(int pid);
51
52void init_tasks(void);
53void split(struct heap* h, unsigned int count, int find_time0);
54
55const char* tsk_name(struct task* t);
56int tsk_cpu(struct task *t);
57u32 per(struct task* t);
58u32 exe(struct task* t);
59u32 idx(struct task* t);
60
61
62u32 count_tasks(void);
63
64#define CHECK(_e, test) if (test) fprintf(stderr, "'%s' failed.\n", #test);
65
66#define for_each_task(t) \
67 for (t = tasks + g_min_task; t < tasks + g_max_task && t->pid; t++)
68
69#define for_each_event(t, e) \
70 for (e = t->events; e; e = e->next)
71
72#define for_each_event_t(t, e, evtype) \
73 for_each_event(t, e) if (e->rec->hdr.type == evtype)
74
75#define find_evtype(e, evtype) \
76 while (e && e->rec->hdr.type != evtype) e = e->next;
77
78#define find(e, evtype) \
79 while (e && e->rec->hdr.type != evtype) e = e->next; if (!e) break;
80
81
82static inline struct st_event_record *find_sys_event(u8 type)
83{
84 struct evlink* pos = sys_events;
85 find_evtype(pos, type);
86 if (pos)
87 return pos->rec;
88 else
89 return NULL;
90}
91
92#endif
diff --git a/include/sched_trace.h b/include/sched_trace.h
new file mode 100644
index 0000000..0f6828c
--- /dev/null
+++ b/include/sched_trace.h
@@ -0,0 +1,149 @@
1#ifndef __SCHED_TRACE_H_
2#define __SCHED_TRACE_H_
3
4#include <stdint.h>
5
6typedef uint8_t u8;
7typedef uint32_t u32;
8typedef uint16_t u16;
9typedef uint64_t u64;
10
11/* A couple of notes about the format:
12 *
13 * - make sure it is in sync with the kernel
14 * - all times in nanoseconds
15 * - endianess issues are the problem of the app
16 */
17
18struct st_trace_header {
19 u8 type; /* Of what type is this record? */
20 u8 cpu; /* On which CPU was it recorded? */
21 u16 pid; /* PID of the task. */
22 u32 job; /* The job sequence number. */
23};
24
25#define ST_NAME_LEN 16
26struct st_name_data {
27 char cmd[ST_NAME_LEN];/* The name of the executable of this process. */
28};
29
30struct st_param_data { /* regular params */
31 u32 wcet;
32 u32 period;
33 u32 phase;
34 u8 partition;
35 u8 __unused[3];
36};
37
38struct st_release_data { /* A job is was/is going to be released. */
39 u64 release; /* What's the release time? */
40 u64 deadline; /* By when must it finish? */
41};
42
43struct st_assigned_data { /* A job was asigned to a CPU. */
44 u64 when;
45 u8 target; /* Where should it execute? */
46 u8 __unused[3];
47};
48
49struct st_switch_to_data { /* A process was switched to on a given CPU. */
50 u64 when; /* When did this occur? */
51 u32 exec_time; /* Time the current job has executed. */
52
53};
54
55struct st_switch_away_data { /* A process was switched away from on a given CPU. */
56 u64 when;
57 u64 exec_time;
58};
59
60struct st_completion_data { /* A job completed. */
61 u64 when;
62 u64 forced:1; /* Set to 1 if job overran and kernel advanced to the
63 * next job automatically; set to 0 otherwise.
64 */
65 u64 exec_time:63; /* Actual execution time of job. */
66};
67
68struct st_block_data { /* A task blocks. */
69 u64 when;
70 u64 __unused;
71};
72
73struct st_resume_data { /* A task resumes. */
74 u64 when;
75 u64 __unused;
76};
77
78struct st_np_enter_data { /* A task becomes non-preemptable. */
79 u64 when;
80 u64 __unused;
81};
82
83struct st_np_exit_data { /* A task becomes preemptable again. */
84 u64 when;
85 u64 __unused;
86};
87
88struct st_action_data { /* Catch-all for misc. events. */
89 u64 when;
90 u8 action;
91 u8 __unused[7];
92};
93
94struct st_sys_release_data {
95 u64 when;
96 u64 release;
97};
98
99#define DATA(x) struct st_ ## x ## _data x;
100
101typedef enum {
102 ST_NAME = 1, /* Start at one, so that we can spot
103 * uninitialized records. */
104 ST_PARAM,
105 ST_RELEASE,
106 ST_ASSIGNED,
107 ST_SWITCH_TO,
108 ST_SWITCH_AWAY,
109 ST_COMPLETION,
110 ST_BLOCK,
111 ST_RESUME,
112 ST_ACTION,
113 ST_SYS_RELEASE,
114 ST_NP_ENTER,
115 ST_NP_EXIT,
116
117 ST_INVALID /* Dummy ID to catch too-large IDs. */
118} st_event_record_type_t;
119
120struct st_event_record {
121 struct st_trace_header hdr;
122 union {
123 u64 raw[2];
124
125 DATA(name);
126 DATA(param);
127 DATA(release);
128 DATA(assigned);
129 DATA(switch_to);
130 DATA(switch_away);
131 DATA(completion);
132 DATA(block);
133 DATA(resume);
134 DATA(action);
135 DATA(sys_release);
136 DATA(np_enter);
137 DATA(np_exit);
138 } data;
139};
140
141#undef DATA
142
143const char* event2name(unsigned int id);
144u64 event_time(struct st_event_record* rec);
145
146void print_event(struct st_event_record *rec);
147void print_all(struct st_event_record *rec, unsigned int count);
148
149#endif