xref: /xnu-8796.121.2/doc/task_ref.md (revision c54f35ca767986246321eb901baf8f5ff7923f6a)
1Task References
2===============
3
4Background
5----------
6
7Tasks in XNU are reference counted. When a task is created it starts with two
8references - one for the caller and one for the task itself. Over the lifetime
9of the task this reference count is modified, for example when a thread is
10created it increments the reference count and when it exits that count drops.
11When a reference count reaches zero, the task is freed.
12
13To grab a reference:
14```c
15task_reference()
16```
17
18To release a reference:
19```c
20task_deallocate()
21```
22
23One of the big problems seen with task references is that difficult to debug
24_leaks_ commonly occur. This happens when a reference is taken but never
25released. The task is kept around indefinitely and eventually the system runs
26out of a finite resource (for example ASIDs). At this point there is very little
27information to determine what code was responsible for the leak.
28
29
30Task Reference Groups
31--------------------
32
33Reference groups are a feature which keep track of statistics (and when
34configured backtrace information) for a set of references. Reference groups are
35hierarchical. To help with debugging the following task reference group
36hierarchy is used:
37
38```
39task
40   -> task_internal
41      -> task_local_internal
42   -> task_kernel
43      -> task_local_internal
44   -> task_mig
45      -> task_local_internal
46   -> task_external
47      -> task_local_external
48      -> task_com.apple.security.sandbox
49          -> task_com.apple.security.sandbox
50      -> task_com.apple.driver.AppleHV
51          -> task_com.apple.driver.AppleHV
52      ...
53```
54
55The `task` group contains a count of all task references in the system. The
56first-level groups are static and sub-divide task references based on the
57sub-system they come from. `task_external` is used for kext references and each
58kext will be dynamically assigned a reference group as needed (if there's
59one available). At the bottom level, there's a per-task (local) ref group under
60each global group.
61The exact hierarchy of task references (specifically what per-task reference
62groups are created) changes depending on the 'task_refgrp' boot arg.
63
64Task reference groups can be explored in `lldb` as follows:
65
66```
67(lldb) showglobaltaskrefgrps
68os_refgrp          name                                           count     retain    release   log
690xffffff801ace9250 task_kernel                                    68        367663    367595    0x0
700xffffff801ace9288 task_internal                                  974       4953      3979      0x0
710xffffff801ace92c0 task_mig                                       0         3670      3670      0x0
720xffffff801ace9218 task_external                                  35        108       73        0x0
730xffffff9369dc7b20 task_com.apple.iokit.IOAcceleratorFamily2      29        77        48        0x0
740xffffff936a3f0a20 task_com.apple.iokit.CoreAnalyticsFamily       1         1         0         0x0
750xffffff936a22cb20 task_com.apple.iokit.EndpointSecurity          0         1         1         0x0
760xffffff936a283f60 task_com.apple.iokit.IOSurface                 5         5         0         0x0
770xffffff936a3f08a0 task_com.apple.security.sandbox                0         24        24        0x0
78
79```
80
81Display a task's reference groups:
82
83```
84(lldb) showtaskrefgrps kernel_task
85os_refgrp          name                                           count     retain    release   log
860xffffff936a4b9200 task_local_kernel                              1         6         5         0x0
870xffffff936a4b9238 task_local_internal                            132       619       487       0x0
88```
89
90The reference group hierarchy for a specific group can be displayed as follows:
91
92```
93(lldb) showosrefgrphierarchy 0xffffff936a3f08a0
940xffffff801ace9988 all                                            1121      377740    376619    0x0
950xffffff801ace91e0 task                                           1077      376394    375317    0x0
960xffffff801ace9218 task_external                                  35        108       73        0x0
970xffffff936a3f08a0 task_com.apple.security.sandbox                0         24        24        0x0
98```
99
100Reference groups are normally disabled, but task reference group statistics
101*are* enabled by default (for `RELEASE` builds, reference groups are not available
102at all). Backtrace logging for all groups is disabled, including task reference
103groups. To enable backtrace logging and reference group statistics, the `rlog`
104boot-arg must be used. Backtrace logging for task reference groups is only
105enabled when `rlog` has been set to a suitable value.
106
107For example
108
109To enable statistics for all reference groups and backtrace logging for the
110*task_external* reference group in particular:
111
112```
113nvram boot-args="rlog=task_external ..."
114```
115
116```
117(lldb) showglobaltaskrefgrps
118os_refgrp          name                                           count     retain    release   log
1190xffffff801e0e9250 task_kernel                                    1259      132739    131480    0x0
1200xffffff801e0e9218 task_external                                  35        100       65        0xffffffa05b3fc000
1210xffffff936d117be0 task_com.apple.iokit.IOAcceleratorFamily2      29        77        48        0x0
1220xffffff936db9fa20 task_com.apple.iokit.CoreAnalyticsFamily       1         1         0         0x0
1230xffffff936d9dbb20 task_com.apple.iokit.EndpointSecurity          0         1         1         0x0
1240xffffff936da324e0 task_com.apple.iokit.IOSurface                 5         5         0         0x0
1250xffffff936db9f8a0 task_com.apple.security.sandbox                0         16        16        0x0
126
127
128(lldb) showbtlogrecords 0xffffffa05b3fc000
129-------- OP 1 Stack Index 0 with active refs 1 of 165 --------
1300xffffff801da7c1cb <kernel.development`ref_log_op at refcnt.c:107>
1310xffffff801d27c35d <kernel.development`task_reference_grp at task_ref.c:274>
1320xffffff801ecc014e <EndpointSecurity`VMMap::taskSelf()>
1330xffffff801eccc845 <EndpointSecurity`EndpointSecurityClient::create(ScopedPointer<MachSendWrapper> const&, proc*, ScopedPointer<EndpointSecurityExternalClient> const&, es_client_config_t const&)>
134...
135```
136