2 * Copyright (c) 2010 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #ifndef __IOKIT_STATISTICS_PRIVATE_H
30 #define __IOKIT_STATISTICS_PRIVATE_H
34 #include <sys/queue.h>
37 #include <libkern/c++/OSKext.h>
38 #include <libkern/OSDebug.h>
40 #include <IOKit/IOMemoryDescriptor.h>
41 #include <IOKit/IOStatistics.h>
44 #error IOStatisticsPrivate.h is for kernel use only
48 #define IOKIT_STATISTICS_RECORDED_USERCLIENT_PROCS 20
51 #define __probable(x) x
54 /* Forward declarations */
59 struct IOEventSourceCounter
;
60 struct IOUserClientCounter
;
61 struct IOWorkLoopCounter
;
62 struct IOUserClientProcessEntry
;
66 /* Allocation tracking */
69 kIOStatisticsMalloc
= 0,
71 kIOStatisticsMallocAligned
,
72 kIOStatisticsFreeAligned
,
73 kIOStatisticsMallocContiguous
,
74 kIOStatisticsFreeContiguous
,
75 kIOStatisticsMallocPageable
,
76 kIOStatisticsFreePageable
,
77 kIOStatisticsAllocCount
80 TAILQ_HEAD(ProcessEntryList
, IOUserClientProcessEntry
);
82 /* Tree and list structs */
84 typedef struct ClassNode
{
85 RB_ENTRY(ClassNode
) tLink
;
86 SLIST_ENTRY(ClassNode
) lLink
;
87 struct KextNode
*parentKext
;
89 uint32_t superClassID
;
90 const OSMetaClass
*metaClass
;
91 SLIST_HEAD(, IOEventSourceCounter
) counterList
;
92 SLIST_HEAD(, IOUserClientCounter
) userClientList
;
95 typedef struct KextNode
{
96 RB_ENTRY(KextNode
) link
;
97 RB_ENTRY(KextNode
) addressLink
;
99 OSKextLoadTag loadTag
;
101 vm_offset_t address_end
;
102 uint32_t memoryCounters
[kIOStatisticsAllocCount
];
104 SLIST_HEAD(, ClassNode
) classList
;
105 SLIST_HEAD(, IOWorkLoopCounter
) workLoopList
;
106 ProcessEntryList userClientCallList
;
109 /* User client tracing */
111 typedef struct IOUserClientProcessEntry
{
112 TAILQ_ENTRY(IOUserClientProcessEntry
) link
;
113 char processName
[kIOStatisticsProcessNameLength
];
116 } IOUserClientProcessEntry
;
120 typedef struct IOInterruptEventSourceCounter
{
122 uint32_t checksForWork
;
123 } IOInterruptEventSourceCounter
;
125 typedef struct IOTimerEventSourceCounter
{
127 uint32_t checksForWork
;
128 } IOTimerEventSourceCounter
;
130 typedef struct IOCommandGateCounter
{
131 uint32_t actionCalls
;
132 } IOCommandGateCounter
;
134 typedef struct IOCommandQueueCounter
{
135 uint32_t actionCalls
;
136 } IOCommandQueueCounter
;
138 typedef struct IOEventSourceCounter
{
139 SLIST_ENTRY(IOEventSourceCounter
) link
;
140 ClassNode
*parentClass
;
141 IOStatisticsCounterType type
;
142 uint64_t startTimeStamp
;
144 uint32_t closeGateCalls
;
145 uint32_t openGateCalls
;
147 IOInterruptEventSourceCounter interrupt
;
148 IOInterruptEventSourceCounter filter
;
149 IOTimerEventSourceCounter timer
;
150 IOCommandGateCounter commandGate
;
151 IOCommandQueueCounter commandQueue
;
153 } IOEventSourceCounter
;
155 typedef struct IOWorkLoopDependency
{
156 RB_ENTRY(IOWorkLoopDependency
) link
;
157 OSKextLoadTag loadTag
;
158 } IOWorkLoopDependency
;
160 typedef struct IOWorkLoopCounter
{
161 SLIST_ENTRY(IOWorkLoopCounter
) link
;
162 KextNode
*parentKext
;
163 int attachedEventSources
;
164 IOWorkLoop
*workLoop
;
165 uint64_t startTimeStamp
;
167 uint32_t closeGateCalls
;
168 uint32_t openGateCalls
;
169 typedef RB_HEAD(DependencyTree
, IOWorkLoopDependency
) DependencyTreeHead
;
170 DependencyTreeHead dependencyHead
;
171 static int loadTagCompare(IOWorkLoopDependency
*e1
, IOWorkLoopDependency
*e2
);
172 RB_PROTOTYPE_SC(static, DependencyTree
, IOWorkLoopDependency
, dependencyLink
, KextTagCompare
);
175 typedef struct IOUserClientCounter
{
176 SLIST_ENTRY(IOUserClientCounter
) link
;
177 ClassNode
*parentClass
;
178 uint32_t clientCalls
;
179 } IOUserClientCounter
;
184 static IORWLock
*lock
;
186 static uint32_t sequenceID
;
188 static uint32_t lastKextIndex
;
189 static uint32_t lastClassIndex
;
191 static uint32_t loadedKexts
;
192 static uint32_t registeredClasses
;
193 static uint32_t registeredCounters
;
194 static uint32_t registeredWorkloops
;
196 static uint32_t attachedEventSources
;
198 static KextNode
*kextHint
;
200 static IOWorkLoopDependency
*nextWorkLoopDependency
;
202 typedef RB_HEAD(KextTree
, KextNode
) KextTreeHead
;
203 static KextTreeHead kextHead
;
204 static int kextNodeCompare(KextNode
*e1
, KextNode
*e2
);
205 RB_PROTOTYPE_SC(static, KextTree
, KextNode
, link
, kextNodeCompare
);
207 typedef RB_HEAD(KextAddressTree
, KextNode
) KextAddressTreeHead
;
208 static KextAddressTreeHead kextAddressHead
;
209 static int kextAddressNodeCompare(KextNode
*e1
, KextNode
*e2
);
210 RB_PROTOTYPE_SC(static, KextAddressTree
, KextNode
, addressLink
, kextAddressNodeCompare
);
212 typedef RB_HEAD(ClassTree
, ClassNode
) ClassTreeHead
;
213 static ClassTreeHead classHead
;
214 static int classNodeCompare(ClassNode
*e1
, ClassNode
*e2
);
215 RB_PROTOTYPE_SC(static, ClassTree
, ClassNode
, tLink
, classNodeCompare
);
217 static int oid_sysctl(__unused
struct sysctl_oid
*oidp
, __unused
void *arg1
, int arg2
, struct sysctl_req
*req
);
219 static uint32_t copyGlobalStatistics(IOStatisticsGlobal
*stats
);
220 static uint32_t copyKextStatistics(IOStatisticsKext
*stats
);
221 static uint32_t copyMemoryStatistics(IOStatisticsMemory
*stats
);
222 static uint32_t copyClassStatistics(IOStatisticsClass
*stats
);
223 static uint32_t copyCounterStatistics(IOStatisticsCounter
*stats
);
224 static uint32_t copyKextIdentifiers(IOStatisticsKextIdentifier
*kextIDs
);
225 static uint32_t copyClassNames(IOStatisticsClassName
*classNames
);
227 static uint32_t copyWorkLoopStatistics(IOStatisticsWorkLoop
*workLoopStats
);
229 static uint32_t copyUserClientStatistics(IOStatisticsUserClientHeader
*stats
, uint32_t loadTag
);
231 static void updateAllocationCounter(vm_offset_t address
, uint32_t index
, vm_size_t size
);
233 static void storeUserClientCallInfo(IOUserClient
*userClient
, IOUserClientCounter
*counter
);
235 static KextNode
*getKextNodeFromBacktrace(boolean_t write
);
236 static void releaseKextNode(KextNode
*node
);
240 static void initialize();
242 static void onKextLoad(OSKext
*kext
, kmod_info_t
*kmod_info
);
243 static void onKextUnload(OSKext
*kext
);
244 static void onClassAdded(OSKext
*parentKext
, OSMetaClass
*metaClass
);
245 static void onClassRemoved(OSKext
*parentKext
, OSMetaClass
*metaClass
);
247 static IOEventSourceCounter
*registerEventSource(OSObject
*inOwner
);
248 static void unregisterEventSource(IOEventSourceCounter
*counter
);
250 static IOWorkLoopCounter
*registerWorkLoop(IOWorkLoop
*workLoop
);
251 static void unregisterWorkLoop(IOWorkLoopCounter
*counter
);
253 static IOUserClientCounter
*registerUserClient(IOUserClient
*userClient
);
254 static void unregisterUserClient(IOUserClientCounter
*counter
);
256 static int getStatistics(sysctl_req
*req
);
257 static int getWorkLoopStatistics(sysctl_req
*req
);
258 static int getUserClientStatistics(sysctl_req
*req
);
260 /* Inlines for counter manipulation.
262 * NOTE: counter access is not expressly guarded here so as not to incur performance penalties
263 * in the instrumented parent objects. Writes are arranged so as to be protected by pre-existing
264 * locks in the parent where appropriate, but reads have no such guarantee. Counters should
265 * therefore be regarded as providing an indication of current state, rather than precisely
266 * accurate statistics.
269 static inline void setCounterType(IOEventSourceCounter
*counter
, IOStatisticsCounterType type
) {
271 counter
->type
= type
;
275 static inline void countOpenGate(IOEventSourceCounter
*counter
) {
277 counter
->timeOnGate
+= mach_absolute_time() - counter
->startTimeStamp
;
278 counter
->openGateCalls
++;
282 static inline void countCloseGate(IOEventSourceCounter
*counter
) {
284 counter
->startTimeStamp
= mach_absolute_time();
285 counter
->closeGateCalls
++;
290 static inline void countInterruptCheckForWork(IOEventSourceCounter
*counter
) {
292 counter
->u
.interrupt
.checksForWork
++;
296 static inline void countInterrupt(IOEventSourceCounter
*counter
) {
298 counter
->u
.interrupt
.produced
++;
303 static inline void countCommandQueueActionCall(IOEventSourceCounter
*counter
) {
305 counter
->u
.commandQueue
.actionCalls
++;
310 static inline void countCommandGateActionCall(IOEventSourceCounter
*counter
) {
312 counter
->u
.commandGate
.actionCalls
++;
317 static inline void countTimerTimeout(IOEventSourceCounter
*counter
) {
319 counter
->u
.timer
.timeouts
++;
324 static void attachWorkLoopEventSource(IOWorkLoopCounter
*wlc
, IOEventSourceCounter
*esc
);
325 static void detachWorkLoopEventSource(IOWorkLoopCounter
*wlc
, IOEventSourceCounter
*esc
);
327 static inline void countWorkLoopOpenGate(IOWorkLoopCounter
*counter
) {
329 counter
->timeOnGate
+= mach_absolute_time() - counter
->startTimeStamp
;
330 counter
->openGateCalls
++;
334 static inline void countWorkLoopCloseGate(IOWorkLoopCounter
*counter
) {
336 counter
->startTimeStamp
= mach_absolute_time();
337 counter
->closeGateCalls
++;
341 /* IOLib allocations */
342 static void countAlloc(uint32_t index
, vm_size_t size
);
345 static void countUserClientCall(IOUserClient
*client
);
350 /* Statistics disabled */
354 static void initialize() {}
357 #endif /* IOKITSTATS */
359 #endif /* __IOKIT_STATISTICS_PRIVATE_H */