This is xnu-11215.1.10. See this file in:
#!/usr/local/bin/luatrace -s
trace_eventname = function(codename, callback)
local debugid = trace.debugid(codename)
if debugid ~= 0 then
trace.single(debugid,callback)
else
printf("WARNING: Cannot locate debugid for '%s'\n", codename)
end
end
initial_timestamp = 0
function event_prefix_string(buf, workq)
if initial_timestamp == 0 then
initial_timestamp = buf.timestamp
end
local secs = trace.convert_timestamp_to_nanoseconds(buf.timestamp - initial_timestamp) / 1000000000
local type
if trace.debugid_is_start(buf.debugid) then
type = "→"
elseif trace.debugid_is_end(buf.debugid) then
type = "←"
else
type = "↔"
end
proc = buf.command
local prefix = string.format("%s %6.9f %-17s [%05d.%06x] %-28s\t",
type, secs, proc, buf.pid, buf.threadid, buf.debugname)
if not workq then
prefix = prefix .. string.format(" 0x%16x", buf.arg1)
end
return prefix
end
function qos_string(qos)
if qos == 0 then
return "--"
elseif qos == 1 then
return "MT"
elseif qos == 2 then
return "BG"
elseif qos == 3 then
return "UT"
elseif qos == 4 then
return "DF"
elseif qos == 5 then
return "IN"
elseif qos == 6 then
return "UI"
elseif qos == 7 then
return "MG"
else
return string.format("??[0x%x]", qos)
end
end
function state_string(strings, state)
local str = ''
local first = true
for name, bit in pairs(strings) do
if (state & bit) == bit then
if not first then
str = str .. ' '
end
str = str .. name
first = false
end
end
return str
end
kqrequest_state_strings = {
['WAKEUP'] = 1,
}
kqueue_state_strings = {
['SEL'] = 0x001,
['SLEEP'] = 0x002,
['PROCWAIT'] = 0x004,
['KEV32'] = 0x008,
['KEV64'] = 0x010,
['KEV_QOS'] = 0x020,
['WORKQ'] = 0x040,
['WORKLOOP'] = 0x080,
['PROCESSING'] = 0x100,
['DRAIN'] = 0x200,
['WAKEUP'] = 0x400,
['DYNAMIC'] = 0x800,
['R2K'] = 0x1000,
['TURNSTILE'] = 0x2000,
}
knote_state_strings = {
['ACTIVE'] = 0x0001,
['QUEUED'] = 0x0002,
['DISABLED'] = 0x0004,
['DROPPING'] = 0x0008,
['LOCKED'] = 0x0010,
['POSTING'] = 0x0020,
['STAYACTIVE'] = 0x0040,
['DEFERDELETE'] = 0x0080,
['MERGE_QOS'] = 0x0100,
['REQVANISH'] = 0x0200,
['VANISHED'] = 0x0400,
['SUPPRESSED'] = 0x0800,
}
kevent_flags_strings = {
['ADD'] = 0x0001,
['DELETE'] = 0x0002,
['ENABLE'] = 0x0004,
['DISABLE'] = 0x0008,
['ONESHOT'] = 0x0010,
['CLEAR'] = 0x0020,
['RECEIPT'] = 0x0040,
['DISPATCH'] = 0x0080,
['UDATA_SPECIFIC'] = 0x0100,
['VANISHED'] = 0x0200,
['FLAG0'] = 0x1000,
['FLAG1'] = 0x2000,
['EOF'] = 0x8000,
['ERROR'] = 0x4000,
}
function kevent_filter_string(filt)
if filt == -1 then
return 'READ'
elseif filt == -2 then
return 'WRITE'
elseif filt == -3 then
return 'AIO'
elseif filt == -4 then
return 'VNODE'
elseif filt == -5 then
return 'PROC'
elseif filt == -6 then
return 'SIGNAL'
elseif filt == -7 then
return 'TIMER'
elseif filt == -8 then
return 'MACHPORT'
elseif filt == -9 then
return 'FS'
elseif filt == -10 then
return 'USER'
-- -11 unused
elseif filt == -12 then
return 'VM'
elseif filt == -13 then
return 'SOCK'
elseif filt == -14 then
return 'MEMORYSTATUS'
elseif filt == -15 then
return 'EXCEPT'
elseif filt == -16 then
return 'NW_CHANNEL'
elseif filt == -17 then
return 'WORKLOOP'
elseif filt == 17 then
return 'KQREAD'
elseif filt == 18 then
return 'PIPE_N'
elseif filt == 19 then
return 'PIPE_R'
elseif filt == 20 then
return 'PIPE_W'
elseif filt == 21 then
return 'PTSD'
elseif filt == 22 then
return 'SOREAD'
elseif filt == 23 then
return 'SOWRITE'
elseif filt == 24 then
return 'SCK'
elseif filt == 25 then
return 'SOEXCEPT'
elseif filt == 26 then
return 'SPEC'
elseif filt == 27 then
return 'BPFREAD'
elseif filt == 28 then
return 'NECP_FD'
elseif filt == 29 then
return 'SKYWALK_CHANNEL_W'
elseif filt == 30 then
return 'SKYWALK_CHANNEL_R'
elseif filt == 31 then
return 'SKYWALK_CHANNEL_E'
elseif filt == 32 then
return 'FSEVENT'
elseif filt == 33 then
return 'VN'
elseif filt == 34 then
return 'TTY'
elseif filt == 35 then
return 'PTMX'
elseif filt == 36 then
return 'DETACHED'
else
return string.format('[%d]', filt)
end
end
-- kqueue lifecycle
function processing_begin(workq)
return function(buf)
local prefix = event_prefix_string(buf, workq)
if trace.debugid_is_start(buf.debugid) then
local qos
if workq then
qos = buf.arg2
else
qos = buf.arg3
end
printf("%s QoS = %s\n", prefix, qos_string(qos))
else
printf("%s request thread = 0x%x, kqrequest state = %s\n", prefix,
buf.arg1, state_string(kqrequest_state_strings, buf.arg2))
end
end
end
trace_eventname("KEVENT_kq_processing_begin", processing_begin(false))
trace_eventname("KEVENT_kqwq_processing_begin", processing_begin(true))
trace_eventname("KEVENT_kqwl_processing_begin", processing_begin(false))
function processing_end(workq)
return function(buf)
local qos
if workq then
qos = buf.arg2
else
qos = buf.arg3
end
printf("%s QoS = %s\n", event_prefix_string(buf, workq), qos_string(qos))
end
end
trace_eventname("KEVENT_kq_processing_end", processing_end(false))
trace_eventname("KEVENT_kqwq_processing_end", processing_end(true))
trace_eventname("KEVENT_kqwl_processing_end", processing_end(false))
trace_eventname("KEVENT_kqwq_bind", function(buf)
printf("%s thread = 0x%x, QoS = %s, kqrequest state = %s\n",
event_prefix_string(buf, true), buf.arg1, qos_string(buf.arg3),
state_string(kqrequest_state_strings, buf.arg4))
end)
trace_eventname("KEVENT_kqwq_unbind", function(buf)
printf("%s thread = 0x%x, QoS = %s\n", event_prefix_string(buf, true),
buf.arg1, qos_string(buf.arg3))
end)
trace_eventname("KEVENT_kqwl_bind", function(buf)
qos = buf.arg3 & 0xff
duplicate = buf.arg3 & (1 << 8)
kqr_override_qos_delta = buf.arg4 >> 8
kqr_state = buf.arg4 & 0xff
printf("%s thread = 0x%x, QoS = %s, override QoS delta = %d, kqrequest state = %s%s\n",
event_prefix_string(buf, false), buf.arg2, qos_string(qos),
kqr_override_qos_delta,
state_string(kqrequest_state_strings, kqr_state),
duplicate and ", duplicate" or "")
end)
trace_eventname("KEVENT_kqwl_unbind", function(buf)
flags = buf.arg3
qos = buf.arg4
printf("%s thread = 0x%x, QoS = %s, flags = 0x%x\n", event_prefix_string(buf, false),
buf.arg2, qos_string(qos), flags)
end)
function thread_request(workq)
return function(buf)
printf("%s QoS = %s, kqrequest state = %s, override QoS delta = %d\n",
event_prefix_string(buf, workq), qos_string(buf.arg2),
state_string(kqrequest_state_strings, buf.arg3), buf.arg3 >> 8)
end
end
function thread_adjust(buf)
tid = buf.arg2
kqr_qos = buf.arg3 >> 8
new_qos = buf.arg3 & 0xff
kqr_qos_override = buf.arg4 >> 8
kqr_state = buf.arg4 & 0xff
printf("%s thread = 0x%x, old/new QoS = %s/%s, old/new override QoS delta = %d/%d, kqrequest state = %s\n",
event_prefix_string(buf, false),
tid,
qos_string(kqr_qos),
qos_string(new_qos),
kqr_qos_override,
new_qos - kqr_qos,
state_string(kqrequest_state_strings, kqr_state))
end
trace_eventname("KEVENT_kqwq_thread_request", thread_request(true))
trace_eventname("KEVENT_kqwl_thread_request", thread_request(false))
trace_eventname("KEVENT_kqwl_thread_adjust", thread_adjust)
function kevent_register(workq)
return function(buf)
printf("%s kevent udata = 0x%x, kevent filter = %s, kevent flags = %s\n",
event_prefix_string(buf, workq), buf.arg2,
kevent_filter_string(buf.arg4),
state_string(kevent_flags_strings, buf.arg3))
end
end
trace_eventname("KEVENT_kq_register", kevent_register(false))
trace_eventname("KEVENT_kqwq_register", kevent_register(true))
trace_eventname("KEVENT_kqwl_register", kevent_register(false))
function kevent_process(workq)
return function(buf)
printf("%s kevent ident = 0x%x, udata = 0x%x, kevent filter = %s, knote status = %s\n",
event_prefix_string(buf, workq), buf.arg3 >> 32, buf.arg2,
kevent_filter_string(buf.arg4),
state_string(knote_state_strings, buf.arg3 & 0xffffffff))
end
end
trace_eventname("KEVENT_kq_process", kevent_process(false))
trace_eventname("KEVENT_kqwq_process", kevent_process(true))
trace_eventname("KEVENT_kqwl_process", kevent_process(false))