2 * Copyright (c) 1998-2016 Apple 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 #include <IOKit/system.h>
31 #include <IOKit/IOService.h>
32 #include <libkern/OSDebug.h>
33 #include <libkern/c++/OSContainers.h>
34 #include <libkern/c++/OSKext.h>
35 #include <libkern/c++/OSUnserialize.h>
36 #include <libkern/Block.h>
37 #include <IOKit/IOCatalogue.h>
38 #include <IOKit/IOCommand.h>
39 #include <IOKit/IODeviceTreeSupport.h>
40 #include <IOKit/IODeviceMemory.h>
41 #include <IOKit/IOInterrupts.h>
42 #include <IOKit/IOInterruptController.h>
43 #include <IOKit/IOPlatformExpert.h>
44 #include <IOKit/IOMessage.h>
45 #include <IOKit/IOLib.h>
46 #include <IOKit/IOKitKeysPrivate.h>
47 #include <IOKit/IOBSD.h>
48 #include <IOKit/IOUserClient.h>
49 #include <IOKit/IOWorkLoop.h>
50 #include <IOKit/IOTimeStamp.h>
51 #include <IOKit/IOHibernatePrivate.h>
52 #include <IOKit/IOInterruptAccountingPrivate.h>
53 #include <IOKit/IOKernelReporters.h>
54 #include <IOKit/AppleKeyStoreInterface.h>
55 #include <IOKit/pwr_mgt/RootDomain.h>
56 #include <IOKit/IOCPU.h>
57 #include <mach/sync_policy.h>
58 #include <IOKit/assert.h>
59 #include <sys/errno.h>
60 #include <sys/kdebug.h>
63 #include <machine/pal_routines.h>
68 #define IOSERVICE_OBFUSCATE(x) ((void *)(VM_KERNEL_ADDRPERM(x)))
70 // disabled since lockForArbitration() can be held externally
71 #define DEBUG_NOTIFIER_LOCKED 0
73 #include "IOServicePrivate.h"
74 #include "IOKitKernelInternal.h"
76 // take lockForArbitration before LOCKNOTIFY
78 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
80 #define super IORegistryEntry
82 OSDefineMetaClassAndStructors(IOService
, IORegistryEntry
)
84 OSDefineMetaClassAndStructors(_IOServiceNotifier
, IONotifier
)
85 OSDefineMetaClassAndStructors(_IOServiceNullNotifier
, IONotifier
)
87 OSDefineMetaClassAndStructors(_IOServiceInterestNotifier
, IONotifier
)
89 OSDefineMetaClassAndStructors(_IOConfigThread
, OSObject
)
91 OSDefineMetaClassAndStructors(_IOServiceJob
, OSObject
)
93 OSDefineMetaClassAndStructors(IOResources
, IOService
)
95 OSDefineMetaClassAndStructors(_IOOpenServiceIterator
, OSIterator
)
97 OSDefineMetaClassAndAbstractStructors(IONotifier
, OSObject
)
99 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
101 static IOPlatformExpert
* gIOPlatform
;
102 static class IOPMrootDomain
* gIOPMRootDomain
;
103 const IORegistryPlane
* gIOServicePlane
;
104 const IORegistryPlane
* gIOPowerPlane
;
105 const OSSymbol
* gIODeviceMemoryKey
;
106 const OSSymbol
* gIOInterruptControllersKey
;
107 const OSSymbol
* gIOInterruptSpecifiersKey
;
109 const OSSymbol
* gIOResourcesKey
;
110 const OSSymbol
* gIOResourceMatchKey
;
111 const OSSymbol
* gIOResourceMatchedKey
;
112 const OSSymbol
* gIOProviderClassKey
;
113 const OSSymbol
* gIONameMatchKey
;
114 const OSSymbol
* gIONameMatchedKey
;
115 const OSSymbol
* gIOPropertyMatchKey
;
116 const OSSymbol
* gIOPropertyExistsMatchKey
;
117 const OSSymbol
* gIOLocationMatchKey
;
118 const OSSymbol
* gIOParentMatchKey
;
119 const OSSymbol
* gIOPathMatchKey
;
120 const OSSymbol
* gIOMatchCategoryKey
;
121 const OSSymbol
* gIODefaultMatchCategoryKey
;
122 const OSSymbol
* gIOMatchedServiceCountKey
;
124 const OSSymbol
* gIOServiceLegacyMatchingRegistryIDKey
;
127 const OSSymbol
* gIOMapperIDKey
;
128 const OSSymbol
* gIOUserClientClassKey
;
129 const OSSymbol
* gIOKitDebugKey
;
131 const OSSymbol
* gIOCommandPoolSizeKey
;
133 const OSSymbol
* gIOConsoleLockedKey
;
134 const OSSymbol
* gIOConsoleUsersKey
;
135 const OSSymbol
* gIOConsoleSessionUIDKey
;
136 const OSSymbol
* gIOConsoleSessionAuditIDKey
;
137 const OSSymbol
* gIOConsoleUsersSeedKey
;
138 const OSSymbol
* gIOConsoleSessionOnConsoleKey
;
139 const OSSymbol
* gIOConsoleSessionLoginDoneKey
;
140 const OSSymbol
* gIOConsoleSessionSecureInputPIDKey
;
141 const OSSymbol
* gIOConsoleSessionScreenLockedTimeKey
;
142 const OSSymbol
* gIOConsoleSessionScreenIsLockedKey
;
143 clock_sec_t gIOConsoleLockTime
;
144 static bool gIOConsoleLoggedIn
;
146 static OSBoolean
* gIOConsoleBooterLockState
;
147 static uint32_t gIOScreenLockState
;
149 static IORegistryEntry
* gIOChosenEntry
;
151 static int gIOResourceGenerationCount
;
153 const OSSymbol
* gIOServiceKey
;
154 const OSSymbol
* gIOPublishNotification
;
155 const OSSymbol
* gIOFirstPublishNotification
;
156 const OSSymbol
* gIOMatchedNotification
;
157 const OSSymbol
* gIOFirstMatchNotification
;
158 const OSSymbol
* gIOTerminatedNotification
;
159 const OSSymbol
* gIOWillTerminateNotification
;
161 const OSSymbol
* gIOGeneralInterest
;
162 const OSSymbol
* gIOBusyInterest
;
163 const OSSymbol
* gIOAppPowerStateInterest
;
164 const OSSymbol
* gIOPriorityPowerStateInterest
;
165 const OSSymbol
* gIOConsoleSecurityInterest
;
167 const OSSymbol
* gIOBSDKey
;
168 const OSSymbol
* gIOBSDNameKey
;
169 const OSSymbol
* gIOBSDMajorKey
;
170 const OSSymbol
* gIOBSDMinorKey
;
171 const OSSymbol
* gIOBSDUnitKey
;
173 const OSSymbol
* gAKSGetKey
;
174 #if defined(__i386__) || defined(__x86_64__)
175 const OSSymbol
* gIOCreateEFIDevicePathSymbol
;
178 static OSDictionary
* gNotifications
;
179 static IORecursiveLock
* gNotificationLock
;
181 static IOService
* gIOResources
;
182 static IOService
* gIOServiceRoot
;
184 static OSOrderedSet
* gJobs
;
185 static semaphore_port_t gJobsSemaphore
;
186 static IOLock
* gJobsLock
;
187 static int gOutstandingJobs
;
188 static int gNumConfigThreads
;
189 static int gNumWaitingThreads
;
190 static IOLock
* gIOServiceBusyLock
;
193 static thread_t gIOTerminateThread
;
194 static thread_t gIOTerminateWorkerThread
;
195 static UInt32 gIOTerminateWork
;
196 static OSArray
* gIOTerminatePhase2List
;
197 static OSArray
* gIOStopList
;
198 static OSArray
* gIOStopProviderList
;
199 static OSArray
* gIOFinalizeList
;
201 static SInt32 gIOConsoleUsersSeed
;
202 static OSData
* gIOConsoleUsersSeedValue
;
204 extern const OSSymbol
* gIODTPHandleKey
;
206 const OSSymbol
* gIOPlatformFunctionHandlerSet
;
208 static IOLock
* gIOConsoleUsersLock
;
209 static thread_call_t gIOConsoleLockCallout
;
210 static IONotifier
* gIOServiceNullNotifier
;
212 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
214 #define LOCKREADNOTIFY() \
215 IORecursiveLockLock( gNotificationLock )
216 #define LOCKWRITENOTIFY() \
217 IORecursiveLockLock( gNotificationLock )
218 #define LOCKWRITE2READNOTIFY()
219 #define UNLOCKNOTIFY() \
220 IORecursiveLockUnlock( gNotificationLock )
221 #define SLEEPNOTIFY(event) \
222 IORecursiveLockSleep( gNotificationLock, (void *)(event), THREAD_UNINT )
223 #define SLEEPNOTIFYTO(event, deadline) \
224 IORecursiveLockSleepDeadline( gNotificationLock, (void *)(event), deadline, THREAD_UNINT )
225 #define WAKEUPNOTIFY(event) \
226 IORecursiveLockWakeup( gNotificationLock, (void *)(event), /* wake one */ false )
228 #define randomDelay() \
229 int del = read_processor_clock(); \
230 del = (((int)IOThreadSelf()) ^ del ^ (del >> 10)) & 0x3ff; \
233 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
235 #define queue_element(entry, element, type, field) do { \
236 vm_address_t __ele = (vm_address_t) (entry); \
237 __ele -= -4 + ((size_t)(&((type) 4)->field)); \
238 (element) = (type) __ele; \
241 #define iterqueue(que, elt) \
242 for (queue_entry_t elt = queue_first(que); \
243 !queue_end(que, elt); \
244 elt = queue_next(elt))
246 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
248 struct IOInterruptAccountingReporter
{
249 IOSimpleReporter
* reporter
; /* Reporter responsible for communicating the statistics */
250 IOInterruptAccountingData
* statistics
; /* The live statistics values, if any */
253 struct ArbitrationLockQueueElement
{
262 static queue_head_t gArbitrationLockQueueActive
;
263 static queue_head_t gArbitrationLockQueueWaiting
;
264 static queue_head_t gArbitrationLockQueueFree
;
265 static IOLock
* gArbitrationLockQueueLock
;
267 bool IOService::isInactive( void ) const
268 { return( 0 != (kIOServiceInactiveState
& getState())); }
270 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
272 #if defined(__i386__) || defined(__x86_64__)
274 // Only used by the intel implementation of
275 // IOService::requireMaxBusStall(UInt32 ns)
276 // IOService::requireMaxInterruptDelay(uint32_t ns)
279 IOService
* fService
;
285 kCpuDelayBusStall
, kCpuDelayInterrupt
,
289 static OSData
*sCpuDelayData
= OSData::withCapacity(8 * sizeof(CpuDelayEntry
));
290 static IORecursiveLock
*sCpuDelayLock
= IORecursiveLockAlloc();
291 static OSArray
*sCpuLatencyHandlers
[kCpuNumDelayTypes
];
292 const OSSymbol
*sCPULatencyFunctionName
[kCpuNumDelayTypes
];
293 static OSNumber
* sCPULatencyHolder
[kCpuNumDelayTypes
];
294 static char sCPULatencyHolderName
[kCpuNumDelayTypes
][128];
295 static OSNumber
* sCPULatencySet
[kCpuNumDelayTypes
];
298 requireMaxCpuDelay(IOService
* service
, UInt32 ns
, UInt32 delayType
);
300 setLatencyHandler(UInt32 delayType
, IOService
* target
, bool enable
);
302 #endif /* defined(__i386__) || defined(__x86_64__) */
304 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
306 void IOService::initialize( void )
310 gIOServicePlane
= IORegistryEntry::makePlane( kIOServicePlane
);
311 gIOPowerPlane
= IORegistryEntry::makePlane( kIOPowerPlane
);
313 gIOProviderClassKey
= OSSymbol::withCStringNoCopy( kIOProviderClassKey
);
314 gIONameMatchKey
= OSSymbol::withCStringNoCopy( kIONameMatchKey
);
315 gIONameMatchedKey
= OSSymbol::withCStringNoCopy( kIONameMatchedKey
);
316 gIOPropertyMatchKey
= OSSymbol::withCStringNoCopy( kIOPropertyMatchKey
);
317 gIOPropertyExistsMatchKey
= OSSymbol::withCStringNoCopy( kIOPropertyExistsMatchKey
);
318 gIOPathMatchKey
= OSSymbol::withCStringNoCopy( kIOPathMatchKey
);
319 gIOLocationMatchKey
= OSSymbol::withCStringNoCopy( kIOLocationMatchKey
);
320 gIOParentMatchKey
= OSSymbol::withCStringNoCopy( kIOParentMatchKey
);
322 gIOMatchCategoryKey
= OSSymbol::withCStringNoCopy( kIOMatchCategoryKey
);
323 gIODefaultMatchCategoryKey
= OSSymbol::withCStringNoCopy(
324 kIODefaultMatchCategoryKey
);
325 gIOMatchedServiceCountKey
= OSSymbol::withCStringNoCopy(
326 kIOMatchedServiceCountKey
);
328 gIOServiceLegacyMatchingRegistryIDKey
= OSSymbol::withCStringNoCopy(
329 kIOServiceLegacyMatchingRegistryIDKey
);
332 gIOUserClientClassKey
= OSSymbol::withCStringNoCopy( kIOUserClientClassKey
);
334 gIOResourcesKey
= OSSymbol::withCStringNoCopy( kIOResourcesClass
);
335 gIOResourceMatchKey
= OSSymbol::withCStringNoCopy( kIOResourceMatchKey
);
336 gIOResourceMatchedKey
= OSSymbol::withCStringNoCopy( kIOResourceMatchedKey
);
338 gIODeviceMemoryKey
= OSSymbol::withCStringNoCopy( "IODeviceMemory" );
339 gIOInterruptControllersKey
340 = OSSymbol::withCStringNoCopy("IOInterruptControllers");
341 gIOInterruptSpecifiersKey
342 = OSSymbol::withCStringNoCopy("IOInterruptSpecifiers");
344 gIOMapperIDKey
= OSSymbol::withCStringNoCopy(kIOMapperIDKey
);
346 gIOKitDebugKey
= OSSymbol::withCStringNoCopy( kIOKitDebugKey
);
348 gIOCommandPoolSizeKey
= OSSymbol::withCStringNoCopy( kIOCommandPoolSizeKey
);
350 gIOGeneralInterest
= OSSymbol::withCStringNoCopy( kIOGeneralInterest
);
351 gIOBusyInterest
= OSSymbol::withCStringNoCopy( kIOBusyInterest
);
352 gIOAppPowerStateInterest
= OSSymbol::withCStringNoCopy( kIOAppPowerStateInterest
);
353 gIOPriorityPowerStateInterest
= OSSymbol::withCStringNoCopy( kIOPriorityPowerStateInterest
);
354 gIOConsoleSecurityInterest
= OSSymbol::withCStringNoCopy( kIOConsoleSecurityInterest
);
356 gIOBSDKey
= OSSymbol::withCStringNoCopy(kIOBSDKey
);
357 gIOBSDNameKey
= OSSymbol::withCStringNoCopy(kIOBSDNameKey
);
358 gIOBSDMajorKey
= OSSymbol::withCStringNoCopy(kIOBSDMajorKey
);
359 gIOBSDMinorKey
= OSSymbol::withCStringNoCopy(kIOBSDMinorKey
);
360 gIOBSDUnitKey
= OSSymbol::withCStringNoCopy(kIOBSDUnitKey
);
362 gNotifications
= OSDictionary::withCapacity( 1 );
363 gIOPublishNotification
= OSSymbol::withCStringNoCopy(
364 kIOPublishNotification
);
365 gIOFirstPublishNotification
= OSSymbol::withCStringNoCopy(
366 kIOFirstPublishNotification
);
367 gIOMatchedNotification
= OSSymbol::withCStringNoCopy(
368 kIOMatchedNotification
);
369 gIOFirstMatchNotification
= OSSymbol::withCStringNoCopy(
370 kIOFirstMatchNotification
);
371 gIOTerminatedNotification
= OSSymbol::withCStringNoCopy(
372 kIOTerminatedNotification
);
373 gIOWillTerminateNotification
= OSSymbol::withCStringNoCopy(
374 kIOWillTerminateNotification
);
375 gIOServiceKey
= OSSymbol::withCStringNoCopy( kIOServiceClass
);
377 gIOConsoleLockedKey
= OSSymbol::withCStringNoCopy( kIOConsoleLockedKey
);
378 gIOConsoleUsersKey
= OSSymbol::withCStringNoCopy( kIOConsoleUsersKey
);
379 gIOConsoleSessionUIDKey
= OSSymbol::withCStringNoCopy( kIOConsoleSessionUIDKey
);
380 gIOConsoleSessionAuditIDKey
= OSSymbol::withCStringNoCopy( kIOConsoleSessionAuditIDKey
);
382 gIOConsoleUsersSeedKey
= OSSymbol::withCStringNoCopy(kIOConsoleUsersSeedKey
);
383 gIOConsoleSessionOnConsoleKey
= OSSymbol::withCStringNoCopy(kIOConsoleSessionOnConsoleKey
);
384 gIOConsoleSessionLoginDoneKey
= OSSymbol::withCStringNoCopy(kIOConsoleSessionLoginDoneKey
);
385 gIOConsoleSessionSecureInputPIDKey
= OSSymbol::withCStringNoCopy(kIOConsoleSessionSecureInputPIDKey
);
386 gIOConsoleSessionScreenLockedTimeKey
= OSSymbol::withCStringNoCopy(kIOConsoleSessionScreenLockedTimeKey
);
387 gIOConsoleSessionScreenIsLockedKey
= OSSymbol::withCStringNoCopy(kIOConsoleSessionScreenIsLockedKey
);
389 gIOConsoleUsersSeedValue
= OSData::withBytesNoCopy(&gIOConsoleUsersSeed
, sizeof(gIOConsoleUsersSeed
));
391 gIOPlatformFunctionHandlerSet
= OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerSet
);
392 #if defined(__i386__) || defined(__x86_64__)
393 sCPULatencyFunctionName
[kCpuDelayBusStall
] = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerMaxBusDelay
);
394 sCPULatencyFunctionName
[kCpuDelayInterrupt
] = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerMaxInterruptDelay
);
396 for (idx
= 0; idx
< kCpuNumDelayTypes
; idx
++)
398 sCPULatencySet
[idx
] = OSNumber::withNumber(-1U, 32);
399 sCPULatencyHolder
[idx
] = OSNumber::withNumber(0ULL, 64);
400 assert(sCPULatencySet
[idx
] && sCPULatencyHolder
[idx
]);
402 gIOCreateEFIDevicePathSymbol
= OSSymbol::withCString("CreateEFIDevicePath");
404 gNotificationLock
= IORecursiveLockAlloc();
406 gAKSGetKey
= OSSymbol::withCStringNoCopy(AKS_PLATFORM_FUNCTION_GETKEY
);
408 assert( gIOServicePlane
&& gIODeviceMemoryKey
409 && gIOInterruptControllersKey
&& gIOInterruptSpecifiersKey
410 && gIOResourcesKey
&& gNotifications
&& gNotificationLock
411 && gIOProviderClassKey
&& gIONameMatchKey
&& gIONameMatchedKey
412 && gIOMatchCategoryKey
&& gIODefaultMatchCategoryKey
413 && gIOPublishNotification
&& gIOMatchedNotification
414 && gIOTerminatedNotification
&& gIOServiceKey
415 && gIOConsoleUsersKey
&& gIOConsoleSessionUIDKey
416 && gIOConsoleSessionOnConsoleKey
&& gIOConsoleSessionSecureInputPIDKey
417 && gIOConsoleUsersSeedKey
&& gIOConsoleUsersSeedValue
);
419 gJobsLock
= IOLockAlloc();
420 gJobs
= OSOrderedSet::withCapacity( 10 );
422 gIOServiceBusyLock
= IOLockAlloc();
424 gIOConsoleUsersLock
= IOLockAlloc();
426 err
= semaphore_create(kernel_task
, &gJobsSemaphore
, SYNC_POLICY_FIFO
, 0);
428 gIOConsoleLockCallout
= thread_call_allocate(&IOService::consoleLockTimer
, NULL
);
430 IORegistryEntry::getRegistryRoot()->setProperty(gIOConsoleLockedKey
, kOSBooleanTrue
);
432 assert( gIOServiceBusyLock
&& gJobs
&& gJobsLock
&& gIOConsoleUsersLock
433 && gIOConsoleLockCallout
&& (err
== KERN_SUCCESS
) );
435 gIOResources
= IOResources::resources();
436 assert( gIOResources
);
438 gIOServiceNullNotifier
= OSTypeAlloc(_IOServiceNullNotifier
);
439 assert(gIOServiceNullNotifier
);
441 gArbitrationLockQueueLock
= IOLockAlloc();
442 queue_init(&gArbitrationLockQueueActive
);
443 queue_init(&gArbitrationLockQueueWaiting
);
444 queue_init(&gArbitrationLockQueueFree
);
446 assert( gArbitrationLockQueueLock
);
448 gIOTerminatePhase2List
= OSArray::withCapacity( 2 );
449 gIOStopList
= OSArray::withCapacity( 16 );
450 gIOStopProviderList
= OSArray::withCapacity( 16 );
451 gIOFinalizeList
= OSArray::withCapacity( 16 );
452 assert( gIOTerminatePhase2List
&& gIOStopList
&& gIOStopProviderList
&& gIOFinalizeList
);
454 // worker thread that is responsible for terminating / cleaning up threads
455 kernel_thread_start(&terminateThread
, NULL
, &gIOTerminateWorkerThread
);
456 assert(gIOTerminateWorkerThread
);
457 thread_set_thread_name(gIOTerminateWorkerThread
, "IOServiceTerminateThread");
460 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
462 #if defined(__i386__) || defined(__x86_64__)
465 const char *getCpuDelayBusStallHolderName(void);
466 const char *getCpuDelayBusStallHolderName(void) {
467 return sCPULatencyHolderName
[kCpuDelayBusStall
];
470 const char *getCpuInterruptDelayHolderName(void);
471 const char *getCpuInterruptDelayHolderName(void) {
472 return sCPULatencyHolderName
[kCpuDelayInterrupt
];
479 static UInt64
getDebugFlags( OSDictionary
* props
)
481 OSNumber
* debugProp
;
484 debugProp
= OSDynamicCast( OSNumber
,
485 props
->getObject( gIOKitDebugKey
));
487 debugFlags
= debugProp
->unsigned64BitValue();
489 debugFlags
= gIOKitDebug
;
491 return( debugFlags
);
494 static UInt64
getDebugFlags( IOService
* inst
)
497 OSNumber
* debugProp
;
500 prop
= inst
->copyProperty(gIOKitDebugKey
);
501 debugProp
= OSDynamicCast(OSNumber
, prop
);
503 debugFlags
= debugProp
->unsigned64BitValue();
505 debugFlags
= gIOKitDebug
;
507 OSSafeReleaseNULL(prop
);
509 return( debugFlags
);
513 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
515 // Probe a matched service and return an instance to be started.
516 // The default score is from the property table, & may be altered
517 // during probe to change the start order.
519 IOService
* IOService::probe( IOService
* provider
,
525 bool IOService::start( IOService
* provider
)
530 void IOService::stop( IOService
* provider
)
534 bool IOService::init( OSDictionary
* dictionary
)
538 ret
= super::init(dictionary
);
539 if (!ret
) return (false);
540 if (reserved
) return (true);
542 reserved
= IONew(ExpansionData
, 1);
543 if (!reserved
) return (false);
544 bzero(reserved
, sizeof(*reserved
));
547 * TODO: Improve on this. Previous efforts to more lazily allocate this
548 * lock based on the presence of specifiers ran into issues as some
549 * platforms set up the specifiers after IOService initialization.
551 * We may be able to get away with a global lock, as this should only be
552 * contended by IOReporting clients and driver start/stop (unless a
553 * driver wants to remove/add handlers in the course of normal operation,
554 * which should be unlikely).
556 reserved
->interruptStatisticsLock
= IOLockAlloc();
557 if (!reserved
->interruptStatisticsLock
) return (false);
562 bool IOService::init( IORegistryEntry
* from
,
563 const IORegistryPlane
* inPlane
)
567 ret
= super::init(from
, inPlane
);
568 if (!ret
) return (false);
569 if (reserved
) return (true);
571 reserved
= IONew(ExpansionData
, 1);
572 if (!reserved
) return (false);
573 bzero(reserved
, sizeof(*reserved
));
576 * TODO: Improve on this. Previous efforts to more lazily allocate this
577 * lock based on the presence of specifiers ran into issues as some
578 * platforms set up the specifiers after IOService initialization.
580 * We may be able to get away with a global lock, as this should only be
581 * contended by IOReporting clients and driver start/stop (unless a
582 * driver wants to remove/add handlers in the course of normal operation,
583 * which should be unlikely).
585 reserved
->interruptStatisticsLock
= IOLockAlloc();
586 if (!reserved
->interruptStatisticsLock
) return (false);
591 void IOService::free( void )
594 requireMaxBusStall(0);
595 requireMaxInterruptDelay(0);
596 if( getPropertyTable())
597 unregisterAllInterest();
601 if (reserved
->interruptStatisticsArray
) {
602 for (i
= 0; i
< reserved
->interruptStatisticsArrayCount
; i
++) {
603 if (reserved
->interruptStatisticsArray
[i
].reporter
)
604 reserved
->interruptStatisticsArray
[i
].reporter
->release();
607 IODelete(reserved
->interruptStatisticsArray
, IOInterruptAccountingReporter
, reserved
->interruptStatisticsArrayCount
);
610 if (reserved
->interruptStatisticsLock
)
611 IOLockFree(reserved
->interruptStatisticsLock
);
612 IODelete(reserved
, ExpansionData
, 1);
615 if (_numInterruptSources
&& _interruptSources
)
617 for (i
= 0; i
< _numInterruptSources
; i
++) {
618 void * block
= _interruptSourcesPrivate(this)[i
].vectorBlock
;
619 if (block
) Block_release(block
);
621 IOFree(_interruptSources
,
622 _numInterruptSources
* sizeofAllIOInterruptSource
);
623 _interruptSources
= 0;
630 * Attach in service plane
632 bool IOService::attach( IOService
* provider
)
636 AbsoluteTime deadline
;
637 int waitResult
= THREAD_AWAKENED
;
638 bool wait
, computeDeadline
= true;
642 if( gIOKitDebug
& kIOLogAttach
)
643 LOG( "%s::attach(%s)\n", getName(),
644 provider
->getName());
650 provider
->lockForArbitration();
651 if (provider
->__state
[0] & kIOServiceInactiveState
) ok
= false;
654 count
= provider
->getChildCount(gIOServicePlane
);
655 wait
= (count
> (kIOServiceBusyMax
- 4));
656 if (!wait
) ok
= attachToParent(provider
, gIOServicePlane
);
659 IOLog("stalling for detach from %s\n", provider
->getName());
660 IOLockLock( gIOServiceBusyLock
);
661 provider
->__state
[1] |= kIOServiceWaitDetachState
;
664 provider
->unlockForArbitration();
669 clock_interval_to_deadline(15, kSecondScale
, &deadline
);
670 computeDeadline
= false;
672 assert_wait_deadline((event_t
)&provider
->__provider
, THREAD_UNINT
, deadline
);
673 IOLockUnlock( gIOServiceBusyLock
);
674 waitResult
= thread_block(THREAD_CONTINUE_NULL
);
675 wait
= (waitResult
!= THREAD_TIMED_OUT
);
681 gIOServiceRoot
= this;
682 ok
= attachToParent( getRegistryRoot(), gIOServicePlane
);
685 if (ok
&& !__provider
) (void) getProvider();
690 IOService
* IOService::getServiceRoot( void )
692 return( gIOServiceRoot
);
695 void IOService::detach( IOService
* provider
)
697 IOService
* newProvider
= 0;
701 if( gIOKitDebug
& kIOLogAttach
)
702 LOG("%s::detach(%s)\n", getName(), provider
->getName());
704 lockForArbitration();
706 uint64_t regID1
= provider
->getRegistryEntryID();
707 uint64_t regID2
= getRegistryEntryID();
711 (uintptr_t) (regID1
>> 32),
713 (uintptr_t) (regID2
>> 32));
715 adjParent
= ((busy
= (__state
[1] & kIOServiceBusyStateMask
))
716 && (provider
== getProvider()));
718 detachFromParent( provider
, gIOServicePlane
);
721 newProvider
= getProvider();
722 if( busy
&& (__state
[1] & kIOServiceTermPhase3State
) && (0 == newProvider
))
723 _adjustBusy( -busy
);
726 if (kIOServiceInactiveState
& __state
[0]) {
727 getMetaClass()->removeInstance(this);
728 IORemoveServicePlatformActions(this);
731 unlockForArbitration();
733 if( newProvider
&& adjParent
) {
734 newProvider
->lockForArbitration();
735 newProvider
->_adjustBusy(1);
736 newProvider
->unlockForArbitration();
739 // check for last client detach from a terminated service
740 if( provider
->lockForArbitration( true ))
742 if (kIOServiceStartState
& __state
[1])
744 provider
->scheduleTerminatePhase2();
746 if( adjParent
) provider
->_adjustBusy( -1 );
747 if( (provider
->__state
[1] & kIOServiceTermPhase3State
)
748 && (0 == provider
->getClient())) {
749 provider
->scheduleFinalize(false);
752 IOLockLock( gIOServiceBusyLock
);
753 if (kIOServiceWaitDetachState
& provider
->__state
[1])
755 provider
->__state
[1] &= ~kIOServiceWaitDetachState
;
756 thread_wakeup(&provider
->__provider
);
758 IOLockUnlock( gIOServiceBusyLock
);
760 provider
->unlockForArbitration();
765 * Register instance - publish it for matching
768 void IOService::registerService( IOOptionBits options
)
774 enum { kMaxPathLen
= 256 };
775 enum { kMaxChars
= 63 };
777 IORegistryEntry
* parent
= this;
778 IORegistryEntry
* root
= getRegistryRoot();
779 while( parent
&& (parent
!= root
))
780 parent
= parent
->getParentEntry( gIOServicePlane
);
782 if( parent
!= root
) {
783 IOLog("%s: not registry member at registerService()\n", getName());
787 // Allow the Platform Expert to adjust this node.
788 if( gIOPlatform
&& (!gIOPlatform
->platformAdjustService(this)))
791 IOInstallServicePlatformActions(this);
793 if( (this != gIOResources
)
794 && (kIOLogRegister
& gIOKitDebug
)) {
796 pathBuf
= (char *) IOMalloc( kMaxPathLen
);
798 IOLog( "Registering: " );
801 if( pathBuf
&& getPath( pathBuf
, &len
, gIOServicePlane
)) {
804 if( len
> kMaxChars
) {
808 if( (skip
= strchr( path
, '/')))
814 IOLog( "%s\n", path
);
817 IOFree( pathBuf
, kMaxPathLen
);
820 startMatching( options
);
823 void IOService::startMatching( IOOptionBits options
)
825 IOService
* provider
;
828 bool needWake
= false;
833 lockForArbitration();
835 sync
= (options
& kIOServiceSynchronous
)
836 || ((provider
= getProvider())
837 && (provider
->__state
[1] & kIOServiceSynchronousState
));
839 if ( options
& kIOServiceAsynchronous
)
842 needConfig
= (0 == (__state
[1] & (kIOServiceNeedConfigState
| kIOServiceConfigRunning
)))
843 && (0 == (__state
[0] & kIOServiceInactiveState
));
845 __state
[1] |= kIOServiceNeedConfigState
;
847 // __state[0] &= ~kIOServiceInactiveState;
849 // if( sync) LOG("OSKernelStackRemaining = %08x @ %s\n",
850 // OSKernelStackRemaining(), getName());
853 needWake
= (0 != (kIOServiceSyncPubState
& __state
[1]));
857 __state
[1] |= kIOServiceSynchronousState
;
859 __state
[1] &= ~kIOServiceSynchronousState
;
861 if( needConfig
) prevBusy
= _adjustBusy( 1 );
863 unlockForArbitration();
868 IOLockLock( gIOServiceBusyLock
);
869 thread_wakeup( (event_t
) this/*&__state[1]*/ );
870 IOLockUnlock( gIOServiceBusyLock
);
872 } else if( !sync
|| (kIOServiceAsynchronous
& options
)) {
874 ok
= (0 != _IOServiceJob::startJob( this, kMatchNubJob
, options
));
878 if( (__state
[1] & kIOServiceNeedConfigState
))
879 doServiceMatch( options
);
881 lockForArbitration();
882 IOLockLock( gIOServiceBusyLock
);
884 waitAgain
= ((prevBusy
< (__state
[1] & kIOServiceBusyStateMask
))
885 && (0 == (__state
[0] & kIOServiceInactiveState
)));
888 __state
[1] |= kIOServiceSyncPubState
| kIOServiceBusyWaiterState
;
890 __state
[1] &= ~kIOServiceSyncPubState
;
892 unlockForArbitration();
895 assert_wait( (event_t
) this/*&__state[1]*/, THREAD_UNINT
);
897 IOLockUnlock( gIOServiceBusyLock
);
899 thread_block(THREAD_CONTINUE_NULL
);
901 } while( waitAgain
);
905 IOReturn
IOService::catalogNewDrivers( OSOrderedSet
* newTables
)
907 OSDictionary
* table
;
917 while( (table
= (OSDictionary
*) newTables
->getFirstObject())) {
920 set
= (OSSet
*) copyExistingServices( table
,
921 kIOServiceRegisteredState
,
922 kIOServiceExistingSet
);
927 count
+= set
->getCount();
930 allSet
->merge((const OSSet
*) set
);
938 if( getDebugFlags( table
) & kIOLogMatch
)
939 LOG("Matching service count = %ld\n", (long)count
);
941 newTables
->removeObject(table
);
945 while( (service
= (IOService
*) allSet
->getAnyObject())) {
946 service
->startMatching(kIOServiceAsynchronous
);
947 allSet
->removeObject(service
);
952 newTables
->release();
954 return( kIOReturnSuccess
);
957 _IOServiceJob
* _IOServiceJob::startJob( IOService
* nub
, int type
,
958 IOOptionBits options
)
962 job
= new _IOServiceJob
;
963 if( job
&& !job
->init()) {
971 job
->options
= options
;
972 nub
->retain(); // thread will release()
980 * Called on a registered service to see if it matches
984 bool IOService::matchPropertyTable( OSDictionary
* table
, SInt32
* score
)
986 return( matchPropertyTable(table
) );
989 bool IOService::matchPropertyTable( OSDictionary
* table
)
995 * Called on a matched service to allocate resources
996 * before first driver is attached.
999 IOReturn
IOService::getResources( void )
1001 return( kIOReturnSuccess
);
1005 * Client/provider accessors
1008 IOService
* IOService::getProvider( void ) const
1010 IOService
* self
= (IOService
*) this;
1014 generation
= getRegistryEntryGenerationCount();
1015 if( __providerGeneration
== generation
)
1016 return( __provider
);
1018 parent
= (IOService
*) getParentEntry( gIOServicePlane
);
1019 if( parent
== IORegistryEntry::getRegistryRoot())
1020 /* root is not an IOService */
1023 self
->__provider
= parent
;
1025 // save the count from before call to getParentEntry()
1026 self
->__providerGeneration
= generation
;
1031 IOWorkLoop
* IOService::getWorkLoop() const
1033 IOService
*provider
= getProvider();
1036 return provider
->getWorkLoop();
1041 OSIterator
* IOService::getProviderIterator( void ) const
1043 return( getParentIterator( gIOServicePlane
));
1046 IOService
* IOService::getClient( void ) const
1048 return( (IOService
*) getChildEntry( gIOServicePlane
));
1051 OSIterator
* IOService::getClientIterator( void ) const
1053 return( getChildIterator( gIOServicePlane
));
1056 OSIterator
* _IOOpenServiceIterator::iterator( OSIterator
* _iter
,
1057 const IOService
* client
,
1058 const IOService
* provider
)
1060 _IOOpenServiceIterator
* inst
;
1065 inst
= new _IOOpenServiceIterator
;
1067 if( inst
&& !inst
->init()) {
1073 inst
->client
= client
;
1074 inst
->provider
= provider
;
1080 void _IOOpenServiceIterator::free()
1084 last
->unlockForArbitration();
1088 OSObject
* _IOOpenServiceIterator::getNextObject()
1093 last
->unlockForArbitration();
1095 while( (next
= (IOService
*) iter
->getNextObject())) {
1097 next
->lockForArbitration();
1098 if( (client
&& (next
->isOpen( client
)))
1099 || (provider
&& (provider
->isOpen( next
))) )
1101 next
->unlockForArbitration();
1109 bool _IOOpenServiceIterator::isValid()
1111 return( iter
->isValid() );
1114 void _IOOpenServiceIterator::reset()
1117 last
->unlockForArbitration();
1123 OSIterator
* IOService::getOpenProviderIterator( void ) const
1125 return( _IOOpenServiceIterator::iterator( getProviderIterator(), this, 0 ));
1128 OSIterator
* IOService::getOpenClientIterator( void ) const
1130 return( _IOOpenServiceIterator::iterator( getClientIterator(), 0, this ));
1134 IOReturn
IOService::callPlatformFunction( const OSSymbol
* functionName
,
1135 bool waitForFunction
,
1136 void *param1
, void *param2
,
1137 void *param3
, void *param4
)
1139 IOReturn result
= kIOReturnUnsupported
;
1140 IOService
*provider
;
1142 if (gIOPlatformFunctionHandlerSet
== functionName
)
1144 #if defined(__i386__) || defined(__x86_64__)
1145 const OSSymbol
* functionHandlerName
= (const OSSymbol
*) param1
;
1146 IOService
* target
= (IOService
*) param2
;
1147 bool enable
= (param3
!= 0);
1149 if (sCPULatencyFunctionName
[kCpuDelayBusStall
] == functionHandlerName
)
1150 result
= setLatencyHandler(kCpuDelayBusStall
, target
, enable
);
1151 else if (sCPULatencyFunctionName
[kCpuDelayInterrupt
] == param1
)
1152 result
= setLatencyHandler(kCpuDelayInterrupt
, target
, enable
);
1153 #endif /* defined(__i386__) || defined(__x86_64__) */
1156 if ((kIOReturnUnsupported
== result
) && (provider
= getProvider())) {
1157 result
= provider
->callPlatformFunction(functionName
, waitForFunction
,
1158 param1
, param2
, param3
, param4
);
1164 IOReturn
IOService::callPlatformFunction( const char * functionName
,
1165 bool waitForFunction
,
1166 void *param1
, void *param2
,
1167 void *param3
, void *param4
)
1169 IOReturn result
= kIOReturnNoMemory
;
1170 const OSSymbol
*functionSymbol
= OSSymbol::withCString(functionName
);
1172 if (functionSymbol
!= 0) {
1173 result
= callPlatformFunction(functionSymbol
, waitForFunction
,
1174 param1
, param2
, param3
, param4
);
1175 functionSymbol
->release();
1183 * Accessors for global services
1186 IOPlatformExpert
* IOService::getPlatform( void )
1188 return( gIOPlatform
);
1191 class IOPMrootDomain
* IOService::getPMRootDomain( void )
1193 return( gIOPMRootDomain
);
1196 IOService
* IOService::getResourceService( void )
1198 return( gIOResources
);
1201 void IOService::setPlatform( IOPlatformExpert
* platform
)
1203 gIOPlatform
= platform
;
1204 gIOResources
->attachToParent( gIOServiceRoot
, gIOServicePlane
);
1206 #if defined(__i386__) || defined(__x86_64__)
1208 static const char * keys
[kCpuNumDelayTypes
] = {
1209 kIOPlatformMaxBusDelay
, kIOPlatformMaxInterruptDelay
};
1210 const OSObject
* objs
[2];
1214 for (idx
= 0; idx
< kCpuNumDelayTypes
; idx
++)
1216 objs
[0] = sCPULatencySet
[idx
];
1217 objs
[1] = sCPULatencyHolder
[idx
];
1218 array
= OSArray::withObjects(objs
, 2);
1220 platform
->setProperty(keys
[idx
], array
);
1223 #endif /* defined(__i386__) || defined(__x86_64__) */
1226 void IOService::setPMRootDomain( class IOPMrootDomain
* rootDomain
)
1228 gIOPMRootDomain
= rootDomain
;
1229 publishResource("IOKit");
1236 bool IOService::lockForArbitration( bool isSuccessRequired
)
1240 ArbitrationLockQueueElement
* element
;
1241 ArbitrationLockQueueElement
* active
;
1242 ArbitrationLockQueueElement
* waiting
;
1244 enum { kPutOnFreeQueue
, kPutOnActiveQueue
, kPutOnWaitingQueue
} action
;
1246 // lock global access
1247 IOTakeLock( gArbitrationLockQueueLock
);
1249 // obtain an unused queue element
1250 if( !queue_empty( &gArbitrationLockQueueFree
)) {
1251 queue_remove_first( &gArbitrationLockQueueFree
,
1253 ArbitrationLockQueueElement
*,
1256 element
= IONew( ArbitrationLockQueueElement
, 1 );
1260 // prepare the queue element
1261 element
->thread
= IOThreadSelf();
1262 element
->service
= this;
1264 element
->required
= isSuccessRequired
;
1265 element
->aborted
= false;
1267 // determine whether this object is already locked (ie. on active queue)
1269 queue_iterate( &gArbitrationLockQueueActive
,
1271 ArbitrationLockQueueElement
*,
1274 if( active
->service
== element
->service
) {
1280 if( found
) { // this object is already locked
1282 // determine whether it is the same or a different thread trying to lock
1283 if( active
->thread
!= element
->thread
) { // it is a different thread
1285 ArbitrationLockQueueElement
* victim
= 0;
1287 // before placing this new thread on the waiting queue, we look for
1288 // a deadlock cycle...
1291 // determine whether the active thread holding the object we
1292 // want is waiting for another object to be unlocked
1294 queue_iterate( &gArbitrationLockQueueWaiting
,
1296 ArbitrationLockQueueElement
*,
1299 if( waiting
->thread
== active
->thread
) {
1300 assert( false == waiting
->aborted
);
1306 if( found
) { // yes, active thread waiting for another object
1308 // this may be a candidate for rejection if the required
1309 // flag is not set, should we detect a deadlock later on
1310 if( false == waiting
->required
)
1313 // find the thread that is holding this other object, that
1314 // is blocking the active thread from proceeding (fun :-)
1316 queue_iterate( &gArbitrationLockQueueActive
,
1317 active
, // (reuse active queue element)
1318 ArbitrationLockQueueElement
*,
1321 if( active
->service
== waiting
->service
) {
1327 // someone must be holding it or it wouldn't be waiting
1330 if( active
->thread
== element
->thread
) {
1332 // doh, it's waiting for the thread that originated
1333 // this whole lock (ie. current thread) -> deadlock
1334 if( false == element
->required
) { // willing to fail?
1336 // the originating thread doesn't have the required
1337 // flag, so it can fail
1338 success
= false; // (fail originating lock request)
1339 break; // (out of while)
1341 } else { // originating thread is not willing to fail
1343 // see if we came across a waiting thread that did
1344 // not have the 'required' flag set: we'll fail it
1347 // we do have a willing victim, fail it's lock
1348 victim
->aborted
= true;
1350 // take the victim off the waiting queue
1351 queue_remove( &gArbitrationLockQueueWaiting
,
1353 ArbitrationLockQueueElement
*,
1357 IOLockWakeup( gArbitrationLockQueueLock
,
1359 /* one thread */ true );
1361 // allow this thread to proceed (ie. wait)
1362 success
= true; // (put request on wait queue)
1363 break; // (out of while)
1366 // all the waiting threads we came across in
1367 // finding this loop had the 'required' flag
1368 // set, so we've got a deadlock we can't avoid
1369 panic("I/O Kit: Unrecoverable deadlock.");
1373 // repeat while loop, redefining active thread to be the
1374 // thread holding "this other object" (see above), and
1375 // looking for threads waiting on it; note the active
1376 // variable points to "this other object" already... so
1377 // there nothing to do in this else clause.
1379 } else { // no, active thread is not waiting for another object
1381 success
= true; // (put request on wait queue)
1382 break; // (out of while)
1386 if( success
) { // put the request on the waiting queue?
1387 kern_return_t wait_result
;
1389 // place this thread on the waiting queue and put it to sleep;
1390 // we place it at the tail of the queue...
1391 queue_enter( &gArbitrationLockQueueWaiting
,
1393 ArbitrationLockQueueElement
*,
1396 // declare that this thread will wait for a given event
1397 restart_sleep
: wait_result
= assert_wait( element
,
1398 element
->required
? THREAD_UNINT
1399 : THREAD_INTERRUPTIBLE
);
1401 // unlock global access
1402 IOUnlock( gArbitrationLockQueueLock
);
1404 // put thread to sleep, waiting for our event to fire...
1405 if (wait_result
== THREAD_WAITING
)
1406 wait_result
= thread_block(THREAD_CONTINUE_NULL
);
1409 // ...and we've been woken up; we might be in one of two states:
1410 // (a) we've been aborted and our queue element is not on
1411 // any of the three queues, but is floating around
1412 // (b) we're allowed to proceed with the lock and we have
1413 // already been moved from the waiting queue to the
1415 // ...plus a 3rd state, should the thread have been interrupted:
1416 // (c) we're still on the waiting queue
1418 // determine whether we were interrupted out of our sleep
1419 if( THREAD_INTERRUPTED
== wait_result
) {
1421 // re-lock global access
1422 IOTakeLock( gArbitrationLockQueueLock
);
1424 // determine whether we're still on the waiting queue
1426 queue_iterate( &gArbitrationLockQueueWaiting
,
1427 waiting
, // (reuse waiting queue element)
1428 ArbitrationLockQueueElement
*,
1431 if( waiting
== element
) {
1437 if( found
) { // yes, we're still on the waiting queue
1439 // determine whether we're willing to fail
1440 if( false == element
->required
) {
1442 // mark us as aborted
1443 element
->aborted
= true;
1445 // take us off the waiting queue
1446 queue_remove( &gArbitrationLockQueueWaiting
,
1448 ArbitrationLockQueueElement
*,
1450 } else { // we are not willing to fail
1452 // ignore interruption, go back to sleep
1457 // unlock global access
1458 IOUnlock( gArbitrationLockQueueLock
);
1460 // proceed as though this were a normal wake up
1461 wait_result
= THREAD_AWAKENED
;
1464 assert( THREAD_AWAKENED
== wait_result
);
1466 // determine whether we've been aborted while we were asleep
1467 if( element
->aborted
) {
1468 assert( false == element
->required
);
1470 // re-lock global access
1471 IOTakeLock( gArbitrationLockQueueLock
);
1473 action
= kPutOnFreeQueue
;
1475 } else { // we weren't aborted, so we must be ready to go :-)
1477 // we've already been moved from waiting to active queue
1481 } else { // the lock request is to be failed
1483 // return unused queue element to queue
1484 action
= kPutOnFreeQueue
;
1486 } else { // it is the same thread, recursive access is allowed
1488 // add one level of recursion
1491 // return unused queue element to queue
1492 action
= kPutOnFreeQueue
;
1495 } else { // this object is not already locked, so let this thread through
1496 action
= kPutOnActiveQueue
;
1500 // put the new element on a queue
1501 if( kPutOnActiveQueue
== action
) {
1502 queue_enter( &gArbitrationLockQueueActive
,
1504 ArbitrationLockQueueElement
*,
1506 } else if( kPutOnFreeQueue
== action
) {
1507 queue_enter( &gArbitrationLockQueueFree
,
1509 ArbitrationLockQueueElement
*,
1512 assert( 0 ); // kPutOnWaitingQueue never occurs, handled specially above
1515 // unlock global access
1516 IOUnlock( gArbitrationLockQueueLock
);
1521 void IOService::unlockForArbitration( void )
1524 ArbitrationLockQueueElement
* element
;
1526 // lock global access
1527 IOTakeLock( gArbitrationLockQueueLock
);
1529 // find the lock element for this object (ie. on active queue)
1531 queue_iterate( &gArbitrationLockQueueActive
,
1533 ArbitrationLockQueueElement
*,
1536 if( element
->service
== this ) {
1544 // determine whether the lock has been taken recursively
1545 if( element
->count
> 1 ) {
1546 // undo one level of recursion
1551 // remove it from the active queue
1552 queue_remove( &gArbitrationLockQueueActive
,
1554 ArbitrationLockQueueElement
*,
1557 // put it on the free queue
1558 queue_enter( &gArbitrationLockQueueFree
,
1560 ArbitrationLockQueueElement
*,
1563 // determine whether a thread is waiting for object (head to tail scan)
1565 queue_iterate( &gArbitrationLockQueueWaiting
,
1567 ArbitrationLockQueueElement
*,
1570 if( element
->service
== this ) {
1576 if ( found
) { // we found an interested thread on waiting queue
1578 // remove it from the waiting queue
1579 queue_remove( &gArbitrationLockQueueWaiting
,
1581 ArbitrationLockQueueElement
*,
1584 // put it on the active queue
1585 queue_enter( &gArbitrationLockQueueActive
,
1587 ArbitrationLockQueueElement
*,
1590 // wake the waiting thread
1591 IOLockWakeup( gArbitrationLockQueueLock
,
1593 /* one thread */ true );
1597 // unlock global access
1598 IOUnlock( gArbitrationLockQueueLock
);
1601 uint32_t IOService::isLockedForArbitration(IOService
* service
)
1603 #if DEBUG_NOTIFIER_LOCKED
1605 ArbitrationLockQueueElement
* active
;
1607 // lock global access
1608 IOLockLock(gArbitrationLockQueueLock
);
1610 // determine whether this object is already locked (ie. on active queue)
1612 queue_iterate(&gArbitrationLockQueueActive
,
1614 ArbitrationLockQueueElement
*,
1617 if ((active
->thread
== IOThreadSelf())
1618 && (!service
|| (active
->service
== service
)))
1621 count
+= active
->count
;
1625 IOLockUnlock(gArbitrationLockQueueLock
);
1629 #else /* DEBUG_NOTIFIER_LOCKED */
1633 #endif /* DEBUG_NOTIFIER_LOCKED */
1636 void IOService::applyToProviders( IOServiceApplierFunction applier
,
1639 applyToParents( (IORegistryEntryApplierFunction
) applier
,
1640 context
, gIOServicePlane
);
1643 void IOService::applyToClients( IOServiceApplierFunction applier
,
1646 applyToChildren( (IORegistryEntryApplierFunction
) applier
,
1647 context
, gIOServicePlane
);
1656 // send a message to a client or interested party of this service
1657 IOReturn
IOService::messageClient( UInt32 type
, OSObject
* client
,
1658 void * argument
, vm_size_t argSize
)
1661 IOService
* service
;
1662 _IOServiceInterestNotifier
* notify
;
1664 if( (service
= OSDynamicCast( IOService
, client
)))
1665 ret
= service
->message( type
, this, argument
);
1667 else if( (notify
= OSDynamicCast( _IOServiceInterestNotifier
, client
))) {
1669 _IOServiceNotifierInvocation invocation
;
1672 invocation
.thread
= current_thread();
1675 willNotify
= (0 != (kIOServiceNotifyEnable
& notify
->state
));
1678 queue_enter( ¬ify
->handlerInvocations
, &invocation
,
1679 _IOServiceNotifierInvocation
*, link
);
1685 ret
= (*notify
->handler
)( notify
->target
, notify
->ref
,
1686 type
, this, argument
, argSize
);
1689 queue_remove( ¬ify
->handlerInvocations
, &invocation
,
1690 _IOServiceNotifierInvocation
*, link
);
1691 if( kIOServiceNotifyWaiter
& notify
->state
) {
1692 notify
->state
&= ~kIOServiceNotifyWaiter
;
1693 WAKEUPNOTIFY( notify
);
1698 ret
= kIOReturnSuccess
;
1701 ret
= kIOReturnBadArgument
;
1707 applyToInterestNotifiers(const IORegistryEntry
*target
,
1708 const OSSymbol
* typeOfInterest
,
1709 OSObjectApplierFunction applier
,
1712 OSArray
* copyArray
= 0;
1717 prop
= target
->copyProperty(typeOfInterest
);
1718 IOCommand
*notifyList
= OSDynamicCast(IOCommand
, prop
);
1721 copyArray
= OSArray::withCapacity(1);
1723 // iterate over queue, entry is set to each element in the list
1724 iterqueue(¬ifyList
->fCommandChain
, entry
) {
1725 _IOServiceInterestNotifier
* notify
;
1727 queue_element(entry
, notify
, _IOServiceInterestNotifier
*, chain
);
1728 copyArray
->setObject(notify
);
1737 for( index
= 0; (next
= copyArray
->getObject( index
)); index
++)
1738 (*applier
)(next
, context
);
1739 copyArray
->release();
1742 OSSafeReleaseNULL(prop
);
1745 void IOService::applyToInterested( const OSSymbol
* typeOfInterest
,
1746 OSObjectApplierFunction applier
,
1749 if (gIOGeneralInterest
== typeOfInterest
)
1750 applyToClients( (IOServiceApplierFunction
) applier
, context
);
1751 applyToInterestNotifiers(this, typeOfInterest
, applier
, context
);
1754 struct MessageClientsContext
{
1755 IOService
* service
;
1762 static void messageClientsApplier( OSObject
* object
, void * ctx
)
1765 MessageClientsContext
* context
= (MessageClientsContext
*) ctx
;
1767 ret
= context
->service
->messageClient( context
->type
,
1768 object
, context
->argument
, context
->argSize
);
1769 if( kIOReturnSuccess
!= ret
)
1773 // send a message to all clients
1774 IOReturn
IOService::messageClients( UInt32 type
,
1775 void * argument
, vm_size_t argSize
)
1777 MessageClientsContext context
;
1779 context
.service
= this;
1780 context
.type
= type
;
1781 context
.argument
= argument
;
1782 context
.argSize
= argSize
;
1783 context
.ret
= kIOReturnSuccess
;
1785 applyToInterested( gIOGeneralInterest
,
1786 &messageClientsApplier
, &context
);
1788 return( context
.ret
);
1791 IOReturn
IOService::acknowledgeNotification( IONotificationRef notification
,
1792 IOOptionBits response
)
1794 return( kIOReturnUnsupported
);
1797 IONotifier
* IOService::registerInterest( const OSSymbol
* typeOfInterest
,
1798 IOServiceInterestHandler handler
, void * target
, void * ref
)
1800 _IOServiceInterestNotifier
* notify
= 0;
1801 IOReturn rc
= kIOReturnError
;
1803 notify
= new _IOServiceInterestNotifier
;
1804 if (!notify
) return NULL
;
1806 if(notify
->init()) {
1807 rc
= registerInterestForNotifier(notify
, typeOfInterest
,
1808 handler
, target
, ref
);
1811 if (rc
!= kIOReturnSuccess
) {
1822 IOServiceInterestHandlerToBlock( void * target __unused
, void * refCon
,
1823 UInt32 messageType
, IOService
* provider
,
1824 void * messageArgument
, vm_size_t argSize
)
1826 return ((IOServiceInterestHandlerBlock
) refCon
)(messageType
, provider
, messageArgument
, argSize
);
1829 IONotifier
* IOService::registerInterest(const OSSymbol
* typeOfInterest
,
1830 IOServiceInterestHandlerBlock handler
)
1832 IONotifier
* notify
;
1835 block
= Block_copy(handler
);
1836 if (!block
) return (NULL
);
1838 notify
= registerInterest(typeOfInterest
, &IOServiceInterestHandlerToBlock
, NULL
, block
);
1840 if (!notify
) Block_release(block
);
1845 IOReturn
IOService::registerInterestForNotifier( IONotifier
*svcNotify
, const OSSymbol
* typeOfInterest
,
1846 IOServiceInterestHandler handler
, void * target
, void * ref
)
1848 IOReturn rc
= kIOReturnSuccess
;
1849 _IOServiceInterestNotifier
*notify
= 0;
1851 if (!svcNotify
|| !(notify
= OSDynamicCast(_IOServiceInterestNotifier
, svcNotify
)))
1852 return( kIOReturnBadArgument
);
1854 notify
->handler
= handler
;
1855 notify
->target
= target
;
1858 if( (typeOfInterest
!= gIOGeneralInterest
)
1859 && (typeOfInterest
!= gIOBusyInterest
)
1860 && (typeOfInterest
!= gIOAppPowerStateInterest
)
1861 && (typeOfInterest
!= gIOConsoleSecurityInterest
)
1862 && (typeOfInterest
!= gIOPriorityPowerStateInterest
))
1863 return( kIOReturnBadArgument
);
1865 lockForArbitration();
1866 if( 0 == (__state
[0] & kIOServiceInactiveState
)) {
1868 notify
->state
= kIOServiceNotifyEnable
;
1874 // Get the head of the notifier linked list
1875 IOCommand
* notifyList
;
1876 OSObject
* obj
= copyProperty( typeOfInterest
);
1877 if (!(notifyList
= OSDynamicCast(IOCommand
, obj
))) {
1878 notifyList
= OSTypeAlloc(IOCommand
);
1881 bool ok
= setProperty( typeOfInterest
, notifyList
);
1882 notifyList
->release();
1883 if (!ok
) notifyList
= 0;
1886 if (obj
) obj
->release();
1889 enqueue(¬ifyList
->fCommandChain
, ¬ify
->chain
);
1890 notify
->retain(); // ref'ed while in list
1896 rc
= kIOReturnNotReady
;
1898 unlockForArbitration();
1903 static void cleanInterestList( OSObject
* head
)
1905 IOCommand
*notifyHead
= OSDynamicCast(IOCommand
, head
);
1910 while ( queue_entry_t entry
= dequeue(¬ifyHead
->fCommandChain
) ) {
1911 queue_next(entry
) = queue_prev(entry
) = 0;
1913 _IOServiceInterestNotifier
* notify
;
1915 queue_element(entry
, notify
, _IOServiceInterestNotifier
*, chain
);
1921 void IOService::unregisterAllInterest( void )
1925 prop
= copyProperty(gIOGeneralInterest
);
1926 cleanInterestList(prop
);
1927 OSSafeReleaseNULL(prop
);
1929 prop
= copyProperty(gIOBusyInterest
);
1930 cleanInterestList(prop
);
1931 OSSafeReleaseNULL(prop
);
1933 prop
= copyProperty(gIOAppPowerStateInterest
);
1934 cleanInterestList(prop
);
1935 OSSafeReleaseNULL(prop
);
1937 prop
= copyProperty(gIOPriorityPowerStateInterest
);
1938 cleanInterestList(prop
);
1939 OSSafeReleaseNULL(prop
);
1941 prop
= copyProperty(gIOConsoleSecurityInterest
);
1942 cleanInterestList(prop
);
1943 OSSafeReleaseNULL(prop
);
1947 * _IOServiceInterestNotifier
1950 // wait for all threads, other than the current one,
1951 // to exit the handler
1953 void _IOServiceInterestNotifier::wait()
1955 _IOServiceNotifierInvocation
* next
;
1960 queue_iterate( &handlerInvocations
, next
,
1961 _IOServiceNotifierInvocation
*, link
) {
1962 if( next
->thread
!= current_thread() ) {
1968 state
|= kIOServiceNotifyWaiter
;
1975 void _IOServiceInterestNotifier::free()
1977 assert( queue_empty( &handlerInvocations
));
1979 if (handler
== &IOServiceInterestHandlerToBlock
) Block_release(ref
);
1984 void _IOServiceInterestNotifier::remove()
1988 if( queue_next( &chain
)) {
1990 queue_next( &chain
) = queue_prev( &chain
) = 0;
1994 state
&= ~kIOServiceNotifyEnable
;
2003 bool _IOServiceInterestNotifier::disable()
2009 ret
= (0 != (kIOServiceNotifyEnable
& state
));
2010 state
&= ~kIOServiceNotifyEnable
;
2019 void _IOServiceInterestNotifier::enable( bool was
)
2023 state
|= kIOServiceNotifyEnable
;
2025 state
&= ~kIOServiceNotifyEnable
;
2029 bool _IOServiceInterestNotifier::init()
2031 queue_init( &handlerInvocations
);
2032 return (OSObject::init());
2034 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2040 #define tailQ(o) setObject(o)
2041 #define headQ(o) setObject(0, o)
2042 #define TLOG(fmt, args...) { if(kIOLogYield & gIOKitDebug) { IOLog("[%llx] ", thread_tid(current_thread())); IOLog(fmt, ## args); }}
2044 static void _workLoopAction( IOWorkLoop::Action action
,
2045 IOService
* service
,
2046 void * p0
= 0, void * p1
= 0,
2047 void * p2
= 0, void * p3
= 0 )
2051 if( (wl
= service
->getWorkLoop())) {
2053 wl
->runAction( action
, service
, p0
, p1
, p2
, p3
);
2056 (*action
)( service
, p0
, p1
, p2
, p3
);
2059 bool IOService::requestTerminate( IOService
* provider
, IOOptionBits options
)
2063 // if its our only provider
2064 ok
= isParent( provider
, gIOServicePlane
, true);
2068 provider
->terminateClient( this, options
| kIOServiceRecursing
);
2069 ok
= (0 != (kIOServiceInactiveState
& __state
[0]));
2076 bool IOService::terminatePhase1( IOOptionBits options
)
2081 OSArray
* makeInactive
;
2082 OSArray
* waitingInactive
;
2083 int waitResult
= THREAD_AWAKENED
;
2087 bool startPhase2
= false;
2089 TLOG("%s[0x%qx]::terminatePhase1(%08llx)\n", getName(), getRegistryEntryID(), (long long)options
);
2091 uint64_t regID
= getRegistryEntryID();
2093 IOSERVICE_TERMINATE_PHASE1
,
2095 (uintptr_t) (regID
>> 32),
2097 (uintptr_t) options
);
2100 if( options
& kIOServiceRecursing
) {
2101 lockForArbitration();
2102 if (0 == (kIOServiceInactiveState
& __state
[0]))
2104 __state
[0] |= kIOServiceInactiveState
;
2105 __state
[1] |= kIOServiceRecursing
| kIOServiceTermPhase1State
;
2107 unlockForArbitration();
2113 makeInactive
= OSArray::withCapacity( 16 );
2114 waitingInactive
= OSArray::withCapacity( 16 );
2115 if(!makeInactive
|| !waitingInactive
) return( false );
2122 didInactive
= victim
->lockForArbitration( true );
2125 uint64_t regID1
= victim
->getRegistryEntryID();
2126 IOServiceTrace(IOSERVICE_TERM_SET_INACTIVE
,
2128 (uintptr_t) (regID1
>> 32),
2129 (uintptr_t) victim
->__state
[1],
2132 enum { kRP1
= kIOServiceRecursing
| kIOServiceTermPhase1State
};
2133 didInactive
= (kRP1
== (victim
->__state
[1] & kRP1
))
2134 || (0 == (victim
->__state
[0] & kIOServiceInactiveState
));
2138 // a multiply attached IOService can be visited twice
2139 if (-1U == waitingInactive
->getNextIndexOfObject(victim
, 0)) do
2141 IOLockLock(gIOServiceBusyLock
);
2142 wait
= (victim
->__state
[1] & kIOServiceTermPhase1State
);
2144 TLOG("%s[0x%qx]::waitPhase1(%s[0x%qx])\n",
2145 getName(), getRegistryEntryID(), victim
->getName(), victim
->getRegistryEntryID());
2146 victim
->__state
[1] |= kIOServiceTerm1WaiterState
;
2147 victim
->unlockForArbitration();
2148 assert_wait((event_t
)&victim
->__state
[1], THREAD_UNINT
);
2150 IOLockUnlock(gIOServiceBusyLock
);
2152 waitResult
= thread_block(THREAD_CONTINUE_NULL
);
2153 TLOG("%s[0x%qx]::did waitPhase1(%s[0x%qx])\n",
2154 getName(), getRegistryEntryID(), victim
->getName(), victim
->getRegistryEntryID());
2155 victim
->lockForArbitration();
2158 while (wait
&& (waitResult
!= THREAD_TIMED_OUT
));
2162 victim
->__state
[0] |= kIOServiceInactiveState
;
2163 victim
->__state
[0] &= ~(kIOServiceRegisteredState
| kIOServiceMatchedState
2164 | kIOServiceFirstPublishState
| kIOServiceFirstMatchState
);
2165 victim
->__state
[1] &= ~kIOServiceRecursing
;
2166 victim
->__state
[1] |= kIOServiceTermPhase1State
;
2167 waitingInactive
->headQ(victim
);
2170 if (kIOServiceTerminateNeedWillTerminate
& options
)
2172 victim
->__state
[1] |= kIOServiceNeedWillTerminate
;
2175 victim
->_adjustBusy( 1 );
2177 victim
->unlockForArbitration();
2179 if( victim
== this) startPhase2
= didInactive
;
2182 OSArray
* notifiers
;
2183 notifiers
= victim
->copyNotifiers(gIOTerminatedNotification
, 0, 0xffffffff);
2184 victim
->invokeNotifiers(¬ifiers
);
2186 IOUserClient::destroyUserReferences( victim
);
2188 iter
= victim
->getClientIterator();
2190 while( (client
= (IOService
*) iter
->getNextObject())) {
2191 TLOG("%s[0x%qx]::requestTerminate(%s[0x%qx], %08llx)\n",
2192 client
->getName(), client
->getRegistryEntryID(),
2193 victim
->getName(), victim
->getRegistryEntryID(), (long long)options
);
2194 ok
= client
->requestTerminate( victim
, options
);
2195 TLOG("%s[0x%qx]::requestTerminate(%s[0x%qx], ok = %d)\n",
2196 client
->getName(), client
->getRegistryEntryID(),
2197 victim
->getName(), victim
->getRegistryEntryID(), ok
);
2199 uint64_t regID1
= client
->getRegistryEntryID();
2200 uint64_t regID2
= victim
->getRegistryEntryID();
2202 (ok
? IOSERVICE_TERMINATE_REQUEST_OK
2203 : IOSERVICE_TERMINATE_REQUEST_FAIL
),
2205 (uintptr_t) (regID1
>> 32),
2207 (uintptr_t) (regID2
>> 32));
2210 makeInactive
->setObject( client
);
2216 victim
= (IOService
*) makeInactive
->getObject(0);
2219 makeInactive
->removeObject(0);
2222 makeInactive
->release();
2224 while ((victim
= (IOService
*) waitingInactive
->getObject(0)))
2227 waitingInactive
->removeObject(0);
2229 victim
->lockForArbitration();
2230 victim
->__state
[1] &= ~kIOServiceTermPhase1State
;
2231 if (kIOServiceTerm1WaiterState
& victim
->__state
[1])
2233 victim
->__state
[1] &= ~kIOServiceTerm1WaiterState
;
2234 TLOG("%s[0x%qx]::wakePhase1\n", victim
->getName(), victim
->getRegistryEntryID());
2235 IOLockLock( gIOServiceBusyLock
);
2236 thread_wakeup( (event_t
) &victim
->__state
[1]);
2237 IOLockUnlock( gIOServiceBusyLock
);
2239 victim
->unlockForArbitration();
2242 waitingInactive
->release();
2247 lockForArbitration();
2248 scheduleTerminatePhase2(options
);
2249 unlockForArbitration();
2256 void IOService::setTerminateDefer(IOService
* provider
, bool defer
)
2258 lockForArbitration();
2259 if (defer
) __state
[1] |= kIOServiceStartState
;
2260 else __state
[1] &= ~kIOServiceStartState
;
2261 unlockForArbitration();
2263 if (provider
&& !defer
)
2265 provider
->lockForArbitration();
2266 provider
->scheduleTerminatePhase2();
2267 provider
->unlockForArbitration();
2271 // Must call this while holding gJobsLock
2272 void IOService::waitToBecomeTerminateThread(void)
2274 IOLockAssert(gJobsLock
, kIOLockAssertOwned
);
2277 wait
= (gIOTerminateThread
!= THREAD_NULL
);
2279 IOLockSleep(gJobsLock
, &gIOTerminateThread
, THREAD_UNINT
);
2282 gIOTerminateThread
= current_thread();
2285 // call with lockForArbitration
2286 void IOService::scheduleTerminatePhase2( IOOptionBits options
)
2288 AbsoluteTime deadline
;
2290 int waitResult
= THREAD_AWAKENED
;
2291 bool wait
= false, haveDeadline
= false;
2293 if (!(__state
[0] & kIOServiceInactiveState
)) return;
2295 regID1
= getRegistryEntryID();
2297 IOSERVICE_TERM_SCHED_PHASE2
,
2299 (uintptr_t) (regID1
>> 32),
2300 (uintptr_t) __state
[1],
2301 (uintptr_t) options
);
2303 if (__state
[1] & kIOServiceTermPhase1State
) return;
2306 unlockForArbitration();
2307 options
|= kIOServiceRequired
;
2308 IOLockLock( gJobsLock
);
2310 if( (options
& kIOServiceSynchronous
)
2311 && (current_thread() != gIOTerminateThread
)) {
2313 waitToBecomeTerminateThread();
2314 gIOTerminatePhase2List
->setObject( this );
2318 while( gIOTerminateWork
)
2319 terminateWorker( options
);
2320 wait
= (0 != (__state
[1] & kIOServiceBusyStateMask
));
2322 /* wait for the victim to go non-busy */
2323 if( !haveDeadline
) {
2324 clock_interval_to_deadline( 15, kSecondScale
, &deadline
);
2325 haveDeadline
= true;
2327 /* let others do work while we wait */
2328 gIOTerminateThread
= 0;
2329 IOLockWakeup( gJobsLock
, (event_t
) &gIOTerminateThread
, /* one-thread */ false);
2330 waitResult
= IOLockSleepDeadline( gJobsLock
, &gIOTerminateWork
,
2331 deadline
, THREAD_UNINT
);
2332 if (__improbable(waitResult
== THREAD_TIMED_OUT
)) {
2333 panic("%s[0x%qx]::terminate(kIOServiceSynchronous) timeout\n", getName(), getRegistryEntryID());
2335 waitToBecomeTerminateThread();
2337 } while(gIOTerminateWork
|| (wait
&& (waitResult
!= THREAD_TIMED_OUT
)));
2339 gIOTerminateThread
= 0;
2340 IOLockWakeup( gJobsLock
, (event_t
) &gIOTerminateThread
, /* one-thread */ false);
2343 // ! kIOServiceSynchronous
2345 gIOTerminatePhase2List
->setObject( this );
2346 if( 0 == gIOTerminateWork
++) {
2347 assert(gIOTerminateWorkerThread
);
2348 IOLockWakeup(gJobsLock
, (event_t
)&gIOTerminateWork
, /* one-thread */ false );
2352 IOLockUnlock( gJobsLock
);
2353 lockForArbitration();
2357 __attribute__((__noreturn__
))
2358 void IOService::terminateThread( void * arg
, wait_result_t waitResult
)
2360 // IOLockSleep re-acquires the lock on wakeup, so we only need to do this once
2361 IOLockLock(gJobsLock
);
2363 if (gIOTerminateThread
!= gIOTerminateWorkerThread
) {
2364 waitToBecomeTerminateThread();
2367 while (gIOTerminateWork
)
2368 terminateWorker( (uintptr_t)arg
);
2370 gIOTerminateThread
= 0;
2371 IOLockWakeup( gJobsLock
, (event_t
) &gIOTerminateThread
, /* one-thread */ false);
2372 IOLockSleep(gJobsLock
, &gIOTerminateWork
, THREAD_UNINT
);
2376 void IOService::scheduleStop( IOService
* provider
)
2378 uint64_t regID1
= getRegistryEntryID();
2379 uint64_t regID2
= provider
->getRegistryEntryID();
2381 TLOG("%s[0x%qx]::scheduleStop(%s[0x%qx])\n", getName(), regID1
, provider
->getName(), regID2
);
2383 IOSERVICE_TERMINATE_SCHEDULE_STOP
,
2385 (uintptr_t) (regID1
>> 32),
2387 (uintptr_t) (regID2
>> 32));
2389 IOLockLock( gJobsLock
);
2390 gIOStopList
->tailQ( this );
2391 gIOStopProviderList
->tailQ( provider
);
2393 if( 0 == gIOTerminateWork
++) {
2394 assert(gIOTerminateWorkerThread
);
2395 IOLockWakeup(gJobsLock
, (event_t
)&gIOTerminateWork
, /* one-thread */ false );
2398 IOLockUnlock( gJobsLock
);
2401 void IOService::scheduleFinalize(bool now
)
2403 uint64_t regID1
= getRegistryEntryID();
2405 TLOG("%s[0x%qx]::scheduleFinalize\n", getName(), regID1
);
2407 IOSERVICE_TERMINATE_SCHEDULE_FINALIZE
,
2409 (uintptr_t) (regID1
>> 32),
2412 if (now
|| IOUserClient::finalizeUserReferences(this))
2414 IOLockLock( gJobsLock
);
2415 gIOFinalizeList
->tailQ(this);
2416 if( 0 == gIOTerminateWork
++) {
2417 assert(gIOTerminateWorkerThread
);
2418 IOLockWakeup(gJobsLock
, (event_t
)&gIOTerminateWork
, /* one-thread */ false );
2420 IOLockUnlock( gJobsLock
);
2424 bool IOService::willTerminate( IOService
* provider
, IOOptionBits options
)
2429 bool IOService::didTerminate( IOService
* provider
, IOOptionBits options
, bool * defer
)
2431 if( false == *defer
) {
2433 if( lockForArbitration( true )) {
2434 if( false == provider
->handleIsOpen( this ))
2435 scheduleStop( provider
);
2438 message( kIOMessageServiceIsRequestingClose
, provider
, (void *)(uintptr_t) options
);
2439 if( false == provider
->handleIsOpen( this ))
2440 scheduleStop( provider
);
2443 unlockForArbitration();
2450 void IOService::actionWillTerminate( IOService
* victim
, IOOptionBits options
,
2451 OSArray
* doPhase2List
,
2452 void *unused2 __unused
,
2453 void *unused3 __unused
)
2458 uint64_t regID1
, regID2
= victim
->getRegistryEntryID();
2460 iter
= victim
->getClientIterator();
2462 while( (client
= (IOService
*) iter
->getNextObject())) {
2464 regID1
= client
->getRegistryEntryID();
2465 TLOG("%s[0x%qx]::willTerminate(%s[0x%qx], %08llx)\n",
2466 client
->getName(), regID1
,
2467 victim
->getName(), regID2
, (long long)options
);
2469 IOSERVICE_TERMINATE_WILL
,
2471 (uintptr_t) (regID1
>> 32),
2473 (uintptr_t) (regID2
>> 32));
2475 ok
= client
->willTerminate( victim
, options
);
2476 doPhase2List
->tailQ( client
);
2482 void IOService::actionDidTerminate( IOService
* victim
, IOOptionBits options
,
2483 void *unused1 __unused
, void *unused2 __unused
,
2484 void *unused3 __unused
)
2489 uint64_t regID1
, regID2
= victim
->getRegistryEntryID();
2491 victim
->messageClients( kIOMessageServiceIsTerminated
, (void *)(uintptr_t) options
);
2493 iter
= victim
->getClientIterator();
2495 while( (client
= (IOService
*) iter
->getNextObject())) {
2497 regID1
= client
->getRegistryEntryID();
2498 TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], %08llx)\n",
2499 client
->getName(), regID1
,
2500 victim
->getName(), regID2
, (long long)options
);
2502 client
->didTerminate( victim
, options
, &defer
);
2505 (defer
? IOSERVICE_TERMINATE_DID_DEFER
2506 : IOSERVICE_TERMINATE_DID
),
2508 (uintptr_t) (regID1
>> 32),
2510 (uintptr_t) (regID2
>> 32));
2512 TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], defer %d)\n",
2513 client
->getName(), regID1
,
2514 victim
->getName(), regID2
, defer
);
2521 void IOService::actionWillStop( IOService
* victim
, IOOptionBits options
,
2522 void *unused1 __unused
, void *unused2 __unused
,
2523 void *unused3 __unused
)
2526 IOService
* provider
;
2528 uint64_t regID1
, regID2
= victim
->getRegistryEntryID();
2530 iter
= victim
->getProviderIterator();
2532 while( (provider
= (IOService
*) iter
->getNextObject())) {
2534 regID1
= provider
->getRegistryEntryID();
2535 TLOG("%s[0x%qx]::willTerminate(%s[0x%qx], %08llx)\n",
2536 victim
->getName(), regID2
,
2537 provider
->getName(), regID1
, (long long)options
);
2539 IOSERVICE_TERMINATE_WILL
,
2541 (uintptr_t) (regID2
>> 32),
2543 (uintptr_t) (regID1
>> 32));
2545 ok
= victim
->willTerminate( provider
, options
);
2551 void IOService::actionDidStop( IOService
* victim
, IOOptionBits options
,
2552 void *unused1 __unused
, void *unused2 __unused
,
2553 void *unused3 __unused
)
2556 IOService
* provider
;
2558 uint64_t regID1
, regID2
= victim
->getRegistryEntryID();
2560 iter
= victim
->getProviderIterator();
2562 while( (provider
= (IOService
*) iter
->getNextObject())) {
2564 regID1
= provider
->getRegistryEntryID();
2565 TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], %08llx)\n",
2566 victim
->getName(), regID2
,
2567 provider
->getName(), regID1
, (long long)options
);
2568 victim
->didTerminate( provider
, options
, &defer
);
2571 (defer
? IOSERVICE_TERMINATE_DID_DEFER
2572 : IOSERVICE_TERMINATE_DID
),
2574 (uintptr_t) (regID2
>> 32),
2576 (uintptr_t) (regID1
>> 32));
2578 TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], defer %d)\n",
2579 victim
->getName(), regID2
,
2580 provider
->getName(), regID1
, defer
);
2587 void IOService::actionFinalize( IOService
* victim
, IOOptionBits options
,
2588 void *unused1 __unused
, void *unused2 __unused
,
2589 void *unused3 __unused
)
2591 uint64_t regID1
= victim
->getRegistryEntryID();
2592 TLOG("%s[0x%qx]::finalize(%08llx)\n", victim
->getName(), regID1
, (long long)options
);
2594 IOSERVICE_TERMINATE_FINALIZE
,
2596 (uintptr_t) (regID1
>> 32),
2599 victim
->finalize( options
);
2602 void IOService::actionStop( IOService
* provider
, IOService
* client
,
2603 void *unused1 __unused
, void *unused2 __unused
,
2604 void *unused3 __unused
)
2606 uint64_t regID1
= provider
->getRegistryEntryID();
2607 uint64_t regID2
= client
->getRegistryEntryID();
2609 TLOG("%s[0x%qx]::stop(%s[0x%qx])\n", client
->getName(), regID2
, provider
->getName(), regID1
);
2611 IOSERVICE_TERMINATE_STOP
,
2613 (uintptr_t) (regID1
>> 32),
2615 (uintptr_t) (regID2
>> 32));
2617 client
->stop( provider
);
2618 if( provider
->isOpen( client
))
2619 provider
->close( client
);
2621 TLOG("%s[0x%qx]::detach(%s[0x%qx])\n", client
->getName(), regID2
, provider
->getName(), regID1
);
2622 client
->detach( provider
);
2625 void IOService::terminateWorker( IOOptionBits options
)
2627 OSArray
* doPhase2List
;
2628 OSArray
* didPhase2List
;
2634 IOService
* provider
;
2640 options
|= kIOServiceRequired
;
2642 doPhase2List
= OSArray::withCapacity( 16 );
2643 didPhase2List
= OSArray::withCapacity( 16 );
2644 freeList
= OSSet::withCapacity( 16 );
2645 if( (0 == doPhase2List
) || (0 == didPhase2List
) || (0 == freeList
))
2649 workDone
= gIOTerminateWork
;
2651 while( (victim
= (IOService
*) gIOTerminatePhase2List
->getObject(0) )) {
2654 gIOTerminatePhase2List
->removeObject(0);
2655 IOLockUnlock( gJobsLock
);
2657 uint64_t regID1
= victim
->getRegistryEntryID();
2659 IOSERVICE_TERM_START_PHASE2
,
2661 (uintptr_t) (regID1
>> 32),
2667 doPhase2
= victim
->lockForArbitration( true );
2669 doPhase2
= (0 != (kIOServiceInactiveState
& victim
->__state
[0]));
2672 uint64_t regID1
= victim
->getRegistryEntryID();
2674 IOSERVICE_TERM_TRY_PHASE2
,
2676 (uintptr_t) (regID1
>> 32),
2677 (uintptr_t) victim
->__state
[1],
2680 doPhase2
= (0 == (victim
->__state
[1] &
2681 (kIOServiceTermPhase1State
2682 | kIOServiceTermPhase2State
2683 | kIOServiceConfigState
)));
2685 if (doPhase2
&& (iter
= victim
->getClientIterator())) {
2686 while (doPhase2
&& (client
= (IOService
*) iter
->getNextObject())) {
2687 doPhase2
= (0 == (client
->__state
[1] & kIOServiceStartState
));
2690 uint64_t regID1
= client
->getRegistryEntryID();
2692 IOSERVICE_TERM_UC_DEFER
,
2694 (uintptr_t) (regID1
>> 32),
2695 (uintptr_t) client
->__state
[1],
2697 TLOG("%s[0x%qx]::defer phase2(%s[0x%qx])\n",
2698 victim
->getName(), victim
->getRegistryEntryID(),
2699 client
->getName(), client
->getRegistryEntryID());
2705 victim
->__state
[1] |= kIOServiceTermPhase2State
;
2707 victim
->unlockForArbitration();
2711 if (kIOServiceNeedWillTerminate
& victim
->__state
[1]) {
2712 _workLoopAction( (IOWorkLoop::Action
) &actionWillStop
,
2713 victim
, (void *)(uintptr_t) options
, NULL
);
2716 OSArray
* notifiers
;
2717 notifiers
= victim
->copyNotifiers(gIOWillTerminateNotification
, 0, 0xffffffff);
2718 victim
->invokeNotifiers(¬ifiers
);
2720 _workLoopAction( (IOWorkLoop::Action
) &actionWillTerminate
,
2721 victim
, (void *)(uintptr_t) options
, (void *)(uintptr_t) doPhase2List
);
2723 didPhase2List
->headQ( victim
);
2726 victim
= (IOService
*) doPhase2List
->getObject(0);
2729 doPhase2List
->removeObject(0);
2733 while( (victim
= (IOService
*) didPhase2List
->getObject(0)) ) {
2734 bool scheduleFinalize
= false;
2735 if( victim
->lockForArbitration( true )) {
2736 victim
->__state
[1] |= kIOServiceTermPhase3State
;
2737 scheduleFinalize
= (0 == victim
->getClient());
2738 victim
->unlockForArbitration();
2740 _workLoopAction( (IOWorkLoop::Action
) &actionDidTerminate
,
2741 victim
, (void *)(uintptr_t) options
);
2742 if (kIOServiceNeedWillTerminate
& victim
->__state
[1]) {
2743 _workLoopAction( (IOWorkLoop::Action
) &actionDidStop
,
2744 victim
, (void *)(uintptr_t) options
, NULL
);
2746 // no clients - will go to finalize
2747 if (scheduleFinalize
) victim
->scheduleFinalize(false);
2748 didPhase2List
->removeObject(0);
2750 IOLockLock( gJobsLock
);
2757 while( (victim
= (IOService
*) gIOFinalizeList
->getObject(0))) {
2758 bool sendFinal
= false;
2759 IOLockUnlock( gJobsLock
);
2760 if (victim
->lockForArbitration(true)) {
2761 sendFinal
= (0 == (victim
->__state
[1] & kIOServiceFinalized
));
2762 if (sendFinal
) victim
->__state
[1] |= kIOServiceFinalized
;
2763 victim
->unlockForArbitration();
2766 _workLoopAction( (IOWorkLoop::Action
) &actionFinalize
,
2767 victim
, (void *)(uintptr_t) options
);
2769 IOLockLock( gJobsLock
);
2771 freeList
->setObject( victim
);
2772 // safe if finalize list is append only
2773 gIOFinalizeList
->removeObject(0);
2777 (!doPhase3
) && (client
= (IOService
*) gIOStopList
->getObject(idx
)); ) {
2779 provider
= (IOService
*) gIOStopProviderList
->getObject(idx
);
2782 uint64_t regID1
= provider
->getRegistryEntryID();
2783 uint64_t regID2
= client
->getRegistryEntryID();
2785 if( !provider
->isChild( client
, gIOServicePlane
)) {
2786 // may be multiply queued - nop it
2787 TLOG("%s[0x%qx]::nop stop(%s[0x%qx])\n", client
->getName(), regID2
, provider
->getName(), regID1
);
2789 IOSERVICE_TERMINATE_STOP_NOP
,
2791 (uintptr_t) (regID1
>> 32),
2793 (uintptr_t) (regID2
>> 32));
2796 // a terminated client is not ready for stop if it has clients, skip it
2797 bool deferStop
= (0 != (kIOServiceInactiveState
& client
->__state
[0]));
2798 IOLockUnlock( gJobsLock
);
2799 if (deferStop
&& client
->lockForArbitration(true)) {
2800 deferStop
= (0 == (client
->__state
[1] & kIOServiceFinalized
));
2801 //deferStop = (!deferStop && (0 != client->getClient()));
2802 //deferStop = (0 != client->getClient());
2803 client
->unlockForArbitration();
2805 TLOG("%s[0x%qx]::defer stop()\n", client
->getName(), regID2
);
2806 IOServiceTrace(IOSERVICE_TERMINATE_STOP_DEFER
,
2808 (uintptr_t) (regID1
>> 32),
2810 (uintptr_t) (regID2
>> 32));
2813 IOLockLock( gJobsLock
);
2817 _workLoopAction( (IOWorkLoop::Action
) &actionStop
,
2818 provider
, (void *) client
);
2819 IOLockLock( gJobsLock
);
2820 // check the finalize list now
2824 freeList
->setObject( client
);
2825 freeList
->setObject( provider
);
2827 // safe if stop list is append only
2828 gIOStopList
->removeObject( idx
);
2829 gIOStopProviderList
->removeObject( idx
);
2833 } while( doPhase3
);
2835 gIOTerminateWork
-= workDone
;
2836 moreToDo
= (gIOTerminateWork
!= 0);
2839 TLOG("iokit terminate done, %d stops remain\n", gIOStopList
->getCount());
2841 IOSERVICE_TERMINATE_DONE
,
2842 (uintptr_t) gIOStopList
->getCount(), 0, 0, 0);
2845 } while( moreToDo
);
2847 IOLockUnlock( gJobsLock
);
2849 freeList
->release();
2850 doPhase2List
->release();
2851 didPhase2List
->release();
2853 IOLockLock( gJobsLock
);
2856 bool IOService::finalize( IOOptionBits options
)
2859 IOService
* provider
;
2860 uint64_t regID1
, regID2
= getRegistryEntryID();
2862 iter
= getProviderIterator();
2866 while( (provider
= (IOService
*) iter
->getNextObject())) {
2869 if( 0 == (__state
[1] & kIOServiceTermPhase3State
)) {
2870 /* we come down here on programmatic terminate */
2872 regID1
= provider
->getRegistryEntryID();
2873 TLOG("%s[0x%qx]::stop1(%s[0x%qx])\n", getName(), regID2
, provider
->getName(), regID1
);
2875 IOSERVICE_TERMINATE_STOP
,
2877 (uintptr_t) (regID1
>> 32),
2879 (uintptr_t) (regID2
>> 32));
2882 if( provider
->isOpen( this ))
2883 provider
->close( this );
2887 if( provider
->lockForArbitration( true )) {
2888 if( 0 == (provider
->__state
[1] & kIOServiceTermPhase3State
))
2889 scheduleStop( provider
);
2890 provider
->unlockForArbitration();
2907 void IOService::doServiceTerminate( IOOptionBits options
)
2911 // a method in case someone needs to override it
2912 bool IOService::terminateClient( IOService
* client
, IOOptionBits options
)
2916 if( client
->isParent( this, gIOServicePlane
, true))
2917 // we are the clients only provider
2918 ok
= client
->terminate( options
);
2925 bool IOService::terminate( IOOptionBits options
)
2927 options
|= kIOServiceTerminate
;
2929 return( terminatePhase1( options
));
2932 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2938 struct ServiceOpenMessageContext
2940 IOService
* service
;
2942 IOService
* excludeClient
;
2943 IOOptionBits options
;
2946 static void serviceOpenMessageApplier( OSObject
* object
, void * ctx
)
2948 ServiceOpenMessageContext
* context
= (ServiceOpenMessageContext
*) ctx
;
2950 if( object
!= context
->excludeClient
)
2951 context
->service
->messageClient( context
->type
, object
, (void *)(uintptr_t) context
->options
);
2954 bool IOService::open( IOService
* forClient
,
2955 IOOptionBits options
,
2959 ServiceOpenMessageContext context
;
2961 context
.service
= this;
2962 context
.type
= kIOMessageServiceIsAttemptingOpen
;
2963 context
.excludeClient
= forClient
;
2964 context
.options
= options
;
2966 applyToInterested( gIOGeneralInterest
,
2967 &serviceOpenMessageApplier
, &context
);
2969 if( false == lockForArbitration(false) )
2972 ok
= (0 == (__state
[0] & kIOServiceInactiveState
));
2974 ok
= handleOpen( forClient
, options
, arg
);
2976 unlockForArbitration();
2981 void IOService::close( IOService
* forClient
,
2982 IOOptionBits options
)
2987 lockForArbitration();
2989 wasClosed
= handleIsOpen( forClient
);
2991 handleClose( forClient
, options
);
2992 last
= (__state
[1] & kIOServiceTermPhase3State
);
2995 unlockForArbitration();
2998 forClient
->scheduleStop( this );
3000 else if( wasClosed
) {
3002 ServiceOpenMessageContext context
;
3004 context
.service
= this;
3005 context
.type
= kIOMessageServiceWasClosed
;
3006 context
.excludeClient
= forClient
;
3007 context
.options
= options
;
3009 applyToInterested( gIOGeneralInterest
,
3010 &serviceOpenMessageApplier
, &context
);
3014 bool IOService::isOpen( const IOService
* forClient
) const
3016 IOService
* self
= (IOService
*) this;
3019 self
->lockForArbitration();
3021 ok
= handleIsOpen( forClient
);
3023 self
->unlockForArbitration();
3028 bool IOService::handleOpen( IOService
* forClient
,
3029 IOOptionBits options
,
3034 ok
= (0 == __owner
);
3036 __owner
= forClient
;
3038 else if( options
& kIOServiceSeize
) {
3039 ok
= (kIOReturnSuccess
== messageClient( kIOMessageServiceIsRequestingClose
,
3040 __owner
, (void *)(uintptr_t) options
));
3041 if( ok
&& (0 == __owner
))
3042 __owner
= forClient
;
3049 void IOService::handleClose( IOService
* forClient
,
3050 IOOptionBits options
)
3052 if( __owner
== forClient
)
3056 bool IOService::handleIsOpen( const IOService
* forClient
) const
3059 return( __owner
== forClient
);
3061 return( __owner
!= forClient
);
3065 * Probing & starting
3067 static SInt32
IONotifyOrdering( const OSMetaClassBase
* inObj1
, const OSMetaClassBase
* inObj2
, void * ref
)
3069 const _IOServiceNotifier
* obj1
= (const _IOServiceNotifier
*) inObj1
;
3070 const _IOServiceNotifier
* obj2
= (const _IOServiceNotifier
*) inObj2
;
3078 val1
= obj1
->priority
;
3081 val2
= obj2
->priority
;
3083 return ( val1
- val2
);
3086 static SInt32
IOServiceObjectOrder( const OSObject
* entry
, void * ref
)
3088 OSDictionary
* dict
;
3089 IOService
* service
;
3090 _IOServiceNotifier
* notify
;
3091 OSSymbol
* key
= (OSSymbol
*) ref
;
3097 result
= kIODefaultProbeScore
;
3098 if( (dict
= OSDynamicCast( OSDictionary
, entry
)))
3099 offset
= OSDynamicCast(OSNumber
, dict
->getObject( key
));
3100 else if( (notify
= OSDynamicCast( _IOServiceNotifier
, entry
)))
3101 return( notify
->priority
);
3102 else if( (service
= OSDynamicCast( IOService
, entry
)))
3104 prop
= service
->copyProperty(key
);
3105 offset
= OSDynamicCast(OSNumber
, prop
);
3112 if (offset
) result
= offset
->unsigned32BitValue();
3114 OSSafeReleaseNULL(prop
);
3119 SInt32
IOServiceOrdering( const OSMetaClassBase
* inObj1
, const OSMetaClassBase
* inObj2
, void * ref
)
3121 const OSObject
* obj1
= (const OSObject
*) inObj1
;
3122 const OSObject
* obj2
= (const OSObject
*) inObj2
;
3130 val1
= IOServiceObjectOrder( obj1
, ref
);
3133 val2
= IOServiceObjectOrder( obj2
, ref
);
3135 return ( val1
- val2
);
3138 IOService
* IOService::copyClientWithCategory( const OSSymbol
* category
)
3140 IOService
* service
= 0;
3142 const OSSymbol
* nextCat
;
3144 iter
= getClientIterator();
3146 while( (service
= (IOService
*) iter
->getNextObject())) {
3147 if( kIOServiceInactiveState
& service
->__state
[0])
3149 nextCat
= (const OSSymbol
*) OSDynamicCast( OSSymbol
,
3150 service
->getProperty( gIOMatchCategoryKey
));
3151 if( category
== nextCat
)
3162 IOService
* IOService::getClientWithCategory( const OSSymbol
* category
)
3165 service
= copyClientWithCategory(category
);
3171 bool IOService::invokeNotifier( _IOServiceNotifier
* notify
)
3173 _IOServiceNotifierInvocation invocation
;
3176 invocation
.thread
= current_thread();
3178 #if DEBUG_NOTIFIER_LOCKED
3180 if ((count
= isLockedForArbitration(0)))
3182 IOLog("[%s, 0x%x]\n", notify
->type
->getCStringNoCopy(), count
);
3183 panic("[%s, 0x%x]\n", notify
->type
->getCStringNoCopy(), count
);
3185 #endif /* DEBUG_NOTIFIER_LOCKED */
3188 willNotify
= (0 != (kIOServiceNotifyEnable
& notify
->state
));
3191 queue_enter( ¬ify
->handlerInvocations
, &invocation
,
3192 _IOServiceNotifierInvocation
*, link
);
3198 ret
= (*notify
->handler
)(notify
->target
, notify
->ref
, this, notify
);
3201 queue_remove( ¬ify
->handlerInvocations
, &invocation
,
3202 _IOServiceNotifierInvocation
*, link
);
3203 if( kIOServiceNotifyWaiter
& notify
->state
) {
3204 notify
->state
&= ~kIOServiceNotifyWaiter
;
3205 WAKEUPNOTIFY( notify
);
3213 bool IOService::invokeNotifiers(OSArray
** willSend
)
3216 _IOServiceNotifier
* notify
;
3220 if (!array
) return (true);
3223 for( unsigned int idx
= 0;
3224 (notify
= (_IOServiceNotifier
*) array
->getObject(idx
));
3226 ret
&= invokeNotifier(notify
);
3235 * Alloc and probe matching classes,
3236 * called on the provider instance
3239 void IOService::probeCandidates( OSOrderedSet
* matches
)
3241 OSDictionary
* match
= 0;
3244 IOService
* newInst
;
3245 OSDictionary
* props
;
3248 OSOrderedSet
* familyMatches
= 0;
3249 OSOrderedSet
* startList
;
3250 OSDictionary
* startDict
= 0;
3251 const OSSymbol
* category
;
3253 _IOServiceNotifier
* notify
;
3254 OSObject
* nextMatch
= 0;
3256 bool needReloc
= false;
3260 IOService
* client
= NULL
;
3264 while( !needReloc
&& (nextMatch
= matches
->getFirstObject())) {
3266 nextMatch
->retain();
3267 matches
->removeObject(nextMatch
);
3269 if( (notify
= OSDynamicCast( _IOServiceNotifier
, nextMatch
))) {
3271 if (0 == (__state
[0] & kIOServiceInactiveState
)) invokeNotifier( notify
);
3272 nextMatch
->release();
3276 } else if( !(match
= OSDynamicCast( OSDictionary
, nextMatch
))) {
3277 nextMatch
->release();
3284 debugFlags
= getDebugFlags( match
);
3288 category
= OSDynamicCast( OSSymbol
,
3289 match
->getObject( gIOMatchCategoryKey
));
3291 category
= gIODefaultMatchCategoryKey
;
3293 if( (client
= copyClientWithCategory(category
)) ) {
3295 if( (debugFlags
& kIOLogMatch
) && (this != gIOResources
))
3296 LOG("%s: match category %s exists\n", getName(),
3297 category
->getCStringNoCopy());
3299 nextMatch
->release();
3308 // create a copy now in case its modified during matching
3309 props
= OSDictionary::withDictionary( match
, match
->getCount());
3312 props
->setCapacityIncrement(1);
3314 // check the nub matches
3315 if( false == matchPassive(props
, kIOServiceChangesOK
| kIOServiceClassDone
))
3318 // Check to see if driver reloc has been loaded.
3319 needReloc
= (false == gIOCatalogue
->isModuleLoaded( match
));
3322 if( debugFlags
& kIOLogCatalogue
)
3323 LOG("%s: stalling for module\n", getName());
3325 // If reloc hasn't been loaded, exit;
3326 // reprobing will occur after reloc has been loaded.
3330 // reorder on family matchPropertyTable score.
3331 if( 0 == familyMatches
)
3332 familyMatches
= OSOrderedSet::withCapacity( 1,
3333 IOServiceOrdering
, (void *) gIOProbeScoreKey
);
3335 familyMatches
->setObject( props
);
3340 nextMatch
->release();
3349 if( familyMatches
) {
3352 && (props
= (OSDictionary
*) familyMatches
->getFirstObject())) {
3355 familyMatches
->removeObject( props
);
3360 debugFlags
= getDebugFlags( props
);
3363 symbol
= OSDynamicCast( OSSymbol
,
3364 props
->getObject( gIOClassKey
));
3368 //IOLog("%s alloc (symbol %p props %p)\n", symbol->getCStringNoCopy(), IOSERVICE_OBFUSCATE(symbol), IOSERVICE_OBFUSCATE(props));
3370 // alloc the driver instance
3371 inst
= (IOService
*) OSMetaClass::allocClassWithName( symbol
);
3373 if( !inst
|| !OSDynamicCast(IOService
, inst
)) {
3374 IOLog("Couldn't alloc class \"%s\"\n",
3375 symbol
->getCStringNoCopy());
3379 // init driver instance
3380 if( !(inst
->init( props
))) {
3382 if( debugFlags
& kIOLogStart
)
3383 IOLog("%s::init fails\n", symbol
->getCStringNoCopy());
3387 if( __state
[1] & kIOServiceSynchronousState
)
3388 inst
->__state
[1] |= kIOServiceSynchronousState
;
3390 // give the driver the default match category if not specified
3391 category
= OSDynamicCast( OSSymbol
,
3392 props
->getObject( gIOMatchCategoryKey
));
3394 category
= gIODefaultMatchCategoryKey
;
3395 inst
->setProperty( gIOMatchCategoryKey
, (OSObject
*) category
);
3396 // attach driver instance
3397 if( !(inst
->attach( this )))
3400 // pass in score from property table
3401 score
= familyMatches
->orderObject( props
);
3403 // & probe the new driver instance
3405 if( debugFlags
& kIOLogProbe
)
3406 LOG("%s::probe(%s)\n",
3407 inst
->getMetaClass()->getClassName(), getName());
3410 newInst
= inst
->probe( this, &score
);
3411 inst
->detach( this );
3414 if( debugFlags
& kIOLogProbe
)
3415 IOLog("%s::probe fails\n", symbol
->getCStringNoCopy());
3421 newPri
= OSNumber::withNumber( score
, 32 );
3423 newInst
->setProperty( gIOProbeScoreKey
, newPri
);
3427 // add to start list for the match category
3429 startDict
= OSDictionary::withCapacity( 1 );
3430 assert( startDict
);
3431 startList
= (OSOrderedSet
*)
3432 startDict
->getObject( category
);
3433 if( 0 == startList
) {
3434 startList
= OSOrderedSet::withCapacity( 1,
3435 IOServiceOrdering
, (void *) gIOProbeScoreKey
);
3436 if( startDict
&& startList
) {
3437 startDict
->setObject( category
, startList
);
3438 startList
->release();
3441 assert( startList
);
3443 startList
->setObject( newInst
);
3451 familyMatches
->release();
3455 // start the best (until success) of each category
3457 iter
= OSCollectionIterator::withCollection( startDict
);
3459 while( (category
= (const OSSymbol
*) iter
->getNextObject())) {
3461 startList
= (OSOrderedSet
*) startDict
->getObject( category
);
3462 assert( startList
);
3467 while( true // (!started)
3468 && (inst
= (IOService
*)startList
->getFirstObject())) {
3471 startList
->removeObject(inst
);
3474 debugFlags
= getDebugFlags( inst
);
3476 if( debugFlags
& kIOLogStart
) {
3478 LOG( "match category exists, skipping " );
3479 LOG( "%s::start(%s) <%d>\n", inst
->getName(),
3480 getName(), inst
->getRetainCount());
3483 if( false == started
)
3484 started
= startCandidate( inst
);
3486 if( (debugFlags
& kIOLogStart
) && (false == started
))
3487 LOG( "%s::start(%s) <%d> failed\n", inst
->getName(), getName(),
3488 inst
->getRetainCount());
3497 // adjust the busy count by +1 if matching is stalled for a module,
3498 // or -1 if a previously stalled matching is complete.
3499 lockForArbitration();
3501 uint64_t regID
= getRegistryEntryID();
3504 adjBusy
= (__state
[1] & kIOServiceModuleStallState
) ? 0 : 1;
3508 IOSERVICE_MODULESTALL
,
3510 (uintptr_t) (regID
>> 32),
3514 __state
[1] |= kIOServiceModuleStallState
;
3517 } else if( __state
[1] & kIOServiceModuleStallState
) {
3520 IOSERVICE_MODULEUNSTALL
,
3522 (uintptr_t) (regID
>> 32),
3526 __state
[1] &= ~kIOServiceModuleStallState
;
3530 _adjustBusy( adjBusy
);
3531 unlockForArbitration();
3534 startDict
->release();
3538 * Start a previously attached & probed instance,
3539 * called on exporting object instance
3542 bool IOService::startCandidate( IOService
* service
)
3546 ok
= service
->attach( this );
3550 if (this != gIOResources
)
3552 // stall for any nub resources
3554 // stall for any driver resources
3555 service
->checkResources();
3558 AbsoluteTime startTime
;
3559 AbsoluteTime endTime
;
3562 if (kIOLogStart
& gIOKitDebug
)
3563 clock_get_uptime(&startTime
);
3565 ok
= service
->start(this);
3567 if (kIOLogStart
& gIOKitDebug
)
3569 clock_get_uptime(&endTime
);
3571 if (CMP_ABSOLUTETIME(&endTime
, &startTime
) > 0)
3573 SUB_ABSOLUTETIME(&endTime
, &startTime
);
3574 absolutetime_to_nanoseconds(endTime
, &nano
);
3575 if (nano
> 500000000ULL)
3576 IOLog("%s::start took %ld ms\n", service
->getName(), (long)(UInt32
)(nano
/ 1000000ULL));
3580 service
->detach( this );
3585 void IOService::publishResource( const char * key
, OSObject
* value
)
3587 const OSSymbol
* sym
;
3589 if( (sym
= OSSymbol::withCString( key
))) {
3590 publishResource( sym
, value
);
3595 void IOService::publishResource( const OSSymbol
* key
, OSObject
* value
)
3598 value
= (OSObject
*) gIOServiceKey
;
3600 gIOResources
->setProperty( key
, value
);
3602 if( IORecursiveLockHaveLock( gNotificationLock
))
3605 gIOResourceGenerationCount
++;
3606 gIOResources
->registerService();
3609 bool IOService::addNeededResource( const char * key
)
3611 OSObject
* resourcesProp
;
3616 resourcesProp
= copyProperty( gIOResourceMatchKey
);
3617 if (!resourcesProp
) return(false);
3619 newKey
= OSString::withCString( key
);
3622 resourcesProp
->release();
3626 set
= OSDynamicCast( OSSet
, resourcesProp
);
3628 set
= OSSet::withCapacity( 1 );
3630 set
->setObject( resourcesProp
);
3635 set
->setObject( newKey
);
3637 ret
= setProperty( gIOResourceMatchKey
, set
);
3639 resourcesProp
->release();
3644 bool IOService::checkResource( OSObject
* matching
)
3647 OSDictionary
* table
;
3649 if( (str
= OSDynamicCast( OSString
, matching
))) {
3650 if( gIOResources
->getProperty( str
))
3655 table
= resourceMatching( str
);
3656 else if( (table
= OSDynamicCast( OSDictionary
, matching
)))
3659 IOLog("%s: Can't match using: %s\n", getName(),
3660 matching
->getMetaClass()->getClassName());
3661 /* false would stall forever */
3665 if( gIOKitDebug
& kIOLogConfig
)
3666 LOG("config(%p): stalling %s\n", IOSERVICE_OBFUSCATE(IOThreadSelf()), getName());
3668 waitForService( table
);
3670 if( gIOKitDebug
& kIOLogConfig
)
3671 LOG("config(%p): waking\n", IOSERVICE_OBFUSCATE(IOThreadSelf()) );
3676 bool IOService::checkResources( void )
3678 OSObject
* resourcesProp
;
3683 resourcesProp
= copyProperty( gIOResourceMatchKey
);
3684 if( 0 == resourcesProp
)
3687 if( (set
= OSDynamicCast( OSSet
, resourcesProp
))) {
3689 iter
= OSCollectionIterator::withCollection( set
);
3691 while( ok
&& (resourcesProp
= iter
->getNextObject()) )
3692 ok
= checkResource( resourcesProp
);
3697 ok
= checkResource( resourcesProp
);
3699 OSSafeReleaseNULL(resourcesProp
);
3705 void _IOConfigThread::configThread( void )
3707 _IOConfigThread
* inst
;
3710 if( !(inst
= new _IOConfigThread
))
3715 if (KERN_SUCCESS
!= kernel_thread_start(&_IOConfigThread::main
, inst
, &unused
))
3728 void _IOConfigThread::free( void )
3730 thread_deallocate(current_thread());
3734 void IOService::doServiceMatch( IOOptionBits options
)
3736 _IOServiceNotifier
* notify
;
3738 OSOrderedSet
* matches
;
3739 OSArray
* resourceKeys
= 0;
3740 SInt32 catalogGeneration
;
3741 bool keepGuessing
= true;
3742 bool reRegistered
= true;
3744 OSArray
* notifiers
[2] = {0};
3746 // job->nub->deliverNotification( gIOPublishNotification,
3747 // kIOServiceRegisteredState, 0xffffffff );
3749 while( keepGuessing
) {
3751 matches
= gIOCatalogue
->findDrivers( this, &catalogGeneration
);
3752 // the matches list should always be created by findDrivers()
3755 lockForArbitration();
3756 if( 0 == (__state
[0] & kIOServiceFirstPublishState
)) {
3757 getMetaClass()->addInstance(this);
3758 notifiers
[0] = copyNotifiers(gIOFirstPublishNotification
,
3759 kIOServiceFirstPublishState
, 0xffffffff );
3762 __state
[1] &= ~kIOServiceNeedConfigState
;
3763 __state
[1] |= kIOServiceConfigState
| kIOServiceConfigRunning
;
3764 didRegister
= (0 == (kIOServiceRegisteredState
& __state
[0]));
3765 __state
[0] |= kIOServiceRegisteredState
;
3767 keepGuessing
&= (0 == (__state
[0] & kIOServiceInactiveState
));
3768 if (reRegistered
&& keepGuessing
) {
3769 iter
= OSCollectionIterator::withCollection( (OSOrderedSet
*)
3770 gNotifications
->getObject( gIOPublishNotification
) );
3772 while((notify
= (_IOServiceNotifier
*)
3773 iter
->getNextObject())) {
3775 if( matchPassive(notify
->matching
, 0)
3776 && (kIOServiceNotifyEnable
& notify
->state
))
3777 matches
->setObject( notify
);
3784 unlockForArbitration();
3785 invokeNotifiers(¬ifiers
[0]);
3787 if (keepGuessing
&& matches
->getCount() && (kIOReturnSuccess
== getResources()))
3789 if (this == gIOResources
)
3791 if (resourceKeys
) resourceKeys
->release();
3792 resourceKeys
= copyPropertyKeys();
3794 probeCandidates( matches
);
3800 lockForArbitration();
3801 reRegistered
= (0 != (__state
[1] & kIOServiceNeedConfigState
));
3803 (reRegistered
|| (catalogGeneration
!=
3804 gIOCatalogue
->getGenerationCount()))
3805 && (0 == (__state
[0] & kIOServiceInactiveState
));
3808 unlockForArbitration();
3811 if( (0 == (__state
[0] & kIOServiceInactiveState
))
3812 && (0 == (__state
[1] & kIOServiceModuleStallState
)) ) {
3814 if (resourceKeys
) setProperty(gIOResourceMatchedKey
, resourceKeys
);
3816 notifiers
[0] = copyNotifiers(gIOMatchedNotification
,
3817 kIOServiceMatchedState
, 0xffffffff);
3818 if( 0 == (__state
[0] & kIOServiceFirstMatchState
))
3819 notifiers
[1] = copyNotifiers(gIOFirstMatchNotification
,
3820 kIOServiceFirstMatchState
, 0xffffffff);
3823 __state
[1] &= ~kIOServiceConfigRunning
;
3824 unlockForArbitration();
3826 if (resourceKeys
) resourceKeys
->release();
3828 invokeNotifiers(¬ifiers
[0]);
3829 invokeNotifiers(¬ifiers
[1]);
3831 lockForArbitration();
3832 __state
[1] &= ~kIOServiceConfigState
;
3833 scheduleTerminatePhase2();
3836 unlockForArbitration();
3839 UInt32
IOService::_adjustBusy( SInt32 delta
)
3844 bool wasQuiet
, nowQuiet
, needWake
;
3847 result
= __state
[1] & kIOServiceBusyStateMask
;
3851 next
->lockForArbitration();
3852 count
= next
->__state
[1] & kIOServiceBusyStateMask
;
3853 wasQuiet
= (0 == count
);
3854 if (((delta
< 0) && wasQuiet
) || ((delta
> 0) && (kIOServiceBusyMax
== count
)))
3855 OSReportWithBacktrace("%s: bad busy count (%d,%d)\n", next
->getName(), count
, delta
);
3858 next
->__state
[1] = (next
->__state
[1] & ~kIOServiceBusyStateMask
) | count
;
3859 nowQuiet
= (0 == count
);
3860 needWake
= (0 != (kIOServiceBusyWaiterState
& next
->__state
[1]));
3863 next
->__state
[1] &= ~kIOServiceBusyWaiterState
;
3864 IOLockLock( gIOServiceBusyLock
);
3865 thread_wakeup( (event_t
) next
);
3866 IOLockUnlock( gIOServiceBusyLock
);
3869 next
->unlockForArbitration();
3871 if( (wasQuiet
|| nowQuiet
) ) {
3873 uint64_t regID
= next
->getRegistryEntryID();
3875 ((wasQuiet
/*nowBusy*/) ? IOSERVICE_BUSY
: IOSERVICE_NONBUSY
),
3877 (uintptr_t) (regID
>> 32),
3883 next
->__timeBusy
= mach_absolute_time();
3887 next
->__accumBusy
+= mach_absolute_time() - next
->__timeBusy
;
3888 next
->__timeBusy
= 0;
3891 MessageClientsContext context
;
3893 context
.service
= next
;
3894 context
.type
= kIOMessageServiceBusyStateChange
;
3895 context
.argument
= (void *) wasQuiet
; /*nowBusy*/
3896 context
.argSize
= 0;
3898 applyToInterestNotifiers( next
, gIOBusyInterest
,
3899 &messageClientsApplier
, &context
);
3902 if( nowQuiet
&& (next
== gIOServiceRoot
)) {
3903 OSKext::considerUnloads();
3904 IOServiceTrace(IOSERVICE_REGISTRY_QUIET
, 0, 0, 0, 0);
3909 delta
= nowQuiet
? -1 : +1;
3911 } while( (wasQuiet
|| nowQuiet
) && (next
= next
->getProvider()));
3916 void IOService::adjustBusy( SInt32 delta
)
3918 lockForArbitration();
3919 _adjustBusy( delta
);
3920 unlockForArbitration();
3923 uint64_t IOService::getAccumulatedBusyTime( void )
3925 uint64_t accumBusy
= __accumBusy
;
3926 uint64_t timeBusy
= __timeBusy
;
3931 accumBusy
= __accumBusy
;
3932 timeBusy
= __timeBusy
;
3934 accumBusy
+= mach_absolute_time() - timeBusy
;
3936 while (timeBusy
!= __timeBusy
);
3938 absolutetime_to_nanoseconds(*(AbsoluteTime
*)&accumBusy
, &nano
);
3943 UInt32
IOService::getBusyState( void )
3945 return( __state
[1] & kIOServiceBusyStateMask
);
3948 IOReturn
IOService::waitForState( UInt32 mask
, UInt32 value
,
3949 mach_timespec_t
* timeout
)
3951 panic("waitForState");
3952 return (kIOReturnUnsupported
);
3955 IOReturn
IOService::waitForState( UInt32 mask
, UInt32 value
,
3959 int waitResult
= THREAD_AWAKENED
;
3960 bool computeDeadline
= true;
3961 AbsoluteTime abstime
;
3964 lockForArbitration();
3965 IOLockLock( gIOServiceBusyLock
);
3966 wait
= (value
!= (__state
[1] & mask
));
3968 __state
[1] |= kIOServiceBusyWaiterState
;
3969 unlockForArbitration();
3970 if( timeout
!= UINT64_MAX
) {
3971 if( computeDeadline
) {
3972 AbsoluteTime nsinterval
;
3973 nanoseconds_to_absolutetime(timeout
, &nsinterval
);
3974 clock_absolutetime_interval_to_deadline(nsinterval
, &abstime
);
3975 computeDeadline
= false;
3977 assert_wait_deadline((event_t
)this, THREAD_UNINT
, __OSAbsoluteTime(abstime
));
3980 assert_wait((event_t
)this, THREAD_UNINT
);
3982 unlockForArbitration();
3983 IOLockUnlock( gIOServiceBusyLock
);
3985 waitResult
= thread_block(THREAD_CONTINUE_NULL
);
3987 } while( wait
&& (waitResult
!= THREAD_TIMED_OUT
));
3989 if( waitResult
== THREAD_TIMED_OUT
)
3990 return( kIOReturnTimeout
);
3992 return( kIOReturnSuccess
);
3995 IOReturn
IOService::waitQuiet( uint64_t timeout
)
3999 char * string
= NULL
;
4000 char * panicString
= NULL
;
4002 size_t panicStringLen
;
4008 enum { kTimeoutExtensions
= 4 };
4010 time
= mach_absolute_time();
4012 for (loops
= 0; loops
< kTimeoutExtensions
; loops
++)
4014 ret
= waitForState( kIOServiceBusyStateMask
, 0, timeout
);
4016 if (loops
&& (kIOReturnSuccess
== ret
))
4018 time
= mach_absolute_time() - time
;
4019 absolutetime_to_nanoseconds(*(AbsoluteTime
*)&time
, &nano
);
4020 IOLog("busy extended ok[%d], (%llds, %llds)\n",
4021 loops
, timeout
/ 1000000000ULL, nano
/ 1000000000ULL);
4024 else if (kIOReturnTimeout
!= ret
) break;
4025 else if (timeout
< 41000000000) break;
4028 IORegistryIterator
* iter
;
4030 OSOrderedSet
* leaves
;
4032 IOService
* nextParent
;
4037 panicStringLen
= 256;
4038 if (!string
) string
= IONew(char, len
);
4039 if (!panicString
) panicString
= IONew(char, panicStringLen
);
4041 kextdWait
= OSKext::isWaitingKextd();
4042 iter
= IORegistryIterator::iterateOver(this, gIOServicePlane
, kIORegistryIterateRecursively
);
4043 leaves
= OSOrderedSet::withCapacity(4);
4044 if (iter
) set
= iter
->iterateAll();
4045 if (string
&& panicString
&& leaves
&& set
)
4047 string
[0] = panicString
[0] = 0;
4048 set
->setObject(this);
4049 while ((next
= (IOService
*) set
->getLastObject()))
4051 if (next
->getBusyState())
4053 if (kIOServiceModuleStallState
& next
->__state
[1]) kextdWait
= true;
4054 leaves
->setObject(next
);
4056 while ((nextParent
= nextParent
->getProvider()))
4058 set
->removeObject(nextParent
);
4059 leaves
->removeObject(nextParent
);
4062 set
->removeObject(next
);
4065 while ((next
= (IOService
*) leaves
->getLastObject()))
4067 l
= snprintf(s
, len
, "%s'%s'", ((s
== string
) ? "" : ", "), next
->getName());
4068 if (l
>= len
) break;
4071 leaves
->removeObject(next
);
4074 OSSafeReleaseNULL(leaves
);
4075 OSSafeReleaseNULL(set
);
4076 OSSafeReleaseNULL(iter
);
4079 dopanic
= ((loops
>= (kTimeoutExtensions
- 1)) && (kIOWaitQuietPanics
& gIOKitDebug
));
4080 snprintf(panicString
, panicStringLen
,
4081 "%s[%d], (%llds): %s",
4082 kextdWait
? "kextd stall" : "busy timeout",
4083 loops
, timeout
/ 1000000000ULL,
4084 string
? string
: "");
4085 IOLog("%s\n", panicString
);
4086 if (dopanic
) panic("%s", panicString
);
4087 else if (!loops
) getPMRootDomain()->startSpinDump(1);
4090 if (string
) IODelete(string
, char, 256);
4091 if (panicString
) IODelete(panicString
, char, panicStringLen
);
4096 IOReturn
IOService::waitQuiet( mach_timespec_t
* timeout
)
4102 timeoutNS
= timeout
->tv_sec
;
4103 timeoutNS
*= kSecondScale
;
4104 timeoutNS
+= timeout
->tv_nsec
;
4107 timeoutNS
= UINT64_MAX
;
4109 return (waitQuiet(timeoutNS
));
4112 bool IOService::serializeProperties( OSSerialize
* s
) const
4115 ((IOService
*)this)->setProperty( ((IOService
*)this)->__state
,
4116 sizeof( __state
), "__state");
4118 return( super::serializeProperties(s
) );
4122 void _IOConfigThread::main(void * arg
, wait_result_t result
)
4124 _IOConfigThread
* self
= (_IOConfigThread
*) arg
;
4125 _IOServiceJob
* job
;
4129 thread_precedence_policy_data_t precedence
= { -1 };
4131 kr
= thread_policy_set(current_thread(),
4132 THREAD_PRECEDENCE_POLICY
,
4133 (thread_policy_t
) &precedence
,
4134 THREAD_PRECEDENCE_POLICY_COUNT
);
4135 if (KERN_SUCCESS
!= kr
)
4136 IOLog("thread_policy_set(%d)\n", kr
);
4142 semaphore_wait( gJobsSemaphore
);
4144 IOTakeLock( gJobsLock
);
4145 job
= (_IOServiceJob
*) gJobs
->getFirstObject();
4147 gJobs
->removeObject(job
);
4150 // gNumConfigThreads--; // we're out of service
4151 gNumWaitingThreads
--; // we're out of service
4153 IOUnlock( gJobsLock
);
4159 if( gIOKitDebug
& kIOLogConfig
)
4160 LOG("config(%p): starting on %s, %d\n",
4161 IOSERVICE_OBFUSCATE(IOThreadSelf()), job
->nub
->getName(), job
->type
);
4163 switch( job
->type
) {
4166 nub
->doServiceMatch( job
->options
);
4170 LOG("config(%p): strange type (%d)\n",
4171 IOSERVICE_OBFUSCATE(IOThreadSelf()), job
->type
);
4178 IOTakeLock( gJobsLock
);
4179 alive
= (gOutstandingJobs
> gNumWaitingThreads
);
4181 gNumWaitingThreads
++; // back in service
4182 // gNumConfigThreads++;
4184 if( 0 == --gNumConfigThreads
) {
4185 // IOLog("MATCH IDLE\n");
4186 IOLockWakeup( gJobsLock
, (event_t
) &gNumConfigThreads
, /* one-thread */ false );
4189 IOUnlock( gJobsLock
);
4194 if( gIOKitDebug
& kIOLogConfig
)
4195 LOG("config(%p): terminating\n", IOSERVICE_OBFUSCATE(IOThreadSelf()) );
4200 IOReturn
IOService::waitMatchIdle( UInt32 msToWait
)
4203 int waitResult
= THREAD_AWAKENED
;
4204 bool computeDeadline
= true;
4205 AbsoluteTime deadline
;
4207 IOLockLock( gJobsLock
);
4209 wait
= (0 != gNumConfigThreads
);
4212 if( computeDeadline
) {
4213 clock_interval_to_deadline(
4214 msToWait
, kMillisecondScale
, &deadline
);
4215 computeDeadline
= false;
4217 waitResult
= IOLockSleepDeadline( gJobsLock
, &gNumConfigThreads
,
4218 deadline
, THREAD_UNINT
);
4220 waitResult
= IOLockSleep( gJobsLock
, &gNumConfigThreads
,
4224 } while( wait
&& (waitResult
!= THREAD_TIMED_OUT
));
4225 IOLockUnlock( gJobsLock
);
4227 if( waitResult
== THREAD_TIMED_OUT
)
4228 return( kIOReturnTimeout
);
4230 return( kIOReturnSuccess
);
4233 void IOService::cpusRunning(void)
4235 gCPUsRunning
= true;
4238 void _IOServiceJob::pingConfig( _IOServiceJob
* job
)
4245 IOTakeLock( gJobsLock
);
4248 gJobs
->setLastObject( job
);
4250 count
= gNumWaitingThreads
;
4251 // if( gNumConfigThreads) count++;// assume we're called from a config thread
4253 create
= ( (gOutstandingJobs
> count
)
4254 && ((gNumConfigThreads
< kMaxConfigThreads
)
4255 || (job
->nub
== gIOResources
)
4258 gNumConfigThreads
++;
4259 gNumWaitingThreads
++;
4262 IOUnlock( gJobsLock
);
4267 if( gIOKitDebug
& kIOLogConfig
)
4268 LOG("config(%d): creating\n", gNumConfigThreads
- 1);
4269 _IOConfigThread::configThread();
4272 semaphore_signal( gJobsSemaphore
);
4275 struct IOServiceMatchContext
4277 OSDictionary
* table
;
4285 bool IOService::instanceMatch(const OSObject
* entry
, void * context
)
4287 IOServiceMatchContext
* ctx
= (typeof(ctx
)) context
;
4288 IOService
* service
= (typeof(service
)) entry
;
4289 OSDictionary
* table
= ctx
->table
;
4290 uint32_t options
= ctx
->options
;
4291 uint32_t state
= ctx
->state
;
4298 match
= ((state
== (state
& service
->__state
[0]))
4299 && (0 == (service
->__state
[0] & kIOServiceInactiveState
)));
4301 ctx
->count
+= table
->getCount();
4302 match
= service
->matchInternal(table
, options
, &done
);
4309 if ((kIONotifyOnce
& options
) && (ctx
->done
== ctx
->count
))
4312 ctx
->result
= service
;
4315 else if (!ctx
->result
)
4317 ctx
->result
= OSSet::withObjects((const OSObject
**) &service
, 1, 1);
4321 ((OSSet
*)ctx
->result
)->setObject(service
);
4326 // internal - call with gNotificationLock
4327 OSObject
* IOService::copyExistingServices( OSDictionary
* matching
,
4328 IOOptionBits inState
, IOOptionBits options
)
4330 OSObject
* current
= 0;
4332 IOService
* service
;
4340 OSSerialize
* s
= OSSerialize::withCapacity(128);
4341 matching
->serialize(s
);
4344 if((obj
= matching
->getObject(gIOProviderClassKey
))
4346 && gIOResourcesKey
->isEqualTo(obj
)
4347 && (service
= gIOResources
))
4349 if( (inState
== (service
->__state
[0] & inState
))
4350 && (0 == (service
->__state
[0] & kIOServiceInactiveState
))
4351 && service
->matchPassive(matching
, options
))
4353 if( options
& kIONotifyOnce
)
4359 current
= OSSet::withObjects((const OSObject
**) &service
, 1, 1 );
4364 IOServiceMatchContext ctx
;
4365 ctx
.table
= matching
;
4366 ctx
.state
= inState
;
4369 ctx
.options
= options
;
4372 if ((str
= OSDynamicCast(OSString
, obj
)))
4374 const OSSymbol
* sym
= OSSymbol::withString(str
);
4375 OSMetaClass::applyToInstancesOfClassName(sym
, instanceMatch
, &ctx
);
4380 IOService::gMetaClass
.applyToInstances(instanceMatch
, &ctx
);
4384 current
= ctx
.result
;
4386 options
|= kIOServiceInternalDone
| kIOServiceClassDone
;
4387 if (current
&& (ctx
.done
!= ctx
.count
))
4390 source
= OSDynamicCast(OSSet
, current
);
4392 while ((service
= (IOService
*) source
->getAnyObject()))
4394 if (service
->matchPassive(matching
, options
))
4396 if( options
& kIONotifyOnce
)
4404 ((OSSet
*)current
)->setObject( service
);
4408 current
= OSSet::withObjects(
4409 (const OSObject
**) &service
, 1, 1 );
4412 source
->removeObject(service
);
4420 OSObject
* _current
= 0;
4422 iter
= IORegistryIterator::iterateOver( gIOServicePlane
,
4423 kIORegistryIterateRecursively
);
4427 while( (service
= (IOService
*) iter
->getNextObject())) {
4428 if( (inState
== (service
->__state
[0] & inState
))
4429 && (0 == (service
->__state
[0] & kIOServiceInactiveState
))
4430 && service
->matchPassive(matching
, 0)) {
4432 if( options
& kIONotifyOnce
) {
4438 ((OSSet
*)_current
)->setObject( service
);
4440 _current
= OSSet::withObjects(
4441 (const OSObject
**) &service
, 1, 1 );
4444 } while( !service
&& !iter
->isValid());
4449 if ( ((current
!= 0) != (_current
!= 0))
4450 || (current
&& _current
&& !current
->isEqualTo(_current
)))
4452 OSSerialize
* s1
= OSSerialize::withCapacity(128);
4453 OSSerialize
* s2
= OSSerialize::withCapacity(128);
4454 current
->serialize(s1
);
4455 _current
->serialize(s2
);
4456 kprintf("**mismatch** %p %p\n%s\n%s\n%s\n", IOSERVICE_OBFUSCATE(current
),
4457 IOSERVICE_OBFUSCATE(_current
), s
->text(), s1
->text(), s2
->text());
4462 if (_current
) _current
->release();
4468 if( current
&& (0 == (options
& (kIONotifyOnce
| kIOServiceExistingSet
)))) {
4469 iter
= OSCollectionIterator::withCollection( (OSSet
*)current
);
4478 OSIterator
* IOService::getMatchingServices( OSDictionary
* matching
)
4482 // is a lock even needed?
4485 iter
= (OSIterator
*) copyExistingServices( matching
,
4486 kIOServiceMatchedState
);
4493 IOService
* IOService::copyMatchingService( OSDictionary
* matching
)
4495 IOService
* service
;
4497 // is a lock even needed?
4500 service
= (IOService
*) copyExistingServices( matching
,
4501 kIOServiceMatchedState
, kIONotifyOnce
);
4508 struct _IOServiceMatchingNotificationHandlerRef
4510 IOServiceNotificationHandler handler
;
4514 static bool _IOServiceMatchingNotificationHandler( void * target
, void * refCon
,
4515 IOService
* newService
,
4516 IONotifier
* notifier
)
4518 return ((*((_IOServiceNotifier
*) notifier
)->compatHandler
)(target
, refCon
, newService
));
4521 // internal - call with gNotificationLock
4522 IONotifier
* IOService::setNotification(
4523 const OSSymbol
* type
, OSDictionary
* matching
,
4524 IOServiceMatchingNotificationHandler handler
, void * target
, void * ref
,
4527 _IOServiceNotifier
* notify
= 0;
4533 notify
= new _IOServiceNotifier
;
4534 if( notify
&& !notify
->init()) {
4540 notify
->handler
= handler
;
4541 notify
->target
= target
;
4542 notify
->type
= type
;
4543 notify
->matching
= matching
;
4545 if (handler
== &_IOServiceMatchingNotificationHandler
)
4547 notify
->compatHandler
= ((_IOServiceMatchingNotificationHandlerRef
*)ref
)->handler
;
4548 notify
->ref
= ((_IOServiceMatchingNotificationHandlerRef
*)ref
)->ref
;
4552 notify
->priority
= priority
;
4553 notify
->state
= kIOServiceNotifyEnable
;
4554 queue_init( ¬ify
->handlerInvocations
);
4558 if( 0 == (set
= (OSOrderedSet
*) gNotifications
->getObject( type
))) {
4559 set
= OSOrderedSet::withCapacity( 1,
4560 IONotifyOrdering
, 0 );
4562 gNotifications
->setObject( type
, set
);
4566 notify
->whence
= set
;
4568 set
->setObject( notify
);
4574 // internal - call with gNotificationLock
4575 IONotifier
* IOService::doInstallNotification(
4576 const OSSymbol
* type
, OSDictionary
* matching
,
4577 IOServiceMatchingNotificationHandler handler
,
4578 void * target
, void * ref
,
4579 SInt32 priority
, OSIterator
** existing
)
4582 IONotifier
* notify
;
4583 IOOptionBits inState
;
4588 if( type
== gIOPublishNotification
)
4589 inState
= kIOServiceRegisteredState
;
4591 else if( type
== gIOFirstPublishNotification
)
4592 inState
= kIOServiceFirstPublishState
;
4594 else if (type
== gIOMatchedNotification
)
4595 inState
= kIOServiceMatchedState
;
4597 else if (type
== gIOFirstMatchNotification
)
4598 inState
= kIOServiceFirstMatchState
;
4600 else if ((type
== gIOTerminatedNotification
) || (type
== gIOWillTerminateNotification
))
4605 notify
= setNotification( type
, matching
, handler
, target
, ref
, priority
);
4608 // get the current set
4609 exist
= (OSIterator
*) copyExistingServices( matching
, inState
);
4618 #if !defined(__LP64__)
4619 IONotifier
* IOService::installNotification(const OSSymbol
* type
, OSDictionary
* matching
,
4620 IOServiceNotificationHandler handler
,
4621 void * target
, void * refCon
,
4622 SInt32 priority
, OSIterator
** existing
)
4624 IONotifier
* result
;
4625 _IOServiceMatchingNotificationHandlerRef ref
;
4626 ref
.handler
= handler
;
4629 result
= (_IOServiceNotifier
*) installNotification( type
, matching
,
4630 &_IOServiceMatchingNotificationHandler
,
4631 target
, &ref
, priority
, existing
);
4633 matching
->release();
4637 #endif /* !defined(__LP64__) */
4640 IONotifier
* IOService::installNotification(
4641 const OSSymbol
* type
, OSDictionary
* matching
,
4642 IOServiceMatchingNotificationHandler handler
,
4643 void * target
, void * ref
,
4644 SInt32 priority
, OSIterator
** existing
)
4646 IONotifier
* notify
;
4650 notify
= doInstallNotification( type
, matching
, handler
, target
, ref
,
4651 priority
, existing
);
4653 // in case handler remove()s
4654 if (notify
) notify
->retain();
4661 IONotifier
* IOService::addNotification(
4662 const OSSymbol
* type
, OSDictionary
* matching
,
4663 IOServiceNotificationHandler handler
,
4664 void * target
, void * refCon
,
4667 IONotifier
* result
;
4668 _IOServiceMatchingNotificationHandlerRef ref
;
4670 ref
.handler
= handler
;
4673 result
= addMatchingNotification(type
, matching
, &_IOServiceMatchingNotificationHandler
,
4674 target
, &ref
, priority
);
4677 matching
->release();
4682 IONotifier
* IOService::addMatchingNotification(
4683 const OSSymbol
* type
, OSDictionary
* matching
,
4684 IOServiceMatchingNotificationHandler handler
,
4685 void * target
, void * ref
,
4688 OSIterator
* existing
= NULL
;
4690 _IOServiceNotifier
* notify
;
4693 ret
= notify
= (_IOServiceNotifier
*) installNotification( type
, matching
,
4694 handler
, target
, ref
, priority
, &existing
);
4695 if (!ret
) return (0);
4697 // send notifications for existing set
4700 while( (next
= (IOService
*) existing
->getNextObject()))
4702 if( 0 == (next
->__state
[0] & kIOServiceInactiveState
))
4704 next
->invokeNotifier( notify
);
4707 existing
->release();
4711 bool removed
= (0 == notify
->whence
);
4713 if (removed
) ret
= gIOServiceNullNotifier
;
4720 IOServiceMatchingNotificationHandlerToBlock( void * target __unused
, void * refCon
,
4721 IOService
* newService
,
4722 IONotifier
* notifier
)
4724 return ((IOServiceMatchingNotificationHandlerBlock
) refCon
)(newService
, notifier
);
4727 IONotifier
* IOService::addMatchingNotification(
4728 const OSSymbol
* type
, OSDictionary
* matching
,
4730 IOServiceMatchingNotificationHandlerBlock handler
)
4732 IONotifier
* notify
;
4735 block
= Block_copy(handler
);
4736 if (!block
) return (NULL
);
4738 notify
= addMatchingNotification(type
, matching
,
4739 &IOServiceMatchingNotificationHandlerToBlock
, NULL
, block
, priority
);
4741 if (!notify
) Block_release(block
);
4747 bool IOService::syncNotificationHandler(
4748 void * /* target */, void * ref
,
4749 IOService
* newService
,
4750 IONotifier
* notifier
)
4754 if (!*((IOService
**) ref
))
4756 newService
->retain();
4757 (*(IOService
**) ref
) = newService
;
4765 IOService
* IOService::waitForMatchingService( OSDictionary
* matching
,
4768 IONotifier
* notify
= 0;
4769 // priority doesn't help us much since we need a thread wakeup
4770 SInt32 priority
= 0;
4781 result
= (IOService
*) copyExistingServices( matching
,
4782 kIOServiceMatchedState
, kIONotifyOnce
);
4785 notify
= IOService::setNotification( gIOMatchedNotification
, matching
,
4786 &IOService::syncNotificationHandler
, (void *) 0,
4787 &result
, priority
);
4790 if (UINT64_MAX
!= timeout
)
4792 AbsoluteTime deadline
;
4793 nanoseconds_to_absolutetime(timeout
, &deadline
);
4794 clock_absolutetime_interval_to_deadline(deadline
, &deadline
);
4795 SLEEPNOTIFYTO(&result
, deadline
);
4799 SLEEPNOTIFY(&result
);
4807 notify
->remove(); // dequeues
4812 IOService
* IOService::waitForService( OSDictionary
* matching
,
4813 mach_timespec_t
* timeout
)
4820 timeoutNS
= timeout
->tv_sec
;
4821 timeoutNS
*= kSecondScale
;
4822 timeoutNS
+= timeout
->tv_nsec
;
4825 timeoutNS
= UINT64_MAX
;
4827 result
= waitForMatchingService(matching
, timeoutNS
);
4829 matching
->release();
4836 void IOService::deliverNotification( const OSSymbol
* type
,
4837 IOOptionBits orNewState
, IOOptionBits andNewState
)
4839 panic("deliverNotification");
4842 OSArray
* IOService::copyNotifiers(const OSSymbol
* type
,
4843 IOOptionBits orNewState
, IOOptionBits andNewState
)
4845 _IOServiceNotifier
* notify
;
4847 OSArray
* willSend
= 0;
4849 lockForArbitration();
4851 if( (0 == (__state
[0] & kIOServiceInactiveState
))
4852 || (type
== gIOTerminatedNotification
)
4853 || (type
== gIOWillTerminateNotification
)) {
4857 iter
= OSCollectionIterator::withCollection( (OSOrderedSet
*)
4858 gNotifications
->getObject( type
) );
4861 while( (notify
= (_IOServiceNotifier
*) iter
->getNextObject())) {
4863 if( matchPassive(notify
->matching
, 0)
4864 && (kIOServiceNotifyEnable
& notify
->state
)) {
4866 willSend
= OSArray::withCapacity(8);
4868 willSend
->setObject( notify
);
4873 __state
[0] = (__state
[0] | orNewState
) & andNewState
;
4877 unlockForArbitration();
4883 IOOptionBits
IOService::getState( void ) const
4885 return( __state
[0] );
4889 * Helpers to make matching objects for simple cases
4892 OSDictionary
* IOService::serviceMatching( const OSString
* name
,
4893 OSDictionary
* table
)
4896 const OSString
* str
;
4898 str
= OSSymbol::withString(name
);
4903 table
= OSDictionary::withCapacity( 2 );
4905 table
->setObject(gIOProviderClassKey
, (OSObject
*)str
);
4911 OSDictionary
* IOService::serviceMatching( const char * name
,
4912 OSDictionary
* table
)
4914 const OSString
* str
;
4916 str
= OSSymbol::withCString( name
);
4920 table
= serviceMatching( str
, table
);
4925 OSDictionary
* IOService::nameMatching( const OSString
* name
,
4926 OSDictionary
* table
)
4929 table
= OSDictionary::withCapacity( 2 );
4931 table
->setObject( gIONameMatchKey
, (OSObject
*)name
);
4936 OSDictionary
* IOService::nameMatching( const char * name
,
4937 OSDictionary
* table
)
4939 const OSString
* str
;
4941 str
= OSSymbol::withCString( name
);
4945 table
= nameMatching( str
, table
);
4950 OSDictionary
* IOService::resourceMatching( const OSString
* str
,
4951 OSDictionary
* table
)
4953 table
= serviceMatching( gIOResourcesKey
, table
);
4955 table
->setObject( gIOResourceMatchKey
, (OSObject
*) str
);
4960 OSDictionary
* IOService::resourceMatching( const char * name
,
4961 OSDictionary
* table
)
4963 const OSSymbol
* str
;
4965 str
= OSSymbol::withCString( name
);
4969 table
= resourceMatching( str
, table
);
4975 OSDictionary
* IOService::propertyMatching( const OSSymbol
* key
, const OSObject
* value
,
4976 OSDictionary
* table
)
4978 OSDictionary
* properties
;
4980 properties
= OSDictionary::withCapacity( 2 );
4983 properties
->setObject( key
, value
);
4986 table
= OSDictionary::withCapacity( 2 );
4988 table
->setObject( gIOPropertyMatchKey
, properties
);
4990 properties
->release();
4995 OSDictionary
* IOService::registryEntryIDMatching( uint64_t entryID
,
4996 OSDictionary
* table
)
5000 num
= OSNumber::withNumber( entryID
, 64 );
5005 table
= OSDictionary::withCapacity( 2 );
5007 table
->setObject( gIORegistryEntryIDKey
, num
);
5017 * _IOServiceNotifier
5020 // wait for all threads, other than the current one,
5021 // to exit the handler
5023 void _IOServiceNotifier::wait()
5025 _IOServiceNotifierInvocation
* next
;
5030 queue_iterate( &handlerInvocations
, next
,
5031 _IOServiceNotifierInvocation
*, link
) {
5032 if( next
->thread
!= current_thread() ) {
5038 state
|= kIOServiceNotifyWaiter
;
5045 void _IOServiceNotifier::free()
5047 assert( queue_empty( &handlerInvocations
));
5049 if (handler
== &IOServiceMatchingNotificationHandlerToBlock
) Block_release(ref
);
5054 void _IOServiceNotifier::remove()
5059 whence
->removeObject( (OSObject
*) this );
5063 matching
->release();
5067 state
&= ~kIOServiceNotifyEnable
;
5076 bool _IOServiceNotifier::disable()
5082 ret
= (0 != (kIOServiceNotifyEnable
& state
));
5083 state
&= ~kIOServiceNotifyEnable
;
5092 void _IOServiceNotifier::enable( bool was
)
5096 state
|= kIOServiceNotifyEnable
;
5098 state
&= ~kIOServiceNotifyEnable
;
5104 * _IOServiceNullNotifier
5107 void _IOServiceNullNotifier::taggedRetain(const void *tag
) const {}
5108 void _IOServiceNullNotifier::taggedRelease(const void *tag
, const int when
) const {}
5109 void _IOServiceNullNotifier::free() {}
5110 void _IOServiceNullNotifier::wait() {}
5111 void _IOServiceNullNotifier::remove() {}
5112 void _IOServiceNullNotifier::enable(bool was
) {}
5113 bool _IOServiceNullNotifier::disable() { return(false); }
5119 IOService
* IOResources::resources( void )
5123 inst
= new IOResources
;
5124 if( inst
&& !inst
->init()) {
5132 bool IOResources::init( OSDictionary
* dictionary
)
5134 // Do super init first
5135 if ( !IOService::init() )
5138 // Allow PAL layer to publish a value
5139 const char *property_name
;
5142 pal_get_resource_property( &property_name
, &property_value
);
5144 if( property_name
) {
5146 const OSSymbol
* sym
;
5148 if( (num
= OSNumber::withNumber(property_value
, 32)) != 0 ) {
5149 if( (sym
= OSSymbol::withCString( property_name
)) != 0 ) {
5150 this->setProperty( sym
, num
);
5160 IOReturn
IOResources::newUserClient(task_t owningTask
, void * securityID
,
5161 UInt32 type
, OSDictionary
* properties
,
5162 IOUserClient
** handler
)
5164 return( kIOReturnUnsupported
);
5167 IOWorkLoop
* IOResources::getWorkLoop() const
5169 // If we are the resource root
5170 // then use the platform's workloop
5171 if (this == (IOResources
*) gIOResources
)
5172 return getPlatform()->getWorkLoop();
5174 return IOService::getWorkLoop();
5177 bool IOResources::matchPropertyTable( OSDictionary
* table
)
5187 prop
= table
->getObject( gIOResourceMatchKey
);
5188 str
= OSDynamicCast( OSString
, prop
);
5190 ok
= (0 != getProperty( str
));
5192 else if( (set
= OSDynamicCast( OSSet
, prop
))) {
5194 iter
= OSCollectionIterator::withCollection( set
);
5196 while( ok
&& (str
= OSDynamicCast( OSString
, iter
->getNextObject()) ))
5197 ok
= (0 != getProperty( str
));
5202 else if ((prop
= table
->getObject(gIOResourceMatchedKey
)))
5204 obj
= copyProperty(gIOResourceMatchedKey
);
5205 keys
= OSDynamicCast(OSArray
, obj
);
5209 // assuming OSSymbol
5210 ok
= ((-1U) != keys
->getNextIndexOfObject(prop
, 0));
5212 OSSafeReleaseNULL(obj
);
5218 void IOService::consoleLockTimer(thread_call_param_t p0
, thread_call_param_t p1
)
5220 IOService::updateConsoleUsers(NULL
, 0);
5223 void IOService::updateConsoleUsers(OSArray
* consoleUsers
, IOMessage systemMessage
)
5225 IORegistryEntry
* regEntry
;
5226 OSObject
* locked
= kOSBooleanFalse
;
5229 OSDictionary
* user
;
5230 static IOMessage sSystemPower
;
5231 clock_sec_t now
= 0;
5232 clock_usec_t microsecs
;
5234 regEntry
= IORegistryEntry::getRegistryRoot();
5236 if (!gIOChosenEntry
)
5237 gIOChosenEntry
= IORegistryEntry::fromPath("/chosen", gIODTPlane
);
5239 IOLockLock(gIOConsoleUsersLock
);
5243 sSystemPower
= systemMessage
;
5245 if (kIOMessageSystemHasPoweredOn
== systemMessage
)
5247 uint32_t lockState
= IOHibernateWasScreenLocked();
5252 case kIOScreenLockLocked
:
5253 case kIOScreenLockFileVaultDialog
:
5254 gIOConsoleBooterLockState
= kOSBooleanTrue
;
5256 case kIOScreenLockNoLock
:
5257 gIOConsoleBooterLockState
= 0;
5259 case kIOScreenLockUnlocked
:
5261 gIOConsoleBooterLockState
= kOSBooleanFalse
;
5265 #endif /* HIBERNATION */
5271 bool loginLocked
= true;
5273 gIOConsoleLoggedIn
= false;
5275 (user
= OSDynamicCast(OSDictionary
, consoleUsers
->getObject(idx
)));
5278 gIOConsoleLoggedIn
|= ((kOSBooleanTrue
== user
->getObject(gIOConsoleSessionOnConsoleKey
))
5279 && (kOSBooleanTrue
== user
->getObject(gIOConsoleSessionLoginDoneKey
)));
5281 loginLocked
&= (kOSBooleanTrue
== user
->getObject(gIOConsoleSessionScreenIsLockedKey
));
5284 num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionScreenLockedTimeKey
));
5288 if (!loginLocked
) gIOConsoleBooterLockState
= 0;
5289 IOLog("IOConsoleUsers: time(%d) %ld->%d, lin %d, llk %d, \n",
5290 (num
!= 0), gIOConsoleLockTime
, (num
? num
->unsigned32BitValue() : 0),
5291 gIOConsoleLoggedIn
, loginLocked
);
5292 #endif /* HIBERNATION */
5293 gIOConsoleLockTime
= num
? num
->unsigned32BitValue() : 0;
5296 if (!gIOConsoleLoggedIn
5297 || (kIOMessageSystemWillSleep
== sSystemPower
)
5298 || (kIOMessageSystemPagingOff
== sSystemPower
))
5300 locked
= kOSBooleanTrue
;
5303 else if (gIOConsoleBooterLockState
)
5305 locked
= gIOConsoleBooterLockState
;
5307 #endif /* HIBERNATION */
5308 else if (gIOConsoleLockTime
)
5310 clock_get_calendar_microtime(&now
, µsecs
);
5311 if (gIOConsoleLockTime
> now
)
5313 AbsoluteTime deadline
;
5314 clock_interval_to_deadline(gIOConsoleLockTime
- now
, kSecondScale
, &deadline
);
5315 thread_call_enter_delayed(gIOConsoleLockCallout
, deadline
);
5319 locked
= kOSBooleanTrue
;
5323 publish
= (consoleUsers
|| (locked
!= regEntry
->getProperty(gIOConsoleLockedKey
)));
5326 regEntry
->setProperty(gIOConsoleLockedKey
, locked
);
5329 regEntry
->setProperty(gIOConsoleUsersKey
, consoleUsers
);
5331 OSIncrementAtomic( &gIOConsoleUsersSeed
);
5337 if (locked
== kOSBooleanTrue
) gIOScreenLockState
= kIOScreenLockLocked
;
5338 else if (gIOConsoleLockTime
) gIOScreenLockState
= kIOScreenLockUnlocked
;
5339 else gIOScreenLockState
= kIOScreenLockNoLock
;
5340 gIOChosenEntry
->setProperty(kIOScreenLockStateKey
, &gIOScreenLockState
, sizeof(gIOScreenLockState
));
5342 IOLog("IOConsoleUsers: gIOScreenLockState %d, hs %d, bs %d, now %ld, sm 0x%x\n",
5343 gIOScreenLockState
, gIOHibernateState
, (gIOConsoleBooterLockState
!= 0), now
, systemMessage
);
5345 #endif /* HIBERNATION */
5347 IOLockUnlock(gIOConsoleUsersLock
);
5351 publishResource( gIOConsoleUsersSeedKey
, gIOConsoleUsersSeedValue
);
5353 MessageClientsContext context
;
5355 context
.service
= getServiceRoot();
5356 context
.type
= kIOMessageConsoleSecurityChange
;
5357 context
.argument
= (void *) regEntry
;
5358 context
.argSize
= 0;
5360 applyToInterestNotifiers(getServiceRoot(), gIOConsoleSecurityInterest
,
5361 &messageClientsApplier
, &context
);
5365 IOReturn
IOResources::setProperties( OSObject
* properties
)
5368 const OSSymbol
* key
;
5369 OSDictionary
* dict
;
5370 OSCollectionIterator
* iter
;
5372 err
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
5373 if ( kIOReturnSuccess
!= err
)
5376 dict
= OSDynamicCast(OSDictionary
, properties
);
5378 return( kIOReturnBadArgument
);
5380 iter
= OSCollectionIterator::withCollection( dict
);
5382 return( kIOReturnBadArgument
);
5384 while( (key
= OSDynamicCast(OSSymbol
, iter
->getNextObject())))
5386 if (gIOConsoleUsersKey
== key
) do
5388 OSArray
* consoleUsers
;
5389 consoleUsers
= OSDynamicCast(OSArray
, dict
->getObject(key
));
5392 IOService::updateConsoleUsers(consoleUsers
, 0);
5396 publishResource( key
, dict
->getObject(key
) );
5401 return( kIOReturnSuccess
);
5405 * Helpers for matching dictionaries.
5406 * Keys existing in matching are checked in properties.
5407 * Keys may be a string or OSCollection of IOStrings
5410 bool IOService::compareProperty( OSDictionary
* matching
,
5417 value
= matching
->getObject( key
);
5420 prop
= copyProperty(key
);
5421 ok
= value
->isEqualTo(prop
);
5422 if (prop
) prop
->release();
5431 bool IOService::compareProperty( OSDictionary
* matching
,
5432 const OSString
* key
)
5438 value
= matching
->getObject( key
);
5441 prop
= copyProperty(key
);
5442 ok
= value
->isEqualTo(prop
);
5443 if (prop
) prop
->release();
5451 bool IOService::compareProperties( OSDictionary
* matching
,
5452 OSCollection
* keys
)
5454 OSCollectionIterator
* iter
;
5455 const OSString
* key
;
5458 if( !matching
|| !keys
)
5461 iter
= OSCollectionIterator::withCollection( keys
);
5464 while( ok
&& (key
= OSDynamicCast( OSString
, iter
->getNextObject())))
5465 ok
= compareProperty( matching
, key
);
5469 keys
->release(); // !! consume a ref !!
5474 /* Helper to add a location matching dict to the table */
5476 OSDictionary
* IOService::addLocation( OSDictionary
* table
)
5478 OSDictionary
* dict
;
5483 dict
= OSDictionary::withCapacity( 1 );
5485 table
->setObject( gIOLocationMatchKey
, dict
);
5493 * Go looking for a provider to match a location dict.
5496 IOService
* IOService::matchLocation( IOService
* /* client */ )
5500 parent
= getProvider();
5503 parent
= parent
->matchLocation( this );
5508 bool IOService::matchInternal(OSDictionary
* table
, uint32_t options
, uint32_t * did
)
5513 IORegistryEntry
* entry
;
5516 bool changesOK
= (0 != (kIOServiceChangesOK
& options
));
5522 count
= table
->getCount();
5525 str
= OSDynamicCast(OSString
, table
->getObject(gIOProviderClassKey
));
5528 match
= ((kIOServiceClassDone
& options
) || (0 != metaCast(str
)));
5530 match
= (0 != metaCast( str
));
5531 if ((kIOServiceClassDone
& options
) && !match
) panic("classDone");
5533 if ((!match
) || (done
== count
)) break;
5536 obj
= table
->getObject( gIONameMatchKey
);
5539 match
= compareNames( obj
, changesOK
? &matched
: 0 );
5541 if( changesOK
&& matched
) {
5542 // leave a hint as to which name matched
5543 table
->setObject( gIONameMatchedKey
, matched
);
5546 if (done
== count
) break;
5549 str
= OSDynamicCast( OSString
, table
->getObject( gIOLocationMatchKey
));
5552 const OSSymbol
* sym
;
5555 sym
= copyLocation();
5557 match
= sym
->isEqualTo( str
);
5560 if ((!match
) || (done
== count
)) break;
5563 obj
= table
->getObject( gIOPropertyMatchKey
);
5566 OSDictionary
* dict
;
5567 OSDictionary
* nextDict
;
5571 dict
= dictionaryWithProperties();
5573 nextDict
= OSDynamicCast( OSDictionary
, obj
);
5577 iter
= OSCollectionIterator::withCollection(
5578 OSDynamicCast(OSCollection
, obj
));
5581 || (iter
&& (0 != (nextDict
= OSDynamicCast(OSDictionary
,
5582 iter
->getNextObject()))))) {
5583 match
= dict
->isEqualTo( nextDict
, nextDict
);
5592 if ((!match
) || (done
== count
)) break;
5595 obj
= table
->getObject( gIOPropertyExistsMatchKey
);
5598 OSDictionary
* dict
;
5603 dict
= dictionaryWithProperties();
5605 nextKey
= OSDynamicCast( OSString
, obj
);
5609 iter
= OSCollectionIterator::withCollection(
5610 OSDynamicCast(OSCollection
, obj
));
5613 || (iter
&& (0 != (nextKey
= OSDynamicCast(OSString
,
5614 iter
->getNextObject()))))) {
5615 match
= (0 != dict
->getObject(nextKey
));
5624 if ((!match
) || (done
== count
)) break;
5627 str
= OSDynamicCast( OSString
, table
->getObject( gIOPathMatchKey
));
5630 entry
= IORegistryEntry::fromPath( str
->getCStringNoCopy() );
5631 match
= (this == entry
);
5634 if ((!match
) || (done
== count
)) break;
5637 num
= OSDynamicCast( OSNumber
, table
->getObject( gIORegistryEntryIDKey
));
5640 match
= (getRegistryEntryID() == num
->unsigned64BitValue());
5641 if ((!match
) || (done
== count
)) break;
5644 num
= OSDynamicCast( OSNumber
, table
->getObject( gIOMatchedServiceCountKey
));
5648 IOService
* service
= 0;
5649 UInt32 serviceCount
= 0;
5652 iter
= getClientIterator();
5654 while( (service
= (IOService
*) iter
->getNextObject())) {
5655 if( kIOServiceInactiveState
& service
->__state
[0])
5657 if( 0 == service
->getProperty( gIOMatchCategoryKey
))
5663 match
= (serviceCount
== num
->unsigned32BitValue());
5664 if ((!match
) || (done
== count
)) break;
5667 #define propMatch(key) \
5668 obj = table->getObject(key); \
5673 prop = copyProperty(key); \
5674 match = obj->isEqualTo(prop); \
5675 if (prop) prop->release(); \
5676 if ((!match) || (done == count)) break; \
5678 propMatch(gIOBSDNameKey
)
5679 propMatch(gIOBSDMajorKey
)
5680 propMatch(gIOBSDMinorKey
)
5681 propMatch(gIOBSDUnitKey
)
5686 if (did
) *did
= done
;
5690 bool IOService::passiveMatch( OSDictionary
* table
, bool changesOK
)
5692 return (matchPassive(table
, changesOK
? kIOServiceChangesOK
: 0));
5695 bool IOService::matchPassive(OSDictionary
* table
, uint32_t options
)
5698 OSDictionary
* nextTable
;
5702 bool matchParent
= false;
5708 #if !CONFIG_EMBEDDED
5709 OSArray
* aliasServiceRegIds
= NULL
;
5710 IOService
* foundAlternateService
= NULL
;
5714 OSDictionary
* root
= table
;
5722 count
= table
->getCount();
5723 if (!(kIOServiceInternalDone
& options
))
5725 match
= where
->matchInternal(table
, options
, &done
);
5726 // don't call family if we've done all the entries in the table
5727 if ((!match
) || (done
== count
)) break;
5730 // pass in score from property table
5731 score
= IOServiceObjectOrder( table
, (void *) gIOProbeScoreKey
);
5733 // do family specific matching
5734 match
= where
->matchPropertyTable( table
, &score
);
5738 if( kIOLogMatch
& getDebugFlags( table
))
5739 LOG("%s: family specific matching fails\n", where
->getName());
5744 if (kIOServiceChangesOK
& options
) {
5746 newPri
= OSNumber::withNumber( score
, 32 );
5748 table
->setObject( gIOProbeScoreKey
, newPri
);
5754 matchParent
= false;
5756 nextTable
= OSDynamicCast(OSDictionary
,
5757 table
->getObject( gIOParentMatchKey
));
5759 // look for a matching entry anywhere up to root
5766 table
= OSDynamicCast(OSDictionary
,
5767 table
->getObject( gIOLocationMatchKey
));
5769 // look for a matching entry at matchLocation()
5771 where
= where
->getProvider();
5772 if (where
&& (where
= where
->matchLocation(where
))) continue;
5782 if(matchParent
== true) {
5783 #if !CONFIG_EMBEDDED
5784 // check if service has an alias to search its other "parents" if a parent match isn't found
5785 OSObject
* prop
= where
->copyProperty(gIOServiceLegacyMatchingRegistryIDKey
);
5786 OSNumber
* alternateRegistryID
= OSDynamicCast(OSNumber
, prop
);
5787 if(alternateRegistryID
!= NULL
) {
5788 if(aliasServiceRegIds
== NULL
)
5790 aliasServiceRegIds
= OSArray::withCapacity(sizeof(alternateRegistryID
));
5792 aliasServiceRegIds
->setObject(alternateRegistryID
);
5794 OSSafeReleaseNULL(prop
);
5801 where
= where
->getProvider();
5802 #if !CONFIG_EMBEDDED
5804 // there were no matching parent services, check to see if there are aliased services that have a matching parent
5805 if(aliasServiceRegIds
!= NULL
) {
5806 unsigned int numAliasedServices
= aliasServiceRegIds
->getCount();
5807 if(numAliasedServices
!= 0) {
5808 OSNumber
* alternateRegistryID
= OSDynamicCast(OSNumber
, aliasServiceRegIds
->getObject(numAliasedServices
- 1));
5809 if(alternateRegistryID
!= NULL
) {
5810 OSDictionary
* alternateMatchingDict
= IOService::registryEntryIDMatching(alternateRegistryID
->unsigned64BitValue());
5811 aliasServiceRegIds
->removeObject(numAliasedServices
- 1);
5812 if(alternateMatchingDict
!= NULL
) {
5813 OSSafeReleaseNULL(foundAlternateService
);
5814 foundAlternateService
= IOService::copyMatchingService(alternateMatchingDict
);
5815 alternateMatchingDict
->release();
5816 if(foundAlternateService
!= NULL
) {
5817 where
= foundAlternateService
;
5826 while( where
!= NULL
);
5828 #if !CONFIG_EMBEDDED
5829 OSSafeReleaseNULL(foundAlternateService
);
5830 OSSafeReleaseNULL(aliasServiceRegIds
);
5836 OSSerialize
* s
= OSSerialize::withCapacity(128);
5838 kprintf("parent match 0x%llx, %d,\n%s\n", getRegistryEntryID(), match
, s
->text());
5847 IOReturn
IOService::newUserClient( task_t owningTask
, void * securityID
,
5848 UInt32 type
, OSDictionary
* properties
,
5849 IOUserClient
** handler
)
5851 const OSSymbol
*userClientClass
= 0;
5852 IOUserClient
*client
;
5856 if (kIOReturnSuccess
== newUserClient( owningTask
, securityID
, type
, handler
))
5857 return kIOReturnSuccess
;
5859 // First try my own properties for a user client class name
5860 prop
= copyProperty(gIOUserClientClassKey
);
5862 if (OSDynamicCast(OSSymbol
, prop
))
5863 userClientClass
= (const OSSymbol
*) prop
;
5864 else if (OSDynamicCast(OSString
, prop
)) {
5865 userClientClass
= OSSymbol::withString((OSString
*) prop
);
5866 if (userClientClass
)
5867 setProperty(gIOUserClientClassKey
,
5868 (OSObject
*) userClientClass
);
5872 // Didn't find one so lets just bomb out now without further ado.
5873 if (!userClientClass
)
5875 OSSafeReleaseNULL(prop
);
5876 return kIOReturnUnsupported
;
5879 // This reference is consumed by the IOServiceOpen call
5880 temp
= OSMetaClass::allocClassWithName(userClientClass
);
5881 OSSafeReleaseNULL(prop
);
5883 return kIOReturnNoMemory
;
5885 if (OSDynamicCast(IOUserClient
, temp
))
5886 client
= (IOUserClient
*) temp
;
5889 return kIOReturnUnsupported
;
5892 if ( !client
->initWithTask(owningTask
, securityID
, type
, properties
) ) {
5894 return kIOReturnBadArgument
;
5897 if ( !client
->attach(this) ) {
5899 return kIOReturnUnsupported
;
5902 if ( !client
->start(this) ) {
5903 client
->detach(this);
5905 return kIOReturnUnsupported
;
5909 return kIOReturnSuccess
;
5912 IOReturn
IOService::newUserClient( task_t owningTask
, void * securityID
,
5913 UInt32 type
, IOUserClient
** handler
)
5915 return( kIOReturnUnsupported
);
5918 IOReturn
IOService::requestProbe( IOOptionBits options
)
5920 return( kIOReturnUnsupported
);
5924 * Convert an IOReturn to text. Subclasses which add additional
5925 * IOReturn's should override this method and call
5926 * super::stringFromReturn if the desired value is not found.
5929 const char * IOService::stringFromReturn( IOReturn rtn
)
5931 static const IONamedValue IOReturn_values
[] = {
5932 {kIOReturnSuccess
, "success" },
5933 {kIOReturnError
, "general error" },
5934 {kIOReturnNoMemory
, "memory allocation error" },
5935 {kIOReturnNoResources
, "resource shortage" },
5936 {kIOReturnIPCError
, "Mach IPC failure" },
5937 {kIOReturnNoDevice
, "no such device" },
5938 {kIOReturnNotPrivileged
, "privilege violation" },
5939 {kIOReturnBadArgument
, "invalid argument" },
5940 {kIOReturnLockedRead
, "device is read locked" },
5941 {kIOReturnLockedWrite
, "device is write locked" },
5942 {kIOReturnExclusiveAccess
, "device is exclusive access" },
5943 {kIOReturnBadMessageID
, "bad IPC message ID" },
5944 {kIOReturnUnsupported
, "unsupported function" },
5945 {kIOReturnVMError
, "virtual memory error" },
5946 {kIOReturnInternalError
, "internal driver error" },
5947 {kIOReturnIOError
, "I/O error" },
5948 {kIOReturnCannotLock
, "cannot acquire lock" },
5949 {kIOReturnNotOpen
, "device is not open" },
5950 {kIOReturnNotReadable
, "device is not readable" },
5951 {kIOReturnNotWritable
, "device is not writeable" },
5952 {kIOReturnNotAligned
, "alignment error" },
5953 {kIOReturnBadMedia
, "media error" },
5954 {kIOReturnStillOpen
, "device is still open" },
5955 {kIOReturnRLDError
, "rld failure" },
5956 {kIOReturnDMAError
, "DMA failure" },
5957 {kIOReturnBusy
, "device is busy" },
5958 {kIOReturnTimeout
, "I/O timeout" },
5959 {kIOReturnOffline
, "device is offline" },
5960 {kIOReturnNotReady
, "device is not ready" },
5961 {kIOReturnNotAttached
, "device/channel is not attached" },
5962 {kIOReturnNoChannels
, "no DMA channels available" },
5963 {kIOReturnNoSpace
, "no space for data" },
5964 {kIOReturnPortExists
, "device port already exists" },
5965 {kIOReturnCannotWire
, "cannot wire physical memory" },
5966 {kIOReturnNoInterrupt
, "no interrupt attached" },
5967 {kIOReturnNoFrames
, "no DMA frames enqueued" },
5968 {kIOReturnMessageTooLarge
, "message is too large" },
5969 {kIOReturnNotPermitted
, "operation is not permitted" },
5970 {kIOReturnNoPower
, "device is without power" },
5971 {kIOReturnNoMedia
, "media is not present" },
5972 {kIOReturnUnformattedMedia
, "media is not formatted" },
5973 {kIOReturnUnsupportedMode
, "unsupported mode" },
5974 {kIOReturnUnderrun
, "data underrun" },
5975 {kIOReturnOverrun
, "data overrun" },
5976 {kIOReturnDeviceError
, "device error" },
5977 {kIOReturnNoCompletion
, "no completion routine" },
5978 {kIOReturnAborted
, "operation was aborted" },
5979 {kIOReturnNoBandwidth
, "bus bandwidth would be exceeded" },
5980 {kIOReturnNotResponding
, "device is not responding" },
5981 {kIOReturnInvalid
, "unanticipated driver error" },
5985 return IOFindNameForValue(rtn
, IOReturn_values
);
5989 * Convert an IOReturn to an errno.
5991 int IOService::errnoFromReturn( IOReturn rtn
)
5993 if (unix_err(err_get_code(rtn
)) == rtn
)
5994 return err_get_code(rtn
);
5998 case kIOReturnSuccess
:
6000 case kIOReturnNoMemory
:
6002 case kIOReturnNoDevice
:
6004 case kIOReturnVMError
:
6006 case kIOReturnNotPermitted
:
6008 case kIOReturnNotPrivileged
:
6010 case kIOReturnIOError
:
6012 case kIOReturnNotWritable
:
6014 case kIOReturnBadArgument
:
6016 case kIOReturnUnsupported
:
6020 case kIOReturnNoPower
:
6022 case kIOReturnDeviceError
:
6024 case kIOReturnTimeout
:
6026 case kIOReturnMessageTooLarge
:
6028 case kIOReturnNoSpace
:
6030 case kIOReturnCannotLock
:
6034 case kIOReturnBadMessageID
:
6035 case kIOReturnNoCompletion
:
6036 case kIOReturnNotAligned
:
6038 case kIOReturnNotReady
:
6040 case kIOReturnRLDError
:
6042 case kIOReturnPortExists
:
6043 case kIOReturnStillOpen
:
6045 case kIOReturnExclusiveAccess
:
6046 case kIOReturnLockedRead
:
6047 case kIOReturnLockedWrite
:
6048 case kIOReturnNotOpen
:
6049 case kIOReturnNotReadable
:
6051 case kIOReturnCannotWire
:
6052 case kIOReturnNoResources
:
6054 case kIOReturnAborted
:
6055 case kIOReturnOffline
:
6056 case kIOReturnNotResponding
:
6058 case kIOReturnBadMedia
:
6059 case kIOReturnNoMedia
:
6060 case kIOReturnNotAttached
:
6061 case kIOReturnUnformattedMedia
:
6062 return(ENXIO
); // (media error)
6063 case kIOReturnDMAError
:
6064 case kIOReturnOverrun
:
6065 case kIOReturnUnderrun
:
6066 return(EIO
); // (transfer error)
6067 case kIOReturnNoBandwidth
:
6068 case kIOReturnNoChannels
:
6069 case kIOReturnNoFrames
:
6070 case kIOReturnNoInterrupt
:
6071 return(EIO
); // (hardware error)
6072 case kIOReturnError
:
6073 case kIOReturnInternalError
:
6074 case kIOReturnInvalid
:
6075 return(EIO
); // (generic error)
6076 case kIOReturnIPCError
:
6077 return(EIO
); // (ipc error)
6079 return(EIO
); // (all other errors)
6083 IOReturn
IOService::message( UInt32 type
, IOService
* provider
,
6087 * Generic entry point for calls from the provider. A return value of
6088 * kIOReturnSuccess indicates that the message was received, and where
6089 * applicable, that it was successful.
6092 return kIOReturnUnsupported
;
6099 IOItemCount
IOService::getDeviceMemoryCount( void )
6104 array
= OSDynamicCast( OSArray
, getProperty( gIODeviceMemoryKey
));
6106 count
= array
->getCount();
6113 IODeviceMemory
* IOService::getDeviceMemoryWithIndex( unsigned int index
)
6116 IODeviceMemory
* range
;
6118 array
= OSDynamicCast( OSArray
, getProperty( gIODeviceMemoryKey
));
6120 range
= (IODeviceMemory
*) array
->getObject( index
);
6127 IOMemoryMap
* IOService::mapDeviceMemoryWithIndex( unsigned int index
,
6128 IOOptionBits options
)
6130 IODeviceMemory
* range
;
6133 range
= getDeviceMemoryWithIndex( index
);
6135 map
= range
->map( options
);
6142 OSArray
* IOService::getDeviceMemory( void )
6144 return( OSDynamicCast( OSArray
, getProperty( gIODeviceMemoryKey
)));
6148 void IOService::setDeviceMemory( OSArray
* array
)
6150 setProperty( gIODeviceMemoryKey
, array
);
6154 * For machines where the transfers on an I/O bus can stall because
6155 * the CPU is in an idle mode, These APIs allow a driver to specify
6156 * the maximum bus stall that they can handle. 0 indicates no limit.
6159 setCPUSnoopDelay(UInt32 __unused ns
)
6161 #if defined(__i386__) || defined(__x86_64__)
6162 ml_set_maxsnoop(ns
);
6163 #endif /* defined(__i386__) || defined(__x86_64__) */
6169 #if defined(__i386__) || defined(__x86_64__)
6170 return ml_get_maxsnoop();
6173 #endif /* defined(__i386__) || defined(__x86_64__) */
6176 #if defined(__i386__) || defined(__x86_64__)
6178 requireMaxCpuDelay(IOService
* service
, UInt32 ns
, UInt32 delayType
)
6180 static const UInt kNoReplace
= -1U; // Must be an illegal index
6181 UInt replace
= kNoReplace
;
6182 bool setCpuDelay
= false;
6184 IORecursiveLockLock(sCpuDelayLock
);
6186 UInt count
= sCpuDelayData
->getLength() / sizeof(CpuDelayEntry
);
6187 CpuDelayEntry
*entries
= (CpuDelayEntry
*) sCpuDelayData
->getBytesNoCopy();
6188 IOService
* holder
= NULL
;
6191 const CpuDelayEntry ne
= {service
, ns
, delayType
};
6193 // Set maximum delay.
6194 for (UInt i
= 0; i
< count
; i
++) {
6195 IOService
*thisService
= entries
[i
].fService
;
6196 bool sameType
= (delayType
== entries
[i
].fDelayType
);
6197 if ((service
== thisService
) && sameType
)
6199 else if (!thisService
) {
6200 if (kNoReplace
== replace
)
6203 else if (sameType
) {
6204 const UInt32 thisMax
= entries
[i
].fMaxDelay
;
6208 holder
= thisService
;
6214 if (kNoReplace
== replace
)
6215 sCpuDelayData
->appendBytes(&ne
, sizeof(ne
));
6217 entries
[replace
] = ne
;
6220 ns
= -1U; // Set to max unsigned, i.e. no restriction
6222 for (UInt i
= 0; i
< count
; i
++) {
6223 // Clear a maximum delay.
6224 IOService
*thisService
= entries
[i
].fService
;
6225 if (thisService
&& (delayType
== entries
[i
].fDelayType
)) {
6226 UInt32 thisMax
= entries
[i
].fMaxDelay
;
6227 if (service
== thisService
)
6229 else if (thisMax
< ns
) {
6231 holder
= thisService
;
6236 // Check if entry found
6237 if (kNoReplace
!= replace
) {
6238 entries
[replace
].fService
= 0; // Null the entry
6245 if (holder
&& debug_boot_arg
) {
6246 strlcpy(sCPULatencyHolderName
[delayType
], holder
->getName(), sizeof(sCPULatencyHolderName
[delayType
]));
6249 // Must be safe to call from locked context
6250 if (delayType
== kCpuDelayBusStall
)
6252 ml_set_maxbusdelay(ns
);
6254 else if (delayType
== kCpuDelayInterrupt
)
6256 ml_set_maxintdelay(ns
);
6258 sCPULatencyHolder
[delayType
]->setValue(holder
? holder
->getRegistryEntryID() : 0);
6259 sCPULatencySet
[delayType
]->setValue(ns
);
6261 OSArray
* handlers
= sCpuLatencyHandlers
[delayType
];
6263 if (handlers
) for (unsigned int idx
= 0;
6264 (target
= (IOService
*) handlers
->getObject(idx
));
6267 target
->callPlatformFunction(sCPULatencyFunctionName
[delayType
], false,
6268 (void *) (uintptr_t) ns
, holder
,
6273 IORecursiveLockUnlock(sCpuDelayLock
);
6277 setLatencyHandler(UInt32 delayType
, IOService
* target
, bool enable
)
6279 IOReturn result
= kIOReturnNotFound
;
6283 IORecursiveLockLock(sCpuDelayLock
);
6287 if (enable
&& !sCpuLatencyHandlers
[delayType
])
6288 sCpuLatencyHandlers
[delayType
] = OSArray::withCapacity(4);
6289 array
= sCpuLatencyHandlers
[delayType
];
6292 idx
= array
->getNextIndexOfObject(target
, 0);
6297 array
->removeObject(idx
);
6298 result
= kIOReturnSuccess
;
6304 result
= kIOReturnExclusiveAccess
;
6307 array
->setObject(target
);
6309 UInt count
= sCpuDelayData
->getLength() / sizeof(CpuDelayEntry
);
6310 CpuDelayEntry
*entries
= (CpuDelayEntry
*) sCpuDelayData
->getBytesNoCopy();
6311 UInt32 ns
= -1U; // Set to max unsigned, i.e. no restriction
6312 IOService
* holder
= NULL
;
6314 for (UInt i
= 0; i
< count
; i
++) {
6315 if (entries
[i
].fService
6316 && (delayType
== entries
[i
].fDelayType
)
6317 && (entries
[i
].fMaxDelay
< ns
)) {
6318 ns
= entries
[i
].fMaxDelay
;
6319 holder
= entries
[i
].fService
;
6322 target
->callPlatformFunction(sCPULatencyFunctionName
[delayType
], false,
6323 (void *) (uintptr_t) ns
, holder
,
6325 result
= kIOReturnSuccess
;
6330 IORecursiveLockUnlock(sCpuDelayLock
);
6335 #endif /* defined(__i386__) || defined(__x86_64__) */
6338 requireMaxBusStall(UInt32 __unused ns
)
6340 #if defined(__i386__) || defined(__x86_64__)
6341 requireMaxCpuDelay(this, ns
, kCpuDelayBusStall
);
6346 requireMaxInterruptDelay(uint32_t __unused ns
)
6348 #if defined(__i386__) || defined(__x86_64__)
6349 requireMaxCpuDelay(this, ns
, kCpuDelayInterrupt
);
6357 IOReturn
IOService::resolveInterrupt(IOService
*nub
, int source
)
6359 IOInterruptController
*interruptController
;
6362 OSSymbol
*interruptControllerName
;
6364 IOInterruptSource
*interruptSources
;
6366 // Get the parents list from the nub.
6367 array
= OSDynamicCast(OSArray
, nub
->getProperty(gIOInterruptControllersKey
));
6368 if (array
== 0) return kIOReturnNoResources
;
6370 // Allocate space for the IOInterruptSources if needed... then return early.
6371 if (nub
->_interruptSources
== 0) {
6372 numSources
= array
->getCount();
6373 interruptSources
= (IOInterruptSource
*)IOMalloc(
6374 numSources
* sizeofAllIOInterruptSource
);
6375 if (interruptSources
== 0) return kIOReturnNoMemory
;
6377 bzero(interruptSources
, numSources
* sizeofAllIOInterruptSource
);
6379 nub
->_numInterruptSources
= numSources
;
6380 nub
->_interruptSources
= interruptSources
;
6381 return kIOReturnSuccess
;
6384 interruptControllerName
= OSDynamicCast(OSSymbol
,array
->getObject(source
));
6385 if (interruptControllerName
== 0) return kIOReturnNoResources
;
6387 interruptController
= getPlatform()->lookUpInterruptController(interruptControllerName
);
6388 if (interruptController
== 0) return kIOReturnNoResources
;
6390 // Get the interrupt numbers from the nub.
6391 array
= OSDynamicCast(OSArray
, nub
->getProperty(gIOInterruptSpecifiersKey
));
6392 if (array
== 0) return kIOReturnNoResources
;
6393 data
= OSDynamicCast(OSData
, array
->getObject(source
));
6394 if (data
== 0) return kIOReturnNoResources
;
6396 // Set the interruptController and interruptSource in the nub's table.
6397 interruptSources
= nub
->_interruptSources
;
6398 interruptSources
[source
].interruptController
= interruptController
;
6399 interruptSources
[source
].vectorData
= data
;
6401 return kIOReturnSuccess
;
6404 IOReturn
IOService::lookupInterrupt(int source
, bool resolve
, IOInterruptController
**interruptController
)
6408 /* Make sure the _interruptSources are set */
6409 if (_interruptSources
== 0) {
6410 ret
= resolveInterrupt(this, source
);
6411 if (ret
!= kIOReturnSuccess
) return ret
;
6414 /* Make sure the local source number is valid */
6415 if ((source
< 0) || (source
>= _numInterruptSources
))
6416 return kIOReturnNoInterrupt
;
6418 /* Look up the contoller for the local source */
6419 *interruptController
= _interruptSources
[source
].interruptController
;
6421 if (*interruptController
== NULL
) {
6422 if (!resolve
) return kIOReturnNoInterrupt
;
6424 /* Try to resolve the interrupt */
6425 ret
= resolveInterrupt(this, source
);
6426 if (ret
!= kIOReturnSuccess
) return ret
;
6428 *interruptController
= _interruptSources
[source
].interruptController
;
6431 return kIOReturnSuccess
;
6434 IOReturn
IOService::registerInterrupt(int source
, OSObject
*target
,
6435 IOInterruptAction handler
,
6438 IOInterruptController
*interruptController
;
6441 ret
= lookupInterrupt(source
, true, &interruptController
);
6442 if (ret
!= kIOReturnSuccess
) return ret
;
6444 /* Register the source */
6445 return interruptController
->registerInterrupt(this, source
, target
,
6446 (IOInterruptHandler
)handler
,
6450 static void IOServiceInterruptActionToBlock( OSObject
* target
, void * refCon
,
6451 IOService
* nub
, int source
)
6453 ((IOInterruptActionBlock
)(refCon
))(nub
, source
);
6456 IOReturn
IOService::registerInterruptBlock(int source
, OSObject
*target
,
6457 IOInterruptActionBlock handler
)
6462 block
= Block_copy(handler
);
6463 if (!block
) return (kIOReturnNoMemory
);
6465 ret
= registerInterrupt(source
, target
, &IOServiceInterruptActionToBlock
, block
);
6466 if (kIOReturnSuccess
!= ret
) {
6467 Block_release(block
);
6470 _interruptSourcesPrivate(this)[source
].vectorBlock
= block
;
6475 IOReturn
IOService::unregisterInterrupt(int source
)
6478 IOInterruptController
*interruptController
;
6481 ret
= lookupInterrupt(source
, false, &interruptController
);
6482 if (ret
!= kIOReturnSuccess
) return ret
;
6484 /* Unregister the source */
6485 block
= _interruptSourcesPrivate(this)[source
].vectorBlock
;
6486 ret
= interruptController
->unregisterInterrupt(this, source
);
6487 if ((kIOReturnSuccess
== ret
) && (block
= _interruptSourcesPrivate(this)[source
].vectorBlock
)) {
6488 _interruptSourcesPrivate(this)[source
].vectorBlock
= NULL
;
6489 Block_release(block
);
6495 IOReturn
IOService::addInterruptStatistics(IOInterruptAccountingData
* statistics
, int source
)
6497 IOReportLegend
* legend
= NULL
;
6498 IOInterruptAccountingData
* oldValue
= NULL
;
6499 IOInterruptAccountingReporter
* newArray
= NULL
;
6500 char subgroupName
[64];
6501 int newArraySize
= 0;
6505 return kIOReturnBadArgument
;
6509 * We support statistics on a maximum of 256 interrupts per nub; if a nub
6510 * has more than 256 interrupt specifiers associated with it, and tries
6511 * to register a high interrupt index with interrupt accounting, panic.
6512 * Having more than 256 interrupts associated with a single nub is
6513 * probably a sign that something fishy is going on.
6515 if (source
> IA_INDEX_MAX
) {
6516 panic("addInterruptStatistics called for an excessively large index (%d)", source
);
6520 * TODO: This is ugly (wrapping a lock around an allocation). I'm only
6521 * leaving it as is because the likelihood of contention where we are
6522 * actually growing the array is minimal (we would realistically need
6523 * to be starting a driver for the first time, with an IOReporting
6524 * client already in place). Nonetheless, cleanup that can be done
6525 * to adhere to best practices; it'll make the code more complicated,
6528 IOLockLock(reserved
->interruptStatisticsLock
);
6531 * Lazily allocate the statistics array.
6533 if (!reserved
->interruptStatisticsArray
) {
6534 reserved
->interruptStatisticsArray
= IONew(IOInterruptAccountingReporter
, 1);
6535 assert(reserved
->interruptStatisticsArray
);
6536 reserved
->interruptStatisticsArrayCount
= 1;
6537 bzero(reserved
->interruptStatisticsArray
, sizeof(*reserved
->interruptStatisticsArray
));
6540 if (source
>= reserved
->interruptStatisticsArrayCount
) {
6542 * We're still within the range of supported indices, but we are out
6543 * of space in the current array. Do a nasty realloc (because
6544 * IORealloc isn't a thing) here. We'll double the size with each
6547 * Yes, the "next power of 2" could be more efficient; but this will
6548 * be invoked incredibly rarely. Who cares.
6550 newArraySize
= (reserved
->interruptStatisticsArrayCount
<< 1);
6552 while (newArraySize
<= source
)
6553 newArraySize
= (newArraySize
<< 1);
6554 newArray
= IONew(IOInterruptAccountingReporter
, newArraySize
);
6559 * TODO: This even zeroes the memory it is about to overwrite.
6560 * Shameful; fix it. Not particularly high impact, however.
6562 bzero(newArray
, newArraySize
* sizeof(*newArray
));
6563 memcpy(newArray
, reserved
->interruptStatisticsArray
, reserved
->interruptStatisticsArrayCount
* sizeof(*newArray
));
6564 IODelete(reserved
->interruptStatisticsArray
, IOInterruptAccountingReporter
, reserved
->interruptStatisticsArrayCount
);
6565 reserved
->interruptStatisticsArray
= newArray
;
6566 reserved
->interruptStatisticsArrayCount
= newArraySize
;
6569 if (!reserved
->interruptStatisticsArray
[source
].reporter
) {
6571 * We don't have a reporter associated with this index yet, so we
6572 * need to create one.
6575 * TODO: Some statistics do in fact have common units (time); should this be
6576 * split into separate reporters to communicate this?
6578 reserved
->interruptStatisticsArray
[source
].reporter
= IOSimpleReporter::with(this, kIOReportCategoryPower
, kIOReportUnitNone
);
6581 * Each statistic is given an identifier based on the interrupt index (which
6582 * should be unique relative to any single nub) and the statistic involved.
6583 * We should now have a sane (small and positive) index, so start
6584 * constructing the channels for statistics.
6586 for (i
= 0; i
< IA_NUM_INTERRUPT_ACCOUNTING_STATISTICS
; i
++) {
6588 * TODO: Currently, this does not add channels for disabled statistics.
6589 * Will this be confusing for clients? If so, we should just add the
6590 * channels; we can avoid updating the channels even if they exist.
6592 if (IA_GET_STATISTIC_ENABLED(i
))
6593 reserved
->interruptStatisticsArray
[source
].reporter
->addChannel(IA_GET_CHANNEL_ID(source
, i
), kInterruptAccountingStatisticNameArray
[i
]);
6597 * We now need to add the legend for this reporter to the registry.
6599 OSObject
* prop
= copyProperty(kIOReportLegendKey
);
6600 legend
= IOReportLegend::with(OSDynamicCast(OSArray
, prop
));
6601 OSSafeReleaseNULL(prop
);
6604 * Note that while we compose the subgroup name, we do not need to
6605 * manage its lifecycle (the reporter will handle this).
6607 snprintf(subgroupName
, sizeof(subgroupName
), "%s %d", getName(), source
);
6608 subgroupName
[sizeof(subgroupName
) - 1] = 0;
6609 legend
->addReporterLegend(reserved
->interruptStatisticsArray
[source
].reporter
, kInterruptAccountingGroupName
, subgroupName
);
6610 setProperty(kIOReportLegendKey
, legend
->getLegend());
6614 * TODO: Is this a good idea? Probably not; my assumption is it opts
6615 * all entities who register interrupts into public disclosure of all
6616 * IOReporting channels. Unfortunately, this appears to be as fine
6619 setProperty(kIOReportLegendPublicKey
, true);
6623 * Don't stomp existing entries. If we are about to, panic; this
6624 * probably means we failed to tear down our old interrupt source
6627 oldValue
= reserved
->interruptStatisticsArray
[source
].statistics
;
6630 panic("addInterruptStatistics call for index %d would have clobbered existing statistics", source
);
6633 reserved
->interruptStatisticsArray
[source
].statistics
= statistics
;
6636 * Inherit the reporter values for each statistic. The target may
6637 * be torn down as part of the runtime of the service (especially
6638 * for sleep/wake), so we inherit in order to avoid having values
6639 * reset for no apparent reason. Our statistics are ultimately
6640 * tied to the index and the sevice, not to an individual target,
6641 * so we should maintain them accordingly.
6643 interruptAccountingDataInheritChannels(reserved
->interruptStatisticsArray
[source
].statistics
, reserved
->interruptStatisticsArray
[source
].reporter
);
6645 IOLockUnlock(reserved
->interruptStatisticsLock
);
6647 return kIOReturnSuccess
;
6650 IOReturn
IOService::removeInterruptStatistics(int source
)
6652 IOInterruptAccountingData
* value
= NULL
;
6655 return kIOReturnBadArgument
;
6658 IOLockLock(reserved
->interruptStatisticsLock
);
6661 * We dynamically grow the statistics array, so an excessively
6662 * large index value has NEVER been registered. This either
6663 * means our cap on the array size is too small (unlikely), or
6664 * that we have been passed a corrupt index (this must be passed
6665 * the plain index into the interrupt specifier list).
6667 if (source
>= reserved
->interruptStatisticsArrayCount
) {
6668 panic("removeInterruptStatistics called for index %d, which was never registered", source
);
6671 assert(reserved
->interruptStatisticsArray
);
6674 * If there is no existing entry, we are most likely trying to
6675 * free an interrupt owner twice, or we have corrupted the
6678 value
= reserved
->interruptStatisticsArray
[source
].statistics
;
6681 panic("removeInterruptStatistics called for empty index %d", source
);
6685 * We update the statistics, so that any delta with the reporter
6686 * state is not lost.
6688 interruptAccountingDataUpdateChannels(reserved
->interruptStatisticsArray
[source
].statistics
, reserved
->interruptStatisticsArray
[source
].reporter
);
6689 reserved
->interruptStatisticsArray
[source
].statistics
= NULL
;
6690 IOLockUnlock(reserved
->interruptStatisticsLock
);
6692 return kIOReturnSuccess
;
6695 IOReturn
IOService::getInterruptType(int source
, int *interruptType
)
6697 IOInterruptController
*interruptController
;
6700 ret
= lookupInterrupt(source
, true, &interruptController
);
6701 if (ret
!= kIOReturnSuccess
) return ret
;
6703 /* Return the type */
6704 return interruptController
->getInterruptType(this, source
, interruptType
);
6707 IOReturn
IOService::enableInterrupt(int source
)
6709 IOInterruptController
*interruptController
;
6712 ret
= lookupInterrupt(source
, false, &interruptController
);
6713 if (ret
!= kIOReturnSuccess
) return ret
;
6715 /* Enable the source */
6716 return interruptController
->enableInterrupt(this, source
);
6719 IOReturn
IOService::disableInterrupt(int source
)
6721 IOInterruptController
*interruptController
;
6724 ret
= lookupInterrupt(source
, false, &interruptController
);
6725 if (ret
!= kIOReturnSuccess
) return ret
;
6727 /* Disable the source */
6728 return interruptController
->disableInterrupt(this, source
);
6731 IOReturn
IOService::causeInterrupt(int source
)
6733 IOInterruptController
*interruptController
;
6736 ret
= lookupInterrupt(source
, false, &interruptController
);
6737 if (ret
!= kIOReturnSuccess
) return ret
;
6739 /* Cause an interrupt for the source */
6740 return interruptController
->causeInterrupt(this, source
);
6743 IOReturn
IOService::configureReport(IOReportChannelList
*channelList
,
6744 IOReportConfigureAction action
,
6750 for (cnt
= 0; cnt
< channelList
->nchannels
; cnt
++) {
6751 if ( channelList
->channels
[cnt
].channel_id
== kPMPowerStatesChID
) {
6752 if (pwrMgt
) configurePowerStatesReport(action
, result
);
6753 else return kIOReturnUnsupported
;
6755 else if ( channelList
->channels
[cnt
].channel_id
== kPMCurrStateChID
) {
6756 if (pwrMgt
) configureSimplePowerReport(action
, result
);
6757 else return kIOReturnUnsupported
;
6761 IOLockLock(reserved
->interruptStatisticsLock
);
6763 /* The array count is signed (because the interrupt indices are signed), hence the cast */
6764 for (cnt
= 0; cnt
< (unsigned) reserved
->interruptStatisticsArrayCount
; cnt
++) {
6765 if (reserved
->interruptStatisticsArray
[cnt
].reporter
) {
6767 * If the reporter is currently associated with the statistics
6768 * for an event source, we may need to update the reporter.
6770 if (reserved
->interruptStatisticsArray
[cnt
].statistics
)
6771 interruptAccountingDataUpdateChannels(reserved
->interruptStatisticsArray
[cnt
].statistics
, reserved
->interruptStatisticsArray
[cnt
].reporter
);
6773 reserved
->interruptStatisticsArray
[cnt
].reporter
->configureReport(channelList
, action
, result
, destination
);
6777 IOLockUnlock(reserved
->interruptStatisticsLock
);
6779 return kIOReturnSuccess
;
6782 IOReturn
IOService::updateReport(IOReportChannelList
*channelList
,
6783 IOReportUpdateAction action
,
6789 for (cnt
= 0; cnt
< channelList
->nchannels
; cnt
++) {
6790 if ( channelList
->channels
[cnt
].channel_id
== kPMPowerStatesChID
) {
6791 if (pwrMgt
) updatePowerStatesReport(action
, result
, destination
);
6792 else return kIOReturnUnsupported
;
6794 else if ( channelList
->channels
[cnt
].channel_id
== kPMCurrStateChID
) {
6795 if (pwrMgt
) updateSimplePowerReport(action
, result
, destination
);
6796 else return kIOReturnUnsupported
;
6800 IOLockLock(reserved
->interruptStatisticsLock
);
6802 /* The array count is signed (because the interrupt indices are signed), hence the cast */
6803 for (cnt
= 0; cnt
< (unsigned) reserved
->interruptStatisticsArrayCount
; cnt
++) {
6804 if (reserved
->interruptStatisticsArray
[cnt
].reporter
) {
6806 * If the reporter is currently associated with the statistics
6807 * for an event source, we need to update the reporter.
6809 if (reserved
->interruptStatisticsArray
[cnt
].statistics
)
6810 interruptAccountingDataUpdateChannels(reserved
->interruptStatisticsArray
[cnt
].statistics
, reserved
->interruptStatisticsArray
[cnt
].reporter
);
6812 reserved
->interruptStatisticsArray
[cnt
].reporter
->updateReport(channelList
, action
, result
, destination
);
6816 IOLockUnlock(reserved
->interruptStatisticsLock
);
6818 return kIOReturnSuccess
;
6821 uint64_t IOService::getAuthorizationID( void )
6823 return reserved
->authorizationID
;
6826 IOReturn
IOService::setAuthorizationID( uint64_t authorizationID
)
6828 OSObject
* entitlement
;
6831 entitlement
= IOUserClient::copyClientEntitlement( current_task( ), "com.apple.private.iokit.IOServiceSetAuthorizationID" );
6835 if ( entitlement
== kOSBooleanTrue
)
6837 reserved
->authorizationID
= authorizationID
;
6839 status
= kIOReturnSuccess
;
6843 status
= kIOReturnNotPrivileged
;
6846 entitlement
->release( );
6850 status
= kIOReturnNotPrivileged
;
6857 OSMetaClassDefineReservedUsed(IOService
, 0);
6858 OSMetaClassDefineReservedUsed(IOService
, 1);
6859 OSMetaClassDefineReservedUnused(IOService
, 2);
6860 OSMetaClassDefineReservedUnused(IOService
, 3);
6861 OSMetaClassDefineReservedUnused(IOService
, 4);
6862 OSMetaClassDefineReservedUnused(IOService
, 5);
6863 OSMetaClassDefineReservedUnused(IOService
, 6);
6864 OSMetaClassDefineReservedUnused(IOService
, 7);
6866 OSMetaClassDefineReservedUsed(IOService
, 0);
6867 OSMetaClassDefineReservedUsed(IOService
, 1);
6868 OSMetaClassDefineReservedUsed(IOService
, 2);
6869 OSMetaClassDefineReservedUsed(IOService
, 3);
6870 OSMetaClassDefineReservedUsed(IOService
, 4);
6871 OSMetaClassDefineReservedUsed(IOService
, 5);
6872 OSMetaClassDefineReservedUsed(IOService
, 6);
6873 OSMetaClassDefineReservedUsed(IOService
, 7);
6875 OSMetaClassDefineReservedUnused(IOService
, 8);
6876 OSMetaClassDefineReservedUnused(IOService
, 9);
6877 OSMetaClassDefineReservedUnused(IOService
, 10);
6878 OSMetaClassDefineReservedUnused(IOService
, 11);
6879 OSMetaClassDefineReservedUnused(IOService
, 12);
6880 OSMetaClassDefineReservedUnused(IOService
, 13);
6881 OSMetaClassDefineReservedUnused(IOService
, 14);
6882 OSMetaClassDefineReservedUnused(IOService
, 15);
6883 OSMetaClassDefineReservedUnused(IOService
, 16);
6884 OSMetaClassDefineReservedUnused(IOService
, 17);
6885 OSMetaClassDefineReservedUnused(IOService
, 18);
6886 OSMetaClassDefineReservedUnused(IOService
, 19);
6887 OSMetaClassDefineReservedUnused(IOService
, 20);
6888 OSMetaClassDefineReservedUnused(IOService
, 21);
6889 OSMetaClassDefineReservedUnused(IOService
, 22);
6890 OSMetaClassDefineReservedUnused(IOService
, 23);
6891 OSMetaClassDefineReservedUnused(IOService
, 24);
6892 OSMetaClassDefineReservedUnused(IOService
, 25);
6893 OSMetaClassDefineReservedUnused(IOService
, 26);
6894 OSMetaClassDefineReservedUnused(IOService
, 27);
6895 OSMetaClassDefineReservedUnused(IOService
, 28);
6896 OSMetaClassDefineReservedUnused(IOService
, 29);
6897 OSMetaClassDefineReservedUnused(IOService
, 30);
6898 OSMetaClassDefineReservedUnused(IOService
, 31);
6899 OSMetaClassDefineReservedUnused(IOService
, 32);
6900 OSMetaClassDefineReservedUnused(IOService
, 33);
6901 OSMetaClassDefineReservedUnused(IOService
, 34);
6902 OSMetaClassDefineReservedUnused(IOService
, 35);
6903 OSMetaClassDefineReservedUnused(IOService
, 36);
6904 OSMetaClassDefineReservedUnused(IOService
, 37);
6905 OSMetaClassDefineReservedUnused(IOService
, 38);
6906 OSMetaClassDefineReservedUnused(IOService
, 39);
6907 OSMetaClassDefineReservedUnused(IOService
, 40);
6908 OSMetaClassDefineReservedUnused(IOService
, 41);
6909 OSMetaClassDefineReservedUnused(IOService
, 42);
6910 OSMetaClassDefineReservedUnused(IOService
, 43);
6911 OSMetaClassDefineReservedUnused(IOService
, 44);
6912 OSMetaClassDefineReservedUnused(IOService
, 45);
6913 OSMetaClassDefineReservedUnused(IOService
, 46);
6914 OSMetaClassDefineReservedUnused(IOService
, 47);