1*0f4c859eSApple OSS DistributionsTask References 2*0f4c859eSApple OSS Distributions=============== 3*0f4c859eSApple OSS Distributions 4*0f4c859eSApple OSS DistributionsBackground 5*0f4c859eSApple OSS Distributions---------- 6*0f4c859eSApple OSS Distributions 7*0f4c859eSApple OSS DistributionsTasks in XNU are reference counted. When a task is created it starts with two 8*0f4c859eSApple OSS Distributionsreferences - one for the caller and one for the task itself. Over the lifetime 9*0f4c859eSApple OSS Distributionsof the task this reference count is modified, for example when a thread is 10*0f4c859eSApple OSS Distributionscreated it increments the reference count and when it exits that count drops. 11*0f4c859eSApple OSS DistributionsWhen a reference count reaches zero, the task is freed. 12*0f4c859eSApple OSS Distributions 13*0f4c859eSApple OSS DistributionsTo grab a reference: 14*0f4c859eSApple OSS Distributions```c 15*0f4c859eSApple OSS Distributionstask_reference() 16*0f4c859eSApple OSS Distributions``` 17*0f4c859eSApple OSS Distributions 18*0f4c859eSApple OSS DistributionsTo release a reference: 19*0f4c859eSApple OSS Distributions```c 20*0f4c859eSApple OSS Distributionstask_deallocate() 21*0f4c859eSApple OSS Distributions``` 22*0f4c859eSApple OSS Distributions 23*0f4c859eSApple OSS DistributionsOne of the big problems seen with task references is that difficult to debug 24*0f4c859eSApple OSS Distributions_leaks_ commonly occur. This happens when a reference is taken but never 25*0f4c859eSApple OSS Distributionsreleased. The task is kept around indefinitely and eventually the system runs 26*0f4c859eSApple OSS Distributionsout of a finite resource (for example ASIDs). At this point there is very little 27*0f4c859eSApple OSS Distributionsinformation to determine what code was responsible for the leak. 28*0f4c859eSApple OSS Distributions 29*0f4c859eSApple OSS Distributions 30*0f4c859eSApple OSS DistributionsTask Reference Groups 31*0f4c859eSApple OSS Distributions-------------------- 32*0f4c859eSApple OSS Distributions 33*0f4c859eSApple OSS DistributionsReference groups are a feature which keep track of statistics (and when 34*0f4c859eSApple OSS Distributionsconfigured backtrace information) for a set of references. Reference groups are 35*0f4c859eSApple OSS Distributionshierarchical. To help with debugging the following task reference group 36*0f4c859eSApple OSS Distributionshierarchy is used: 37*0f4c859eSApple OSS Distributions 38*0f4c859eSApple OSS Distributions``` 39*0f4c859eSApple OSS Distributionstask 40*0f4c859eSApple OSS Distributions -> task_internal 41*0f4c859eSApple OSS Distributions -> task_local_internal 42*0f4c859eSApple OSS Distributions -> task_kernel 43*0f4c859eSApple OSS Distributions -> task_local_internal 44*0f4c859eSApple OSS Distributions -> task_mig 45*0f4c859eSApple OSS Distributions -> task_local_internal 46*0f4c859eSApple OSS Distributions -> task_external 47*0f4c859eSApple OSS Distributions -> task_local_external 48*0f4c859eSApple OSS Distributions -> task_com.apple.security.sandbox 49*0f4c859eSApple OSS Distributions -> task_com.apple.security.sandbox 50*0f4c859eSApple OSS Distributions -> task_com.apple.driver.AppleHV 51*0f4c859eSApple OSS Distributions -> task_com.apple.driver.AppleHV 52*0f4c859eSApple OSS Distributions ... 53*0f4c859eSApple OSS Distributions``` 54*0f4c859eSApple OSS Distributions 55*0f4c859eSApple OSS DistributionsThe `task` group contains a count of all task references in the system. The 56*0f4c859eSApple OSS Distributionsfirst-level groups are static and sub-divide task references based on the 57*0f4c859eSApple OSS Distributionssub-system they come from. `task_external` is used for kext references and each 58*0f4c859eSApple OSS Distributionskext will be dynamically assigned a reference group as needed (if there's 59*0f4c859eSApple OSS Distributionsone available). At the bottom level, there's a per-task (local) ref group under 60*0f4c859eSApple OSS Distributionseach global group. 61*0f4c859eSApple OSS DistributionsThe exact hierarchy of task references (specifically what per-task reference 62*0f4c859eSApple OSS Distributionsgroups are created) changes depending on the 'task_refgrp' boot arg. 63*0f4c859eSApple OSS Distributions 64*0f4c859eSApple OSS DistributionsTask reference groups can be explored in `lldb` as follows: 65*0f4c859eSApple OSS Distributions 66*0f4c859eSApple OSS Distributions``` 67*0f4c859eSApple OSS Distributions(lldb) showglobaltaskrefgrps 68*0f4c859eSApple OSS Distributionsos_refgrp name count retain release log 69*0f4c859eSApple OSS Distributions0xffffff801ace9250 task_kernel 68 367663 367595 0x0 70*0f4c859eSApple OSS Distributions0xffffff801ace9288 task_internal 974 4953 3979 0x0 71*0f4c859eSApple OSS Distributions0xffffff801ace92c0 task_mig 0 3670 3670 0x0 72*0f4c859eSApple OSS Distributions0xffffff801ace9218 task_external 35 108 73 0x0 73*0f4c859eSApple OSS Distributions0xffffff9369dc7b20 task_com.apple.iokit.IOAcceleratorFamily2 29 77 48 0x0 74*0f4c859eSApple OSS Distributions0xffffff936a3f0a20 task_com.apple.iokit.CoreAnalyticsFamily 1 1 0 0x0 75*0f4c859eSApple OSS Distributions0xffffff936a22cb20 task_com.apple.iokit.EndpointSecurity 0 1 1 0x0 76*0f4c859eSApple OSS Distributions0xffffff936a283f60 task_com.apple.iokit.IOSurface 5 5 0 0x0 77*0f4c859eSApple OSS Distributions0xffffff936a3f08a0 task_com.apple.security.sandbox 0 24 24 0x0 78*0f4c859eSApple OSS Distributions 79*0f4c859eSApple OSS Distributions``` 80*0f4c859eSApple OSS Distributions 81*0f4c859eSApple OSS DistributionsDisplay a task's reference groups: 82*0f4c859eSApple OSS Distributions 83*0f4c859eSApple OSS Distributions``` 84*0f4c859eSApple OSS Distributions(lldb) showtaskrefgrps kernel_task 85*0f4c859eSApple OSS Distributionsos_refgrp name count retain release log 86*0f4c859eSApple OSS Distributions0xffffff936a4b9200 task_local_kernel 1 6 5 0x0 87*0f4c859eSApple OSS Distributions0xffffff936a4b9238 task_local_internal 132 619 487 0x0 88*0f4c859eSApple OSS Distributions``` 89*0f4c859eSApple OSS Distributions 90*0f4c859eSApple OSS DistributionsThe reference group hierarchy for a specific group can be displayed as follows: 91*0f4c859eSApple OSS Distributions 92*0f4c859eSApple OSS Distributions``` 93*0f4c859eSApple OSS Distributions(lldb) showosrefgrphierarchy 0xffffff936a3f08a0 94*0f4c859eSApple OSS Distributions0xffffff801ace9988 all 1121 377740 376619 0x0 95*0f4c859eSApple OSS Distributions0xffffff801ace91e0 task 1077 376394 375317 0x0 96*0f4c859eSApple OSS Distributions0xffffff801ace9218 task_external 35 108 73 0x0 97*0f4c859eSApple OSS Distributions0xffffff936a3f08a0 task_com.apple.security.sandbox 0 24 24 0x0 98*0f4c859eSApple OSS Distributions``` 99*0f4c859eSApple OSS Distributions 100*0f4c859eSApple OSS DistributionsReference groups are normally disabled, but task reference group statistics 101*0f4c859eSApple OSS Distributions*are* enabled by default (for `RELEASE` builds, reference groups are not available 102*0f4c859eSApple OSS Distributionsat all). Backtrace logging for all groups is disabled, including task reference 103*0f4c859eSApple OSS Distributionsgroups. To enable backtrace logging and reference group statistics, the `rlog` 104*0f4c859eSApple OSS Distributionsboot-arg must be used. Backtrace logging for task reference groups is only 105*0f4c859eSApple OSS Distributionsenabled when `rlog` has been set to a suitable value. 106*0f4c859eSApple OSS Distributions 107*0f4c859eSApple OSS DistributionsFor example 108*0f4c859eSApple OSS Distributions 109*0f4c859eSApple OSS DistributionsTo enable statistics for all reference groups and backtrace logging for the 110*0f4c859eSApple OSS Distributions*task_external* reference group in particular: 111*0f4c859eSApple OSS Distributions 112*0f4c859eSApple OSS Distributions``` 113*0f4c859eSApple OSS Distributionsnvram boot-args="rlog=task_external ..." 114*0f4c859eSApple OSS Distributions``` 115*0f4c859eSApple OSS Distributions 116*0f4c859eSApple OSS Distributions``` 117*0f4c859eSApple OSS Distributions(lldb) showglobaltaskrefgrps 118*0f4c859eSApple OSS Distributionsos_refgrp name count retain release log 119*0f4c859eSApple OSS Distributions0xffffff801e0e9250 task_kernel 1259 132739 131480 0x0 120*0f4c859eSApple OSS Distributions0xffffff801e0e9218 task_external 35 100 65 0xffffffa05b3fc000 121*0f4c859eSApple OSS Distributions0xffffff936d117be0 task_com.apple.iokit.IOAcceleratorFamily2 29 77 48 0x0 122*0f4c859eSApple OSS Distributions0xffffff936db9fa20 task_com.apple.iokit.CoreAnalyticsFamily 1 1 0 0x0 123*0f4c859eSApple OSS Distributions0xffffff936d9dbb20 task_com.apple.iokit.EndpointSecurity 0 1 1 0x0 124*0f4c859eSApple OSS Distributions0xffffff936da324e0 task_com.apple.iokit.IOSurface 5 5 0 0x0 125*0f4c859eSApple OSS Distributions0xffffff936db9f8a0 task_com.apple.security.sandbox 0 16 16 0x0 126*0f4c859eSApple OSS Distributions 127*0f4c859eSApple OSS Distributions 128*0f4c859eSApple OSS Distributions(lldb) showbtlogrecords 0xffffffa05b3fc000 129*0f4c859eSApple OSS Distributions-------- OP 1 Stack Index 0 with active refs 1 of 165 -------- 130*0f4c859eSApple OSS Distributions0xffffff801da7c1cb <kernel.development`ref_log_op at refcnt.c:107> 131*0f4c859eSApple OSS Distributions0xffffff801d27c35d <kernel.development`task_reference_grp at task_ref.c:274> 132*0f4c859eSApple OSS Distributions0xffffff801ecc014e <EndpointSecurity`VMMap::taskSelf()> 133*0f4c859eSApple OSS Distributions0xffffff801eccc845 <EndpointSecurity`EndpointSecurityClient::create(ScopedPointer<MachSendWrapper> const&, proc*, ScopedPointer<EndpointSecurityExternalClient> const&, es_client_config_t const&)> 134*0f4c859eSApple OSS Distributions... 135*0f4c859eSApple OSS Distributions``` 136