2 * Copyright (c) 1998-2014 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 <IOKit/IOCatalogue.h>
37 #include <IOKit/IOCommand.h>
38 #include <IOKit/IODeviceTreeSupport.h>
39 #include <IOKit/IODeviceMemory.h>
40 #include <IOKit/IOInterrupts.h>
41 #include <IOKit/IOInterruptController.h>
42 #include <IOKit/IOPlatformExpert.h>
43 #include <IOKit/IOMessage.h>
44 #include <IOKit/IOLib.h>
45 #include <IOKit/IOKitKeysPrivate.h>
46 #include <IOKit/IOBSD.h>
47 #include <IOKit/IOUserClient.h>
48 #include <IOKit/IOWorkLoop.h>
49 #include <IOKit/IOTimeStamp.h>
50 #include <IOKit/IOHibernatePrivate.h>
51 #include <IOKit/IOInterruptAccountingPrivate.h>
52 #include <IOKit/IOKernelReporters.h>
53 #include <mach/sync_policy.h>
54 #include <IOKit/assert.h>
55 #include <sys/errno.h>
57 #include <machine/pal_routines.h>
62 #define OBFUSCATE(x) ((void *)(VM_KERNEL_ADDRPERM(x)))
64 #include "IOServicePrivate.h"
65 #include "IOKitKernelInternal.h"
67 // take lockForArbitration before LOCKNOTIFY
69 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
71 #define super IORegistryEntry
73 OSDefineMetaClassAndStructors(IOService
, IORegistryEntry
)
75 OSDefineMetaClassAndStructors(_IOServiceNotifier
, IONotifier
)
77 OSDefineMetaClassAndStructors(_IOServiceInterestNotifier
, IONotifier
)
79 OSDefineMetaClassAndStructors(_IOConfigThread
, OSObject
)
81 OSDefineMetaClassAndStructors(_IOServiceJob
, OSObject
)
83 OSDefineMetaClassAndStructors(IOResources
, IOService
)
85 OSDefineMetaClassAndStructors(_IOOpenServiceIterator
, OSIterator
)
87 OSDefineMetaClassAndAbstractStructors(IONotifier
, OSObject
)
89 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
91 static IOPlatformExpert
* gIOPlatform
;
92 static class IOPMrootDomain
* gIOPMRootDomain
;
93 const IORegistryPlane
* gIOServicePlane
;
94 const IORegistryPlane
* gIOPowerPlane
;
95 const OSSymbol
* gIODeviceMemoryKey
;
96 const OSSymbol
* gIOInterruptControllersKey
;
97 const OSSymbol
* gIOInterruptSpecifiersKey
;
99 const OSSymbol
* gIOResourcesKey
;
100 const OSSymbol
* gIOResourceMatchKey
;
101 const OSSymbol
* gIOProviderClassKey
;
102 const OSSymbol
* gIONameMatchKey
;
103 const OSSymbol
* gIONameMatchedKey
;
104 const OSSymbol
* gIOPropertyMatchKey
;
105 const OSSymbol
* gIOLocationMatchKey
;
106 const OSSymbol
* gIOParentMatchKey
;
107 const OSSymbol
* gIOPathMatchKey
;
108 const OSSymbol
* gIOMatchCategoryKey
;
109 const OSSymbol
* gIODefaultMatchCategoryKey
;
110 const OSSymbol
* gIOMatchedServiceCountKey
;
112 const OSSymbol
* gIOMapperIDKey
;
113 const OSSymbol
* gIOUserClientClassKey
;
114 const OSSymbol
* gIOKitDebugKey
;
116 const OSSymbol
* gIOCommandPoolSizeKey
;
118 const OSSymbol
* gIOConsoleLockedKey
;
119 const OSSymbol
* gIOConsoleUsersKey
;
120 const OSSymbol
* gIOConsoleSessionUIDKey
;
121 const OSSymbol
* gIOConsoleSessionAuditIDKey
;
122 const OSSymbol
* gIOConsoleUsersSeedKey
;
123 const OSSymbol
* gIOConsoleSessionOnConsoleKey
;
124 const OSSymbol
* gIOConsoleSessionLoginDoneKey
;
125 const OSSymbol
* gIOConsoleSessionSecureInputPIDKey
;
126 const OSSymbol
* gIOConsoleSessionScreenLockedTimeKey
;
128 clock_sec_t gIOConsoleLockTime
;
129 static bool gIOConsoleLoggedIn
;
131 static uint32_t gIOScreenLockState
;
133 static IORegistryEntry
* gIOChosenEntry
;
135 static int gIOResourceGenerationCount
;
137 const OSSymbol
* gIOServiceKey
;
138 const OSSymbol
* gIOPublishNotification
;
139 const OSSymbol
* gIOFirstPublishNotification
;
140 const OSSymbol
* gIOMatchedNotification
;
141 const OSSymbol
* gIOFirstMatchNotification
;
142 const OSSymbol
* gIOTerminatedNotification
;
144 const OSSymbol
* gIOGeneralInterest
;
145 const OSSymbol
* gIOBusyInterest
;
146 const OSSymbol
* gIOAppPowerStateInterest
;
147 const OSSymbol
* gIOPriorityPowerStateInterest
;
148 const OSSymbol
* gIOConsoleSecurityInterest
;
150 static OSDictionary
* gNotifications
;
151 static IORecursiveLock
* gNotificationLock
;
153 static IOService
* gIOResources
;
154 static IOService
* gIOServiceRoot
;
156 static OSOrderedSet
* gJobs
;
157 static semaphore_port_t gJobsSemaphore
;
158 static IOLock
* gJobsLock
;
159 static int gOutstandingJobs
;
160 static int gNumConfigThreads
;
161 static int gNumWaitingThreads
;
162 static IOLock
* gIOServiceBusyLock
;
164 static thread_t gIOTerminateThread
;
165 static UInt32 gIOTerminateWork
;
166 static OSArray
* gIOTerminatePhase2List
;
167 static OSArray
* gIOStopList
;
168 static OSArray
* gIOStopProviderList
;
169 static OSArray
* gIOFinalizeList
;
171 static SInt32 gIOConsoleUsersSeed
;
172 static OSData
* gIOConsoleUsersSeedValue
;
174 extern const OSSymbol
* gIODTPHandleKey
;
176 const OSSymbol
* gIOPlatformSleepActionKey
;
177 const OSSymbol
* gIOPlatformWakeActionKey
;
178 const OSSymbol
* gIOPlatformQuiesceActionKey
;
179 const OSSymbol
* gIOPlatformActiveActionKey
;
180 const OSSymbol
* gIOPlatformHaltRestartActionKey
;
182 const OSSymbol
* gIOPlatformFunctionHandlerSet
;
184 static IOLock
* gIOConsoleUsersLock
;
185 static thread_call_t gIOConsoleLockCallout
;
187 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
189 #define LOCKREADNOTIFY() \
190 IORecursiveLockLock( gNotificationLock )
191 #define LOCKWRITENOTIFY() \
192 IORecursiveLockLock( gNotificationLock )
193 #define LOCKWRITE2READNOTIFY()
194 #define UNLOCKNOTIFY() \
195 IORecursiveLockUnlock( gNotificationLock )
196 #define SLEEPNOTIFY(event) \
197 IORecursiveLockSleep( gNotificationLock, (void *)(event), THREAD_UNINT )
198 #define SLEEPNOTIFYTO(event, deadline) \
199 IORecursiveLockSleepDeadline( gNotificationLock, (void *)(event), deadline, THREAD_UNINT )
200 #define WAKEUPNOTIFY(event) \
201 IORecursiveLockWakeup( gNotificationLock, (void *)(event), /* wake one */ false )
203 #define randomDelay() \
204 int del = read_processor_clock(); \
205 del = (((int)IOThreadSelf()) ^ del ^ (del >> 10)) & 0x3ff; \
208 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
210 #define queue_element(entry, element, type, field) do { \
211 vm_address_t __ele = (vm_address_t) (entry); \
212 __ele -= -4 + ((size_t)(&((type) 4)->field)); \
213 (element) = (type) __ele; \
216 #define iterqueue(que, elt) \
217 for (queue_entry_t elt = queue_first(que); \
218 !queue_end(que, elt); \
219 elt = queue_next(elt))
221 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
223 struct IOInterruptAccountingReporter
{
224 IOSimpleReporter
* reporter
; /* Reporter responsible for communicating the statistics */
225 IOInterruptAccountingData
* statistics
; /* The live statistics values, if any */
228 struct ArbitrationLockQueueElement
{
237 static queue_head_t gArbitrationLockQueueActive
;
238 static queue_head_t gArbitrationLockQueueWaiting
;
239 static queue_head_t gArbitrationLockQueueFree
;
240 static IOLock
* gArbitrationLockQueueLock
;
242 bool IOService::isInactive( void ) const
243 { return( 0 != (kIOServiceInactiveState
& getState())); }
245 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
247 #if defined(__i386__) || defined(__x86_64__)
249 // Only used by the intel implementation of
250 // IOService::requireMaxBusStall(UInt32 ns)
251 // IOService::requireMaxInterruptDelay(uint32_t ns)
254 IOService
* fService
;
260 kCpuDelayBusStall
, kCpuDelayInterrupt
,
264 static OSData
*sCpuDelayData
= OSData::withCapacity(8 * sizeof(CpuDelayEntry
));
265 static IORecursiveLock
*sCpuDelayLock
= IORecursiveLockAlloc();
266 static OSArray
*sCpuLatencyHandlers
[kCpuNumDelayTypes
];
267 const OSSymbol
*sCPULatencyFunctionName
[kCpuNumDelayTypes
];
268 static OSNumber
* sCPULatencyHolder
[kCpuNumDelayTypes
];
269 static OSNumber
* sCPULatencySet
[kCpuNumDelayTypes
];
272 requireMaxCpuDelay(IOService
* service
, UInt32 ns
, UInt32 delayType
);
274 setLatencyHandler(UInt32 delayType
, IOService
* target
, bool enable
);
276 #endif /* defined(__i386__) || defined(__x86_64__) */
278 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
280 void IOService::initialize( void )
284 gIOServicePlane
= IORegistryEntry::makePlane( kIOServicePlane
);
285 gIOPowerPlane
= IORegistryEntry::makePlane( kIOPowerPlane
);
287 gIOProviderClassKey
= OSSymbol::withCStringNoCopy( kIOProviderClassKey
);
288 gIONameMatchKey
= OSSymbol::withCStringNoCopy( kIONameMatchKey
);
289 gIONameMatchedKey
= OSSymbol::withCStringNoCopy( kIONameMatchedKey
);
290 gIOPropertyMatchKey
= OSSymbol::withCStringNoCopy( kIOPropertyMatchKey
);
291 gIOPathMatchKey
= OSSymbol::withCStringNoCopy( kIOPathMatchKey
);
292 gIOLocationMatchKey
= OSSymbol::withCStringNoCopy( kIOLocationMatchKey
);
293 gIOParentMatchKey
= OSSymbol::withCStringNoCopy( kIOParentMatchKey
);
295 gIOMatchCategoryKey
= OSSymbol::withCStringNoCopy( kIOMatchCategoryKey
);
296 gIODefaultMatchCategoryKey
= OSSymbol::withCStringNoCopy(
297 kIODefaultMatchCategoryKey
);
298 gIOMatchedServiceCountKey
= OSSymbol::withCStringNoCopy(
299 kIOMatchedServiceCountKey
);
301 gIOUserClientClassKey
= OSSymbol::withCStringNoCopy( kIOUserClientClassKey
);
303 gIOResourcesKey
= OSSymbol::withCStringNoCopy( kIOResourcesClass
);
304 gIOResourceMatchKey
= OSSymbol::withCStringNoCopy( kIOResourceMatchKey
);
306 gIODeviceMemoryKey
= OSSymbol::withCStringNoCopy( "IODeviceMemory" );
307 gIOInterruptControllersKey
308 = OSSymbol::withCStringNoCopy("IOInterruptControllers");
309 gIOInterruptSpecifiersKey
310 = OSSymbol::withCStringNoCopy("IOInterruptSpecifiers");
312 gIOMapperIDKey
= OSSymbol::withCStringNoCopy(kIOMapperIDKey
);
314 gIOKitDebugKey
= OSSymbol::withCStringNoCopy( kIOKitDebugKey
);
316 gIOCommandPoolSizeKey
= OSSymbol::withCStringNoCopy( kIOCommandPoolSizeKey
);
318 gIOGeneralInterest
= OSSymbol::withCStringNoCopy( kIOGeneralInterest
);
319 gIOBusyInterest
= OSSymbol::withCStringNoCopy( kIOBusyInterest
);
320 gIOAppPowerStateInterest
= OSSymbol::withCStringNoCopy( kIOAppPowerStateInterest
);
321 gIOPriorityPowerStateInterest
= OSSymbol::withCStringNoCopy( kIOPriorityPowerStateInterest
);
322 gIOConsoleSecurityInterest
= OSSymbol::withCStringNoCopy( kIOConsoleSecurityInterest
);
324 gNotifications
= OSDictionary::withCapacity( 1 );
325 gIOPublishNotification
= OSSymbol::withCStringNoCopy(
326 kIOPublishNotification
);
327 gIOFirstPublishNotification
= OSSymbol::withCStringNoCopy(
328 kIOFirstPublishNotification
);
329 gIOMatchedNotification
= OSSymbol::withCStringNoCopy(
330 kIOMatchedNotification
);
331 gIOFirstMatchNotification
= OSSymbol::withCStringNoCopy(
332 kIOFirstMatchNotification
);
333 gIOTerminatedNotification
= OSSymbol::withCStringNoCopy(
334 kIOTerminatedNotification
);
335 gIOServiceKey
= OSSymbol::withCStringNoCopy( kIOServiceClass
);
337 gIOConsoleLockedKey
= OSSymbol::withCStringNoCopy( kIOConsoleLockedKey
);
338 gIOConsoleUsersKey
= OSSymbol::withCStringNoCopy( kIOConsoleUsersKey
);
339 gIOConsoleSessionUIDKey
= OSSymbol::withCStringNoCopy( kIOConsoleSessionUIDKey
);
340 gIOConsoleSessionAuditIDKey
= OSSymbol::withCStringNoCopy( kIOConsoleSessionAuditIDKey
);
342 gIOConsoleUsersSeedKey
= OSSymbol::withCStringNoCopy(kIOConsoleUsersSeedKey
);
343 gIOConsoleSessionOnConsoleKey
= OSSymbol::withCStringNoCopy(kIOConsoleSessionOnConsoleKey
);
344 gIOConsoleSessionLoginDoneKey
= OSSymbol::withCStringNoCopy(kIOConsoleSessionLoginDoneKey
);
345 gIOConsoleSessionSecureInputPIDKey
= OSSymbol::withCStringNoCopy(kIOConsoleSessionSecureInputPIDKey
);
346 gIOConsoleSessionScreenLockedTimeKey
= OSSymbol::withCStringNoCopy(kIOConsoleSessionScreenLockedTimeKey
);
348 gIOConsoleUsersSeedValue
= OSData::withBytesNoCopy(&gIOConsoleUsersSeed
, sizeof(gIOConsoleUsersSeed
));
350 gIOPlatformSleepActionKey
= OSSymbol::withCStringNoCopy(kIOPlatformSleepActionKey
);
351 gIOPlatformWakeActionKey
= OSSymbol::withCStringNoCopy(kIOPlatformWakeActionKey
);
352 gIOPlatformQuiesceActionKey
= OSSymbol::withCStringNoCopy(kIOPlatformQuiesceActionKey
);
353 gIOPlatformActiveActionKey
= OSSymbol::withCStringNoCopy(kIOPlatformActiveActionKey
);
354 gIOPlatformHaltRestartActionKey
= OSSymbol::withCStringNoCopy(kIOPlatformHaltRestartActionKey
);
356 gIOPlatformFunctionHandlerSet
= OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerSet
);
357 #if defined(__i386__) || defined(__x86_64__)
358 sCPULatencyFunctionName
[kCpuDelayBusStall
] = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerMaxBusDelay
);
359 sCPULatencyFunctionName
[kCpuDelayInterrupt
] = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerMaxInterruptDelay
);
361 for (idx
= 0; idx
< kCpuNumDelayTypes
; idx
++)
363 sCPULatencySet
[idx
] = OSNumber::withNumber(-1U, 32);
364 sCPULatencyHolder
[idx
] = OSNumber::withNumber(0ULL, 64);
365 assert(sCPULatencySet
[idx
] && sCPULatencyHolder
[idx
]);
368 gNotificationLock
= IORecursiveLockAlloc();
370 assert( gIOServicePlane
&& gIODeviceMemoryKey
371 && gIOInterruptControllersKey
&& gIOInterruptSpecifiersKey
372 && gIOResourcesKey
&& gNotifications
&& gNotificationLock
373 && gIOProviderClassKey
&& gIONameMatchKey
&& gIONameMatchedKey
374 && gIOMatchCategoryKey
&& gIODefaultMatchCategoryKey
375 && gIOPublishNotification
&& gIOMatchedNotification
376 && gIOTerminatedNotification
&& gIOServiceKey
377 && gIOConsoleUsersKey
&& gIOConsoleSessionUIDKey
378 && gIOConsoleSessionOnConsoleKey
&& gIOConsoleSessionSecureInputPIDKey
379 && gIOConsoleUsersSeedKey
&& gIOConsoleUsersSeedValue
);
381 gJobsLock
= IOLockAlloc();
382 gJobs
= OSOrderedSet::withCapacity( 10 );
384 gIOServiceBusyLock
= IOLockAlloc();
386 gIOConsoleUsersLock
= IOLockAlloc();
388 err
= semaphore_create(kernel_task
, &gJobsSemaphore
, SYNC_POLICY_FIFO
, 0);
390 gIOConsoleLockCallout
= thread_call_allocate(&IOService::consoleLockTimer
, NULL
);
392 IORegistryEntry::getRegistryRoot()->setProperty(gIOConsoleLockedKey
, kOSBooleanTrue
);
394 assert( gIOServiceBusyLock
&& gJobs
&& gJobsLock
&& gIOConsoleUsersLock
395 && gIOConsoleLockCallout
&& (err
== KERN_SUCCESS
) );
397 gIOResources
= IOResources::resources();
398 assert( gIOResources
);
400 gArbitrationLockQueueLock
= IOLockAlloc();
401 queue_init(&gArbitrationLockQueueActive
);
402 queue_init(&gArbitrationLockQueueWaiting
);
403 queue_init(&gArbitrationLockQueueFree
);
405 assert( gArbitrationLockQueueLock
);
407 gIOTerminatePhase2List
= OSArray::withCapacity( 2 );
408 gIOStopList
= OSArray::withCapacity( 16 );
409 gIOStopProviderList
= OSArray::withCapacity( 16 );
410 gIOFinalizeList
= OSArray::withCapacity( 16 );
411 assert( gIOTerminatePhase2List
&& gIOStopList
&& gIOStopProviderList
&& gIOFinalizeList
);
414 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
417 static UInt64
getDebugFlags( OSDictionary
* props
)
419 OSNumber
* debugProp
;
422 debugProp
= OSDynamicCast( OSNumber
,
423 props
->getObject( gIOKitDebugKey
));
425 debugFlags
= debugProp
->unsigned64BitValue();
427 debugFlags
= gIOKitDebug
;
429 return( debugFlags
);
433 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
435 // Probe a matched service and return an instance to be started.
436 // The default score is from the property table, & may be altered
437 // during probe to change the start order.
439 IOService
* IOService::probe( IOService
* provider
,
445 bool IOService::start( IOService
* provider
)
450 void IOService::stop( IOService
* provider
)
454 bool IOService::init( OSDictionary
* dictionary
)
458 ret
= super::init(dictionary
);
463 reserved
= IONew(ExpansionData
, 1);
470 bzero(reserved
, sizeof(*reserved
));
473 * TODO: Improve on this. Previous efforts to more lazily allocate this
474 * lock based on the presence of specifiers ran into issues as some
475 * platforms set up the specifiers after IOService initialization.
477 * We may be able to get away with a global lock, as this should only be
478 * contended by IOReporting clients and driver start/stop (unless a
479 * driver wants to remove/add handlers in the course of normal operation,
480 * which should be unlikely).
482 reserved
->interruptStatisticsLock
= IOLockAlloc();
484 if (!reserved
->interruptStatisticsLock
) {
493 bool IOService::init( IORegistryEntry
* from
,
494 const IORegistryPlane
* inPlane
)
498 ret
= super::init(from
, inPlane
);
503 reserved
= IONew(ExpansionData
, 1);
510 bzero(reserved
, sizeof(*reserved
));
513 * TODO: Improve on this. Previous efforts to more lazily allocate this
514 * lock based on the presence of specifiers ran into issues as some
515 * platforms set up the specifiers after IOService initialization.
517 * We may be able to get away with a global lock, as this should only be
518 * contended by IOReporting clients and driver start/stop (unless a
519 * driver wants to remove/add handlers in the course of normal operation,
520 * which should be unlikely).
522 reserved
->interruptStatisticsLock
= IOLockAlloc();
524 if (!reserved
->interruptStatisticsLock
) {
533 void IOService::free( void )
536 requireMaxBusStall(0);
537 requireMaxInterruptDelay(0);
538 if( getPropertyTable())
539 unregisterAllInterest();
543 if (reserved
->interruptStatisticsArray
) {
544 for (i
= 0; i
< reserved
->interruptStatisticsArrayCount
; i
++) {
545 if (reserved
->interruptStatisticsArray
[i
].reporter
)
546 reserved
->interruptStatisticsArray
[i
].reporter
->release();
549 IODelete(reserved
->interruptStatisticsArray
, IOInterruptAccountingReporter
, reserved
->interruptStatisticsArrayCount
);
552 if (reserved
->interruptStatisticsLock
)
553 IOLockFree(reserved
->interruptStatisticsLock
);
554 IODelete(reserved
, ExpansionData
, 1);
561 * Attach in service plane
563 bool IOService::attach( IOService
* provider
)
569 if( gIOKitDebug
& kIOLogAttach
)
570 LOG( "%s::attach(%s)\n", getName(),
571 provider
->getName());
573 provider
->lockForArbitration();
574 if( provider
->__state
[0] & kIOServiceInactiveState
)
577 ok
= attachToParent( provider
, gIOServicePlane
);
578 provider
->unlockForArbitration();
581 gIOServiceRoot
= this;
582 ok
= attachToParent( getRegistryRoot(), gIOServicePlane
);
585 if (ok
&& !__provider
) (void) getProvider();
590 IOService
* IOService::getServiceRoot( void )
592 return( gIOServiceRoot
);
595 void IOService::detach( IOService
* provider
)
597 IOService
* newProvider
= 0;
601 if( gIOKitDebug
& kIOLogAttach
)
602 LOG("%s::detach(%s)\n", getName(), provider
->getName());
604 lockForArbitration();
606 adjParent
= ((busy
= (__state
[1] & kIOServiceBusyStateMask
))
607 && (provider
== getProvider()));
609 detachFromParent( provider
, gIOServicePlane
);
612 newProvider
= getProvider();
613 if( busy
&& (__state
[1] & kIOServiceTermPhase3State
) && (0 == newProvider
))
614 _adjustBusy( -busy
);
617 if (kIOServiceInactiveState
& __state
[0]) {
618 getMetaClass()->removeInstance(this);
621 unlockForArbitration();
624 newProvider
->lockForArbitration();
625 newProvider
->_adjustBusy(1);
626 newProvider
->unlockForArbitration();
629 // check for last client detach from a terminated service
630 if( provider
->lockForArbitration( true ))
632 if (kIOServiceStartState
& __state
[1])
634 provider
->scheduleTerminatePhase2();
636 if( adjParent
) provider
->_adjustBusy( -1 );
637 if( (provider
->__state
[1] & kIOServiceTermPhase3State
)
638 && (0 == provider
->getClient())) {
639 provider
->scheduleFinalize();
641 provider
->unlockForArbitration();
646 * Register instance - publish it for matching
649 void IOService::registerService( IOOptionBits options
)
655 enum { kMaxPathLen
= 256 };
656 enum { kMaxChars
= 63 };
658 IORegistryEntry
* parent
= this;
659 IORegistryEntry
* root
= getRegistryRoot();
660 while( parent
&& (parent
!= root
))
661 parent
= parent
->getParentEntry( gIOServicePlane
);
663 if( parent
!= root
) {
664 IOLog("%s: not registry member at registerService()\n", getName());
668 // Allow the Platform Expert to adjust this node.
669 if( gIOPlatform
&& (!gIOPlatform
->platformAdjustService(this)))
672 if( (this != gIOResources
)
673 && (kIOLogRegister
& gIOKitDebug
)) {
675 pathBuf
= (char *) IOMalloc( kMaxPathLen
);
677 IOLog( "Registering: " );
680 if( pathBuf
&& getPath( pathBuf
, &len
, gIOServicePlane
)) {
683 if( len
> kMaxChars
) {
687 if( (skip
= strchr( path
, '/')))
693 IOLog( "%s\n", path
);
696 IOFree( pathBuf
, kMaxPathLen
);
699 startMatching( options
);
702 void IOService::startMatching( IOOptionBits options
)
704 IOService
* provider
;
707 bool needWake
= false;
712 lockForArbitration();
714 sync
= (options
& kIOServiceSynchronous
)
715 || ((provider
= getProvider())
716 && (provider
->__state
[1] & kIOServiceSynchronousState
));
718 if ( options
& kIOServiceAsynchronous
)
721 needConfig
= (0 == (__state
[1] & (kIOServiceNeedConfigState
| kIOServiceConfigState
)))
722 && (0 == (__state
[0] & kIOServiceInactiveState
));
724 __state
[1] |= kIOServiceNeedConfigState
;
726 // __state[0] &= ~kIOServiceInactiveState;
728 // if( sync) LOG("OSKernelStackRemaining = %08x @ %s\n",
729 // OSKernelStackRemaining(), getName());
732 needWake
= (0 != (kIOServiceSyncPubState
& __state
[1]));
736 __state
[1] |= kIOServiceSynchronousState
;
738 __state
[1] &= ~kIOServiceSynchronousState
;
740 if( needConfig
) prevBusy
= _adjustBusy( 1 );
742 unlockForArbitration();
747 IOLockLock( gIOServiceBusyLock
);
748 thread_wakeup( (event_t
) this/*&__state[1]*/ );
749 IOLockUnlock( gIOServiceBusyLock
);
751 } else if( !sync
|| (kIOServiceAsynchronous
& options
)) {
753 ok
= (0 != _IOServiceJob::startJob( this, kMatchNubJob
, options
));
757 if( (__state
[1] & kIOServiceNeedConfigState
))
758 doServiceMatch( options
);
760 lockForArbitration();
761 IOLockLock( gIOServiceBusyLock
);
763 waitAgain
= ((prevBusy
< (__state
[1] & kIOServiceBusyStateMask
))
764 && (0 == (__state
[0] & kIOServiceInactiveState
)));
767 __state
[1] |= kIOServiceSyncPubState
| kIOServiceBusyWaiterState
;
769 __state
[1] &= ~kIOServiceSyncPubState
;
771 unlockForArbitration();
774 assert_wait( (event_t
) this/*&__state[1]*/, THREAD_UNINT
);
776 IOLockUnlock( gIOServiceBusyLock
);
778 thread_block(THREAD_CONTINUE_NULL
);
780 } while( waitAgain
);
784 IOReturn
IOService::catalogNewDrivers( OSOrderedSet
* newTables
)
786 OSDictionary
* table
;
796 while( (table
= (OSDictionary
*) newTables
->getFirstObject())) {
799 set
= (OSSet
*) copyExistingServices( table
,
800 kIOServiceRegisteredState
,
801 kIOServiceExistingSet
);
806 count
+= set
->getCount();
809 allSet
->merge((const OSSet
*) set
);
817 if( getDebugFlags( table
) & kIOLogMatch
)
818 LOG("Matching service count = %ld\n", (long)count
);
820 newTables
->removeObject(table
);
824 while( (service
= (IOService
*) allSet
->getAnyObject())) {
825 service
->startMatching(kIOServiceAsynchronous
);
826 allSet
->removeObject(service
);
831 newTables
->release();
833 return( kIOReturnSuccess
);
836 _IOServiceJob
* _IOServiceJob::startJob( IOService
* nub
, int type
,
837 IOOptionBits options
)
841 job
= new _IOServiceJob
;
842 if( job
&& !job
->init()) {
850 job
->options
= options
;
851 nub
->retain(); // thread will release()
859 * Called on a registered service to see if it matches
863 bool IOService::matchPropertyTable( OSDictionary
* table
, SInt32
* score
)
865 return( matchPropertyTable(table
) );
868 bool IOService::matchPropertyTable( OSDictionary
* table
)
874 * Called on a matched service to allocate resources
875 * before first driver is attached.
878 IOReturn
IOService::getResources( void )
880 return( kIOReturnSuccess
);
884 * Client/provider accessors
887 IOService
* IOService::getProvider( void ) const
889 IOService
* self
= (IOService
*) this;
893 generation
= getGenerationCount();
894 if( __providerGeneration
== generation
)
895 return( __provider
);
897 parent
= (IOService
*) getParentEntry( gIOServicePlane
);
898 if( parent
== IORegistryEntry::getRegistryRoot())
899 /* root is not an IOService */
902 self
->__provider
= parent
;
904 // save the count from before call to getParentEntry()
905 self
->__providerGeneration
= generation
;
910 IOWorkLoop
* IOService::getWorkLoop() const
912 IOService
*provider
= getProvider();
915 return provider
->getWorkLoop();
920 OSIterator
* IOService::getProviderIterator( void ) const
922 return( getParentIterator( gIOServicePlane
));
925 IOService
* IOService::getClient( void ) const
927 return( (IOService
*) getChildEntry( gIOServicePlane
));
930 OSIterator
* IOService::getClientIterator( void ) const
932 return( getChildIterator( gIOServicePlane
));
935 OSIterator
* _IOOpenServiceIterator::iterator( OSIterator
* _iter
,
936 const IOService
* client
,
937 const IOService
* provider
)
939 _IOOpenServiceIterator
* inst
;
944 inst
= new _IOOpenServiceIterator
;
946 if( inst
&& !inst
->init()) {
952 inst
->client
= client
;
953 inst
->provider
= provider
;
959 void _IOOpenServiceIterator::free()
963 last
->unlockForArbitration();
967 OSObject
* _IOOpenServiceIterator::getNextObject()
972 last
->unlockForArbitration();
974 while( (next
= (IOService
*) iter
->getNextObject())) {
976 next
->lockForArbitration();
977 if( (client
&& (next
->isOpen( client
)))
978 || (provider
&& (provider
->isOpen( next
))) )
980 next
->unlockForArbitration();
988 bool _IOOpenServiceIterator::isValid()
990 return( iter
->isValid() );
993 void _IOOpenServiceIterator::reset()
996 last
->unlockForArbitration();
1002 OSIterator
* IOService::getOpenProviderIterator( void ) const
1004 return( _IOOpenServiceIterator::iterator( getProviderIterator(), this, 0 ));
1007 OSIterator
* IOService::getOpenClientIterator( void ) const
1009 return( _IOOpenServiceIterator::iterator( getClientIterator(), 0, this ));
1013 IOReturn
IOService::callPlatformFunction( const OSSymbol
* functionName
,
1014 bool waitForFunction
,
1015 void *param1
, void *param2
,
1016 void *param3
, void *param4
)
1018 IOReturn result
= kIOReturnUnsupported
;
1019 IOService
*provider
;
1021 if (gIOPlatformFunctionHandlerSet
== functionName
)
1023 #if defined(__i386__) || defined(__x86_64__)
1024 const OSSymbol
* functionHandlerName
= (const OSSymbol
*) param1
;
1025 IOService
* target
= (IOService
*) param2
;
1026 bool enable
= (param3
!= 0);
1028 if (sCPULatencyFunctionName
[kCpuDelayBusStall
] == functionHandlerName
)
1029 result
= setLatencyHandler(kCpuDelayBusStall
, target
, enable
);
1030 else if (sCPULatencyFunctionName
[kCpuDelayInterrupt
] == param1
)
1031 result
= setLatencyHandler(kCpuDelayInterrupt
, target
, enable
);
1032 #endif /* defined(__i386__) || defined(__x86_64__) */
1035 if ((kIOReturnUnsupported
== result
) && (provider
= getProvider())) {
1036 result
= provider
->callPlatformFunction(functionName
, waitForFunction
,
1037 param1
, param2
, param3
, param4
);
1043 IOReturn
IOService::callPlatformFunction( const char * functionName
,
1044 bool waitForFunction
,
1045 void *param1
, void *param2
,
1046 void *param3
, void *param4
)
1048 IOReturn result
= kIOReturnNoMemory
;
1049 const OSSymbol
*functionSymbol
= OSSymbol::withCString(functionName
);
1051 if (functionSymbol
!= 0) {
1052 result
= callPlatformFunction(functionSymbol
, waitForFunction
,
1053 param1
, param2
, param3
, param4
);
1054 functionSymbol
->release();
1062 * Accessors for global services
1065 IOPlatformExpert
* IOService::getPlatform( void )
1067 return( gIOPlatform
);
1070 class IOPMrootDomain
* IOService::getPMRootDomain( void )
1072 return( gIOPMRootDomain
);
1075 IOService
* IOService::getResourceService( void )
1077 return( gIOResources
);
1080 void IOService::setPlatform( IOPlatformExpert
* platform
)
1082 gIOPlatform
= platform
;
1083 gIOResources
->attachToParent( gIOServiceRoot
, gIOServicePlane
);
1085 #if defined(__i386__) || defined(__x86_64__)
1087 static const char * keys
[kCpuNumDelayTypes
] = {
1088 kIOPlatformMaxBusDelay
, kIOPlatformMaxInterruptDelay
};
1089 const OSObject
* objs
[2];
1093 for (idx
= 0; idx
< kCpuNumDelayTypes
; idx
++)
1095 objs
[0] = sCPULatencySet
[idx
];
1096 objs
[1] = sCPULatencyHolder
[idx
];
1097 array
= OSArray::withObjects(objs
, 2);
1099 platform
->setProperty(keys
[idx
], array
);
1102 #endif /* defined(__i386__) || defined(__x86_64__) */
1105 void IOService::setPMRootDomain( class IOPMrootDomain
* rootDomain
)
1107 gIOPMRootDomain
= rootDomain
;
1108 publishResource("IOKit");
1115 bool IOService::lockForArbitration( bool isSuccessRequired
)
1119 ArbitrationLockQueueElement
* element
;
1120 ArbitrationLockQueueElement
* active
;
1121 ArbitrationLockQueueElement
* waiting
;
1123 enum { kPutOnFreeQueue
, kPutOnActiveQueue
, kPutOnWaitingQueue
} action
;
1125 // lock global access
1126 IOTakeLock( gArbitrationLockQueueLock
);
1128 // obtain an unused queue element
1129 if( !queue_empty( &gArbitrationLockQueueFree
)) {
1130 queue_remove_first( &gArbitrationLockQueueFree
,
1132 ArbitrationLockQueueElement
*,
1135 element
= IONew( ArbitrationLockQueueElement
, 1 );
1139 // prepare the queue element
1140 element
->thread
= IOThreadSelf();
1141 element
->service
= this;
1143 element
->required
= isSuccessRequired
;
1144 element
->aborted
= false;
1146 // determine whether this object is already locked (ie. on active queue)
1148 queue_iterate( &gArbitrationLockQueueActive
,
1150 ArbitrationLockQueueElement
*,
1153 if( active
->service
== element
->service
) {
1159 if( found
) { // this object is already locked
1161 // determine whether it is the same or a different thread trying to lock
1162 if( active
->thread
!= element
->thread
) { // it is a different thread
1164 ArbitrationLockQueueElement
* victim
= 0;
1166 // before placing this new thread on the waiting queue, we look for
1167 // a deadlock cycle...
1170 // determine whether the active thread holding the object we
1171 // want is waiting for another object to be unlocked
1173 queue_iterate( &gArbitrationLockQueueWaiting
,
1175 ArbitrationLockQueueElement
*,
1178 if( waiting
->thread
== active
->thread
) {
1179 assert( false == waiting
->aborted
);
1185 if( found
) { // yes, active thread waiting for another object
1187 // this may be a candidate for rejection if the required
1188 // flag is not set, should we detect a deadlock later on
1189 if( false == waiting
->required
)
1192 // find the thread that is holding this other object, that
1193 // is blocking the active thread from proceeding (fun :-)
1195 queue_iterate( &gArbitrationLockQueueActive
,
1196 active
, // (reuse active queue element)
1197 ArbitrationLockQueueElement
*,
1200 if( active
->service
== waiting
->service
) {
1206 // someone must be holding it or it wouldn't be waiting
1209 if( active
->thread
== element
->thread
) {
1211 // doh, it's waiting for the thread that originated
1212 // this whole lock (ie. current thread) -> deadlock
1213 if( false == element
->required
) { // willing to fail?
1215 // the originating thread doesn't have the required
1216 // flag, so it can fail
1217 success
= false; // (fail originating lock request)
1218 break; // (out of while)
1220 } else { // originating thread is not willing to fail
1222 // see if we came across a waiting thread that did
1223 // not have the 'required' flag set: we'll fail it
1226 // we do have a willing victim, fail it's lock
1227 victim
->aborted
= true;
1229 // take the victim off the waiting queue
1230 queue_remove( &gArbitrationLockQueueWaiting
,
1232 ArbitrationLockQueueElement
*,
1236 IOLockWakeup( gArbitrationLockQueueLock
,
1238 /* one thread */ true );
1240 // allow this thread to proceed (ie. wait)
1241 success
= true; // (put request on wait queue)
1242 break; // (out of while)
1245 // all the waiting threads we came across in
1246 // finding this loop had the 'required' flag
1247 // set, so we've got a deadlock we can't avoid
1248 panic("I/O Kit: Unrecoverable deadlock.");
1252 // repeat while loop, redefining active thread to be the
1253 // thread holding "this other object" (see above), and
1254 // looking for threads waiting on it; note the active
1255 // variable points to "this other object" already... so
1256 // there nothing to do in this else clause.
1258 } else { // no, active thread is not waiting for another object
1260 success
= true; // (put request on wait queue)
1261 break; // (out of while)
1265 if( success
) { // put the request on the waiting queue?
1266 kern_return_t wait_result
;
1268 // place this thread on the waiting queue and put it to sleep;
1269 // we place it at the tail of the queue...
1270 queue_enter( &gArbitrationLockQueueWaiting
,
1272 ArbitrationLockQueueElement
*,
1275 // declare that this thread will wait for a given event
1276 restart_sleep
: wait_result
= assert_wait( element
,
1277 element
->required
? THREAD_UNINT
1278 : THREAD_INTERRUPTIBLE
);
1280 // unlock global access
1281 IOUnlock( gArbitrationLockQueueLock
);
1283 // put thread to sleep, waiting for our event to fire...
1284 if (wait_result
== THREAD_WAITING
)
1285 wait_result
= thread_block(THREAD_CONTINUE_NULL
);
1288 // ...and we've been woken up; we might be in one of two states:
1289 // (a) we've been aborted and our queue element is not on
1290 // any of the three queues, but is floating around
1291 // (b) we're allowed to proceed with the lock and we have
1292 // already been moved from the waiting queue to the
1294 // ...plus a 3rd state, should the thread have been interrupted:
1295 // (c) we're still on the waiting queue
1297 // determine whether we were interrupted out of our sleep
1298 if( THREAD_INTERRUPTED
== wait_result
) {
1300 // re-lock global access
1301 IOTakeLock( gArbitrationLockQueueLock
);
1303 // determine whether we're still on the waiting queue
1305 queue_iterate( &gArbitrationLockQueueWaiting
,
1306 waiting
, // (reuse waiting queue element)
1307 ArbitrationLockQueueElement
*,
1310 if( waiting
== element
) {
1316 if( found
) { // yes, we're still on the waiting queue
1318 // determine whether we're willing to fail
1319 if( false == element
->required
) {
1321 // mark us as aborted
1322 element
->aborted
= true;
1324 // take us off the waiting queue
1325 queue_remove( &gArbitrationLockQueueWaiting
,
1327 ArbitrationLockQueueElement
*,
1329 } else { // we are not willing to fail
1331 // ignore interruption, go back to sleep
1336 // unlock global access
1337 IOUnlock( gArbitrationLockQueueLock
);
1339 // proceed as though this were a normal wake up
1340 wait_result
= THREAD_AWAKENED
;
1343 assert( THREAD_AWAKENED
== wait_result
);
1345 // determine whether we've been aborted while we were asleep
1346 if( element
->aborted
) {
1347 assert( false == element
->required
);
1349 // re-lock global access
1350 IOTakeLock( gArbitrationLockQueueLock
);
1352 action
= kPutOnFreeQueue
;
1354 } else { // we weren't aborted, so we must be ready to go :-)
1356 // we've already been moved from waiting to active queue
1360 } else { // the lock request is to be failed
1362 // return unused queue element to queue
1363 action
= kPutOnFreeQueue
;
1365 } else { // it is the same thread, recursive access is allowed
1367 // add one level of recursion
1370 // return unused queue element to queue
1371 action
= kPutOnFreeQueue
;
1374 } else { // this object is not already locked, so let this thread through
1375 action
= kPutOnActiveQueue
;
1379 // put the new element on a queue
1380 if( kPutOnActiveQueue
== action
) {
1381 queue_enter( &gArbitrationLockQueueActive
,
1383 ArbitrationLockQueueElement
*,
1385 } else if( kPutOnFreeQueue
== action
) {
1386 queue_enter( &gArbitrationLockQueueFree
,
1388 ArbitrationLockQueueElement
*,
1391 assert( 0 ); // kPutOnWaitingQueue never occurs, handled specially above
1394 // unlock global access
1395 IOUnlock( gArbitrationLockQueueLock
);
1400 void IOService::unlockForArbitration( void )
1403 ArbitrationLockQueueElement
* element
;
1405 // lock global access
1406 IOTakeLock( gArbitrationLockQueueLock
);
1408 // find the lock element for this object (ie. on active queue)
1410 queue_iterate( &gArbitrationLockQueueActive
,
1412 ArbitrationLockQueueElement
*,
1415 if( element
->service
== this ) {
1423 // determine whether the lock has been taken recursively
1424 if( element
->count
> 1 ) {
1425 // undo one level of recursion
1430 // remove it from the active queue
1431 queue_remove( &gArbitrationLockQueueActive
,
1433 ArbitrationLockQueueElement
*,
1436 // put it on the free queue
1437 queue_enter( &gArbitrationLockQueueFree
,
1439 ArbitrationLockQueueElement
*,
1442 // determine whether a thread is waiting for object (head to tail scan)
1444 queue_iterate( &gArbitrationLockQueueWaiting
,
1446 ArbitrationLockQueueElement
*,
1449 if( element
->service
== this ) {
1455 if ( found
) { // we found an interested thread on waiting queue
1457 // remove it from the waiting queue
1458 queue_remove( &gArbitrationLockQueueWaiting
,
1460 ArbitrationLockQueueElement
*,
1463 // put it on the active queue
1464 queue_enter( &gArbitrationLockQueueActive
,
1466 ArbitrationLockQueueElement
*,
1469 // wake the waiting thread
1470 IOLockWakeup( gArbitrationLockQueueLock
,
1472 /* one thread */ true );
1476 // unlock global access
1477 IOUnlock( gArbitrationLockQueueLock
);
1480 void IOService::applyToProviders( IOServiceApplierFunction applier
,
1483 applyToParents( (IORegistryEntryApplierFunction
) applier
,
1484 context
, gIOServicePlane
);
1487 void IOService::applyToClients( IOServiceApplierFunction applier
,
1490 applyToChildren( (IORegistryEntryApplierFunction
) applier
,
1491 context
, gIOServicePlane
);
1500 // send a message to a client or interested party of this service
1501 IOReturn
IOService::messageClient( UInt32 type
, OSObject
* client
,
1502 void * argument
, vm_size_t argSize
)
1505 IOService
* service
;
1506 _IOServiceInterestNotifier
* notify
;
1508 if( (service
= OSDynamicCast( IOService
, client
)))
1509 ret
= service
->message( type
, this, argument
);
1511 else if( (notify
= OSDynamicCast( _IOServiceInterestNotifier
, client
))) {
1513 _IOServiceNotifierInvocation invocation
;
1516 invocation
.thread
= current_thread();
1519 willNotify
= (0 != (kIOServiceNotifyEnable
& notify
->state
));
1522 queue_enter( ¬ify
->handlerInvocations
, &invocation
,
1523 _IOServiceNotifierInvocation
*, link
);
1529 ret
= (*notify
->handler
)( notify
->target
, notify
->ref
,
1530 type
, this, argument
, argSize
);
1533 queue_remove( ¬ify
->handlerInvocations
, &invocation
,
1534 _IOServiceNotifierInvocation
*, link
);
1535 if( kIOServiceNotifyWaiter
& notify
->state
) {
1536 notify
->state
&= ~kIOServiceNotifyWaiter
;
1537 WAKEUPNOTIFY( notify
);
1542 ret
= kIOReturnSuccess
;
1545 ret
= kIOReturnBadArgument
;
1551 applyToInterestNotifiers(const IORegistryEntry
*target
,
1552 const OSSymbol
* typeOfInterest
,
1553 OSObjectApplierFunction applier
,
1556 OSArray
* copyArray
= 0;
1560 IOCommand
*notifyList
=
1561 OSDynamicCast( IOCommand
, target
->getProperty( typeOfInterest
));
1564 copyArray
= OSArray::withCapacity(1);
1566 // iterate over queue, entry is set to each element in the list
1567 iterqueue(¬ifyList
->fCommandChain
, entry
) {
1568 _IOServiceInterestNotifier
* notify
;
1570 queue_element(entry
, notify
, _IOServiceInterestNotifier
*, chain
);
1571 copyArray
->setObject(notify
);
1580 for( index
= 0; (next
= copyArray
->getObject( index
)); index
++)
1581 (*applier
)(next
, context
);
1582 copyArray
->release();
1586 void IOService::applyToInterested( const OSSymbol
* typeOfInterest
,
1587 OSObjectApplierFunction applier
,
1590 if (gIOGeneralInterest
== typeOfInterest
)
1591 applyToClients( (IOServiceApplierFunction
) applier
, context
);
1592 applyToInterestNotifiers(this, typeOfInterest
, applier
, context
);
1595 struct MessageClientsContext
{
1596 IOService
* service
;
1603 static void messageClientsApplier( OSObject
* object
, void * ctx
)
1606 MessageClientsContext
* context
= (MessageClientsContext
*) ctx
;
1608 ret
= context
->service
->messageClient( context
->type
,
1609 object
, context
->argument
, context
->argSize
);
1610 if( kIOReturnSuccess
!= ret
)
1614 // send a message to all clients
1615 IOReturn
IOService::messageClients( UInt32 type
,
1616 void * argument
, vm_size_t argSize
)
1618 MessageClientsContext context
;
1620 context
.service
= this;
1621 context
.type
= type
;
1622 context
.argument
= argument
;
1623 context
.argSize
= argSize
;
1624 context
.ret
= kIOReturnSuccess
;
1626 applyToInterested( gIOGeneralInterest
,
1627 &messageClientsApplier
, &context
);
1629 return( context
.ret
);
1632 IOReturn
IOService::acknowledgeNotification( IONotificationRef notification
,
1633 IOOptionBits response
)
1635 return( kIOReturnUnsupported
);
1638 IONotifier
* IOService::registerInterest( const OSSymbol
* typeOfInterest
,
1639 IOServiceInterestHandler handler
, void * target
, void * ref
)
1641 _IOServiceInterestNotifier
* notify
= 0;
1642 IOReturn rc
= kIOReturnError
;
1644 notify
= new _IOServiceInterestNotifier
;
1645 if (!notify
) return NULL
;
1647 if(notify
->init()) {
1648 rc
= registerInterestForNotifer(notify
, typeOfInterest
,
1649 handler
, target
, ref
);
1652 if (rc
!= kIOReturnSuccess
) {
1660 IOReturn
IOService::registerInterestForNotifer( IONotifier
*svcNotify
, const OSSymbol
* typeOfInterest
,
1661 IOServiceInterestHandler handler
, void * target
, void * ref
)
1663 IOReturn rc
= kIOReturnSuccess
;
1664 _IOServiceInterestNotifier
*notify
= 0;
1666 if( (typeOfInterest
!= gIOGeneralInterest
)
1667 && (typeOfInterest
!= gIOBusyInterest
)
1668 && (typeOfInterest
!= gIOAppPowerStateInterest
)
1669 && (typeOfInterest
!= gIOConsoleSecurityInterest
)
1670 && (typeOfInterest
!= gIOPriorityPowerStateInterest
))
1671 return( kIOReturnBadArgument
);
1673 if (!svcNotify
|| !(notify
= OSDynamicCast(_IOServiceInterestNotifier
, svcNotify
)))
1674 return( kIOReturnBadArgument
);
1676 lockForArbitration();
1677 if( 0 == (__state
[0] & kIOServiceInactiveState
)) {
1679 notify
->handler
= handler
;
1680 notify
->target
= target
;
1682 notify
->state
= kIOServiceNotifyEnable
;
1688 // Get the head of the notifier linked list
1689 IOCommand
* notifyList
;
1690 OSObject
* obj
= copyProperty( typeOfInterest
);
1691 if (!(notifyList
= OSDynamicCast(IOCommand
, obj
))) {
1692 notifyList
= OSTypeAlloc(IOCommand
);
1695 bool ok
= setProperty( typeOfInterest
, notifyList
);
1696 notifyList
->release();
1697 if (!ok
) notifyList
= 0;
1700 if (obj
) obj
->release();
1703 enqueue(¬ifyList
->fCommandChain
, ¬ify
->chain
);
1704 notify
->retain(); // ref'ed while in list
1710 rc
= kIOReturnNotReady
;
1712 unlockForArbitration();
1717 static void cleanInterestList( OSObject
* head
)
1719 IOCommand
*notifyHead
= OSDynamicCast(IOCommand
, head
);
1724 while ( queue_entry_t entry
= dequeue(¬ifyHead
->fCommandChain
) ) {
1725 queue_next(entry
) = queue_prev(entry
) = 0;
1727 _IOServiceInterestNotifier
* notify
;
1729 queue_element(entry
, notify
, _IOServiceInterestNotifier
*, chain
);
1735 void IOService::unregisterAllInterest( void )
1737 cleanInterestList( getProperty( gIOGeneralInterest
));
1738 cleanInterestList( getProperty( gIOBusyInterest
));
1739 cleanInterestList( getProperty( gIOAppPowerStateInterest
));
1740 cleanInterestList( getProperty( gIOPriorityPowerStateInterest
));
1741 cleanInterestList( getProperty( gIOConsoleSecurityInterest
));
1745 * _IOServiceInterestNotifier
1748 // wait for all threads, other than the current one,
1749 // to exit the handler
1751 void _IOServiceInterestNotifier::wait()
1753 _IOServiceNotifierInvocation
* next
;
1758 queue_iterate( &handlerInvocations
, next
,
1759 _IOServiceNotifierInvocation
*, link
) {
1760 if( next
->thread
!= current_thread() ) {
1766 state
|= kIOServiceNotifyWaiter
;
1773 void _IOServiceInterestNotifier::free()
1775 assert( queue_empty( &handlerInvocations
));
1779 void _IOServiceInterestNotifier::remove()
1783 if( queue_next( &chain
)) {
1785 queue_next( &chain
) = queue_prev( &chain
) = 0;
1789 state
&= ~kIOServiceNotifyEnable
;
1798 bool _IOServiceInterestNotifier::disable()
1804 ret
= (0 != (kIOServiceNotifyEnable
& state
));
1805 state
&= ~kIOServiceNotifyEnable
;
1814 void _IOServiceInterestNotifier::enable( bool was
)
1818 state
|= kIOServiceNotifyEnable
;
1820 state
&= ~kIOServiceNotifyEnable
;
1824 bool _IOServiceInterestNotifier::init()
1826 queue_init( &handlerInvocations
);
1827 return (OSObject::init());
1829 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1835 #define tailQ(o) setObject(o)
1836 #define headQ(o) setObject(0, o)
1837 #define TLOG(fmt, args...) { if(kIOLogYield & gIOKitDebug) { IOLog("[%llx] ", thread_tid(current_thread())); IOLog(fmt, ## args); }}
1839 static void _workLoopAction( IOWorkLoop::Action action
,
1840 IOService
* service
,
1841 void * p0
= 0, void * p1
= 0,
1842 void * p2
= 0, void * p3
= 0 )
1846 if( (wl
= service
->getWorkLoop())) {
1848 wl
->runAction( action
, service
, p0
, p1
, p2
, p3
);
1851 (*action
)( service
, p0
, p1
, p2
, p3
);
1854 bool IOService::requestTerminate( IOService
* provider
, IOOptionBits options
)
1858 // if its our only provider
1859 ok
= isParent( provider
, gIOServicePlane
, true);
1863 provider
->terminateClient( this, options
| kIOServiceRecursing
);
1864 ok
= (0 != (__state
[1] & kIOServiceRecursing
));
1871 bool IOService::terminatePhase1( IOOptionBits options
)
1876 OSArray
* makeInactive
;
1877 int waitResult
= THREAD_AWAKENED
;
1881 bool startPhase2
= false;
1883 TLOG("%s[0x%qx]::terminatePhase1(%08llx)\n", getName(), getRegistryEntryID(), (long long)options
);
1885 uint64_t regID
= getRegistryEntryID();
1887 IOSERVICE_TERMINATE_PHASE1
,
1889 (uintptr_t) (regID
>> 32),
1891 (uintptr_t) options
);
1894 if( options
& kIOServiceRecursing
) {
1895 lockForArbitration();
1896 __state
[0] |= kIOServiceInactiveState
;
1897 __state
[1] |= kIOServiceRecursing
;
1898 unlockForArbitration();
1904 makeInactive
= OSArray::withCapacity( 16 );
1913 didInactive
= victim
->lockForArbitration( true );
1915 didInactive
= (0 == (victim
->__state
[0] & kIOServiceInactiveState
))
1916 || (victim
->__state
[1] & kIOServiceRecursing
);
1918 victim
->__state
[0] |= kIOServiceInactiveState
;
1919 victim
->__state
[0] &= ~(kIOServiceRegisteredState
| kIOServiceMatchedState
1920 | kIOServiceFirstPublishState
| kIOServiceFirstMatchState
);
1921 victim
->__state
[1] &= ~kIOServiceRecursing
;
1925 victim
->__state
[1] |= kIOServiceTermPhase1State
;
1926 if (kIOServiceTerminateNeedWillTerminate
& options
)
1928 victim
->__state
[1] |= kIOServiceNeedWillTerminate
;
1932 victim
->_adjustBusy( 1 );
1934 } else if (victim
!= this) do {
1936 IOLockLock(gIOServiceBusyLock
);
1937 wait
= (victim
->__state
[1] & kIOServiceTermPhase1State
);
1939 TLOG("%s[0x%qx]::waitPhase1(%s[0x%qx])\n",
1940 getName(), getRegistryEntryID(), victim
->getName(), victim
->getRegistryEntryID());
1941 victim
->__state
[1] |= kIOServiceTerm1WaiterState
;
1942 victim
->unlockForArbitration();
1943 assert_wait((event_t
)&victim
->__state
[1], THREAD_UNINT
);
1945 IOLockUnlock(gIOServiceBusyLock
);
1947 waitResult
= thread_block(THREAD_CONTINUE_NULL
);
1948 TLOG("%s[0x%qx]::did waitPhase1(%s[0x%qx])\n",
1949 getName(), getRegistryEntryID(), victim
->getName(), victim
->getRegistryEntryID());
1950 victim
->lockForArbitration();
1952 } while( wait
&& (waitResult
!= THREAD_TIMED_OUT
));
1954 victim
->unlockForArbitration();
1957 startPhase2
= didInactive
;
1960 victim
->deliverNotification( gIOTerminatedNotification
, 0, 0xffffffff );
1961 IOUserClient::destroyUserReferences( victim
);
1963 iter
= victim
->getClientIterator();
1965 while( (client
= (IOService
*) iter
->getNextObject())) {
1966 TLOG("%s[0x%qx]::requestTerminate(%s[0x%qx], %08llx)\n",
1967 client
->getName(), client
->getRegistryEntryID(),
1968 victim
->getName(), victim
->getRegistryEntryID(), (long long)options
);
1969 ok
= client
->requestTerminate( victim
, options
);
1970 TLOG("%s[0x%qx]::requestTerminate(%s[0x%qx], ok = %d)\n",
1971 client
->getName(), client
->getRegistryEntryID(),
1972 victim
->getName(), victim
->getRegistryEntryID(), ok
);
1974 uint64_t regID1
= client
->getRegistryEntryID();
1975 uint64_t regID2
= victim
->getRegistryEntryID();
1977 (ok
? IOSERVICE_TERMINATE_REQUEST_OK
1978 : IOSERVICE_TERMINATE_REQUEST_FAIL
),
1980 (uintptr_t) (regID1
>> 32),
1982 (uintptr_t) (regID2
>> 32));
1985 makeInactive
->setObject( client
);
1991 victim
= (IOService
*) makeInactive
->getObject(0);
1994 makeInactive
->removeObject(0);
1998 makeInactive
->release();
2002 lockForArbitration();
2003 __state
[1] &= ~kIOServiceTermPhase1State
;
2004 if (kIOServiceTerm1WaiterState
& __state
[1])
2006 __state
[1] &= ~kIOServiceTerm1WaiterState
;
2007 TLOG("%s[0x%qx]::wakePhase1\n", getName(), getRegistryEntryID());
2008 IOLockLock( gIOServiceBusyLock
);
2009 thread_wakeup( (event_t
) &__state
[1]);
2010 IOLockUnlock( gIOServiceBusyLock
);
2012 unlockForArbitration();
2013 scheduleTerminatePhase2( options
);
2019 void IOService::setTerminateDefer(IOService
* provider
, bool defer
)
2021 lockForArbitration();
2022 if (defer
) __state
[1] |= kIOServiceStartState
;
2023 else __state
[1] &= ~kIOServiceStartState
;
2024 unlockForArbitration();
2026 if (provider
&& !defer
)
2028 provider
->lockForArbitration();
2029 provider
->scheduleTerminatePhase2();
2030 provider
->unlockForArbitration();
2034 // call with lockForArbitration
2035 void IOService::scheduleTerminatePhase2( IOOptionBits options
)
2037 AbsoluteTime deadline
;
2038 int waitResult
= THREAD_AWAKENED
;
2039 bool wait
, haveDeadline
= false;
2041 if (!(__state
[0] & kIOServiceInactiveState
)
2042 || (__state
[1] & kIOServiceTermPhase1State
)) return;
2044 options
|= kIOServiceRequired
;
2048 IOLockLock( gJobsLock
);
2050 if( (options
& kIOServiceSynchronous
)
2051 && (current_thread() != gIOTerminateThread
)) {
2054 wait
= (gIOTerminateThread
!= 0);
2056 // wait to become the terminate thread
2057 IOLockSleep( gJobsLock
, &gIOTerminateThread
, THREAD_UNINT
);
2061 gIOTerminateThread
= current_thread();
2062 gIOTerminatePhase2List
->setObject( this );
2066 while( gIOTerminateWork
)
2067 terminateWorker( options
);
2068 wait
= (0 != (__state
[1] & kIOServiceBusyStateMask
));
2070 // wait for the victim to go non-busy
2071 if( !haveDeadline
) {
2072 clock_interval_to_deadline( 15, kSecondScale
, &deadline
);
2073 haveDeadline
= true;
2075 waitResult
= IOLockSleepDeadline( gJobsLock
, &gIOTerminateWork
,
2076 deadline
, THREAD_UNINT
);
2077 if( waitResult
== THREAD_TIMED_OUT
) {
2078 IOLog("%s[0x%qx]::terminate(kIOServiceSynchronous) timeout\n", getName(), getRegistryEntryID());
2081 } while(gIOTerminateWork
|| (wait
&& (waitResult
!= THREAD_TIMED_OUT
)));
2083 gIOTerminateThread
= 0;
2084 IOLockWakeup( gJobsLock
, (event_t
) &gIOTerminateThread
, /* one-thread */ false);
2087 // ! kIOServiceSynchronous
2089 gIOTerminatePhase2List
->setObject( this );
2090 if( 0 == gIOTerminateWork
++) {
2091 if( !gIOTerminateThread
)
2092 kernel_thread_start(&terminateThread
, (void *)(uintptr_t) options
, &gIOTerminateThread
);
2094 IOLockWakeup(gJobsLock
, (event_t
) &gIOTerminateWork
, /* one-thread */ false );
2098 IOLockUnlock( gJobsLock
);
2103 void IOService::terminateThread( void * arg
, wait_result_t waitResult
)
2105 IOLockLock( gJobsLock
);
2107 while (gIOTerminateWork
)
2108 terminateWorker( (uintptr_t) arg
);
2110 thread_deallocate(gIOTerminateThread
);
2111 gIOTerminateThread
= 0;
2112 IOLockWakeup( gJobsLock
, (event_t
) &gIOTerminateThread
, /* one-thread */ false);
2114 IOLockUnlock( gJobsLock
);
2117 void IOService::scheduleStop( IOService
* provider
)
2119 uint64_t regID1
= getRegistryEntryID();
2120 uint64_t regID2
= provider
->getRegistryEntryID();
2122 TLOG("%s[0x%qx]::scheduleStop(%s[0x%qx])\n", getName(), regID1
, provider
->getName(), regID2
);
2124 IOSERVICE_TERMINATE_SCHEDULE_STOP
,
2126 (uintptr_t) (regID1
>> 32),
2128 (uintptr_t) (regID2
>> 32));
2130 IOLockLock( gJobsLock
);
2131 gIOStopList
->tailQ( this );
2132 gIOStopProviderList
->tailQ( provider
);
2134 if( 0 == gIOTerminateWork
++) {
2135 if( !gIOTerminateThread
)
2136 kernel_thread_start(&terminateThread
, (void *) 0, &gIOTerminateThread
);
2138 IOLockWakeup(gJobsLock
, (event_t
) &gIOTerminateWork
, /* one-thread */ false );
2141 IOLockUnlock( gJobsLock
);
2144 void IOService::scheduleFinalize( void )
2146 uint64_t regID1
= getRegistryEntryID();
2148 TLOG("%s[0x%qx]::scheduleFinalize\n", getName(), regID1
);
2150 IOSERVICE_TERMINATE_SCHEDULE_FINALIZE
,
2152 (uintptr_t) (regID1
>> 32),
2155 IOLockLock( gJobsLock
);
2156 gIOFinalizeList
->tailQ( this );
2158 if( 0 == gIOTerminateWork
++) {
2159 if( !gIOTerminateThread
)
2160 kernel_thread_start(&terminateThread
, (void *) 0, &gIOTerminateThread
);
2162 IOLockWakeup(gJobsLock
, (event_t
) &gIOTerminateWork
, /* one-thread */ false );
2165 IOLockUnlock( gJobsLock
);
2168 bool IOService::willTerminate( IOService
* provider
, IOOptionBits options
)
2173 bool IOService::didTerminate( IOService
* provider
, IOOptionBits options
, bool * defer
)
2175 if( false == *defer
) {
2177 if( lockForArbitration( true )) {
2178 if( false == provider
->handleIsOpen( this ))
2179 scheduleStop( provider
);
2182 message( kIOMessageServiceIsRequestingClose
, provider
, (void *)(uintptr_t) options
);
2183 if( false == provider
->handleIsOpen( this ))
2184 scheduleStop( provider
);
2187 unlockForArbitration();
2194 void IOService::actionWillTerminate( IOService
* victim
, IOOptionBits options
,
2195 OSArray
* doPhase2List
,
2196 void *unused2 __unused
,
2197 void *unused3 __unused
)
2202 uint64_t regID1
, regID2
= victim
->getRegistryEntryID();
2204 iter
= victim
->getClientIterator();
2206 while( (client
= (IOService
*) iter
->getNextObject())) {
2208 regID1
= client
->getRegistryEntryID();
2209 TLOG("%s[0x%qx]::willTerminate(%s[0x%qx], %08llx)\n",
2210 client
->getName(), regID1
,
2211 victim
->getName(), regID2
, (long long)options
);
2213 IOSERVICE_TERMINATE_WILL
,
2215 (uintptr_t) (regID1
>> 32),
2217 (uintptr_t) (regID2
>> 32));
2219 ok
= client
->willTerminate( victim
, options
);
2220 doPhase2List
->tailQ( client
);
2226 void IOService::actionDidTerminate( IOService
* victim
, IOOptionBits options
,
2227 void *unused1 __unused
, void *unused2 __unused
,
2228 void *unused3 __unused
)
2233 uint64_t regID1
, regID2
= victim
->getRegistryEntryID();
2235 victim
->messageClients( kIOMessageServiceIsTerminated
, (void *)(uintptr_t) options
);
2237 iter
= victim
->getClientIterator();
2239 while( (client
= (IOService
*) iter
->getNextObject())) {
2241 regID1
= client
->getRegistryEntryID();
2242 TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], %08llx)\n",
2243 client
->getName(), regID1
,
2244 victim
->getName(), regID2
, (long long)options
);
2245 client
->didTerminate( victim
, options
, &defer
);
2248 (defer
? IOSERVICE_TERMINATE_DID_DEFER
2249 : IOSERVICE_TERMINATE_DID
),
2251 (uintptr_t) (regID1
>> 32),
2253 (uintptr_t) (regID2
>> 32));
2255 TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], defer %d)\n",
2256 client
->getName(), regID1
,
2257 victim
->getName(), regID2
, defer
);
2264 void IOService::actionWillStop( IOService
* victim
, IOOptionBits options
,
2265 void *unused1 __unused
, void *unused2 __unused
,
2266 void *unused3 __unused
)
2269 IOService
* provider
;
2271 uint64_t regID1
, regID2
= victim
->getRegistryEntryID();
2273 iter
= victim
->getProviderIterator();
2275 while( (provider
= (IOService
*) iter
->getNextObject())) {
2277 regID1
= provider
->getRegistryEntryID();
2278 TLOG("%s[0x%qx]::willTerminate(%s[0x%qx], %08llx)\n",
2279 victim
->getName(), regID2
,
2280 provider
->getName(), regID1
, (long long)options
);
2282 IOSERVICE_TERMINATE_WILL
,
2284 (uintptr_t) (regID2
>> 32),
2286 (uintptr_t) (regID1
>> 32));
2288 ok
= victim
->willTerminate( provider
, options
);
2294 void IOService::actionDidStop( IOService
* victim
, IOOptionBits options
,
2295 void *unused1 __unused
, void *unused2 __unused
,
2296 void *unused3 __unused
)
2299 IOService
* provider
;
2301 uint64_t regID1
, regID2
= victim
->getRegistryEntryID();
2303 iter
= victim
->getProviderIterator();
2305 while( (provider
= (IOService
*) iter
->getNextObject())) {
2307 regID1
= provider
->getRegistryEntryID();
2308 TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], %08llx)\n",
2309 victim
->getName(), regID2
,
2310 provider
->getName(), regID1
, (long long)options
);
2311 victim
->didTerminate( provider
, options
, &defer
);
2314 (defer
? IOSERVICE_TERMINATE_DID_DEFER
2315 : IOSERVICE_TERMINATE_DID
),
2317 (uintptr_t) (regID2
>> 32),
2319 (uintptr_t) (regID1
>> 32));
2321 TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], defer %d)\n",
2322 victim
->getName(), regID2
,
2323 provider
->getName(), regID1
, defer
);
2330 void IOService::actionFinalize( IOService
* victim
, IOOptionBits options
,
2331 void *unused1 __unused
, void *unused2 __unused
,
2332 void *unused3 __unused
)
2334 uint64_t regID1
= victim
->getRegistryEntryID();
2335 TLOG("%s[0x%qx]::finalize(%08llx)\n", victim
->getName(), regID1
, (long long)options
);
2337 IOSERVICE_TERMINATE_FINALIZE
,
2339 (uintptr_t) (regID1
>> 32),
2342 victim
->finalize( options
);
2345 void IOService::actionStop( IOService
* provider
, IOService
* client
,
2346 void *unused1 __unused
, void *unused2 __unused
,
2347 void *unused3 __unused
)
2349 uint64_t regID1
= provider
->getRegistryEntryID();
2350 uint64_t regID2
= client
->getRegistryEntryID();
2352 TLOG("%s[0x%qx]::stop(%s[0x%qx])\n", client
->getName(), regID2
, provider
->getName(), regID1
);
2354 IOSERVICE_TERMINATE_STOP
,
2356 (uintptr_t) (regID1
>> 32),
2358 (uintptr_t) (regID2
>> 32));
2360 client
->stop( provider
);
2361 if( provider
->isOpen( client
))
2362 provider
->close( client
);
2364 TLOG("%s[0x%qx]::detach(%s[0x%qx])\n", client
->getName(), regID2
, provider
->getName(), regID1
);
2365 client
->detach( provider
);
2368 void IOService::terminateWorker( IOOptionBits options
)
2370 OSArray
* doPhase2List
;
2371 OSArray
* didPhase2List
;
2377 IOService
* provider
;
2383 options
|= kIOServiceRequired
;
2385 doPhase2List
= OSArray::withCapacity( 16 );
2386 didPhase2List
= OSArray::withCapacity( 16 );
2387 freeList
= OSSet::withCapacity( 16 );
2388 if( (0 == doPhase2List
) || (0 == didPhase2List
) || (0 == freeList
))
2392 workDone
= gIOTerminateWork
;
2394 while( (victim
= (IOService
*) gIOTerminatePhase2List
->getObject(0) )) {
2397 gIOTerminatePhase2List
->removeObject(0);
2398 IOLockUnlock( gJobsLock
);
2402 doPhase2
= victim
->lockForArbitration( true );
2404 doPhase2
= (0 != (kIOServiceInactiveState
& victim
->__state
[0]));
2406 doPhase2
= (0 == (victim
->__state
[1] & kIOServiceTermPhase2State
))
2407 && (0 == (victim
->__state
[1] & kIOServiceConfigState
));
2409 if (doPhase2
&& (iter
= victim
->getClientIterator())) {
2410 while (doPhase2
&& (client
= (IOService
*) iter
->getNextObject())) {
2411 doPhase2
= (0 == (client
->__state
[1] & kIOServiceStartState
));
2413 if (!doPhase2
) TLOG("%s[0x%qx]::defer phase2(%s[0x%qx])\n",
2414 victim
->getName(), victim
->getRegistryEntryID(),
2415 client
->getName(), client
->getRegistryEntryID());
2420 victim
->__state
[1] |= kIOServiceTermPhase2State
;
2422 victim
->unlockForArbitration();
2426 if (kIOServiceNeedWillTerminate
& victim
->__state
[1]) {
2427 _workLoopAction( (IOWorkLoop::Action
) &actionWillStop
,
2428 victim
, (void *)(uintptr_t) options
, NULL
);
2431 if( 0 == victim
->getClient()) {
2432 // no clients - will go to finalize
2433 IOLockLock( gJobsLock
);
2434 gIOFinalizeList
->tailQ( victim
);
2435 IOLockUnlock( gJobsLock
);
2437 _workLoopAction( (IOWorkLoop::Action
) &actionWillTerminate
,
2438 victim
, (void *)(uintptr_t) options
, (void *)(uintptr_t) doPhase2List
);
2440 didPhase2List
->headQ( victim
);
2443 victim
= (IOService
*) doPhase2List
->getObject(0);
2446 doPhase2List
->removeObject(0);
2450 while( (victim
= (IOService
*) didPhase2List
->getObject(0)) ) {
2452 if( victim
->lockForArbitration( true )) {
2453 victim
->__state
[1] |= kIOServiceTermPhase3State
;
2454 victim
->unlockForArbitration();
2456 _workLoopAction( (IOWorkLoop::Action
) &actionDidTerminate
,
2457 victim
, (void *)(uintptr_t) options
);
2458 if (kIOServiceNeedWillTerminate
& victim
->__state
[1]) {
2459 _workLoopAction( (IOWorkLoop::Action
) &actionDidStop
,
2460 victim
, (void *)(uintptr_t) options
, NULL
);
2462 didPhase2List
->removeObject(0);
2464 IOLockLock( gJobsLock
);
2471 while( (victim
= (IOService
*) gIOFinalizeList
->getObject(0))) {
2473 IOLockUnlock( gJobsLock
);
2474 _workLoopAction( (IOWorkLoop::Action
) &actionFinalize
,
2475 victim
, (void *)(uintptr_t) options
);
2476 IOLockLock( gJobsLock
);
2478 freeList
->setObject( victim
);
2479 // safe if finalize list is append only
2480 gIOFinalizeList
->removeObject(0);
2484 (!doPhase3
) && (client
= (IOService
*) gIOStopList
->getObject(idx
)); ) {
2486 provider
= (IOService
*) gIOStopProviderList
->getObject(idx
);
2489 uint64_t regID1
= provider
->getRegistryEntryID();
2490 uint64_t regID2
= client
->getRegistryEntryID();
2492 if( !provider
->isChild( client
, gIOServicePlane
)) {
2493 // may be multiply queued - nop it
2494 TLOG("%s[0x%qx]::nop stop(%s[0x%qx])\n", client
->getName(), regID2
, provider
->getName(), regID1
);
2496 IOSERVICE_TERMINATE_STOP_NOP
,
2498 (uintptr_t) (regID1
>> 32),
2500 (uintptr_t) (regID2
>> 32));
2503 // a terminated client is not ready for stop if it has clients, skip it
2504 if( (kIOServiceInactiveState
& client
->__state
[0]) && client
->getClient()) {
2505 TLOG("%s[0x%qx]::defer stop(%s[0x%qx])\n",
2506 client
->getName(), regID2
,
2507 client
->getClient()->getName(), client
->getClient()->getRegistryEntryID());
2509 IOSERVICE_TERMINATE_STOP_DEFER
,
2511 (uintptr_t) (regID1
>> 32),
2513 (uintptr_t) (regID2
>> 32));
2519 IOLockUnlock( gJobsLock
);
2520 _workLoopAction( (IOWorkLoop::Action
) &actionStop
,
2521 provider
, (void *) client
);
2522 IOLockLock( gJobsLock
);
2523 // check the finalize list now
2527 freeList
->setObject( client
);
2528 freeList
->setObject( provider
);
2530 // safe if stop list is append only
2531 gIOStopList
->removeObject( idx
);
2532 gIOStopProviderList
->removeObject( idx
);
2536 } while( doPhase3
);
2538 gIOTerminateWork
-= workDone
;
2539 moreToDo
= (gIOTerminateWork
!= 0);
2542 TLOG("iokit terminate done, %d stops remain\n", gIOStopList
->getCount());
2544 IOSERVICE_TERMINATE_DONE
,
2545 (uintptr_t) gIOStopList
->getCount(), 0, 0, 0);
2548 } while( moreToDo
);
2550 IOLockUnlock( gJobsLock
);
2552 freeList
->release();
2553 doPhase2List
->release();
2554 didPhase2List
->release();
2556 IOLockLock( gJobsLock
);
2559 bool IOService::finalize( IOOptionBits options
)
2562 IOService
* provider
;
2563 uint64_t regID1
, regID2
= getRegistryEntryID();
2565 iter
= getProviderIterator();
2569 while( (provider
= (IOService
*) iter
->getNextObject())) {
2572 if( 0 == (__state
[1] & kIOServiceTermPhase3State
)) {
2573 /* we come down here on programmatic terminate */
2575 regID1
= provider
->getRegistryEntryID();
2576 TLOG("%s[0x%qx]::stop1(%s[0x%qx])\n", getName(), regID2
, provider
->getName(), regID1
);
2578 IOSERVICE_TERMINATE_STOP
,
2580 (uintptr_t) (regID1
>> 32),
2582 (uintptr_t) (regID2
>> 32));
2585 if( provider
->isOpen( this ))
2586 provider
->close( this );
2590 if( provider
->lockForArbitration( true )) {
2591 if( 0 == (provider
->__state
[1] & kIOServiceTermPhase3State
))
2592 scheduleStop( provider
);
2593 provider
->unlockForArbitration();
2610 void IOService::doServiceTerminate( IOOptionBits options
)
2614 // a method in case someone needs to override it
2615 bool IOService::terminateClient( IOService
* client
, IOOptionBits options
)
2619 if( client
->isParent( this, gIOServicePlane
, true))
2620 // we are the clients only provider
2621 ok
= client
->terminate( options
);
2628 bool IOService::terminate( IOOptionBits options
)
2630 options
|= kIOServiceTerminate
;
2632 return( terminatePhase1( options
));
2635 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2641 struct ServiceOpenMessageContext
2643 IOService
* service
;
2645 IOService
* excludeClient
;
2646 IOOptionBits options
;
2649 static void serviceOpenMessageApplier( OSObject
* object
, void * ctx
)
2651 ServiceOpenMessageContext
* context
= (ServiceOpenMessageContext
*) ctx
;
2653 if( object
!= context
->excludeClient
)
2654 context
->service
->messageClient( context
->type
, object
, (void *)(uintptr_t) context
->options
);
2657 bool IOService::open( IOService
* forClient
,
2658 IOOptionBits options
,
2662 ServiceOpenMessageContext context
;
2664 context
.service
= this;
2665 context
.type
= kIOMessageServiceIsAttemptingOpen
;
2666 context
.excludeClient
= forClient
;
2667 context
.options
= options
;
2669 applyToInterested( gIOGeneralInterest
,
2670 &serviceOpenMessageApplier
, &context
);
2672 if( false == lockForArbitration(false) )
2675 ok
= (0 == (__state
[0] & kIOServiceInactiveState
));
2677 ok
= handleOpen( forClient
, options
, arg
);
2679 unlockForArbitration();
2684 void IOService::close( IOService
* forClient
,
2685 IOOptionBits options
)
2690 lockForArbitration();
2692 wasClosed
= handleIsOpen( forClient
);
2694 handleClose( forClient
, options
);
2695 last
= (__state
[1] & kIOServiceTermPhase3State
);
2698 unlockForArbitration();
2701 forClient
->scheduleStop( this );
2703 else if( wasClosed
) {
2705 ServiceOpenMessageContext context
;
2707 context
.service
= this;
2708 context
.type
= kIOMessageServiceWasClosed
;
2709 context
.excludeClient
= forClient
;
2710 context
.options
= options
;
2712 applyToInterested( gIOGeneralInterest
,
2713 &serviceOpenMessageApplier
, &context
);
2717 bool IOService::isOpen( const IOService
* forClient
) const
2719 IOService
* self
= (IOService
*) this;
2722 self
->lockForArbitration();
2724 ok
= handleIsOpen( forClient
);
2726 self
->unlockForArbitration();
2731 bool IOService::handleOpen( IOService
* forClient
,
2732 IOOptionBits options
,
2737 ok
= (0 == __owner
);
2739 __owner
= forClient
;
2741 else if( options
& kIOServiceSeize
) {
2742 ok
= (kIOReturnSuccess
== messageClient( kIOMessageServiceIsRequestingClose
,
2743 __owner
, (void *)(uintptr_t) options
));
2744 if( ok
&& (0 == __owner
))
2745 __owner
= forClient
;
2752 void IOService::handleClose( IOService
* forClient
,
2753 IOOptionBits options
)
2755 if( __owner
== forClient
)
2759 bool IOService::handleIsOpen( const IOService
* forClient
) const
2762 return( __owner
== forClient
);
2764 return( __owner
!= forClient
);
2768 * Probing & starting
2770 static SInt32
IONotifyOrdering( const OSMetaClassBase
* inObj1
, const OSMetaClassBase
* inObj2
, void * ref
)
2772 const _IOServiceNotifier
* obj1
= (const _IOServiceNotifier
*) inObj1
;
2773 const _IOServiceNotifier
* obj2
= (const _IOServiceNotifier
*) inObj2
;
2781 val1
= obj1
->priority
;
2784 val2
= obj2
->priority
;
2786 return ( val1
- val2
);
2789 static SInt32
IOServiceObjectOrder( const OSObject
* entry
, void * ref
)
2791 OSDictionary
* dict
;
2792 IOService
* service
;
2793 _IOServiceNotifier
* notify
;
2794 OSSymbol
* key
= (OSSymbol
*) ref
;
2797 if( (dict
= OSDynamicCast( OSDictionary
, entry
)))
2798 offset
= OSDynamicCast(OSNumber
, dict
->getObject( key
));
2799 else if( (notify
= OSDynamicCast( _IOServiceNotifier
, entry
)))
2800 return( notify
->priority
);
2802 else if( (service
= OSDynamicCast( IOService
, entry
)))
2803 offset
= OSDynamicCast(OSNumber
, service
->getProperty( key
));
2810 return( (SInt32
) offset
->unsigned32BitValue());
2812 return( kIODefaultProbeScore
);
2815 SInt32
IOServiceOrdering( const OSMetaClassBase
* inObj1
, const OSMetaClassBase
* inObj2
, void * ref
)
2817 const OSObject
* obj1
= (const OSObject
*) inObj1
;
2818 const OSObject
* obj2
= (const OSObject
*) inObj2
;
2826 val1
= IOServiceObjectOrder( obj1
, ref
);
2829 val2
= IOServiceObjectOrder( obj2
, ref
);
2831 return ( val1
- val2
);
2834 IOService
* IOService::copyClientWithCategory( const OSSymbol
* category
)
2836 IOService
* service
= 0;
2838 const OSSymbol
* nextCat
;
2840 iter
= getClientIterator();
2842 while( (service
= (IOService
*) iter
->getNextObject())) {
2843 if( kIOServiceInactiveState
& service
->__state
[0])
2845 nextCat
= (const OSSymbol
*) OSDynamicCast( OSSymbol
,
2846 service
->getProperty( gIOMatchCategoryKey
));
2847 if( category
== nextCat
)
2858 IOService
* IOService::getClientWithCategory( const OSSymbol
* category
)
2861 service
= copyClientWithCategory(category
);
2867 bool IOService::invokeNotifer( _IOServiceNotifier
* notify
)
2869 _IOServiceNotifierInvocation invocation
;
2873 invocation
.thread
= current_thread();
2876 willNotify
= (0 != (kIOServiceNotifyEnable
& notify
->state
));
2879 queue_enter( ¬ify
->handlerInvocations
, &invocation
,
2880 _IOServiceNotifierInvocation
*, link
);
2886 ret
= (*notify
->handler
)(notify
->target
, notify
->ref
, this, notify
);
2889 queue_remove( ¬ify
->handlerInvocations
, &invocation
,
2890 _IOServiceNotifierInvocation
*, link
);
2891 if( kIOServiceNotifyWaiter
& notify
->state
) {
2892 notify
->state
&= ~kIOServiceNotifyWaiter
;
2893 WAKEUPNOTIFY( notify
);
2902 * Alloc and probe matching classes,
2903 * called on the provider instance
2906 void IOService::probeCandidates( OSOrderedSet
* matches
)
2908 OSDictionary
* match
= 0;
2911 IOService
* newInst
;
2912 OSDictionary
* props
;
2915 OSOrderedSet
* familyMatches
= 0;
2916 OSOrderedSet
* startList
;
2917 OSDictionary
* startDict
= 0;
2918 const OSSymbol
* category
;
2920 _IOServiceNotifier
* notify
;
2921 OSObject
* nextMatch
= 0;
2923 bool needReloc
= false;
2927 IOService
* client
= NULL
;
2931 while( !needReloc
&& (nextMatch
= matches
->getFirstObject())) {
2933 nextMatch
->retain();
2934 matches
->removeObject(nextMatch
);
2936 if( (notify
= OSDynamicCast( _IOServiceNotifier
, nextMatch
))) {
2938 lockForArbitration();
2939 if( 0 == (__state
[0] & kIOServiceInactiveState
))
2940 invokeNotifer( notify
);
2941 unlockForArbitration();
2942 nextMatch
->release();
2946 } else if( !(match
= OSDynamicCast( OSDictionary
, nextMatch
))) {
2947 nextMatch
->release();
2954 debugFlags
= getDebugFlags( match
);
2958 category
= OSDynamicCast( OSSymbol
,
2959 match
->getObject( gIOMatchCategoryKey
));
2961 category
= gIODefaultMatchCategoryKey
;
2963 if( (client
= copyClientWithCategory(category
)) ) {
2965 if( (debugFlags
& kIOLogMatch
) && (this != gIOResources
))
2966 LOG("%s: match category %s exists\n", getName(),
2967 category
->getCStringNoCopy());
2969 nextMatch
->release();
2978 // create a copy now in case its modified during matching
2979 props
= OSDictionary::withDictionary( match
, match
->getCount());
2982 props
->setCapacityIncrement(1);
2984 // check the nub matches
2985 if( false == matchPassive(props
, kIOServiceChangesOK
| kIOServiceClassDone
))
2988 // Check to see if driver reloc has been loaded.
2989 needReloc
= (false == gIOCatalogue
->isModuleLoaded( match
));
2992 if( debugFlags
& kIOLogCatalogue
)
2993 LOG("%s: stalling for module\n", getName());
2995 // If reloc hasn't been loaded, exit;
2996 // reprobing will occur after reloc has been loaded.
3000 // reorder on family matchPropertyTable score.
3001 if( 0 == familyMatches
)
3002 familyMatches
= OSOrderedSet::withCapacity( 1,
3003 IOServiceOrdering
, (void *) gIOProbeScoreKey
);
3005 familyMatches
->setObject( props
);
3010 nextMatch
->release();
3019 if( familyMatches
) {
3022 && (props
= (OSDictionary
*) familyMatches
->getFirstObject())) {
3025 familyMatches
->removeObject( props
);
3030 debugFlags
= getDebugFlags( props
);
3033 symbol
= OSDynamicCast( OSSymbol
,
3034 props
->getObject( gIOClassKey
));
3038 //IOLog("%s alloc (symbol %p props %p)\n", symbol->getCStringNoCopy(), OBFUSCATE(symbol), OBFUSCATE(props));
3040 // alloc the driver instance
3041 inst
= (IOService
*) OSMetaClass::allocClassWithName( symbol
);
3044 IOLog("Couldn't alloc class \"%s\"\n",
3045 symbol
->getCStringNoCopy());
3049 // init driver instance
3050 if( !(inst
->init( props
))) {
3052 if( debugFlags
& kIOLogStart
)
3053 IOLog("%s::init fails\n", symbol
->getCStringNoCopy());
3057 if( __state
[1] & kIOServiceSynchronousState
)
3058 inst
->__state
[1] |= kIOServiceSynchronousState
;
3060 // give the driver the default match category if not specified
3061 category
= OSDynamicCast( OSSymbol
,
3062 props
->getObject( gIOMatchCategoryKey
));
3064 category
= gIODefaultMatchCategoryKey
;
3065 inst
->setProperty( gIOMatchCategoryKey
, (OSObject
*) category
);
3066 // attach driver instance
3067 if( !(inst
->attach( this )))
3070 // pass in score from property table
3071 score
= familyMatches
->orderObject( props
);
3073 // & probe the new driver instance
3075 if( debugFlags
& kIOLogProbe
)
3076 LOG("%s::probe(%s)\n",
3077 inst
->getMetaClass()->getClassName(), getName());
3080 newInst
= inst
->probe( this, &score
);
3081 inst
->detach( this );
3084 if( debugFlags
& kIOLogProbe
)
3085 IOLog("%s::probe fails\n", symbol
->getCStringNoCopy());
3091 newPri
= OSNumber::withNumber( score
, 32 );
3093 newInst
->setProperty( gIOProbeScoreKey
, newPri
);
3097 // add to start list for the match category
3099 startDict
= OSDictionary::withCapacity( 1 );
3100 assert( startDict
);
3101 startList
= (OSOrderedSet
*)
3102 startDict
->getObject( category
);
3103 if( 0 == startList
) {
3104 startList
= OSOrderedSet::withCapacity( 1,
3105 IOServiceOrdering
, (void *) gIOProbeScoreKey
);
3106 if( startDict
&& startList
) {
3107 startDict
->setObject( category
, startList
);
3108 startList
->release();
3111 assert( startList
);
3113 startList
->setObject( newInst
);
3121 familyMatches
->release();
3125 // start the best (until success) of each category
3127 iter
= OSCollectionIterator::withCollection( startDict
);
3129 while( (category
= (const OSSymbol
*) iter
->getNextObject())) {
3131 startList
= (OSOrderedSet
*) startDict
->getObject( category
);
3132 assert( startList
);
3137 while( true // (!started)
3138 && (inst
= (IOService
*)startList
->getFirstObject())) {
3141 startList
->removeObject(inst
);
3144 debugFlags
= getDebugFlags( inst
->getPropertyTable() );
3146 if( debugFlags
& kIOLogStart
) {
3148 LOG( "match category exists, skipping " );
3149 LOG( "%s::start(%s) <%d>\n", inst
->getName(),
3150 getName(), inst
->getRetainCount());
3153 if( false == started
)
3154 started
= startCandidate( inst
);
3156 if( (debugFlags
& kIOLogStart
) && (false == started
))
3157 LOG( "%s::start(%s) <%d> failed\n", inst
->getName(), getName(),
3158 inst
->getRetainCount());
3167 // adjust the busy count by +1 if matching is stalled for a module,
3168 // or -1 if a previously stalled matching is complete.
3169 lockForArbitration();
3171 uint64_t regID
= getRegistryEntryID();
3174 adjBusy
= (__state
[1] & kIOServiceModuleStallState
) ? 0 : 1;
3178 IOSERVICE_MODULESTALL
,
3180 (uintptr_t) (regID
>> 32),
3184 __state
[1] |= kIOServiceModuleStallState
;
3187 } else if( __state
[1] & kIOServiceModuleStallState
) {
3190 IOSERVICE_MODULEUNSTALL
,
3192 (uintptr_t) (regID
>> 32),
3196 __state
[1] &= ~kIOServiceModuleStallState
;
3200 _adjustBusy( adjBusy
);
3201 unlockForArbitration();
3204 startDict
->release();
3208 * Start a previously attached & probed instance,
3209 * called on exporting object instance
3212 bool IOService::startCandidate( IOService
* service
)
3216 ok
= service
->attach( this );
3220 if (this != gIOResources
)
3222 // stall for any nub resources
3224 // stall for any driver resources
3225 service
->checkResources();
3228 AbsoluteTime startTime
;
3229 AbsoluteTime endTime
;
3232 if (kIOLogStart
& gIOKitDebug
)
3233 clock_get_uptime(&startTime
);
3235 ok
= service
->start(this);
3237 if (kIOLogStart
& gIOKitDebug
)
3239 clock_get_uptime(&endTime
);
3241 if (CMP_ABSOLUTETIME(&endTime
, &startTime
) > 0)
3243 SUB_ABSOLUTETIME(&endTime
, &startTime
);
3244 absolutetime_to_nanoseconds(endTime
, &nano
);
3245 if (nano
> 500000000ULL)
3246 IOLog("%s::start took %ld ms\n", service
->getName(), (long)(UInt32
)(nano
/ 1000000ULL));
3250 service
->detach( this );
3255 void IOService::publishResource( const char * key
, OSObject
* value
)
3257 const OSSymbol
* sym
;
3259 if( (sym
= OSSymbol::withCString( key
))) {
3260 publishResource( sym
, value
);
3265 void IOService::publishResource( const OSSymbol
* key
, OSObject
* value
)
3268 value
= (OSObject
*) gIOServiceKey
;
3270 gIOResources
->setProperty( key
, value
);
3272 if( IORecursiveLockHaveLock( gNotificationLock
))
3275 gIOResourceGenerationCount
++;
3276 gIOResources
->registerService();
3279 bool IOService::addNeededResource( const char * key
)
3281 OSObject
* resourcesProp
;
3286 resourcesProp
= getProperty( gIOResourceMatchKey
);
3288 newKey
= OSString::withCString( key
);
3289 if( (0 == resourcesProp
) || (0 == newKey
))
3292 set
= OSDynamicCast( OSSet
, resourcesProp
);
3294 set
= OSSet::withCapacity( 1 );
3296 set
->setObject( resourcesProp
);
3301 set
->setObject( newKey
);
3303 ret
= setProperty( gIOResourceMatchKey
, set
);
3309 bool IOService::checkResource( OSObject
* matching
)
3312 OSDictionary
* table
;
3314 if( (str
= OSDynamicCast( OSString
, matching
))) {
3315 if( gIOResources
->getProperty( str
))
3320 table
= resourceMatching( str
);
3321 else if( (table
= OSDynamicCast( OSDictionary
, matching
)))
3324 IOLog("%s: Can't match using: %s\n", getName(),
3325 matching
->getMetaClass()->getClassName());
3326 /* false would stall forever */
3330 if( gIOKitDebug
& kIOLogConfig
)
3331 LOG("config(%p): stalling %s\n", OBFUSCATE(IOThreadSelf()), getName());
3333 waitForService( table
);
3335 if( gIOKitDebug
& kIOLogConfig
)
3336 LOG("config(%p): waking\n", OBFUSCATE(IOThreadSelf()) );
3341 bool IOService::checkResources( void )
3343 OSObject
* resourcesProp
;
3348 resourcesProp
= getProperty( gIOResourceMatchKey
);
3349 if( 0 == resourcesProp
)
3352 if( (set
= OSDynamicCast( OSSet
, resourcesProp
))) {
3354 iter
= OSCollectionIterator::withCollection( set
);
3356 while( ok
&& (resourcesProp
= iter
->getNextObject()) )
3357 ok
= checkResource( resourcesProp
);
3362 ok
= checkResource( resourcesProp
);
3368 void _IOConfigThread::configThread( void )
3370 _IOConfigThread
* inst
;
3373 if( !(inst
= new _IOConfigThread
))
3378 if (KERN_SUCCESS
!= kernel_thread_start(&_IOConfigThread::main
, inst
, &unused
))
3391 void _IOConfigThread::free( void )
3393 thread_deallocate(current_thread());
3397 void IOService::doServiceMatch( IOOptionBits options
)
3399 _IOServiceNotifier
* notify
;
3401 OSOrderedSet
* matches
;
3402 SInt32 catalogGeneration
;
3403 bool keepGuessing
= true;
3404 bool reRegistered
= true;
3407 // job->nub->deliverNotification( gIOPublishNotification,
3408 // kIOServiceRegisteredState, 0xffffffff );
3410 while( keepGuessing
) {
3412 matches
= gIOCatalogue
->findDrivers( this, &catalogGeneration
);
3413 // the matches list should always be created by findDrivers()
3416 lockForArbitration();
3417 if( 0 == (__state
[0] & kIOServiceFirstPublishState
)) {
3418 getMetaClass()->addInstance(this);
3419 deliverNotification( gIOFirstPublishNotification
,
3420 kIOServiceFirstPublishState
, 0xffffffff );
3423 __state
[1] &= ~kIOServiceNeedConfigState
;
3424 __state
[1] |= kIOServiceConfigState
;
3425 didRegister
= (0 == (kIOServiceRegisteredState
& __state
[0]));
3426 __state
[0] |= kIOServiceRegisteredState
;
3428 keepGuessing
&= (0 == (__state
[0] & kIOServiceInactiveState
));
3429 if (reRegistered
&& keepGuessing
) {
3430 iter
= OSCollectionIterator::withCollection( (OSOrderedSet
*)
3431 gNotifications
->getObject( gIOPublishNotification
) );
3433 while((notify
= (_IOServiceNotifier
*)
3434 iter
->getNextObject())) {
3436 if( matchPassive(notify
->matching
, 0)
3437 && (kIOServiceNotifyEnable
& notify
->state
))
3438 matches
->setObject( notify
);
3445 unlockForArbitration();
3447 if (keepGuessing
&& matches
->getCount() && (kIOReturnSuccess
== getResources()))
3448 probeCandidates( matches
);
3453 lockForArbitration();
3454 reRegistered
= (0 != (__state
[1] & kIOServiceNeedConfigState
));
3456 (reRegistered
|| (catalogGeneration
!=
3457 gIOCatalogue
->getGenerationCount()))
3458 && (0 == (__state
[0] & kIOServiceInactiveState
));
3461 unlockForArbitration();
3464 if( (0 == (__state
[0] & kIOServiceInactiveState
))
3465 && (0 == (__state
[1] & kIOServiceModuleStallState
)) ) {
3466 deliverNotification( gIOMatchedNotification
,
3467 kIOServiceMatchedState
, 0xffffffff );
3468 if( 0 == (__state
[0] & kIOServiceFirstMatchState
))
3469 deliverNotification( gIOFirstMatchNotification
,
3470 kIOServiceFirstMatchState
, 0xffffffff );
3473 __state
[1] &= ~kIOServiceConfigState
;
3474 scheduleTerminatePhase2();
3477 unlockForArbitration();
3480 UInt32
IOService::_adjustBusy( SInt32 delta
)
3485 bool wasQuiet
, nowQuiet
, needWake
;
3488 result
= __state
[1] & kIOServiceBusyStateMask
;
3492 next
->lockForArbitration();
3493 count
= next
->__state
[1] & kIOServiceBusyStateMask
;
3494 wasQuiet
= (0 == count
);
3495 if (((delta
< 0) && wasQuiet
) || ((delta
> 0) && (kIOServiceBusyMax
== count
)))
3496 OSReportWithBacktrace("%s: bad busy count (%d,%d)\n", next
->getName(), count
, delta
);
3499 next
->__state
[1] = (next
->__state
[1] & ~kIOServiceBusyStateMask
) | count
;
3500 nowQuiet
= (0 == count
);
3501 needWake
= (0 != (kIOServiceBusyWaiterState
& next
->__state
[1]));
3504 next
->__state
[1] &= ~kIOServiceBusyWaiterState
;
3505 IOLockLock( gIOServiceBusyLock
);
3506 thread_wakeup( (event_t
) next
);
3507 IOLockUnlock( gIOServiceBusyLock
);
3510 next
->unlockForArbitration();
3512 if( (wasQuiet
|| nowQuiet
) ) {
3513 uint64_t regID
= next
->getRegistryEntryID();
3516 ((wasQuiet
/*nowBusy*/) ? IOSERVICE_BUSY
: IOSERVICE_NONBUSY
),
3518 (uintptr_t) (regID
>> 32),
3524 next
->__timeBusy
= mach_absolute_time();
3528 next
->__accumBusy
+= mach_absolute_time() - next
->__timeBusy
;
3529 next
->__timeBusy
= 0;
3532 MessageClientsContext context
;
3534 context
.service
= next
;
3535 context
.type
= kIOMessageServiceBusyStateChange
;
3536 context
.argument
= (void *) wasQuiet
; /*nowBusy*/
3537 context
.argSize
= 0;
3539 applyToInterestNotifiers( next
, gIOBusyInterest
,
3540 &messageClientsApplier
, &context
);
3543 if( nowQuiet
&& (next
== gIOServiceRoot
)) {
3544 OSKext::considerUnloads();
3545 IOServiceTrace(IOSERVICE_REGISTRY_QUIET
, 0, 0, 0, 0);
3550 delta
= nowQuiet
? -1 : +1;
3552 } while( (wasQuiet
|| nowQuiet
) && (next
= next
->getProvider()));
3557 void IOService::adjustBusy( SInt32 delta
)
3559 lockForArbitration();
3560 _adjustBusy( delta
);
3561 unlockForArbitration();
3564 uint64_t IOService::getAccumulatedBusyTime( void )
3566 uint64_t accumBusy
= __accumBusy
;
3567 uint64_t timeBusy
= __timeBusy
;
3572 accumBusy
= __accumBusy
;
3573 timeBusy
= __timeBusy
;
3575 accumBusy
+= mach_absolute_time() - timeBusy
;
3577 while (timeBusy
!= __timeBusy
);
3579 absolutetime_to_nanoseconds(*(AbsoluteTime
*)&accumBusy
, &nano
);
3584 UInt32
IOService::getBusyState( void )
3586 return( __state
[1] & kIOServiceBusyStateMask
);
3589 IOReturn
IOService::waitForState( UInt32 mask
, UInt32 value
,
3590 mach_timespec_t
* timeout
)
3592 panic("waitForState");
3593 return (kIOReturnUnsupported
);
3596 IOReturn
IOService::waitForState( UInt32 mask
, UInt32 value
,
3600 int waitResult
= THREAD_AWAKENED
;
3601 bool computeDeadline
= true;
3602 AbsoluteTime abstime
;
3605 lockForArbitration();
3606 IOLockLock( gIOServiceBusyLock
);
3607 wait
= (value
!= (__state
[1] & mask
));
3609 __state
[1] |= kIOServiceBusyWaiterState
;
3610 unlockForArbitration();
3611 if( timeout
!= UINT64_MAX
) {
3612 if( computeDeadline
) {
3613 AbsoluteTime nsinterval
;
3614 nanoseconds_to_absolutetime(timeout
, &nsinterval
);
3615 clock_absolutetime_interval_to_deadline(nsinterval
, &abstime
);
3616 computeDeadline
= false;
3618 assert_wait_deadline((event_t
)this, THREAD_UNINT
, __OSAbsoluteTime(abstime
));
3621 assert_wait((event_t
)this, THREAD_UNINT
);
3623 unlockForArbitration();
3624 IOLockUnlock( gIOServiceBusyLock
);
3626 waitResult
= thread_block(THREAD_CONTINUE_NULL
);
3628 } while( wait
&& (waitResult
!= THREAD_TIMED_OUT
));
3630 if( waitResult
== THREAD_TIMED_OUT
)
3631 return( kIOReturnTimeout
);
3633 return( kIOReturnSuccess
);
3636 IOReturn
IOService::waitQuiet( uint64_t timeout
)
3639 ret
= waitForState( kIOServiceBusyStateMask
, 0, timeout
);
3640 if ((kIOReturnTimeout
== ret
) && (timeout
>= 30000000000) && (kIOWaitQuietPanics
& gIOKitDebug
))
3642 panic("IOService 0x%llx (%s) busy timeout", getRegistryEntryID(), getName());
3647 IOReturn
IOService::waitQuiet( mach_timespec_t
* timeout
)
3653 timeoutNS
= timeout
->tv_sec
;
3654 timeoutNS
*= kSecondScale
;
3655 timeoutNS
+= timeout
->tv_nsec
;
3658 timeoutNS
= UINT64_MAX
;
3660 return (waitQuiet(timeoutNS
));
3663 bool IOService::serializeProperties( OSSerialize
* s
) const
3666 ((IOService
*)this)->setProperty( ((IOService
*)this)->__state
,
3667 sizeof( __state
), "__state");
3669 return( super::serializeProperties(s
) );
3673 void _IOConfigThread::main(void * arg
, wait_result_t result
)
3675 _IOConfigThread
* self
= (_IOConfigThread
*) arg
;
3676 _IOServiceJob
* job
;
3680 thread_precedence_policy_data_t precedence
= { -1 };
3682 kr
= thread_policy_set(current_thread(),
3683 THREAD_PRECEDENCE_POLICY
,
3684 (thread_policy_t
) &precedence
,
3685 THREAD_PRECEDENCE_POLICY_COUNT
);
3686 if (KERN_SUCCESS
!= kr
)
3687 IOLog("thread_policy_set(%d)\n", kr
);
3693 semaphore_wait( gJobsSemaphore
);
3695 IOTakeLock( gJobsLock
);
3696 job
= (_IOServiceJob
*) gJobs
->getFirstObject();
3698 gJobs
->removeObject(job
);
3701 // gNumConfigThreads--; // we're out of service
3702 gNumWaitingThreads
--; // we're out of service
3704 IOUnlock( gJobsLock
);
3710 if( gIOKitDebug
& kIOLogConfig
)
3711 LOG("config(%p): starting on %s, %d\n",
3712 OBFUSCATE(IOThreadSelf()), job
->nub
->getName(), job
->type
);
3714 switch( job
->type
) {
3717 nub
->doServiceMatch( job
->options
);
3721 LOG("config(%p): strange type (%d)\n",
3722 OBFUSCATE(IOThreadSelf()), job
->type
);
3729 IOTakeLock( gJobsLock
);
3730 alive
= (gOutstandingJobs
> gNumWaitingThreads
);
3732 gNumWaitingThreads
++; // back in service
3733 // gNumConfigThreads++;
3735 if( 0 == --gNumConfigThreads
) {
3736 // IOLog("MATCH IDLE\n");
3737 IOLockWakeup( gJobsLock
, (event_t
) &gNumConfigThreads
, /* one-thread */ false );
3740 IOUnlock( gJobsLock
);
3745 if( gIOKitDebug
& kIOLogConfig
)
3746 LOG("config(%p): terminating\n", OBFUSCATE(IOThreadSelf()) );
3751 IOReturn
IOService::waitMatchIdle( UInt32 msToWait
)
3754 int waitResult
= THREAD_AWAKENED
;
3755 bool computeDeadline
= true;
3756 AbsoluteTime deadline
;
3758 IOLockLock( gJobsLock
);
3760 wait
= (0 != gNumConfigThreads
);
3763 if( computeDeadline
) {
3764 clock_interval_to_deadline(
3765 msToWait
, kMillisecondScale
, &deadline
);
3766 computeDeadline
= false;
3768 waitResult
= IOLockSleepDeadline( gJobsLock
, &gNumConfigThreads
,
3769 deadline
, THREAD_UNINT
);
3771 waitResult
= IOLockSleep( gJobsLock
, &gNumConfigThreads
,
3775 } while( wait
&& (waitResult
!= THREAD_TIMED_OUT
));
3776 IOLockUnlock( gJobsLock
);
3778 if( waitResult
== THREAD_TIMED_OUT
)
3779 return( kIOReturnTimeout
);
3781 return( kIOReturnSuccess
);
3784 void _IOServiceJob::pingConfig( _IOServiceJob
* job
)
3791 IOTakeLock( gJobsLock
);
3794 gJobs
->setLastObject( job
);
3796 count
= gNumWaitingThreads
;
3797 // if( gNumConfigThreads) count++;// assume we're called from a config thread
3799 create
= ( (gOutstandingJobs
> count
)
3800 && (gNumConfigThreads
< kMaxConfigThreads
) );
3802 gNumConfigThreads
++;
3803 gNumWaitingThreads
++;
3806 IOUnlock( gJobsLock
);
3811 if( gIOKitDebug
& kIOLogConfig
)
3812 LOG("config(%d): creating\n", gNumConfigThreads
- 1);
3813 _IOConfigThread::configThread();
3816 semaphore_signal( gJobsSemaphore
);
3819 struct IOServiceMatchContext
3821 OSDictionary
* table
;
3829 bool IOService::instanceMatch(const OSObject
* entry
, void * context
)
3831 IOServiceMatchContext
* ctx
= (typeof(ctx
)) context
;
3832 IOService
* service
= (typeof(service
)) entry
;
3833 OSDictionary
* table
= ctx
->table
;
3834 uint32_t options
= ctx
->options
;
3835 uint32_t state
= ctx
->state
;
3842 match
= ((state
== (state
& service
->__state
[0]))
3843 && (0 == (service
->__state
[0] & kIOServiceInactiveState
)));
3845 ctx
->count
+= table
->getCount();
3846 match
= service
->matchInternal(table
, options
, &done
);
3853 if ((kIONotifyOnce
& options
) && (ctx
->done
== ctx
->count
))
3856 ctx
->result
= service
;
3859 else if (!ctx
->result
)
3861 ctx
->result
= OSSet::withObjects((const OSObject
**) &service
, 1, 1);
3865 ((OSSet
*)ctx
->result
)->setObject(service
);
3870 // internal - call with gNotificationLock
3871 OSObject
* IOService::copyExistingServices( OSDictionary
* matching
,
3872 IOOptionBits inState
, IOOptionBits options
)
3874 OSObject
* current
= 0;
3876 IOService
* service
;
3884 OSSerialize
* s
= OSSerialize::withCapacity(128);
3885 matching
->serialize(s
);
3888 if((obj
= matching
->getObject(gIOProviderClassKey
))
3890 && gIOResourcesKey
->isEqualTo(obj
)
3891 && (service
= gIOResources
))
3893 if( (inState
== (service
->__state
[0] & inState
))
3894 && (0 == (service
->__state
[0] & kIOServiceInactiveState
))
3895 && service
->matchPassive(matching
, options
))
3897 if( options
& kIONotifyOnce
)
3903 current
= OSSet::withObjects((const OSObject
**) &service
, 1, 1 );
3908 IOServiceMatchContext ctx
;
3909 ctx
.table
= matching
;
3910 ctx
.state
= inState
;
3913 ctx
.options
= options
;
3916 if ((str
= OSDynamicCast(OSString
, obj
)))
3918 const OSSymbol
* sym
= OSSymbol::withString(str
);
3919 OSMetaClass::applyToInstancesOfClassName(sym
, instanceMatch
, &ctx
);
3924 IOService::gMetaClass
.applyToInstances(instanceMatch
, &ctx
);
3928 current
= ctx
.result
;
3930 options
|= kIOServiceInternalDone
| kIOServiceClassDone
;
3931 if (current
&& (ctx
.done
!= ctx
.count
))
3934 source
= OSDynamicCast(OSSet
, current
);
3936 while ((service
= (IOService
*) source
->getAnyObject()))
3938 if (service
->matchPassive(matching
, options
))
3940 if( options
& kIONotifyOnce
)
3948 ((OSSet
*)current
)->setObject( service
);
3952 current
= OSSet::withObjects(
3953 (const OSObject
**) &service
, 1, 1 );
3956 source
->removeObject(service
);
3964 OSObject
* _current
= 0;
3966 iter
= IORegistryIterator::iterateOver( gIOServicePlane
,
3967 kIORegistryIterateRecursively
);
3971 while( (service
= (IOService
*) iter
->getNextObject())) {
3972 if( (inState
== (service
->__state
[0] & inState
))
3973 && (0 == (service
->__state
[0] & kIOServiceInactiveState
))
3974 && service
->matchPassive(matching
, 0)) {
3976 if( options
& kIONotifyOnce
) {
3982 ((OSSet
*)_current
)->setObject( service
);
3984 _current
= OSSet::withObjects(
3985 (const OSObject
**) &service
, 1, 1 );
3988 } while( !service
&& !iter
->isValid());
3993 if ( ((current
!= 0) != (_current
!= 0))
3994 || (current
&& _current
&& !current
->isEqualTo(_current
)))
3996 OSSerialize
* s1
= OSSerialize::withCapacity(128);
3997 OSSerialize
* s2
= OSSerialize::withCapacity(128);
3998 current
->serialize(s1
);
3999 _current
->serialize(s2
);
4000 kprintf("**mismatch** %p %p\n%s\n%s\n%s\n", OBFUSCATE(current
),
4001 OBFUSCATE(_current
), s
->text(), s1
->text(), s2
->text());
4006 if (_current
) _current
->release();
4012 if( current
&& (0 == (options
& (kIONotifyOnce
| kIOServiceExistingSet
)))) {
4013 iter
= OSCollectionIterator::withCollection( (OSSet
*)current
);
4022 OSIterator
* IOService::getMatchingServices( OSDictionary
* matching
)
4026 // is a lock even needed?
4029 iter
= (OSIterator
*) copyExistingServices( matching
,
4030 kIOServiceMatchedState
);
4037 IOService
* IOService::copyMatchingService( OSDictionary
* matching
)
4039 IOService
* service
;
4041 // is a lock even needed?
4044 service
= (IOService
*) copyExistingServices( matching
,
4045 kIOServiceMatchedState
, kIONotifyOnce
);
4052 struct _IOServiceMatchingNotificationHandlerRef
4054 IOServiceNotificationHandler handler
;
4058 static bool _IOServiceMatchingNotificationHandler( void * target
, void * refCon
,
4059 IOService
* newService
,
4060 IONotifier
* notifier
)
4062 return ((*((_IOServiceNotifier
*) notifier
)->compatHandler
)(target
, refCon
, newService
));
4065 // internal - call with gNotificationLock
4066 IONotifier
* IOService::setNotification(
4067 const OSSymbol
* type
, OSDictionary
* matching
,
4068 IOServiceMatchingNotificationHandler handler
, void * target
, void * ref
,
4071 _IOServiceNotifier
* notify
= 0;
4077 notify
= new _IOServiceNotifier
;
4078 if( notify
&& !notify
->init()) {
4084 notify
->handler
= handler
;
4085 notify
->target
= target
;
4086 notify
->matching
= matching
;
4088 if (handler
== &_IOServiceMatchingNotificationHandler
)
4090 notify
->compatHandler
= ((_IOServiceMatchingNotificationHandlerRef
*)ref
)->handler
;
4091 notify
->ref
= ((_IOServiceMatchingNotificationHandlerRef
*)ref
)->ref
;
4095 notify
->priority
= priority
;
4096 notify
->state
= kIOServiceNotifyEnable
;
4097 queue_init( ¬ify
->handlerInvocations
);
4101 if( 0 == (set
= (OSOrderedSet
*) gNotifications
->getObject( type
))) {
4102 set
= OSOrderedSet::withCapacity( 1,
4103 IONotifyOrdering
, 0 );
4105 gNotifications
->setObject( type
, set
);
4109 notify
->whence
= set
;
4111 set
->setObject( notify
);
4117 // internal - call with gNotificationLock
4118 IONotifier
* IOService::doInstallNotification(
4119 const OSSymbol
* type
, OSDictionary
* matching
,
4120 IOServiceMatchingNotificationHandler handler
,
4121 void * target
, void * ref
,
4122 SInt32 priority
, OSIterator
** existing
)
4125 IONotifier
* notify
;
4126 IOOptionBits inState
;
4131 if( type
== gIOPublishNotification
)
4132 inState
= kIOServiceRegisteredState
;
4134 else if( type
== gIOFirstPublishNotification
)
4135 inState
= kIOServiceFirstPublishState
;
4137 else if( (type
== gIOMatchedNotification
)
4138 || (type
== gIOFirstMatchNotification
))
4139 inState
= kIOServiceMatchedState
;
4140 else if( type
== gIOTerminatedNotification
)
4145 notify
= setNotification( type
, matching
, handler
, target
, ref
, priority
);
4148 // get the current set
4149 exist
= (OSIterator
*) copyExistingServices( matching
, inState
);
4158 #if !defined(__LP64__)
4159 IONotifier
* IOService::installNotification(const OSSymbol
* type
, OSDictionary
* matching
,
4160 IOServiceNotificationHandler handler
,
4161 void * target
, void * refCon
,
4162 SInt32 priority
, OSIterator
** existing
)
4164 IONotifier
* result
;
4165 _IOServiceMatchingNotificationHandlerRef ref
;
4166 ref
.handler
= handler
;
4169 result
= (_IOServiceNotifier
*) installNotification( type
, matching
,
4170 &_IOServiceMatchingNotificationHandler
,
4171 target
, &ref
, priority
, existing
);
4173 matching
->release();
4177 #endif /* !defined(__LP64__) */
4180 IONotifier
* IOService::installNotification(
4181 const OSSymbol
* type
, OSDictionary
* matching
,
4182 IOServiceMatchingNotificationHandler handler
,
4183 void * target
, void * ref
,
4184 SInt32 priority
, OSIterator
** existing
)
4186 IONotifier
* notify
;
4190 notify
= doInstallNotification( type
, matching
, handler
, target
, ref
,
4191 priority
, existing
);
4198 IONotifier
* IOService::addNotification(
4199 const OSSymbol
* type
, OSDictionary
* matching
,
4200 IOServiceNotificationHandler handler
,
4201 void * target
, void * refCon
,
4204 IONotifier
* result
;
4205 _IOServiceMatchingNotificationHandlerRef ref
;
4207 ref
.handler
= handler
;
4210 result
= addMatchingNotification(type
, matching
, &_IOServiceMatchingNotificationHandler
,
4211 target
, &ref
, priority
);
4214 matching
->release();
4219 IONotifier
* IOService::addMatchingNotification(
4220 const OSSymbol
* type
, OSDictionary
* matching
,
4221 IOServiceMatchingNotificationHandler handler
,
4222 void * target
, void * ref
,
4225 OSIterator
* existing
= NULL
;
4226 _IOServiceNotifier
* notify
;
4229 notify
= (_IOServiceNotifier
*) installNotification( type
, matching
,
4230 handler
, target
, ref
, priority
, &existing
);
4232 // send notifications for existing set
4235 notify
->retain(); // in case handler remove()s
4236 while( (next
= (IOService
*) existing
->getNextObject())) {
4238 next
->lockForArbitration();
4239 if( 0 == (next
->__state
[0] & kIOServiceInactiveState
))
4240 next
->invokeNotifer( notify
);
4241 next
->unlockForArbitration();
4244 existing
->release();
4250 bool IOService::syncNotificationHandler(
4251 void * /* target */, void * ref
,
4252 IOService
* newService
,
4253 IONotifier
* notifier
)
4257 if (!*((IOService
**) ref
))
4259 newService
->retain();
4260 (*(IOService
**) ref
) = newService
;
4268 IOService
* IOService::waitForMatchingService( OSDictionary
* matching
,
4271 IONotifier
* notify
= 0;
4272 // priority doesn't help us much since we need a thread wakeup
4273 SInt32 priority
= 0;
4284 result
= (IOService
*) copyExistingServices( matching
,
4285 kIOServiceMatchedState
, kIONotifyOnce
);
4288 notify
= IOService::setNotification( gIOMatchedNotification
, matching
,
4289 &IOService::syncNotificationHandler
, (void *) 0,
4290 &result
, priority
);
4293 if (UINT64_MAX
!= timeout
)
4295 AbsoluteTime deadline
;
4296 nanoseconds_to_absolutetime(timeout
, &deadline
);
4297 clock_absolutetime_interval_to_deadline(deadline
, &deadline
);
4298 SLEEPNOTIFYTO(&result
, deadline
);
4302 SLEEPNOTIFY(&result
);
4310 notify
->remove(); // dequeues
4315 IOService
* IOService::waitForService( OSDictionary
* matching
,
4316 mach_timespec_t
* timeout
)
4323 timeoutNS
= timeout
->tv_sec
;
4324 timeoutNS
*= kSecondScale
;
4325 timeoutNS
+= timeout
->tv_nsec
;
4328 timeoutNS
= UINT64_MAX
;
4330 result
= waitForMatchingService(matching
, timeoutNS
);
4332 matching
->release();
4339 void IOService::deliverNotification( const OSSymbol
* type
,
4340 IOOptionBits orNewState
, IOOptionBits andNewState
)
4342 _IOServiceNotifier
* notify
;
4344 OSArray
* willSend
= 0;
4346 lockForArbitration();
4348 if( (0 == (__state
[0] & kIOServiceInactiveState
))
4349 || (type
== gIOTerminatedNotification
)) {
4353 iter
= OSCollectionIterator::withCollection( (OSOrderedSet
*)
4354 gNotifications
->getObject( type
) );
4357 while( (notify
= (_IOServiceNotifier
*) iter
->getNextObject())) {
4359 if( matchPassive(notify
->matching
, 0)
4360 && (kIOServiceNotifyEnable
& notify
->state
)) {
4362 willSend
= OSArray::withCapacity(8);
4364 willSend
->setObject( notify
);
4370 __state
[0] = (__state
[0] | orNewState
) & andNewState
;
4376 for( unsigned int idx
= 0;
4377 (notify
= (_IOServiceNotifier
*) willSend
->getObject(idx
));
4379 invokeNotifer( notify
);
4381 willSend
->release();
4383 unlockForArbitration();
4386 IOOptionBits
IOService::getState( void ) const
4388 return( __state
[0] );
4392 * Helpers to make matching objects for simple cases
4395 OSDictionary
* IOService::serviceMatching( const OSString
* name
,
4396 OSDictionary
* table
)
4399 const OSString
* str
;
4401 str
= OSSymbol::withString(name
);
4406 table
= OSDictionary::withCapacity( 2 );
4408 table
->setObject(gIOProviderClassKey
, (OSObject
*)str
);
4414 OSDictionary
* IOService::serviceMatching( const char * name
,
4415 OSDictionary
* table
)
4417 const OSString
* str
;
4419 str
= OSSymbol::withCString( name
);
4423 table
= serviceMatching( str
, table
);
4428 OSDictionary
* IOService::nameMatching( const OSString
* name
,
4429 OSDictionary
* table
)
4432 table
= OSDictionary::withCapacity( 2 );
4434 table
->setObject( gIONameMatchKey
, (OSObject
*)name
);
4439 OSDictionary
* IOService::nameMatching( const char * name
,
4440 OSDictionary
* table
)
4442 const OSString
* str
;
4444 str
= OSSymbol::withCString( name
);
4448 table
= nameMatching( str
, table
);
4453 OSDictionary
* IOService::resourceMatching( const OSString
* str
,
4454 OSDictionary
* table
)
4456 table
= serviceMatching( gIOResourcesKey
, table
);
4458 table
->setObject( gIOResourceMatchKey
, (OSObject
*) str
);
4463 OSDictionary
* IOService::resourceMatching( const char * name
,
4464 OSDictionary
* table
)
4466 const OSSymbol
* str
;
4468 str
= OSSymbol::withCString( name
);
4472 table
= resourceMatching( str
, table
);
4478 OSDictionary
* IOService::propertyMatching( const OSSymbol
* key
, const OSObject
* value
,
4479 OSDictionary
* table
)
4481 OSDictionary
* properties
;
4483 properties
= OSDictionary::withCapacity( 2 );
4486 properties
->setObject( key
, value
);
4489 table
= OSDictionary::withCapacity( 2 );
4491 table
->setObject( gIOPropertyMatchKey
, properties
);
4493 properties
->release();
4498 OSDictionary
* IOService::registryEntryIDMatching( uint64_t entryID
,
4499 OSDictionary
* table
)
4503 num
= OSNumber::withNumber( entryID
, 64 );
4508 table
= OSDictionary::withCapacity( 2 );
4510 table
->setObject( gIORegistryEntryIDKey
, num
);
4520 * _IOServiceNotifier
4523 // wait for all threads, other than the current one,
4524 // to exit the handler
4526 void _IOServiceNotifier::wait()
4528 _IOServiceNotifierInvocation
* next
;
4533 queue_iterate( &handlerInvocations
, next
,
4534 _IOServiceNotifierInvocation
*, link
) {
4535 if( next
->thread
!= current_thread() ) {
4541 state
|= kIOServiceNotifyWaiter
;
4548 void _IOServiceNotifier::free()
4550 assert( queue_empty( &handlerInvocations
));
4554 void _IOServiceNotifier::remove()
4559 whence
->removeObject( (OSObject
*) this );
4563 matching
->release();
4567 state
&= ~kIOServiceNotifyEnable
;
4576 bool _IOServiceNotifier::disable()
4582 ret
= (0 != (kIOServiceNotifyEnable
& state
));
4583 state
&= ~kIOServiceNotifyEnable
;
4592 void _IOServiceNotifier::enable( bool was
)
4596 state
|= kIOServiceNotifyEnable
;
4598 state
&= ~kIOServiceNotifyEnable
;
4606 IOService
* IOResources::resources( void )
4610 inst
= new IOResources
;
4611 if( inst
&& !inst
->init()) {
4619 bool IOResources::init( OSDictionary
* dictionary
)
4621 // Do super init first
4622 if ( !super::init() )
4625 // Allow PAL layer to publish a value
4626 const char *property_name
;
4629 pal_get_resource_property( &property_name
, &property_value
);
4631 if( property_name
) {
4633 const OSSymbol
* sym
;
4635 if( (num
= OSNumber::withNumber(property_value
, 32)) != 0 ) {
4636 if( (sym
= OSSymbol::withCString( property_name
)) != 0 ) {
4637 this->setProperty( sym
, num
);
4647 IOWorkLoop
* IOResources::getWorkLoop() const
4649 // If we are the resource root
4650 // then use the platform's workloop
4651 if (this == (IOResources
*) gIOResources
)
4652 return getPlatform()->getWorkLoop();
4654 return IOService::getWorkLoop();
4657 bool IOResources::matchPropertyTable( OSDictionary
* table
)
4665 prop
= table
->getObject( gIOResourceMatchKey
);
4666 str
= OSDynamicCast( OSString
, prop
);
4668 ok
= (0 != getProperty( str
));
4670 else if( (set
= OSDynamicCast( OSSet
, prop
))) {
4672 iter
= OSCollectionIterator::withCollection( set
);
4674 while( ok
&& (str
= OSDynamicCast( OSString
, iter
->getNextObject()) ))
4675 ok
= (0 != getProperty( str
));
4684 void IOService::consoleLockTimer(thread_call_param_t p0
, thread_call_param_t p1
)
4686 IOService::updateConsoleUsers(NULL
, 0);
4689 void IOService::updateConsoleUsers(OSArray
* consoleUsers
, IOMessage systemMessage
)
4691 IORegistryEntry
* regEntry
;
4692 OSObject
* locked
= kOSBooleanFalse
;
4695 OSDictionary
* user
;
4696 static IOMessage sSystemPower
;
4698 regEntry
= IORegistryEntry::getRegistryRoot();
4700 if (!gIOChosenEntry
)
4701 gIOChosenEntry
= IORegistryEntry::fromPath("/chosen", gIODTPlane
);
4703 IOLockLock(gIOConsoleUsersLock
);
4707 sSystemPower
= systemMessage
;
4709 if ((kIOMessageSystemHasPoweredOn
== systemMessage
) && IOHibernateWasScreenLocked())
4711 locked
= kOSBooleanTrue
;
4713 #endif /* HIBERNATION */
4719 gIOConsoleLoggedIn
= false;
4721 (user
= OSDynamicCast(OSDictionary
, consoleUsers
->getObject(idx
)));
4724 gIOConsoleLoggedIn
|= ((kOSBooleanTrue
== user
->getObject(gIOConsoleSessionOnConsoleKey
))
4725 && (kOSBooleanTrue
== user
->getObject(gIOConsoleSessionLoginDoneKey
)));
4728 num
= OSDynamicCast(OSNumber
, user
->getObject(gIOConsoleSessionScreenLockedTimeKey
));
4731 gIOConsoleLockTime
= num
? num
->unsigned32BitValue() : 0;
4734 if (!gIOConsoleLoggedIn
4735 || (kIOMessageSystemWillSleep
== sSystemPower
)
4736 || (kIOMessageSystemPagingOff
== sSystemPower
))
4738 locked
= kOSBooleanTrue
;
4740 else if (gIOConsoleLockTime
)
4743 clock_usec_t microsecs
;
4745 clock_get_calendar_microtime(&now
, µsecs
);
4746 if (gIOConsoleLockTime
> now
)
4748 AbsoluteTime deadline
;
4749 clock_interval_to_deadline(gIOConsoleLockTime
- now
, kSecondScale
, &deadline
);
4750 thread_call_enter_delayed(gIOConsoleLockCallout
, deadline
);
4754 locked
= kOSBooleanTrue
;
4758 publish
= (consoleUsers
|| (locked
!= regEntry
->getProperty(gIOConsoleLockedKey
)));
4761 regEntry
->setProperty(gIOConsoleLockedKey
, locked
);
4764 regEntry
->setProperty(gIOConsoleUsersKey
, consoleUsers
);
4766 OSIncrementAtomic( &gIOConsoleUsersSeed
);
4772 if (locked
== kOSBooleanTrue
) gIOScreenLockState
= kIOScreenLockLocked
;
4773 else if (gIOConsoleLockTime
) gIOScreenLockState
= kIOScreenLockUnlocked
;
4774 else gIOScreenLockState
= kIOScreenLockNoLock
;
4775 gIOChosenEntry
->setProperty(kIOScreenLockStateKey
, &gIOScreenLockState
, sizeof(gIOScreenLockState
));
4777 #endif /* HIBERNATION */
4779 IOLockUnlock(gIOConsoleUsersLock
);
4783 publishResource( gIOConsoleUsersSeedKey
, gIOConsoleUsersSeedValue
);
4785 MessageClientsContext context
;
4787 context
.service
= getServiceRoot();
4788 context
.type
= kIOMessageConsoleSecurityChange
;
4789 context
.argument
= (void *) regEntry
;
4790 context
.argSize
= 0;
4792 applyToInterestNotifiers(getServiceRoot(), gIOConsoleSecurityInterest
,
4793 &messageClientsApplier
, &context
);
4797 IOReturn
IOResources::setProperties( OSObject
* properties
)
4800 const OSSymbol
* key
;
4801 OSDictionary
* dict
;
4802 OSCollectionIterator
* iter
;
4804 err
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
4805 if ( kIOReturnSuccess
!= err
)
4808 dict
= OSDynamicCast(OSDictionary
, properties
);
4810 return( kIOReturnBadArgument
);
4812 iter
= OSCollectionIterator::withCollection( dict
);
4814 return( kIOReturnBadArgument
);
4816 while( (key
= OSDynamicCast(OSSymbol
, iter
->getNextObject())))
4818 if (gIOConsoleUsersKey
== key
) do
4820 OSArray
* consoleUsers
;
4821 consoleUsers
= OSDynamicCast(OSArray
, dict
->getObject(key
));
4824 IOService::updateConsoleUsers(consoleUsers
, 0);
4828 publishResource( key
, dict
->getObject(key
) );
4833 return( kIOReturnSuccess
);
4837 * Helpers for matching dictionaries.
4838 * Keys existing in matching are checked in properties.
4839 * Keys may be a string or OSCollection of IOStrings
4842 bool IOService::compareProperty( OSDictionary
* matching
,
4848 value
= matching
->getObject( key
);
4850 ok
= value
->isEqualTo( getProperty( key
));
4858 bool IOService::compareProperty( OSDictionary
* matching
,
4859 const OSString
* key
)
4864 value
= matching
->getObject( key
);
4866 ok
= value
->isEqualTo( getProperty( key
));
4873 bool IOService::compareProperties( OSDictionary
* matching
,
4874 OSCollection
* keys
)
4876 OSCollectionIterator
* iter
;
4877 const OSString
* key
;
4880 if( !matching
|| !keys
)
4883 iter
= OSCollectionIterator::withCollection( keys
);
4886 while( ok
&& (key
= OSDynamicCast( OSString
, iter
->getNextObject())))
4887 ok
= compareProperty( matching
, key
);
4891 keys
->release(); // !! consume a ref !!
4896 /* Helper to add a location matching dict to the table */
4898 OSDictionary
* IOService::addLocation( OSDictionary
* table
)
4900 OSDictionary
* dict
;
4905 dict
= OSDictionary::withCapacity( 1 );
4907 table
->setObject( gIOLocationMatchKey
, dict
);
4915 * Go looking for a provider to match a location dict.
4918 IOService
* IOService::matchLocation( IOService
* /* client */ )
4922 parent
= getProvider();
4925 parent
= parent
->matchLocation( this );
4930 bool IOService::matchInternal(OSDictionary
* table
, uint32_t options
, uint32_t * did
)
4935 IORegistryEntry
* entry
;
4938 bool changesOK
= (0 != (kIOServiceChangesOK
& options
));
4944 count
= table
->getCount();
4946 str
= OSDynamicCast(OSString
, table
->getObject(gIOProviderClassKey
));
4949 match
= ((kIOServiceClassDone
& options
) || (0 != metaCast(str
)));
4951 match
= (0 != metaCast( str
));
4952 if ((kIOServiceClassDone
& options
) && !match
) panic("classDone");
4954 if ((!match
) || (done
== count
)) break;
4957 obj
= table
->getObject( gIONameMatchKey
);
4960 match
= compareNames( obj
, changesOK
? &matched
: 0 );
4962 if( changesOK
&& matched
) {
4963 // leave a hint as to which name matched
4964 table
->setObject( gIONameMatchedKey
, matched
);
4967 if (done
== count
) break;
4970 str
= OSDynamicCast( OSString
, table
->getObject( gIOLocationMatchKey
));
4973 const OSSymbol
* sym
;
4976 sym
= copyLocation();
4978 match
= sym
->isEqualTo( str
);
4981 if ((!match
) || (done
== count
)) break;
4984 obj
= table
->getObject( gIOPropertyMatchKey
);
4987 OSDictionary
* dict
;
4988 OSDictionary
* nextDict
;
4992 dict
= dictionaryWithProperties();
4994 nextDict
= OSDynamicCast( OSDictionary
, obj
);
4998 iter
= OSCollectionIterator::withCollection(
4999 OSDynamicCast(OSCollection
, obj
));
5002 || (iter
&& (0 != (nextDict
= OSDynamicCast(OSDictionary
,
5003 iter
->getNextObject()))))) {
5004 match
= dict
->isEqualTo( nextDict
, nextDict
);
5013 if ((!match
) || (done
== count
)) break;
5016 str
= OSDynamicCast( OSString
, table
->getObject( gIOPathMatchKey
));
5019 entry
= IORegistryEntry::fromPath( str
->getCStringNoCopy() );
5020 match
= (this == entry
);
5023 if ((!match
) || (done
== count
)) break;
5026 num
= OSDynamicCast( OSNumber
, table
->getObject( gIORegistryEntryIDKey
));
5029 match
= (getRegistryEntryID() == num
->unsigned64BitValue());
5030 if ((!match
) || (done
== count
)) break;
5033 num
= OSDynamicCast( OSNumber
, table
->getObject( gIOMatchedServiceCountKey
));
5037 IOService
* service
= 0;
5038 UInt32 serviceCount
= 0;
5041 iter
= getClientIterator();
5043 while( (service
= (IOService
*) iter
->getNextObject())) {
5044 if( kIOServiceInactiveState
& service
->__state
[0])
5046 if( 0 == service
->getProperty( gIOMatchCategoryKey
))
5052 match
= (serviceCount
== num
->unsigned32BitValue());
5053 if ((!match
) || (done
== count
)) break;
5056 #define propMatch(key) \
5057 obj = table->getObject(key); \
5062 prop = copyProperty(key); \
5063 match = obj->isEqualTo(prop); \
5064 if (prop) prop->release(); \
5065 if ((!match) || (done == count)) break; \
5067 propMatch(kIOBSDNameKey
)
5068 propMatch(kIOBSDMajorKey
)
5069 propMatch(kIOBSDMinorKey
)
5070 propMatch(kIOBSDUnitKey
)
5075 if (did
) *did
= done
;
5079 bool IOService::passiveMatch( OSDictionary
* table
, bool changesOK
)
5081 return (matchPassive(table
, changesOK
? kIOServiceChangesOK
: 0));
5084 bool IOService::matchPassive(OSDictionary
* table
, uint32_t options
)
5087 OSDictionary
* nextTable
;
5091 bool matchParent
= false;
5098 OSDictionary
* root
= table
;
5106 count
= table
->getCount();
5107 if (!(kIOServiceInternalDone
& options
))
5109 match
= where
->matchInternal(table
, options
, &done
);
5110 // don't call family if we've done all the entries in the table
5111 if ((!match
) || (done
== count
)) break;
5114 // pass in score from property table
5115 score
= IOServiceObjectOrder( table
, (void *) gIOProbeScoreKey
);
5117 // do family specific matching
5118 match
= where
->matchPropertyTable( table
, &score
);
5122 if( kIOLogMatch
& getDebugFlags( table
))
5123 LOG("%s: family specific matching fails\n", where
->getName());
5128 if (kIOServiceChangesOK
& options
) {
5130 newPri
= OSNumber::withNumber( score
, 32 );
5132 table
->setObject( gIOProbeScoreKey
, newPri
);
5138 matchParent
= false;
5140 nextTable
= OSDynamicCast(OSDictionary
,
5141 table
->getObject( gIOParentMatchKey
));
5143 // look for a matching entry anywhere up to root
5150 table
= OSDynamicCast(OSDictionary
,
5151 table
->getObject( gIOLocationMatchKey
));
5153 // look for a matching entry at matchLocation()
5155 where
= where
->getProvider();
5156 if (where
&& (where
= where
->matchLocation(where
))) continue;
5162 while( matchParent
&& (!match
) && (where
= where
->getProvider()) );
5167 OSSerialize
* s
= OSSerialize::withCapacity(128);
5169 kprintf("parent match 0x%llx, %d,\n%s\n", getRegistryEntryID(), match
, s
->text());
5178 IOReturn
IOService::newUserClient( task_t owningTask
, void * securityID
,
5179 UInt32 type
, OSDictionary
* properties
,
5180 IOUserClient
** handler
)
5182 const OSSymbol
*userClientClass
= 0;
5183 IOUserClient
*client
;
5186 if (kIOReturnSuccess
== newUserClient( owningTask
, securityID
, type
, handler
))
5187 return kIOReturnSuccess
;
5189 // First try my own properties for a user client class name
5190 temp
= getProperty(gIOUserClientClassKey
);
5192 if (OSDynamicCast(OSSymbol
, temp
))
5193 userClientClass
= (const OSSymbol
*) temp
;
5194 else if (OSDynamicCast(OSString
, temp
)) {
5195 userClientClass
= OSSymbol::withString((OSString
*) temp
);
5196 if (userClientClass
)
5197 setProperty(kIOUserClientClassKey
,
5198 (OSObject
*) userClientClass
);
5202 // Didn't find one so lets just bomb out now without further ado.
5203 if (!userClientClass
)
5204 return kIOReturnUnsupported
;
5206 // This reference is consumed by the IOServiceOpen call
5207 temp
= OSMetaClass::allocClassWithName(userClientClass
);
5209 return kIOReturnNoMemory
;
5211 if (OSDynamicCast(IOUserClient
, temp
))
5212 client
= (IOUserClient
*) temp
;
5215 return kIOReturnUnsupported
;
5218 if ( !client
->initWithTask(owningTask
, securityID
, type
, properties
) ) {
5220 return kIOReturnBadArgument
;
5223 if ( !client
->attach(this) ) {
5225 return kIOReturnUnsupported
;
5228 if ( !client
->start(this) ) {
5229 client
->detach(this);
5231 return kIOReturnUnsupported
;
5235 return kIOReturnSuccess
;
5238 IOReturn
IOService::newUserClient( task_t owningTask
, void * securityID
,
5239 UInt32 type
, IOUserClient
** handler
)
5241 return( kIOReturnUnsupported
);
5244 IOReturn
IOService::requestProbe( IOOptionBits options
)
5246 return( kIOReturnUnsupported
);
5250 * Convert an IOReturn to text. Subclasses which add additional
5251 * IOReturn's should override this method and call
5252 * super::stringFromReturn if the desired value is not found.
5255 const char * IOService::stringFromReturn( IOReturn rtn
)
5257 static const IONamedValue IOReturn_values
[] = {
5258 {kIOReturnSuccess
, "success" },
5259 {kIOReturnError
, "general error" },
5260 {kIOReturnNoMemory
, "memory allocation error" },
5261 {kIOReturnNoResources
, "resource shortage" },
5262 {kIOReturnIPCError
, "Mach IPC failure" },
5263 {kIOReturnNoDevice
, "no such device" },
5264 {kIOReturnNotPrivileged
, "privilege violation" },
5265 {kIOReturnBadArgument
, "invalid argument" },
5266 {kIOReturnLockedRead
, "device is read locked" },
5267 {kIOReturnLockedWrite
, "device is write locked" },
5268 {kIOReturnExclusiveAccess
, "device is exclusive access" },
5269 {kIOReturnBadMessageID
, "bad IPC message ID" },
5270 {kIOReturnUnsupported
, "unsupported function" },
5271 {kIOReturnVMError
, "virtual memory error" },
5272 {kIOReturnInternalError
, "internal driver error" },
5273 {kIOReturnIOError
, "I/O error" },
5274 {kIOReturnCannotLock
, "cannot acquire lock" },
5275 {kIOReturnNotOpen
, "device is not open" },
5276 {kIOReturnNotReadable
, "device is not readable" },
5277 {kIOReturnNotWritable
, "device is not writeable" },
5278 {kIOReturnNotAligned
, "alignment error" },
5279 {kIOReturnBadMedia
, "media error" },
5280 {kIOReturnStillOpen
, "device is still open" },
5281 {kIOReturnRLDError
, "rld failure" },
5282 {kIOReturnDMAError
, "DMA failure" },
5283 {kIOReturnBusy
, "device is busy" },
5284 {kIOReturnTimeout
, "I/O timeout" },
5285 {kIOReturnOffline
, "device is offline" },
5286 {kIOReturnNotReady
, "device is not ready" },
5287 {kIOReturnNotAttached
, "device/channel is not attached" },
5288 {kIOReturnNoChannels
, "no DMA channels available" },
5289 {kIOReturnNoSpace
, "no space for data" },
5290 {kIOReturnPortExists
, "device port already exists" },
5291 {kIOReturnCannotWire
, "cannot wire physical memory" },
5292 {kIOReturnNoInterrupt
, "no interrupt attached" },
5293 {kIOReturnNoFrames
, "no DMA frames enqueued" },
5294 {kIOReturnMessageTooLarge
, "message is too large" },
5295 {kIOReturnNotPermitted
, "operation is not permitted" },
5296 {kIOReturnNoPower
, "device is without power" },
5297 {kIOReturnNoMedia
, "media is not present" },
5298 {kIOReturnUnformattedMedia
, "media is not formatted" },
5299 {kIOReturnUnsupportedMode
, "unsupported mode" },
5300 {kIOReturnUnderrun
, "data underrun" },
5301 {kIOReturnOverrun
, "data overrun" },
5302 {kIOReturnDeviceError
, "device error" },
5303 {kIOReturnNoCompletion
, "no completion routine" },
5304 {kIOReturnAborted
, "operation was aborted" },
5305 {kIOReturnNoBandwidth
, "bus bandwidth would be exceeded" },
5306 {kIOReturnNotResponding
, "device is not responding" },
5307 {kIOReturnInvalid
, "unanticipated driver error" },
5311 return IOFindNameForValue(rtn
, IOReturn_values
);
5315 * Convert an IOReturn to an errno.
5317 int IOService::errnoFromReturn( IOReturn rtn
)
5319 if (unix_err(err_get_code(rtn
)) == rtn
)
5320 return err_get_code(rtn
);
5324 case kIOReturnSuccess
:
5326 case kIOReturnNoMemory
:
5328 case kIOReturnNoDevice
:
5330 case kIOReturnVMError
:
5332 case kIOReturnNotPermitted
:
5334 case kIOReturnNotPrivileged
:
5336 case kIOReturnIOError
:
5338 case kIOReturnNotWritable
:
5340 case kIOReturnBadArgument
:
5342 case kIOReturnUnsupported
:
5346 case kIOReturnNoPower
:
5348 case kIOReturnDeviceError
:
5350 case kIOReturnTimeout
:
5352 case kIOReturnMessageTooLarge
:
5354 case kIOReturnNoSpace
:
5356 case kIOReturnCannotLock
:
5360 case kIOReturnBadMessageID
:
5361 case kIOReturnNoCompletion
:
5362 case kIOReturnNotAligned
:
5364 case kIOReturnNotReady
:
5366 case kIOReturnRLDError
:
5368 case kIOReturnPortExists
:
5369 case kIOReturnStillOpen
:
5371 case kIOReturnExclusiveAccess
:
5372 case kIOReturnLockedRead
:
5373 case kIOReturnLockedWrite
:
5374 case kIOReturnNotOpen
:
5375 case kIOReturnNotReadable
:
5377 case kIOReturnCannotWire
:
5378 case kIOReturnNoResources
:
5380 case kIOReturnAborted
:
5381 case kIOReturnOffline
:
5382 case kIOReturnNotResponding
:
5384 case kIOReturnBadMedia
:
5385 case kIOReturnNoMedia
:
5386 case kIOReturnNotAttached
:
5387 case kIOReturnUnformattedMedia
:
5388 return(ENXIO
); // (media error)
5389 case kIOReturnDMAError
:
5390 case kIOReturnOverrun
:
5391 case kIOReturnUnderrun
:
5392 return(EIO
); // (transfer error)
5393 case kIOReturnNoBandwidth
:
5394 case kIOReturnNoChannels
:
5395 case kIOReturnNoFrames
:
5396 case kIOReturnNoInterrupt
:
5397 return(EIO
); // (hardware error)
5398 case kIOReturnError
:
5399 case kIOReturnInternalError
:
5400 case kIOReturnInvalid
:
5401 return(EIO
); // (generic error)
5402 case kIOReturnIPCError
:
5403 return(EIO
); // (ipc error)
5405 return(EIO
); // (all other errors)
5409 IOReturn
IOService::message( UInt32 type
, IOService
* provider
,
5413 * Generic entry point for calls from the provider. A return value of
5414 * kIOReturnSuccess indicates that the message was received, and where
5415 * applicable, that it was successful.
5418 return kIOReturnUnsupported
;
5425 IOItemCount
IOService::getDeviceMemoryCount( void )
5430 array
= OSDynamicCast( OSArray
, getProperty( gIODeviceMemoryKey
));
5432 count
= array
->getCount();
5439 IODeviceMemory
* IOService::getDeviceMemoryWithIndex( unsigned int index
)
5442 IODeviceMemory
* range
;
5444 array
= OSDynamicCast( OSArray
, getProperty( gIODeviceMemoryKey
));
5446 range
= (IODeviceMemory
*) array
->getObject( index
);
5453 IOMemoryMap
* IOService::mapDeviceMemoryWithIndex( unsigned int index
,
5454 IOOptionBits options
)
5456 IODeviceMemory
* range
;
5459 range
= getDeviceMemoryWithIndex( index
);
5461 map
= range
->map( options
);
5468 OSArray
* IOService::getDeviceMemory( void )
5470 return( OSDynamicCast( OSArray
, getProperty( gIODeviceMemoryKey
)));
5474 void IOService::setDeviceMemory( OSArray
* array
)
5476 setProperty( gIODeviceMemoryKey
, array
);
5480 * For machines where the transfers on an I/O bus can stall because
5481 * the CPU is in an idle mode, These APIs allow a driver to specify
5482 * the maximum bus stall that they can handle. 0 indicates no limit.
5485 setCPUSnoopDelay(UInt32 __unused ns
)
5487 #if defined(__i386__) || defined(__x86_64__)
5488 ml_set_maxsnoop(ns
);
5489 #endif /* defined(__i386__) || defined(__x86_64__) */
5495 #if defined(__i386__) || defined(__x86_64__)
5496 return ml_get_maxsnoop();
5499 #endif /* defined(__i386__) || defined(__x86_64__) */
5502 #if defined(__i386__) || defined(__x86_64__)
5504 requireMaxCpuDelay(IOService
* service
, UInt32 ns
, UInt32 delayType
)
5506 static const UInt kNoReplace
= -1U; // Must be an illegal index
5507 UInt replace
= kNoReplace
;
5508 bool setCpuDelay
= false;
5510 IORecursiveLockLock(sCpuDelayLock
);
5512 UInt count
= sCpuDelayData
->getLength() / sizeof(CpuDelayEntry
);
5513 CpuDelayEntry
*entries
= (CpuDelayEntry
*) sCpuDelayData
->getBytesNoCopy();
5514 IOService
* holder
= NULL
;
5517 const CpuDelayEntry ne
= {service
, ns
, delayType
};
5519 // Set maximum delay.
5520 for (UInt i
= 0; i
< count
; i
++) {
5521 IOService
*thisService
= entries
[i
].fService
;
5522 bool sameType
= (delayType
== entries
[i
].fDelayType
);
5523 if ((service
== thisService
) && sameType
)
5525 else if (!thisService
) {
5526 if (kNoReplace
== replace
)
5529 else if (sameType
) {
5530 const UInt32 thisMax
= entries
[i
].fMaxDelay
;
5534 holder
= thisService
;
5540 if (kNoReplace
== replace
)
5541 sCpuDelayData
->appendBytes(&ne
, sizeof(ne
));
5543 entries
[replace
] = ne
;
5546 ns
= -1U; // Set to max unsigned, i.e. no restriction
5548 for (UInt i
= 0; i
< count
; i
++) {
5549 // Clear a maximum delay.
5550 IOService
*thisService
= entries
[i
].fService
;
5551 if (thisService
&& (delayType
== entries
[i
].fDelayType
)) {
5552 UInt32 thisMax
= entries
[i
].fMaxDelay
;
5553 if (service
== thisService
)
5555 else if (thisMax
< ns
) {
5557 holder
= thisService
;
5562 // Check if entry found
5563 if (kNoReplace
!= replace
) {
5564 entries
[replace
].fService
= 0; // Null the entry
5571 // Must be safe to call from locked context
5572 if (delayType
== kCpuDelayBusStall
)
5574 ml_set_maxbusdelay(ns
);
5576 else if (delayType
== kCpuDelayInterrupt
)
5578 ml_set_maxintdelay(ns
);
5580 sCPULatencyHolder
[delayType
]->setValue(holder
? holder
->getRegistryEntryID() : 0);
5581 sCPULatencySet
[delayType
]->setValue(ns
);
5583 OSArray
* handlers
= sCpuLatencyHandlers
[delayType
];
5585 if (handlers
) for (unsigned int idx
= 0;
5586 (target
= (IOService
*) handlers
->getObject(idx
));
5589 target
->callPlatformFunction(sCPULatencyFunctionName
[delayType
], false,
5590 (void *) (uintptr_t) ns
, holder
,
5595 IORecursiveLockUnlock(sCpuDelayLock
);
5599 setLatencyHandler(UInt32 delayType
, IOService
* target
, bool enable
)
5601 IOReturn result
= kIOReturnNotFound
;
5605 IORecursiveLockLock(sCpuDelayLock
);
5609 if (enable
&& !sCpuLatencyHandlers
[delayType
])
5610 sCpuLatencyHandlers
[delayType
] = OSArray::withCapacity(4);
5611 array
= sCpuLatencyHandlers
[delayType
];
5614 idx
= array
->getNextIndexOfObject(target
, 0);
5619 array
->removeObject(idx
);
5620 result
= kIOReturnSuccess
;
5626 result
= kIOReturnExclusiveAccess
;
5629 array
->setObject(target
);
5631 UInt count
= sCpuDelayData
->getLength() / sizeof(CpuDelayEntry
);
5632 CpuDelayEntry
*entries
= (CpuDelayEntry
*) sCpuDelayData
->getBytesNoCopy();
5633 UInt32 ns
= -1U; // Set to max unsigned, i.e. no restriction
5634 IOService
* holder
= NULL
;
5636 for (UInt i
= 0; i
< count
; i
++) {
5637 if (entries
[i
].fService
5638 && (delayType
== entries
[i
].fDelayType
)
5639 && (entries
[i
].fMaxDelay
< ns
)) {
5640 ns
= entries
[i
].fMaxDelay
;
5641 holder
= entries
[i
].fService
;
5644 target
->callPlatformFunction(sCPULatencyFunctionName
[delayType
], false,
5645 (void *) (uintptr_t) ns
, holder
,
5647 result
= kIOReturnSuccess
;
5652 IORecursiveLockUnlock(sCpuDelayLock
);
5657 #endif /* defined(__i386__) || defined(__x86_64__) */
5660 requireMaxBusStall(UInt32 __unused ns
)
5662 #if defined(__i386__) || defined(__x86_64__)
5663 requireMaxCpuDelay(this, ns
, kCpuDelayBusStall
);
5668 requireMaxInterruptDelay(uint32_t __unused ns
)
5670 #if defined(__i386__) || defined(__x86_64__)
5671 requireMaxCpuDelay(this, ns
, kCpuDelayInterrupt
);
5679 IOReturn
IOService::resolveInterrupt(IOService
*nub
, int source
)
5681 IOInterruptController
*interruptController
;
5684 OSSymbol
*interruptControllerName
;
5686 IOInterruptSource
*interruptSources
;
5688 // Get the parents list from the nub.
5689 array
= OSDynamicCast(OSArray
, nub
->getProperty(gIOInterruptControllersKey
));
5690 if (array
== 0) return kIOReturnNoResources
;
5692 // Allocate space for the IOInterruptSources if needed... then return early.
5693 if (nub
->_interruptSources
== 0) {
5694 numSources
= array
->getCount();
5695 interruptSources
= (IOInterruptSource
*)IOMalloc(numSources
* sizeof(IOInterruptSource
));
5696 if (interruptSources
== 0) return kIOReturnNoMemory
;
5698 bzero(interruptSources
, numSources
* sizeof(IOInterruptSource
));
5700 nub
->_numInterruptSources
= numSources
;
5701 nub
->_interruptSources
= interruptSources
;
5702 return kIOReturnSuccess
;
5705 interruptControllerName
= OSDynamicCast(OSSymbol
,array
->getObject(source
));
5706 if (interruptControllerName
== 0) return kIOReturnNoResources
;
5708 interruptController
= getPlatform()->lookUpInterruptController(interruptControllerName
);
5709 if (interruptController
== 0) return kIOReturnNoResources
;
5711 // Get the interrupt numbers from the nub.
5712 array
= OSDynamicCast(OSArray
, nub
->getProperty(gIOInterruptSpecifiersKey
));
5713 if (array
== 0) return kIOReturnNoResources
;
5714 data
= OSDynamicCast(OSData
, array
->getObject(source
));
5715 if (data
== 0) return kIOReturnNoResources
;
5717 // Set the interruptController and interruptSource in the nub's table.
5718 interruptSources
= nub
->_interruptSources
;
5719 interruptSources
[source
].interruptController
= interruptController
;
5720 interruptSources
[source
].vectorData
= data
;
5722 return kIOReturnSuccess
;
5725 IOReturn
IOService::lookupInterrupt(int source
, bool resolve
, IOInterruptController
**interruptController
)
5729 /* Make sure the _interruptSources are set */
5730 if (_interruptSources
== 0) {
5731 ret
= resolveInterrupt(this, source
);
5732 if (ret
!= kIOReturnSuccess
) return ret
;
5735 /* Make sure the local source number is valid */
5736 if ((source
< 0) || (source
>= _numInterruptSources
))
5737 return kIOReturnNoInterrupt
;
5739 /* Look up the contoller for the local source */
5740 *interruptController
= _interruptSources
[source
].interruptController
;
5742 if (*interruptController
== NULL
) {
5743 if (!resolve
) return kIOReturnNoInterrupt
;
5745 /* Try to reslove the interrupt */
5746 ret
= resolveInterrupt(this, source
);
5747 if (ret
!= kIOReturnSuccess
) return ret
;
5749 *interruptController
= _interruptSources
[source
].interruptController
;
5752 return kIOReturnSuccess
;
5755 IOReturn
IOService::registerInterrupt(int source
, OSObject
*target
,
5756 IOInterruptAction handler
,
5759 IOInterruptController
*interruptController
;
5762 ret
= lookupInterrupt(source
, true, &interruptController
);
5763 if (ret
!= kIOReturnSuccess
) return ret
;
5765 /* Register the source */
5766 return interruptController
->registerInterrupt(this, source
, target
,
5767 (IOInterruptHandler
)handler
,
5771 IOReturn
IOService::unregisterInterrupt(int source
)
5773 IOInterruptController
*interruptController
;
5776 ret
= lookupInterrupt(source
, false, &interruptController
);
5777 if (ret
!= kIOReturnSuccess
) return ret
;
5779 /* Unregister the source */
5780 return interruptController
->unregisterInterrupt(this, source
);
5783 IOReturn
IOService::addInterruptStatistics(IOInterruptAccountingData
* statistics
, int source
)
5785 IOReportLegend
* legend
= NULL
;
5786 IOInterruptAccountingData
* oldValue
= NULL
;
5787 IOInterruptAccountingReporter
* newArray
= NULL
;
5788 int newArraySize
= 0;
5792 return kIOReturnBadArgument
;
5796 * We support statistics on a maximum of 256 interrupts per nub; if a nub
5797 * has more than 256 interrupt specifiers associated with it, and tries
5798 * to register a high interrupt index with interrupt accounting, panic.
5799 * Having more than 256 interrupts associated with a single nub is
5800 * probably a sign that something fishy is going on.
5802 if (source
> IA_INDEX_MAX
) {
5803 panic("addInterruptStatistics called for an excessively large index (%d)", source
);
5807 * TODO: This is ugly (wrapping a lock around an allocation). I'm only
5808 * leaving it as is because the likelihood of contention where we are
5809 * actually growing the array is minimal (we would realistically need
5810 * to be starting a driver for the first time, with an IOReporting
5811 * client already in place). Nonetheless, cleanup that can be done
5812 * to adhere to best practices; it'll make the code more complicated,
5815 IOLockLock(reserved
->interruptStatisticsLock
);
5818 * Lazily allocate the statistics array.
5820 if (!reserved
->interruptStatisticsArray
) {
5821 reserved
->interruptStatisticsArray
= IONew(IOInterruptAccountingReporter
, 1);
5822 assert(reserved
->interruptStatisticsArray
);
5823 reserved
->interruptStatisticsArrayCount
= 1;
5824 bzero(reserved
->interruptStatisticsArray
, sizeof(*reserved
->interruptStatisticsArray
));
5827 if (source
>= reserved
->interruptStatisticsArrayCount
) {
5829 * We're still within the range of supported indices, but we are out
5830 * of space in the current array. Do a nasty realloc (because
5831 * IORealloc isn't a thing) here. We'll double the size with each
5834 * Yes, the "next power of 2" could be more efficient; but this will
5835 * be invoked incredibly rarely. Who cares.
5837 newArraySize
= (reserved
->interruptStatisticsArrayCount
<< 1);
5839 while (newArraySize
<= source
)
5840 newArraySize
= (newArraySize
<< 1);
5841 newArray
= IONew(IOInterruptAccountingReporter
, newArraySize
);
5846 * TODO: This even zeroes the memory it is about to overwrite.
5847 * Shameful; fix it. Not particularly high impact, however.
5849 bzero(newArray
, newArraySize
* sizeof(*newArray
));
5850 memcpy(newArray
, reserved
->interruptStatisticsArray
, reserved
->interruptStatisticsArrayCount
* sizeof(*newArray
));
5851 IODelete(reserved
->interruptStatisticsArray
, IOInterruptAccountingReporter
, reserved
->interruptStatisticsArrayCount
);
5852 reserved
->interruptStatisticsArray
= newArray
;
5853 reserved
->interruptStatisticsArrayCount
= newArraySize
;
5856 if (!reserved
->interruptStatisticsArray
[source
].reporter
) {
5858 * We don't have a reporter associated with this index yet, so we
5859 * need to create one.
5862 * TODO: Some statistics do in fact have common units (time); should this be
5863 * split into separate reporters to communicate this?
5865 reserved
->interruptStatisticsArray
[source
].reporter
= IOSimpleReporter::with(this, kIOReportCategoryInterrupt
, kIOReportUnitNone
);
5868 * Each statistic is given an identifier based on the interrupt index (which
5869 * should be unique relative to any single nub) and the statistic involved.
5870 * We should now have a sane (small and positive) index, so start
5871 * constructing the channels for statistics.
5873 for (i
= 0; i
< IA_NUM_INTERRUPT_ACCOUNTING_STATISTICS
; i
++) {
5875 * TODO: Currently, this does not add channels for disabled statistics.
5876 * Will this be confusing for clients? If so, we should just add the
5877 * channels; we can avoid updating the channels even if they exist.
5879 if (IA_GET_STATISTIC_ENABLED(i
))
5880 reserved
->interruptStatisticsArray
[source
].reporter
->addChannel(IA_GET_CHANNEL_ID(source
, i
), kInterruptAccountingStatisticNameArray
[i
]);
5884 * We now need to add the legend for this reporter to the registry.
5886 legend
= IOReportLegend::with(OSDynamicCast(OSArray
, getProperty(kIOReportLegendKey
)));
5888 if ((source
>= IA_MAX_SUBGROUP_NAME
) || (source
< 0)) {
5890 * Either we're using a nonsensical index (should never happen), or the
5891 * index is larger than anticipated (may happen, almost certainly won't).
5892 * This may move to live generation of the names in the future, but for
5893 * now, point both cases to a generic subgroup name (this will confuse
5894 * clients, unfortunately).
5896 legend
->addReporterLegend(reserved
->interruptStatisticsArray
[source
].reporter
, kInterruptAccountingGroupName
, kInterruptAccountingGenericSubgroupName
);
5898 legend
->addReporterLegend(reserved
->interruptStatisticsArray
[source
].reporter
, kInterruptAccountingGroupName
, kInterruptAccountingSubgroupNames
[source
]);
5901 setProperty(kIOReportLegendKey
, legend
->getLegend());
5905 * TODO: Is this a good idea? Probably not; my assumption is it opts
5906 * all entities who register interrupts into public disclosure of all
5907 * IOReporting channels. Unfortunately, this appears to be as fine
5910 setProperty(kIOReportLegendPublicKey
, true);
5914 * Don't stomp existing entries. If we are about to, panic; this
5915 * probably means we failed to tear down our old interrupt source
5918 oldValue
= reserved
->interruptStatisticsArray
[source
].statistics
;
5921 panic("addInterruptStatistics call for index %d would have clobbered existing statistics", source
);
5924 reserved
->interruptStatisticsArray
[source
].statistics
= statistics
;
5927 * Inherit the reporter values for each statistic. The target may
5928 * be torn down as part of the runtime of the service (especially
5929 * for sleep/wake), so we inherit in order to avoid having values
5930 * reset for no apparent reason. Our statistics are ultimately
5931 * tied to the index and the sevice, not to an individual target,
5932 * so we should maintain them accordingly.
5934 interruptAccountingDataInheritChannels(reserved
->interruptStatisticsArray
[source
].statistics
, reserved
->interruptStatisticsArray
[source
].reporter
);
5936 IOLockUnlock(reserved
->interruptStatisticsLock
);
5938 return kIOReturnSuccess
;
5941 IOReturn
IOService::removeInterruptStatistics(int source
)
5943 IOInterruptAccountingData
* value
= NULL
;
5946 return kIOReturnBadArgument
;
5949 IOLockLock(reserved
->interruptStatisticsLock
);
5952 * We dynamically grow the statistics array, so an excessively
5953 * large index value has NEVER been registered. This either
5954 * means our cap on the array size is too small (unlikely), or
5955 * that we have been passed a corrupt index (this must be passed
5956 * the plain index into the interrupt specifier list).
5958 if (source
>= reserved
->interruptStatisticsArrayCount
) {
5959 panic("removeInterruptStatistics called for index %d, which was never registered", source
);
5962 assert(reserved
->interruptStatisticsArray
);
5965 * If there is no existing entry, we are most likely trying to
5966 * free an interrupt owner twice, or we have corrupted the
5969 value
= reserved
->interruptStatisticsArray
[source
].statistics
;
5972 panic("removeInterruptStatistics called for empty index %d", source
);
5976 * We update the statistics, so that any delta with the reporter
5977 * state is not lost.
5979 interruptAccountingDataUpdateChannels(reserved
->interruptStatisticsArray
[source
].statistics
, reserved
->interruptStatisticsArray
[source
].reporter
);
5980 reserved
->interruptStatisticsArray
[source
].statistics
= NULL
;
5981 IOLockUnlock(reserved
->interruptStatisticsLock
);
5983 return kIOReturnSuccess
;
5986 IOReturn
IOService::getInterruptType(int source
, int *interruptType
)
5988 IOInterruptController
*interruptController
;
5991 ret
= lookupInterrupt(source
, true, &interruptController
);
5992 if (ret
!= kIOReturnSuccess
) return ret
;
5994 /* Return the type */
5995 return interruptController
->getInterruptType(this, source
, interruptType
);
5998 IOReturn
IOService::enableInterrupt(int source
)
6000 IOInterruptController
*interruptController
;
6003 ret
= lookupInterrupt(source
, false, &interruptController
);
6004 if (ret
!= kIOReturnSuccess
) return ret
;
6006 /* Enable the source */
6007 return interruptController
->enableInterrupt(this, source
);
6010 IOReturn
IOService::disableInterrupt(int source
)
6012 IOInterruptController
*interruptController
;
6015 ret
= lookupInterrupt(source
, false, &interruptController
);
6016 if (ret
!= kIOReturnSuccess
) return ret
;
6018 /* Disable the source */
6019 return interruptController
->disableInterrupt(this, source
);
6022 IOReturn
IOService::causeInterrupt(int source
)
6024 IOInterruptController
*interruptController
;
6027 ret
= lookupInterrupt(source
, false, &interruptController
);
6028 if (ret
!= kIOReturnSuccess
) return ret
;
6030 /* Cause an interrupt for the source */
6031 return interruptController
->causeInterrupt(this, source
);
6034 IOReturn
IOService::configureReport(IOReportChannelList
*channelList
,
6035 IOReportConfigureAction action
,
6041 for (cnt
= 0; cnt
< channelList
->nchannels
; cnt
++) {
6042 if ( channelList
->channels
[cnt
].channel_id
== kPMPowerStatesChID
) {
6043 if (pwrMgt
) configurePowerStatesReport(action
, result
);
6044 else return kIOReturnUnsupported
;
6046 else if ( channelList
->channels
[cnt
].channel_id
== kPMCurrStateChID
) {
6047 if (pwrMgt
) configureSimplePowerReport(action
, result
);
6048 else return kIOReturnUnsupported
;
6052 IOLockLock(reserved
->interruptStatisticsLock
);
6054 /* The array count is signed (because the interrupt indices are signed), hence the cast */
6055 for (cnt
= 0; cnt
< (unsigned) reserved
->interruptStatisticsArrayCount
; cnt
++) {
6056 if (reserved
->interruptStatisticsArray
[cnt
].reporter
) {
6058 * If the reporter is currently associated with the statistics
6059 * for an event source, we may need to update the reporter.
6061 if (reserved
->interruptStatisticsArray
[cnt
].statistics
)
6062 interruptAccountingDataUpdateChannels(reserved
->interruptStatisticsArray
[cnt
].statistics
, reserved
->interruptStatisticsArray
[cnt
].reporter
);
6064 reserved
->interruptStatisticsArray
[cnt
].reporter
->configureReport(channelList
, action
, result
, destination
);
6068 IOLockUnlock(reserved
->interruptStatisticsLock
);
6070 return kIOReturnSuccess
;
6073 IOReturn
IOService::updateReport(IOReportChannelList
*channelList
,
6074 IOReportUpdateAction action
,
6080 for (cnt
= 0; cnt
< channelList
->nchannels
; cnt
++) {
6081 if ( channelList
->channels
[cnt
].channel_id
== kPMPowerStatesChID
) {
6082 if (pwrMgt
) updatePowerStatesReport(action
, result
, destination
);
6083 else return kIOReturnUnsupported
;
6085 else if ( channelList
->channels
[cnt
].channel_id
== kPMCurrStateChID
) {
6086 if (pwrMgt
) updateSimplePowerReport(action
, result
, destination
);
6087 else return kIOReturnUnsupported
;
6091 IOLockLock(reserved
->interruptStatisticsLock
);
6093 /* The array count is signed (because the interrupt indices are signed), hence the cast */
6094 for (cnt
= 0; cnt
< (unsigned) reserved
->interruptStatisticsArrayCount
; cnt
++) {
6095 if (reserved
->interruptStatisticsArray
[cnt
].reporter
) {
6097 * If the reporter is currently associated with the statistics
6098 * for an event source, we need to update the reporter.
6100 if (reserved
->interruptStatisticsArray
[cnt
].statistics
)
6101 interruptAccountingDataUpdateChannels(reserved
->interruptStatisticsArray
[cnt
].statistics
, reserved
->interruptStatisticsArray
[cnt
].reporter
);
6103 reserved
->interruptStatisticsArray
[cnt
].reporter
->updateReport(channelList
, action
, result
, destination
);
6107 IOLockUnlock(reserved
->interruptStatisticsLock
);
6109 return kIOReturnSuccess
;
6112 uint64_t IOService::getAuthorizationID( void )
6114 return reserved
->authorizationID
;
6117 IOReturn
IOService::setAuthorizationID( uint64_t authorizationID
)
6119 OSObject
* entitlement
;
6122 entitlement
= IOUserClient::copyClientEntitlement( current_task( ), "com.apple.private.iokit.IOServiceSetAuthorizationID" );
6126 if ( entitlement
== kOSBooleanTrue
)
6128 reserved
->authorizationID
= authorizationID
;
6130 status
= kIOReturnSuccess
;
6134 status
= kIOReturnNotPrivileged
;
6137 entitlement
->release( );
6141 status
= kIOReturnNotPrivileged
;
6148 OSMetaClassDefineReservedUsed(IOService
, 0);
6149 OSMetaClassDefineReservedUsed(IOService
, 1);
6150 OSMetaClassDefineReservedUnused(IOService
, 2);
6151 OSMetaClassDefineReservedUnused(IOService
, 3);
6152 OSMetaClassDefineReservedUnused(IOService
, 4);
6153 OSMetaClassDefineReservedUnused(IOService
, 5);
6154 OSMetaClassDefineReservedUnused(IOService
, 6);
6155 OSMetaClassDefineReservedUnused(IOService
, 7);
6157 OSMetaClassDefineReservedUsed(IOService
, 0);
6158 OSMetaClassDefineReservedUsed(IOService
, 1);
6159 OSMetaClassDefineReservedUsed(IOService
, 2);
6160 OSMetaClassDefineReservedUsed(IOService
, 3);
6161 OSMetaClassDefineReservedUsed(IOService
, 4);
6162 OSMetaClassDefineReservedUsed(IOService
, 5);
6163 OSMetaClassDefineReservedUsed(IOService
, 6);
6164 OSMetaClassDefineReservedUsed(IOService
, 7);
6166 OSMetaClassDefineReservedUnused(IOService
, 8);
6167 OSMetaClassDefineReservedUnused(IOService
, 9);
6168 OSMetaClassDefineReservedUnused(IOService
, 10);
6169 OSMetaClassDefineReservedUnused(IOService
, 11);
6170 OSMetaClassDefineReservedUnused(IOService
, 12);
6171 OSMetaClassDefineReservedUnused(IOService
, 13);
6172 OSMetaClassDefineReservedUnused(IOService
, 14);
6173 OSMetaClassDefineReservedUnused(IOService
, 15);
6174 OSMetaClassDefineReservedUnused(IOService
, 16);
6175 OSMetaClassDefineReservedUnused(IOService
, 17);
6176 OSMetaClassDefineReservedUnused(IOService
, 18);
6177 OSMetaClassDefineReservedUnused(IOService
, 19);
6178 OSMetaClassDefineReservedUnused(IOService
, 20);
6179 OSMetaClassDefineReservedUnused(IOService
, 21);
6180 OSMetaClassDefineReservedUnused(IOService
, 22);
6181 OSMetaClassDefineReservedUnused(IOService
, 23);
6182 OSMetaClassDefineReservedUnused(IOService
, 24);
6183 OSMetaClassDefineReservedUnused(IOService
, 25);
6184 OSMetaClassDefineReservedUnused(IOService
, 26);
6185 OSMetaClassDefineReservedUnused(IOService
, 27);
6186 OSMetaClassDefineReservedUnused(IOService
, 28);
6187 OSMetaClassDefineReservedUnused(IOService
, 29);
6188 OSMetaClassDefineReservedUnused(IOService
, 30);
6189 OSMetaClassDefineReservedUnused(IOService
, 31);
6190 OSMetaClassDefineReservedUnused(IOService
, 32);
6191 OSMetaClassDefineReservedUnused(IOService
, 33);
6192 OSMetaClassDefineReservedUnused(IOService
, 34);
6193 OSMetaClassDefineReservedUnused(IOService
, 35);
6194 OSMetaClassDefineReservedUnused(IOService
, 36);
6195 OSMetaClassDefineReservedUnused(IOService
, 37);
6196 OSMetaClassDefineReservedUnused(IOService
, 38);
6197 OSMetaClassDefineReservedUnused(IOService
, 39);
6198 OSMetaClassDefineReservedUnused(IOService
, 40);
6199 OSMetaClassDefineReservedUnused(IOService
, 41);
6200 OSMetaClassDefineReservedUnused(IOService
, 42);
6201 OSMetaClassDefineReservedUnused(IOService
, 43);
6202 OSMetaClassDefineReservedUnused(IOService
, 44);
6203 OSMetaClassDefineReservedUnused(IOService
, 45);
6204 OSMetaClassDefineReservedUnused(IOService
, 46);
6205 OSMetaClassDefineReservedUnused(IOService
, 47);