]> git.saurik.com Git - apple/xnu.git/blame - tools/trace/wqtrace.lua
xnu-6153.11.26.tar.gz
[apple/xnu.git] / tools / trace / wqtrace.lua
CommitLineData
d9a64523
A
1#!/usr/local/bin/luatrace -s
2
3trace_codename = function(codename, callback)
4 local debugid = trace.debugid(codename)
5 if debugid ~= 0 then
6 trace.single(debugid,callback)
7 else
8 printf("WARNING: Cannot locate debugid for '%s'\n", codename)
9 end
10end
11
12initial_timestamp = 0
13pid_map = {};
14get_prefix = function(buf)
15 if initial_timestamp == 0 then
16 initial_timestamp = buf.timestamp
17 end
18 local secs = trace.convert_timestamp_to_nanoseconds(buf.timestamp - initial_timestamp) / 1000000000
19
20 local prefix
21 if trace.debugid_is_start(buf.debugid) then
22 prefix = "→"
23 elseif trace.debugid_is_end(buf.debugid) then
24 prefix = "←"
25 else
26 prefix = "↔"
27 end
28
29 local proc
30 if buf.pid == buf[1] then
31 proc = buf.command
32 if pid_map[buf[1]] == nil then
33 pid_map[buf[1]] = buf.command
34 end
35 elseif pid_map[buf[1]] ~= nil then
36 proc = pid_map[buf[1]]
37 else
38 proc = "UNKNOWN"
39 end
40
41 return string.format("%s %6.9f %-17s [%05d.%06x] %-24s",
42 prefix, secs, proc, buf.pid, buf.threadid, buf.debugname)
43end
44
45parse_pthread_priority = function(pri)
46 pri = pri & 0xffffffff
47 if (pri & 0x02000000) == 0x02000000 then
48 return "Manager"
49 end
50 local qos = (pri & 0x00ffff00) >> 8
51 if qos == 0x20 then
52 return string.format("UI[%x]", pri);
53 elseif qos == 0x10 then
54 return string.format("IN[%x]", pri);
55 elseif qos == 0x08 then
56 return string.format("DF[%x]", pri);
57 elseif qos == 0x04 then
58 return string.format("UT[%x]", pri);
59 elseif qos == 0x02 then
60 return string.format("BG[%x]", pri);
61 elseif qos == 0x01 then
62 return string.format("MT[%x]", pri);
63 elseif qos == 0x00 then
64 return string.format("--[%x]", pri);
65 else
66 return string.format("??[%x]", pri);
67 end
68end
69
70parse_thread_qos = function(pri)
71 if pri == 7 then
72 return string.format("MG", pri);
73 elseif pri == 6 then
74 return string.format("UI", pri);
75 elseif pri == 5 then
76 return string.format("IN", pri);
77 elseif pri == 4 then
78 return string.format("DF", pri);
79 elseif pri == 3 then
80 return string.format("UT", pri);
81 elseif pri == 2 then
82 return string.format("BG", pri);
83 elseif pri == 1 then
84 return string.format("MT", pri);
85 elseif pri == 0 then
86 return string.format("--", pri);
87 else
88 return string.format("??[%x]", pri);
89 end
90end
91
92parse_thactive_req_qos = function(pri)
93 if pri ~= 0 then
94 return parse_thread_qos(pri)
95 end
96 return "None"
97end
98
99get_thactive = function(low, high)
100 return string.format("req: %s, MG: %d, UI: %d, IN: %d, DE: %d, UT: %d, BG: %d, MT: %d",
101 parse_thactive_req_qos(high >> (16 * 3)), (high >> (2 * 16)) & 0xffff,
102 (high >> (1 * 16)) & 0xffff, (high >> (0 * 16)) & 0xffff,
103 (low >> (3 * 16)) & 0xffff, (low >> (2 * 16)) & 0xffff,
104 (low >> (1 * 16)) & 0xffff, (low >> (0 * 16)) & 0xffff)
105end
106
107-- workqueue lifecycle
108
109trace_codename("wq_pthread_exit", function(buf)
110 local prefix = get_prefix(buf)
111 if trace.debugid_is_start(buf.debugid) then
112 printf("%s\tprocess is exiting\n",prefix)
113 else
114 printf("%s\tworkqueue marked as exiting and timer is complete\n",prefix)
115 end
116end)
117
118trace_codename("wq_workqueue_exit", function(buf)
119 local prefix = get_prefix(buf)
120 if trace.debugid_is_start(buf.debugid) then
121 printf("%s\tall threads have exited, cleaning up\n",prefix)
122 else
123 printf("%s\tclean up complete\n",prefix)
124 end
125end)
126
127trace_codename("wq_start_add_timer", function(buf)
128 local prefix = get_prefix(buf)
129 printf("%s\tarming timer to fire in %d us (flags: %x, reqcount: %d)\n",
130 prefix, buf.arg4, buf.arg3, buf.arg2)
131end)
132
133trace_codename("wq_add_timer", function(buf)
134 local prefix = get_prefix(buf)
135 if trace.debugid_is_start(buf.debugid) then
136 printf("%s\tadd_timer fired (flags: %x, nthreads: %d, thidlecount: %d)\n",
137 prefix, buf.arg2, buf.arg3, buf.arg4)
138 elseif trace.debugid_is_end(buf.debugid) then
139 printf("%s\tadd_timer completed (start_timer: %x, nthreads: %d, thidlecount: %d)\n",
140 prefix, buf.arg2, buf.arg3, buf.arg4)
141 end
142end)
143
144trace_codename("wq_select_threadreq", function(buf)
145 local prefix = get_prefix(buf)
146 if buf[2] == 0 then
147 printf("%s\tSelection failed: process exiting\n", prefix)
148 elseif buf[2] == 1 then
149 printf("%s\tSelection failed: no request\n", prefix)
150 elseif buf[2] == 2 then
151 printf("%s\tSelection failed: throttled\n", prefix)
cb323159
A
152 elseif buf[2] == 3 then
153 printf("%s\tSelection failed: scheduler would preempt\n", prefix)
d9a64523
A
154 end
155end)
156
157trace_codename("wq_creator_select", function(buf)
158 local prefix = get_prefix(buf)
159 if buf[2] == 1 then
160 printf("%s\t\tcreator %x overridden at %s\n", prefix, buf[3],
161 parse_thread_qos(buf[4]))
162 elseif buf[2] == 2 then
163 printf("%s\t\tcreator %x selected at %s\n", prefix, buf[3],
164 parse_thread_qos(buf[4]))
165 elseif buf[2] == 3 then
166 printf("%s\t\tcreator idled (%d yields)\n", prefix, buf[4])
167 elseif buf[2] == 4 then
168 printf("%s\t\tcreator removed (%d yields)\n", prefix, buf[4])
169 end
170end)
171
172trace_codename("wq_creator_yield", function(buf)
173 local prefix = get_prefix(buf)
174 local reason = "unknown"
175 if buf[2] == 1 then
176 reason = "fast steal rate"
177 elseif buf[2] == 2 then
178 reason = "above ncpu scheduled"
179 end
180 printf("%s\t\tcreator yielded (%s, current:%d snapshot:%d)\n",
181 prefix, reason, buf[3], buf[4])
182end)
183
184trace_codename("wq_thread_logical_run", function(buf)
185 local prefix = get_prefix(buf)
186 if trace.debugid_is_start(buf.debugid) then
187 printf("%s\tthread unparking (request %x)\n", prefix, buf[2])
188 else
189 printf("%s\tthread parking\n", prefix)
190 end
191end)
192
193trace.enable_thread_cputime()
194runthread_time_map = {}
195runthread_cputime_map = {}
196trace_codename("wq_runthread", function(buf)
197 local prefix = get_prefix(buf)
198 if trace.debugid_is_start(buf.debugid) then
199 printf("%s\tSTART running thread\n", prefix)
200 runthread_time_map[buf.threadid] = buf.timestamp;
201 runthread_cputime_map[buf.threadid] = trace.cputime_for_thread(buf.threadid);
202 elseif runthread_time_map[buf.threadid] then
203 local time = buf.timestamp - runthread_time_map[buf.threadid]
204 local cputime = trace.cputime_for_thread(buf.threadid) - runthread_cputime_map[buf.threadid]
205
206 local time_ms = trace.convert_timestamp_to_nanoseconds(time) / 1000000
207 local cputime_ms = trace.convert_timestamp_to_nanoseconds(cputime) / 1000000
208
209 printf("%s\tDONE running thread: time = %6.6f ms, cputime = %6.6f ms\n",
210 prefix, time_ms, cputime_ms)
211
212 runthread_time_map[buf.threadid] = 0
213 runthread_cputime_map[buf.threadid] = 0
214 elseif trace.debugid_is_end(buf.debugid) then
215 printf("%s\tDONE running thread\n", prefix)
216 end
217end)
218
219trace_codename("wq_thactive_update", function(buf)
220 local prefix = get_prefix(buf)
221 local thactive = get_thactive(buf[2], buf[3])
222 printf("%s\tthactive updated (%s)\n", prefix, thactive)
223end)
224
225trace_codename("wq_thread_block", function(buf)
226 local prefix = get_prefix(buf)
227 local req_pri = parse_thread_qos(buf[3] >> 8)
228 if trace.debugid_is_start(buf.debugid) then
229 printf("%s\tthread blocked (activecount: %d, priority: %s, req_pri: %s, reqcount: %d, start_timer: %d)\n",
230 prefix, buf[2], parse_thread_qos(buf[3] & 0xff), req_pri, buf[4] >> 1, buf[4] & 0x1)
231 else
232 printf("%s\tthread unblocked (activecount: %d, priority: %s, req_pri: %s, threads_scheduled: %d)\n",
233 prefix, buf[2], parse_thread_qos(buf[3] & 0xff), req_pri, buf[4])
234 end
235end)
236
237trace_codename("wq_thread_create_failed", function(buf)
238 local prefix = get_prefix(buf)
239 if buf[3] == 0 then
240 printf("%s\tfailed to create new workqueue thread, kern_return: 0x%x\n",
241 prefix, buf[2])
242 elseif buf[3] == 1 then
243 printf("%s\tfailed to vm_map workq thread stack: 0x%x\n", prefix, buf[2])
244 elseif buf[3] == 2 then
245 printf("%s\tfailed to vm_protect workq thread guardsize: 0x%x\n", prefix, buf[2])
246 end
247end)
248
249trace_codename("wq_thread_create", function(buf)
250 printf("%s\tcreated new workqueue thread\n", get_prefix(buf))
251end)
252
253trace_codename("wq_thread_terminate", function(buf)
254 local prefix = get_prefix(buf)
255 local what
256 if trace.debugid_is_start(buf.debugid) then
257 what = "try to terminate thread"
258 else
259 what = "terminated thread"
260 end
261 printf("%s\t%s: currently idle %d\n", prefix, what, buf[2])
262end)
263
264trace_codename("wq_wqops_reqthreads", function(buf)
265 local prefix = get_prefix(buf)
266 printf("%s\tlegacy thread request made for %d threads at %s\n", prefix, buf[2], parse_pthread_priority(buf[3]));
267end)
268
269trace_codename("wq_thread_request_initiate", function(buf)
270 local prefix = get_prefix(buf)
271 printf("%s\tthread request %x made at %s (count:%d)\n", prefix, buf[2], parse_thread_qos(buf[3]), buf[4]);
272end)
273
274trace_codename("wq_thread_request_modify", function(buf)
275 local prefix = get_prefix(buf)
276 printf("%s\tthread request %x priorty updated to %s\n", prefix, buf[2], parse_thread_qos(buf[3]));
277end)
278
279trace_codename("wq_thread_request_cancel", function(buf)
280 local prefix = get_prefix(buf)
281 printf("%s\tthread request %x canceled\n", prefix, buf[2], parse_thread_qos(buf[3]));
282end)
283
284trace_codename("wq_constrained_admission", function(buf)
285 local prefix = get_prefix(buf)
286 if buf[2] == 1 then
287 printf("fail: %s\twq_constrained_threads_scheduled=%d >= wq_max_constrained_threads=%d\n",
288 prefix, buf[3], buf[4])
289 elseif (buf[2] == 2) or (buf[2] == 3) then
290 local success = nil;
291 if buf[2] == 2 then success = "success"
292 else success = "fail" end
293 printf("%s\t%s\tthactive_count=%d + busycount=%d >= wq->wq_max_concurrency\n",
294 prefix, success, buf[3], buf[4])
295 end
296end)
297
298trace_codename("wq_death_call", function(buf)
299 local prefix = get_prefix(buf)
300 if trace.debugid_is_start(buf.debugid) then
301 printf("%s\tentering death call\n", prefix);
302 elseif trace.debugid_is_end(buf.debugid) then
303 printf("%s\tleaving death call\n", prefix);
304 else
305 printf("%s\tscheduling death call\n", prefix);
306 end
307end)
308--
309-- vim:ts=4:sw=4:noet: