aboutsummaryrefslogtreecommitdiffstats
path: root/src
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 /src
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 'src')
-rw-r--r--src/eheap.c38
-rw-r--r--src/job_stats.c220
-rw-r--r--src/load.c236
-rw-r--r--src/stdump.c98
-rw-r--r--src/util.c147
5 files changed, 739 insertions, 0 deletions
diff --git a/src/eheap.c b/src/eheap.c
new file mode 100644
index 0000000..7fe9a6f
--- /dev/null
+++ b/src/eheap.c
@@ -0,0 +1,38 @@
1#include <stdlib.h>
2
3#include "sched_trace.h"
4#include "eheap.h"
5
6int earlier_event(struct heap_node* _a, struct heap_node* _b)
7{
8 struct st_event_record *a, *b;
9 a = heap_node_value(_a);
10 b = heap_node_value(_b);
11 if (event_time(a) == 0 && event_time(b) == 0)
12 /* tie break by PID for consistent ordering */
13 return a->hdr.pid < b->hdr.pid;
14 else
15 return event_time(a) < event_time(b);
16}
17
18
19struct heap* heapify_events(struct st_event_record *ev, unsigned int count)
20{
21 struct heap_node* hn;
22 struct heap* h;
23 h = malloc(sizeof(struct heap));
24 hn = malloc(sizeof(struct heap_node) * count);
25 if (!hn || !h)
26 return NULL;
27 heap_init(h);
28 while (count) {
29 heap_node_init(hn, ev);
30 heap_insert(earlier_event, h, hn);
31 hn++;
32 ev++;
33 count--;
34 }
35 return h;
36}
37
38
diff --git a/src/job_stats.c b/src/job_stats.c
new file mode 100644
index 0000000..156be60
--- /dev/null
+++ b/src/job_stats.c
@@ -0,0 +1,220 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <string.h>
5
6#include "load.h"
7#include "sched_trace.h"
8#include "eheap.h"
9
10/* limit search window in case of missing completions */
11#define MAX_COMPLETIONS_TO_CHECK 20
12
13int want_ms = 0;
14
15static double nano_to_ms(int64_t ns)
16{
17 return ns * 1E-6;
18}
19
20static void print_stats(
21 struct task* t,
22 struct st_event_record *release,
23 struct st_event_record *completion)
24{
25 int64_t lateness;
26 u64 response;
27
28 lateness = completion->data.completion.when;
29 lateness -= release->data.release.deadline;
30 response = completion->data.completion.when;
31 response -= release->data.release.release;
32
33 if (want_ms)
34 printf(" %5u, %5u, %10.2f, %10.2f, %8d, %10.2f, %10.2f, %7d"
35 ", %10.2f\n",
36 release->hdr.pid,
37 release->hdr.job,
38 nano_to_ms(per(t)),
39 nano_to_ms(response),
40 lateness > 0,
41 nano_to_ms(lateness),
42 lateness > 0 ? nano_to_ms(lateness) : 0,
43 completion->data.completion.forced,
44 nano_to_ms(completion->data.completion.exec_time));
45 else
46 printf(" %5u, %5u, %10llu, %10llu, %8d, %10lld, %10lld, %7d"
47 ", %10llu\n",
48 release->hdr.pid,
49 release->hdr.job,
50 (unsigned long long) per(t),
51 (unsigned long long) response,
52 lateness > 0,
53 (long long) lateness,
54 lateness > 0 ? (long long) lateness : 0,
55 completion->data.completion.forced,
56 (unsigned long long) completion->data.completion.exec_time);
57}
58
59static void print_task_info(struct task *t)
60{
61 if (want_ms)
62 printf("# task NAME=%s PID=%d COST=%.2f PERIOD=%.2f CPU=%d\n",
63 tsk_name(t),
64 t->pid,
65 nano_to_ms(exe(t)),
66 nano_to_ms(per(t)),
67 tsk_cpu(t));
68 else
69 printf("# task NAME=%s PID=%d COST=%lu PERIOD=%lu CPU=%d\n",
70 tsk_name(t),
71 t->pid,
72 (unsigned long) exe(t),
73 (unsigned long) per(t),
74 tsk_cpu(t));
75}
76
77static void usage(const char *str)
78{
79 fprintf(stderr,
80 "\n USAGE\n"
81 "\n"
82 " st_job_stats [opts] <file.st>+\n"
83 "\n"
84 " OPTIONS\n"
85 " -r -- skip jobs prior to task-system release\n"
86 " -m -- output milliseconds (default: nanoseconds)\n"
87 " -p PID -- show only data for the task with the given PID\n"
88 " -n NAME -- show only data for the task(s) with the given NAME\n"
89 " -t PERIOD -- show only data for the task(s) with the given PERIOD\n"
90 "\n\n"
91 );
92 if (str) {
93 fprintf(stderr, "Aborted: %s\n", str);
94 exit(1);
95 } else {
96 exit(0);
97 }
98}
99
100#define OPTSTR "rmp:n:t:h"
101
102int main(int argc, char** argv)
103{
104 unsigned int count;
105 struct heap *h;
106
107 struct task *t;
108 struct evlink *e, *pos;
109 struct st_event_record *rec;
110
111 int wait_for_release = 0;
112 u64 sys_release = 0;
113
114 unsigned int pid_filter = 0;
115 const char* name_filter = 0;
116 u32 period_filter = 0;
117
118 int opt;
119
120 while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
121 switch (opt) {
122 case 'r':
123 wait_for_release = 1;
124 break;
125 case 'm':
126 want_ms = 1;
127 break;
128 case 'p':
129 pid_filter = atoi(optarg);
130 if (!pid_filter)
131 usage("Invalid PID.");
132 break;
133 case 't':
134 period_filter = atoi(optarg);
135 if (!period_filter)
136 usage("Invalid period.");
137 break;
138 case 'n':
139 name_filter = optarg;
140 break;
141 case 'h':
142 usage(NULL);
143 break;
144 case ':':
145 usage("Argument missing.");
146 break;
147 case '?':
148 default:
149 usage("Bad argument.");
150 break;
151 }
152 }
153
154 if (want_ms)
155 period_filter *= 1000000; /* ns per ms */
156
157 h = load(argv + optind, argc - optind, &count);
158 if (!h)
159 return 1;
160
161 init_tasks();
162 split(h, count, 1);
163
164 if (wait_for_release) {
165 rec = find_sys_event(ST_SYS_RELEASE);
166 if (rec)
167 sys_release = rec->data.sys_release.release;
168 else {
169 fprintf(stderr, "Could not find task system "
170 "release time.\n");
171 exit(1);
172 }
173 }
174
175 /* print hea