1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
/* sched_trace.h -- record scheduler events to a byte stream for offline analysis.
*/
#ifndef _LINUX_SCHED_TRACE_H_
#define _LINUX_SCHED_TRACE_H_
/* all times in nanoseconds */
struct st_trace_header {
u8 type; /* Of what type is this record? */
u8 cpu; /* On which CPU was it recorded? */
u16 pid; /* PID of the task. */
u32 job; /* The job sequence number. */
};
#define ST_NAME_LEN 16
struct st_name_data {
char cmd[ST_NAME_LEN];/* The name of the executable of this process. */
};
struct st_param_data { /* regular params */
u32 wcet;
u32 period;
u32 phase;
u8 partition;
u8 __unused[3];
};
struct st_release_data { /* A job is was/is going to be released. */
u64 release; /* What's the release time? */
u64 deadline; /* By when must it finish? */
};
struct st_assigned_data { /* A job was asigned to a CPU. */
u64 when;
u8 target; /* Where should it execute? */
u8 __unused[3];
};
struct st_switch_to_data { /* A process was switched to on a given CPU. */
u64 when; /* When did this occur? */
u32 exec_time; /* Time the current job has executed. */
};
struct st_switch_away_data { /* A process was switched away from on a given CPU. */
u64 when;
u64 exec_time;
};
struct st_completion_data { /* A job completed. */
u64 when;
u8 forced:1; /* Set to 1 if job overran and kernel advanced to the
* next task automatically; set to 0 otherwise.
*/
u8 __uflags:7;
u8 __unused[3];
};
struct st_block_data { /* A task blocks. */
u64 when;
u64 __unused;
};
struct st_resume_data { /* A task resumes. */
u64 when;
u64 __unused;
};
struct st_sys_release_data {
u64 when;
u64 release;
};
#define DATA(x) struct st_ ## x ## _data x;
typedef enum {
ST_NAME = 1, /* Start at one, so that we can spot
* uninitialized records. */
ST_PARAM,
ST_RELEASE,
ST_ASSIGNED,
ST_SWITCH_TO,
ST_SWITCH_AWAY,
ST_COMPLETION,
ST_BLOCK,
ST_RESUME,
ST_SYS_RELEASE,
} st_event_record_type_t;
struct st_event_record {
struct st_trace_header hdr;
union {
u64 raw[2];
DATA(name);
DATA(param);
DATA(release);
DATA(assigned);
DATA(switch_to);
DATA(switch_away);
DATA(completion);
DATA(block);
DATA(resume);
DATA(sys_release);
} data;
};
#undef DATA
#ifdef __KERNEL__
#include <linux/sched.h>
#include <litmus/feather_trace.h>
#ifdef CONFIG_SCHED_TASK_TRACE
#define SCHED_TRACE(id, callback, task) \
ft_event1(id, callback, task)
#define SCHED_TRACE2(id, callback, task, xtra) \
ft_event2(id, callback, task, xtra)
/* provide prototypes; needed on sparc64 */
#ifndef NO_TASK_TRACE_DECLS
feather_callback void do_sched_trace_task_name(unsigned long id,
struct task_struct* task);
feather_callback void do_sched_trace_task_param(unsigned long id,
struct task_struct* task);
feather_callback void do_sched_trace_task_release(unsigned long id,
struct task_struct* task);
feather_callback void do_sched_trace_task_switch_to(unsigned long id,
struct task_struct* task);
feather_callback void do_sched_trace_task_switch_away(unsigned long id,
struct task_struct* task);
feather_callback void do_sched_trace_task_completion(unsigned long id,
struct task_struct* task,
unsigned long forced);
feather_callback void do_sched_trace_task_block(unsigned long id,
struct task_struct* task);
feather_callback void do_sched_trace_task_resume(unsigned long id,
struct task_struct* task);
feather_callback void do_sched_trace_sys_release(unsigned long id,
lt_t* start);
#endif
#else
#define SCHED_TRACE(id, callback, task) /* no tracing */
#define SCHED_TRACE2(id, callback, task, xtra) /* no tracing */
#endif
#define SCHED_TRACE_BASE_ID 500
#define sched_trace_task_name(t) \
SCHED_TRACE(SCHED_TRACE_BASE_ID + 1, do_sched_trace_task_name, t)
#define sched_trace_task_param(t) \
SCHED_TRACE(SCHED_TRACE_BASE_ID + 2, do_sched_trace_task_param, t)
#define sched_trace_task_release(t) \
SCHED_TRACE(SCHED_TRACE_BASE_ID + 3, do_sched_trace_task_release, t)
#define sched_trace_task_switch_to(t) \
SCHED_TRACE(SCHED_TRACE_BASE_ID + 4, do_sched_trace_task_switch_to, t)
#define sched_trace_task_switch_away(t) \
SCHED_TRACE(SCHED_TRACE_BASE_ID + 5, do_sched_trace_task_switch_away, t)
#define sched_trace_task_completion(t, forced) \
SCHED_TRACE2(SCHED_TRACE_BASE_ID + 6, do_sched_trace_task_completion, t, \
forced)
#define sched_trace_task_block(t) \
SCHED_TRACE(SCHED_TRACE_BASE_ID + 7, do_sched_trace_task_block, t)
#define sched_trace_task_resume(t) \
SCHED_TRACE(SCHED_TRACE_BASE_ID + 8, do_sched_trace_task_resume, t)
#define sched_trace_sys_release(when) \
SCHED_TRACE(SCHED_TRACE_BASE_ID + 9, do_sched_trace_sys_release, when)
#define sched_trace_quantum_boundary() /* NOT IMPLEMENTED */
#ifdef CONFIG_SCHED_DEBUG_TRACE
void sched_trace_log_message(const char* fmt, ...);
void dump_trace_buffer(int max);
#else
#define sched_trace_log_message(fmt, ...)
#endif
#endif /* __KERNEL__ */
#endif
|