2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <IOKit/system.h>
31 #include <IOKit/IOService.h>
32 #include <libkern/c++/OSContainers.h>
33 #include <libkern/c++/OSUnserialize.h>
34 #include <IOKit/IOCatalogue.h>
35 #include <IOKit/IOCommand.h>
36 #include <IOKit/IODeviceMemory.h>
37 #include <IOKit/IOInterrupts.h>
38 #include <IOKit/IOInterruptController.h>
39 #include <IOKit/IOPlatformExpert.h>
40 #include <IOKit/IOMessage.h>
41 #include <IOKit/IOLib.h>
42 #include <IOKit/IOKitKeysPrivate.h>
43 #include <IOKit/IOBSD.h>
44 #include <IOKit/IOUserClient.h>
45 #include <IOKit/IOWorkLoop.h>
46 #include <mach/sync_policy.h>
47 #include <IOKit/assert.h>
48 #include <sys/errno.h>
53 #include "IOServicePrivate.h"
55 // take lockForArbitration before LOCKNOTIFY
57 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
59 #define super IORegistryEntry
61 OSDefineMetaClassAndStructors(IOService
, IORegistryEntry
)
63 OSDefineMetaClassAndStructors(_IOServiceNotifier
, IONotifier
)
65 OSDefineMetaClassAndStructors(_IOServiceInterestNotifier
, IONotifier
)
67 OSDefineMetaClassAndStructors(_IOConfigThread
, OSObject
)
69 OSDefineMetaClassAndStructors(_IOServiceJob
, OSObject
)
71 OSDefineMetaClassAndStructors(IOResources
, IOService
)
73 OSDefineMetaClassAndStructors(_IOOpenServiceIterator
, OSIterator
)
75 OSDefineMetaClassAndAbstractStructors(IONotifier
, OSObject
)
77 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
79 static IOPlatformExpert
* gIOPlatform
;
80 static class IOPMrootDomain
* gIOPMRootDomain
;
81 const IORegistryPlane
* gIOServicePlane
;
82 const IORegistryPlane
* gIOPowerPlane
;
83 const OSSymbol
* gIODeviceMemoryKey
;
84 const OSSymbol
* gIOInterruptControllersKey
;
85 const OSSymbol
* gIOInterruptSpecifiersKey
;
87 const OSSymbol
* gIOResourcesKey
;
88 const OSSymbol
* gIOResourceMatchKey
;
89 const OSSymbol
* gIOProviderClassKey
;
90 const OSSymbol
* gIONameMatchKey
;
91 const OSSymbol
* gIONameMatchedKey
;
92 const OSSymbol
* gIOPropertyMatchKey
;
93 const OSSymbol
* gIOLocationMatchKey
;
94 const OSSymbol
* gIOParentMatchKey
;
95 const OSSymbol
* gIOPathMatchKey
;
96 const OSSymbol
* gIOMatchCategoryKey
;
97 const OSSymbol
* gIODefaultMatchCategoryKey
;
98 const OSSymbol
* gIOMatchedServiceCountKey
;
100 const OSSymbol
* gIOUserClientClassKey
;
101 const OSSymbol
* gIOKitDebugKey
;
103 const OSSymbol
* gIOCommandPoolSizeKey
;
105 const OSSymbol
* gIOConsoleUsersKey
;
106 const OSSymbol
* gIOConsoleSessionUIDKey
;
107 const OSSymbol
* gIOConsoleUsersSeedKey
;
108 const OSSymbol
* gIOConsoleSessionOnConsoleKey
;
109 const OSSymbol
* gIOConsoleSessionSecureInputPIDKey
;
111 static int gIOResourceGenerationCount
;
113 const OSSymbol
* gIOServiceKey
;
114 const OSSymbol
* gIOPublishNotification
;
115 const OSSymbol
* gIOFirstPublishNotification
;
116 const OSSymbol
* gIOMatchedNotification
;
117 const OSSymbol
* gIOFirstMatchNotification
;
118 const OSSymbol
* gIOTerminatedNotification
;
120 const OSSymbol
* gIOGeneralInterest
;
121 const OSSymbol
* gIOBusyInterest
;
122 const OSSymbol
* gIOAppPowerStateInterest
;
123 const OSSymbol
* gIOPriorityPowerStateInterest
;
125 static OSDictionary
* gNotifications
;
126 static IORecursiveLock
* gNotificationLock
;
128 static IOService
* gIOResources
;
129 static IOService
* gIOServiceRoot
;
131 static OSOrderedSet
* gJobs
;
132 static semaphore_port_t gJobsSemaphore
;
133 static IOLock
* gJobsLock
;
134 static int gOutstandingJobs
;
135 static int gNumConfigThreads
;
136 static int gNumWaitingThreads
;
137 static IOLock
* gIOServiceBusyLock
;
139 static thread_t gIOTerminateThread
;
140 static UInt32 gIOTerminateWork
;
141 static OSArray
* gIOTerminatePhase2List
;
142 static OSArray
* gIOStopList
;
143 static OSArray
* gIOStopProviderList
;
144 static OSArray
* gIOFinalizeList
;
146 static SInt32 gIOConsoleUsersSeed
;
147 static OSData
* gIOConsoleUsersSeedValue
;
149 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
151 #define LOCKREADNOTIFY() \
152 IORecursiveLockLock( gNotificationLock )
153 #define LOCKWRITENOTIFY() \
154 IORecursiveLockLock( gNotificationLock )
155 #define LOCKWRITE2READNOTIFY()
156 #define UNLOCKNOTIFY() \
157 IORecursiveLockUnlock( gNotificationLock )
158 #define SLEEPNOTIFY(event) \
159 IORecursiveLockSleep( gNotificationLock, (void *)(event), THREAD_UNINT )
160 #define WAKEUPNOTIFY(event) \
161 IORecursiveLockWakeup( gNotificationLock, (void *)(event), /* wake one */ false )
163 #define randomDelay() \
164 int del = read_processor_clock(); \
165 del = (((int)IOThreadSelf()) ^ del ^ (del >> 10)) & 0x3ff; \
168 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
170 #define queue_element(entry, element, type, field) do { \
171 vm_address_t __ele = (vm_address_t) (entry); \
172 __ele -= -4 + ((size_t)(&((type) 4)->field)); \
173 (element) = (type) __ele; \
176 #define iterqueue(que, elt) \
177 for (queue_entry_t elt = queue_first(que); \
178 !queue_end(que, elt); \
179 elt = queue_next(elt))
181 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
183 struct ArbitrationLockQueueElement
{
192 static queue_head_t gArbitrationLockQueueActive
;
193 static queue_head_t gArbitrationLockQueueWaiting
;
194 static queue_head_t gArbitrationLockQueueFree
;
195 static IOLock
* gArbitrationLockQueueLock
;
197 bool IOService::isInactive( void ) const
198 { return( 0 != (kIOServiceInactiveState
& getState())); }
200 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
204 // Only used by the intel implementation of
205 // IOService::requireMaxBusStall(UInt32 __unused ns)
208 const IOService
*fService
;
212 static OSData
*sBusStall
= OSData::withCapacity(8 * sizeof(BusStallEntry
));
213 static IOLock
*sBusStallLock
= IOLockAlloc();
214 #endif /* __i386__ */
216 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
218 void IOService::initialize( void )
222 gIOServicePlane
= IORegistryEntry::makePlane( kIOServicePlane
);
223 gIOPowerPlane
= IORegistryEntry::makePlane( kIOPowerPlane
);
225 gIOProviderClassKey
= OSSymbol::withCStringNoCopy( kIOProviderClassKey
);
226 gIONameMatchKey
= OSSymbol::withCStringNoCopy( kIONameMatchKey
);
227 gIONameMatchedKey
= OSSymbol::withCStringNoCopy( kIONameMatchedKey
);
228 gIOPropertyMatchKey
= OSSymbol::withCStringNoCopy( kIOPropertyMatchKey
);
229 gIOPathMatchKey
= OSSymbol::withCStringNoCopy( kIOPathMatchKey
);
230 gIOLocationMatchKey
= OSSymbol::withCStringNoCopy( kIOLocationMatchKey
);
231 gIOParentMatchKey
= OSSymbol::withCStringNoCopy( kIOParentMatchKey
);
233 gIOMatchCategoryKey
= OSSymbol::withCStringNoCopy( kIOMatchCategoryKey
);
234 gIODefaultMatchCategoryKey
= OSSymbol::withCStringNoCopy(
235 kIODefaultMatchCategoryKey
);
236 gIOMatchedServiceCountKey
= OSSymbol::withCStringNoCopy(
237 kIOMatchedServiceCountKey
);
239 gIOUserClientClassKey
= OSSymbol::withCStringNoCopy( kIOUserClientClassKey
);
241 gIOResourcesKey
= OSSymbol::withCStringNoCopy( kIOResourcesClass
);
242 gIOResourceMatchKey
= OSSymbol::withCStringNoCopy( kIOResourceMatchKey
);
244 gIODeviceMemoryKey
= OSSymbol::withCStringNoCopy( "IODeviceMemory" );
245 gIOInterruptControllersKey
246 = OSSymbol::withCStringNoCopy("IOInterruptControllers");
247 gIOInterruptSpecifiersKey
248 = OSSymbol::withCStringNoCopy("IOInterruptSpecifiers");
250 gIOKitDebugKey
= OSSymbol::withCStringNoCopy( kIOKitDebugKey
);
252 gIOCommandPoolSizeKey
= OSSymbol::withCStringNoCopy( kIOCommandPoolSizeKey
);
254 gIOGeneralInterest
= OSSymbol::withCStringNoCopy( kIOGeneralInterest
);
255 gIOBusyInterest
= OSSymbol::withCStringNoCopy( kIOBusyInterest
);
256 gIOAppPowerStateInterest
= OSSymbol::withCStringNoCopy( kIOAppPowerStateInterest
);
257 gIOPriorityPowerStateInterest
= OSSymbol::withCStringNoCopy( kIOPriorityPowerStateInterest
);
259 gNotifications
= OSDictionary::withCapacity( 1 );
260 gIOPublishNotification
= OSSymbol::withCStringNoCopy(
261 kIOPublishNotification
);
262 gIOFirstPublishNotification
= OSSymbol::withCStringNoCopy(
263 kIOFirstPublishNotification
);
264 gIOMatchedNotification
= OSSymbol::withCStringNoCopy(
265 kIOMatchedNotification
);
266 gIOFirstMatchNotification
= OSSymbol::withCStringNoCopy(
267 kIOFirstMatchNotification
);
268 gIOTerminatedNotification
= OSSymbol::withCStringNoCopy(
269 kIOTerminatedNotification
);
270 gIOServiceKey
= OSSymbol::withCStringNoCopy( kIOServiceClass
);
272 gIOConsoleUsersKey
= OSSymbol::withCStringNoCopy( kIOConsoleUsersKey
);
273 gIOConsoleSessionUIDKey
= OSSymbol::withCStringNoCopy( kIOConsoleSessionUIDKey
);
274 gIOConsoleUsersSeedKey
= OSSymbol::withCStringNoCopy( kIOConsoleUsersSeedKey
);
275 gIOConsoleSessionOnConsoleKey
= OSSymbol::withCStringNoCopy( kIOConsoleSessionOnConsoleKey
);
276 gIOConsoleSessionSecureInputPIDKey
= OSSymbol::withCStringNoCopy( kIOConsoleSessionSecureInputPIDKey
);
277 gIOConsoleUsersSeedValue
= OSData::withBytesNoCopy(&gIOConsoleUsersSeed
, sizeof(gIOConsoleUsersSeed
));
279 gNotificationLock
= IORecursiveLockAlloc();
281 assert( gIOServicePlane
&& gIODeviceMemoryKey
282 && gIOInterruptControllersKey
&& gIOInterruptSpecifiersKey
283 && gIOResourcesKey
&& gNotifications
&& gNotificationLock
284 && gIOProviderClassKey
&& gIONameMatchKey
&& gIONameMatchedKey
285 && gIOMatchCategoryKey
&& gIODefaultMatchCategoryKey
286 && gIOPublishNotification
&& gIOMatchedNotification
287 && gIOTerminatedNotification
&& gIOServiceKey
288 && gIOConsoleUsersKey
&& gIOConsoleSessionUIDKey
289 && gIOConsoleSessionOnConsoleKey
&& gIOConsoleSessionSecureInputPIDKey
290 && gIOConsoleUsersSeedKey
&& gIOConsoleUsersSeedValue
);
292 gJobsLock
= IOLockAlloc();
293 gJobs
= OSOrderedSet::withCapacity( 10 );
295 gIOServiceBusyLock
= IOLockAlloc();
297 err
= semaphore_create(kernel_task
, &gJobsSemaphore
, SYNC_POLICY_FIFO
, 0);
299 assert( gIOServiceBusyLock
&& gJobs
&& gJobsLock
&& (err
== KERN_SUCCESS
) );
301 gIOResources
= IOResources::resources();
302 assert( gIOResources
);
304 gArbitrationLockQueueLock
= IOLockAlloc();
305 queue_init(&gArbitrationLockQueueActive
);
306 queue_init(&gArbitrationLockQueueWaiting
);
307 queue_init(&gArbitrationLockQueueFree
);
309 assert( gArbitrationLockQueueLock
);
311 gIOTerminatePhase2List
= OSArray::withCapacity( 2 );
312 gIOStopList
= OSArray::withCapacity( 16 );
313 gIOStopProviderList
= OSArray::withCapacity( 16 );
314 gIOFinalizeList
= OSArray::withCapacity( 16 );
315 assert( gIOTerminatePhase2List
&& gIOStopList
&& gIOStopProviderList
&& gIOFinalizeList
);
318 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
321 static UInt64
getDebugFlags( OSDictionary
* props
)
323 OSNumber
* debugProp
;
326 debugProp
= OSDynamicCast( OSNumber
,
327 props
->getObject( gIOKitDebugKey
));
329 debugFlags
= debugProp
->unsigned64BitValue();
331 debugFlags
= gIOKitDebug
;
333 return( debugFlags
);
337 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
339 // Probe a matched service and return an instance to be started.
340 // The default score is from the property table, & may be altered
341 // during probe to change the start order.
343 IOService
* IOService::probe( IOService
* provider
,
349 bool IOService::start( IOService
* provider
)
354 void IOService::stop( IOService
* provider
)
358 void IOService::free( void )
360 requireMaxBusStall(0);
361 if( getPropertyTable())
362 unregisterAllInterest();
368 * Attach in service plane
370 bool IOService::attach( IOService
* provider
)
376 if( gIOKitDebug
& kIOLogAttach
)
377 LOG( "%s::attach(%s)\n", getName(),
378 provider
->getName());
380 provider
->lockForArbitration();
381 if( provider
->__state
[0] & kIOServiceInactiveState
)
384 ok
= attachToParent( provider
, gIOServicePlane
);
385 provider
->unlockForArbitration();
388 gIOServiceRoot
= this;
389 ok
= attachToParent( getRegistryRoot(), gIOServicePlane
);
395 IOService
* IOService::getServiceRoot( void )
397 return( gIOServiceRoot
);
400 void IOService::detach( IOService
* provider
)
402 IOService
* newProvider
= 0;
406 if( gIOKitDebug
& kIOLogAttach
)
407 LOG("%s::detach(%s)\n", getName(), provider
->getName());
409 lockForArbitration();
411 adjParent
= ((busy
= (__state
[1] & kIOServiceBusyStateMask
))
412 && (provider
== getProvider()));
414 detachFromParent( provider
, gIOServicePlane
);
417 newProvider
= getProvider();
418 if( busy
&& (__state
[1] & kIOServiceTermPhase3State
) && (0 == newProvider
))
419 _adjustBusy( -busy
);
422 unlockForArbitration();
425 newProvider
->lockForArbitration();
426 newProvider
->_adjustBusy(1);
427 newProvider
->unlockForArbitration();
430 // check for last client detach from a terminated service
431 if( provider
->lockForArbitration( true )) {
433 provider
->_adjustBusy( -1 );
434 if( (provider
->__state
[1] & kIOServiceTermPhase3State
)
435 && (0 == provider
->getClient())) {
436 provider
->scheduleFinalize();
438 provider
->unlockForArbitration();
443 * Register instance - publish it for matching
446 void IOService::registerService( IOOptionBits options
)
452 enum { kMaxPathLen
= 256 };
453 enum { kMaxChars
= 63 };
455 IORegistryEntry
* parent
= this;
456 IORegistryEntry
* root
= getRegistryRoot();
457 while( parent
&& (parent
!= root
))
458 parent
= parent
->getParentEntry( gIOServicePlane
);
460 if( parent
!= root
) {
461 IOLog("%s: not registry member at registerService()\n", getName());
465 // Allow the Platform Expert to adjust this node.
466 if( gIOPlatform
&& (!gIOPlatform
->platformAdjustService(this)))
469 if( (this != gIOResources
)
470 && (kIOLogRegister
& gIOKitDebug
)) {
472 pathBuf
= (char *) IOMalloc( kMaxPathLen
);
474 IOLog( "Registering: " );
477 if( pathBuf
&& getPath( pathBuf
, &len
, gIOServicePlane
)) {
480 if( len
> kMaxChars
) {
484 if( (skip
= strchr( path
, '/')))
490 IOLog( "%s\n", path
);
493 IOFree( pathBuf
, kMaxPathLen
);
496 startMatching( options
);
499 void IOService::startMatching( IOOptionBits options
)
501 IOService
* provider
;
504 bool needWake
= false;
509 lockForArbitration();
511 sync
= (options
& kIOServiceSynchronous
)
512 || ((provider
= getProvider())
513 && (provider
->__state
[1] & kIOServiceSynchronousState
));
515 if ( options
& kIOServiceAsynchronous
)
518 needConfig
= (0 == (__state
[1] & (kIOServiceNeedConfigState
| kIOServiceConfigState
)))
519 && (0 == (__state
[0] & kIOServiceInactiveState
));
521 __state
[1] |= kIOServiceNeedConfigState
;
523 // __state[0] &= ~kIOServiceInactiveState;
525 // if( sync) LOG("OSKernelStackRemaining = %08x @ %s\n",
526 // OSKernelStackRemaining(), getName());
529 prevBusy
= _adjustBusy( 1 );
530 needWake
= (0 != (kIOServiceSyncPubState
& __state
[1]));
534 __state
[1] |= kIOServiceSynchronousState
;
536 __state
[1] &= ~kIOServiceSynchronousState
;
538 unlockForArbitration();
543 IOLockLock( gIOServiceBusyLock
);
544 thread_wakeup( (event_t
) this/*&__state[1]*/ );
545 IOLockUnlock( gIOServiceBusyLock
);
547 } else if( !sync
|| (kIOServiceAsynchronous
& options
)) {
549 ok
= (0 != _IOServiceJob::startJob( this, kMatchNubJob
, options
));
553 if( (__state
[1] & kIOServiceNeedConfigState
))
554 doServiceMatch( options
);
556 lockForArbitration();
557 IOLockLock( gIOServiceBusyLock
);
559 waitAgain
= (prevBusy
< (__state
[1] & kIOServiceBusyStateMask
));
561 __state
[1] |= kIOServiceSyncPubState
| kIOServiceBusyWaiterState
;
563 __state
[1] &= ~kIOServiceSyncPubState
;
565 unlockForArbitration();
568 assert_wait( (event_t
) this/*&__state[1]*/, THREAD_UNINT
);
570 IOLockUnlock( gIOServiceBusyLock
);
572 thread_block(THREAD_CONTINUE_NULL
);
574 } while( waitAgain
);
578 IOReturn
IOService::catalogNewDrivers( OSOrderedSet
* newTables
)
580 OSDictionary
* table
;
590 while( (table
= (OSDictionary
*) newTables
->getFirstObject())) {
593 set
= (OSSet
*) getExistingServices( table
,
594 kIOServiceRegisteredState
,
595 kIOServiceExistingSet
);
600 count
+= set
->getCount();
603 allSet
->merge((const OSSet
*) set
);
611 if( getDebugFlags( table
) & kIOLogMatch
)
612 LOG("Matching service count = %ld\n", count
);
614 newTables
->removeObject(table
);
618 while( (service
= (IOService
*) allSet
->getAnyObject())) {
619 service
->startMatching(kIOServiceAsynchronous
);
620 allSet
->removeObject(service
);
625 newTables
->release();
627 return( kIOReturnSuccess
);
630 _IOServiceJob
* _IOServiceJob::startJob( IOService
* nub
, int type
,
631 IOOptionBits options
)
635 job
= new _IOServiceJob
;
636 if( job
&& !job
->init()) {
644 job
->options
= options
;
645 nub
->retain(); // thread will release()
653 * Called on a registered service to see if it matches
657 bool IOService::matchPropertyTable( OSDictionary
* table
, SInt32
* score
)
659 return( matchPropertyTable(table
) );
662 bool IOService::matchPropertyTable( OSDictionary
* table
)
668 * Called on a matched service to allocate resources
669 * before first driver is attached.
672 IOReturn
IOService::getResources( void )
674 return( kIOReturnSuccess
);
678 * Client/provider accessors
681 IOService
* IOService::getProvider( void ) const
683 IOService
* self
= (IOService
*) this;
688 generation
= getGenerationCount();
689 if( __providerGeneration
== generation
)
692 parent
= (IOService
*) getParentEntry( gIOServicePlane
);
693 if( parent
== IORegistryEntry::getRegistryRoot())
694 /* root is not an IOService */
697 self
->__provider
= parent
;
698 // save the count before getParentEntry()
699 self
->__providerGeneration
= generation
;
704 IOWorkLoop
* IOService::getWorkLoop() const
706 IOService
*provider
= getProvider();
709 return provider
->getWorkLoop();
714 OSIterator
* IOService::getProviderIterator( void ) const
716 return( getParentIterator( gIOServicePlane
));
719 IOService
* IOService::getClient( void ) const
721 return( (IOService
*) getChildEntry( gIOServicePlane
));
724 OSIterator
* IOService::getClientIterator( void ) const
726 return( getChildIterator( gIOServicePlane
));
729 OSIterator
* _IOOpenServiceIterator::iterator( OSIterator
* _iter
,
730 const IOService
* client
,
731 const IOService
* provider
)
733 _IOOpenServiceIterator
* inst
;
738 inst
= new _IOOpenServiceIterator
;
740 if( inst
&& !inst
->init()) {
746 inst
->client
= client
;
747 inst
->provider
= provider
;
753 void _IOOpenServiceIterator::free()
757 last
->unlockForArbitration();
761 OSObject
* _IOOpenServiceIterator::getNextObject()
766 last
->unlockForArbitration();
768 while( (next
= (IOService
*) iter
->getNextObject())) {
770 next
->lockForArbitration();
771 if( (client
&& (next
->isOpen( client
)))
772 || (provider
&& (provider
->isOpen( next
))) )
774 next
->unlockForArbitration();
782 bool _IOOpenServiceIterator::isValid()
784 return( iter
->isValid() );
787 void _IOOpenServiceIterator::reset()
790 last
->unlockForArbitration();
796 OSIterator
* IOService::getOpenProviderIterator( void ) const
798 return( _IOOpenServiceIterator::iterator( getProviderIterator(), this, 0 ));
801 OSIterator
* IOService::getOpenClientIterator( void ) const
803 return( _IOOpenServiceIterator::iterator( getClientIterator(), 0, this ));
807 IOReturn
IOService::callPlatformFunction( const OSSymbol
* functionName
,
808 bool waitForFunction
,
809 void *param1
, void *param2
,
810 void *param3
, void *param4
)
812 IOReturn result
= kIOReturnUnsupported
;
813 IOService
*provider
= getProvider();
816 result
= provider
->callPlatformFunction(functionName
, waitForFunction
,
817 param1
, param2
, param3
, param4
);
823 IOReturn
IOService::callPlatformFunction( const char * functionName
,
824 bool waitForFunction
,
825 void *param1
, void *param2
,
826 void *param3
, void *param4
)
828 IOReturn result
= kIOReturnNoMemory
;
829 const OSSymbol
*functionSymbol
= OSSymbol::withCString(functionName
);
831 if (functionSymbol
!= 0) {
832 result
= callPlatformFunction(functionSymbol
, waitForFunction
,
833 param1
, param2
, param3
, param4
);
834 functionSymbol
->release();
842 * Accessors for global services
845 IOPlatformExpert
* IOService::getPlatform( void )
847 return( gIOPlatform
);
850 class IOPMrootDomain
* IOService::getPMRootDomain( void )
852 return( gIOPMRootDomain
);
855 IOService
* IOService::getResourceService( void )
857 return( gIOResources
);
860 void IOService::setPlatform( IOPlatformExpert
* platform
)
862 gIOPlatform
= platform
;
863 gIOResources
->attachToParent( gIOServiceRoot
, gIOServicePlane
);
866 void IOService::setPMRootDomain( class IOPMrootDomain
* rootDomain
)
868 gIOPMRootDomain
= rootDomain
;
869 publishResource("IOKit");
876 bool IOService::lockForArbitration( bool isSuccessRequired
)
880 ArbitrationLockQueueElement
* element
;
881 ArbitrationLockQueueElement
* active
;
882 ArbitrationLockQueueElement
* waiting
;
884 enum { kPutOnFreeQueue
, kPutOnActiveQueue
, kPutOnWaitingQueue
} action
;
886 // lock global access
887 IOTakeLock( gArbitrationLockQueueLock
);
889 // obtain an unused queue element
890 if( !queue_empty( &gArbitrationLockQueueFree
)) {
891 queue_remove_first( &gArbitrationLockQueueFree
,
893 ArbitrationLockQueueElement
*,
896 element
= IONew( ArbitrationLockQueueElement
, 1 );
900 // prepare the queue element
901 element
->thread
= IOThreadSelf();
902 element
->service
= this;
904 element
->required
= isSuccessRequired
;
905 element
->aborted
= false;
907 // determine whether this object is already locked (ie. on active queue)
909 queue_iterate( &gArbitrationLockQueueActive
,
911 ArbitrationLockQueueElement
*,
914 if( active
->service
== element
->service
) {
920 if( found
) { // this object is already locked
922 // determine whether it is the same or a different thread trying to lock
923 if( active
->thread
!= element
->thread
) { // it is a different thread
925 ArbitrationLockQueueElement
* victim
= 0;
927 // before placing this new thread on the waiting queue, we look for
928 // a deadlock cycle...
931 // determine whether the active thread holding the object we
932 // want is waiting for another object to be unlocked
934 queue_iterate( &gArbitrationLockQueueWaiting
,
936 ArbitrationLockQueueElement
*,
939 if( waiting
->thread
== active
->thread
) {
940 assert( false == waiting
->aborted
);
946 if( found
) { // yes, active thread waiting for another object
948 // this may be a candidate for rejection if the required
949 // flag is not set, should we detect a deadlock later on
950 if( false == waiting
->required
)
953 // find the thread that is holding this other object, that
954 // is blocking the active thread from proceeding (fun :-)
956 queue_iterate( &gArbitrationLockQueueActive
,
957 active
, // (reuse active queue element)
958 ArbitrationLockQueueElement
*,
961 if( active
->service
== waiting
->service
) {
967 // someone must be holding it or it wouldn't be waiting
970 if( active
->thread
== element
->thread
) {
972 // doh, it's waiting for the thread that originated
973 // this whole lock (ie. current thread) -> deadlock
974 if( false == element
->required
) { // willing to fail?
976 // the originating thread doesn't have the required
977 // flag, so it can fail
978 success
= false; // (fail originating lock request)
979 break; // (out of while)
981 } else { // originating thread is not willing to fail
983 // see if we came across a waiting thread that did
984 // not have the 'required' flag set: we'll fail it
987 // we do have a willing victim, fail it's lock
988 victim
->aborted
= true;
990 // take the victim off the waiting queue
991 queue_remove( &gArbitrationLockQueueWaiting
,
993 ArbitrationLockQueueElement
*,
997 IOLockWakeup( gArbitrationLockQueueLock
,
999 /* one thread */ true );
1001 // allow this thread to proceed (ie. wait)
1002 success
= true; // (put request on wait queue)
1003 break; // (out of while)
1006 // all the waiting threads we came across in
1007 // finding this loop had the 'required' flag
1008 // set, so we've got a deadlock we can't avoid
1009 panic("I/O Kit: Unrecoverable deadlock.");
1013 // repeat while loop, redefining active thread to be the
1014 // thread holding "this other object" (see above), and
1015 // looking for threads waiting on it; note the active
1016 // variable points to "this other object" already... so
1017 // there nothing to do in this else clause.
1019 } else { // no, active thread is not waiting for another object
1021 success
= true; // (put request on wait queue)
1022 break; // (out of while)
1026 if( success
) { // put the request on the waiting queue?
1027 kern_return_t wait_result
;
1029 // place this thread on the waiting queue and put it to sleep;
1030 // we place it at the tail of the queue...
1031 queue_enter( &gArbitrationLockQueueWaiting
,
1033 ArbitrationLockQueueElement
*,
1036 // declare that this thread will wait for a given event
1037 restart_sleep
: wait_result
= assert_wait( element
,
1038 element
->required
? THREAD_UNINT
1039 : THREAD_INTERRUPTIBLE
);
1041 // unlock global access
1042 IOUnlock( gArbitrationLockQueueLock
);
1044 // put thread to sleep, waiting for our event to fire...
1045 if (wait_result
== THREAD_WAITING
)
1046 wait_result
= thread_block(THREAD_CONTINUE_NULL
);
1049 // ...and we've been woken up; we might be in one of two states:
1050 // (a) we've been aborted and our queue element is not on
1051 // any of the three queues, but is floating around
1052 // (b) we're allowed to proceed with the lock and we have
1053 // already been moved from the waiting queue to the
1055 // ...plus a 3rd state, should the thread have been interrupted:
1056 // (c) we're still on the waiting queue
1058 // determine whether we were interrupted out of our sleep
1059 if( THREAD_INTERRUPTED
== wait_result
) {
1061 // re-lock global access
1062 IOTakeLock( gArbitrationLockQueueLock
);
1064 // determine whether we're still on the waiting queue
1066 queue_iterate( &gArbitrationLockQueueWaiting
,
1067 waiting
, // (reuse waiting queue element)
1068 ArbitrationLockQueueElement
*,
1071 if( waiting
== element
) {
1077 if( found
) { // yes, we're still on the waiting queue
1079 // determine whether we're willing to fail
1080 if( false == element
->required
) {
1082 // mark us as aborted
1083 element
->aborted
= true;
1085 // take us off the waiting queue
1086 queue_remove( &gArbitrationLockQueueWaiting
,
1088 ArbitrationLockQueueElement
*,
1090 } else { // we are not willing to fail
1092 // ignore interruption, go back to sleep
1097 // unlock global access
1098 IOUnlock( gArbitrationLockQueueLock
);
1100 // proceed as though this were a normal wake up
1101 wait_result
= THREAD_AWAKENED
;
1104 assert( THREAD_AWAKENED
== wait_result
);
1106 // determine whether we've been aborted while we were asleep
1107 if( element
->aborted
) {
1108 assert( false == element
->required
);
1110 // re-lock global access
1111 IOTakeLock( gArbitrationLockQueueLock
);
1113 action
= kPutOnFreeQueue
;
1115 } else { // we weren't aborted, so we must be ready to go :-)
1117 // we've already been moved from waiting to active queue
1121 } else { // the lock request is to be failed
1123 // return unused queue element to queue
1124 action
= kPutOnFreeQueue
;
1126 } else { // it is the same thread, recursive access is allowed
1128 // add one level of recursion
1131 // return unused queue element to queue
1132 action
= kPutOnFreeQueue
;
1135 } else { // this object is not already locked, so let this thread through
1136 action
= kPutOnActiveQueue
;
1140 // put the new element on a queue
1141 if( kPutOnActiveQueue
== action
) {
1142 queue_enter( &gArbitrationLockQueueActive
,
1144 ArbitrationLockQueueElement
*,
1146 } else if( kPutOnFreeQueue
== action
) {
1147 queue_enter( &gArbitrationLockQueueFree
,
1149 ArbitrationLockQueueElement
*,
1152 assert( 0 ); // kPutOnWaitingQueue never occurs, handled specially above
1155 // unlock global access
1156 IOUnlock( gArbitrationLockQueueLock
);
1161 void IOService::unlockForArbitration( void )
1164 ArbitrationLockQueueElement
* element
;
1166 // lock global access
1167 IOTakeLock( gArbitrationLockQueueLock
);
1169 // find the lock element for this object (ie. on active queue)
1171 queue_iterate( &gArbitrationLockQueueActive
,
1173 ArbitrationLockQueueElement
*,
1176 if( element
->service
== this ) {
1184 // determine whether the lock has been taken recursively
1185 if( element
->count
> 1 ) {
1186 // undo one level of recursion
1191 // remove it from the active queue
1192 queue_remove( &gArbitrationLockQueueActive
,
1194 ArbitrationLockQueueElement
*,
1197 // put it on the free queue
1198 queue_enter( &gArbitrationLockQueueFree
,
1200 ArbitrationLockQueueElement
*,
1203 // determine whether a thread is waiting for object (head to tail scan)
1205 queue_iterate( &gArbitrationLockQueueWaiting
,
1207 ArbitrationLockQueueElement
*,
1210 if( element
->service
== this ) {
1216 if ( found
) { // we found an interested thread on waiting queue
1218 // remove it from the waiting queue
1219 queue_remove( &gArbitrationLockQueueWaiting
,
1221 ArbitrationLockQueueElement
*,
1224 // put it on the active queue
1225 queue_enter( &gArbitrationLockQueueActive
,
1227 ArbitrationLockQueueElement
*,
1230 // wake the waiting thread
1231 IOLockWakeup( gArbitrationLockQueueLock
,
1233 /* one thread */ true );
1237 // unlock global access
1238 IOUnlock( gArbitrationLockQueueLock
);
1241 void IOService::applyToProviders( IOServiceApplierFunction applier
,
1244 applyToParents( (IORegistryEntryApplierFunction
) applier
,
1245 context
, gIOServicePlane
);
1248 void IOService::applyToClients( IOServiceApplierFunction applier
,
1251 applyToChildren( (IORegistryEntryApplierFunction
) applier
,
1252 context
, gIOServicePlane
);
1261 // send a message to a client or interested party of this service
1262 IOReturn
IOService::messageClient( UInt32 type
, OSObject
* client
,
1263 void * argument
, vm_size_t argSize
)
1266 IOService
* service
;
1267 _IOServiceInterestNotifier
* notify
;
1269 if( (service
= OSDynamicCast( IOService
, client
)))
1270 ret
= service
->message( type
, this, argument
);
1272 else if( (notify
= OSDynamicCast( _IOServiceInterestNotifier
, client
))) {
1274 _IOServiceNotifierInvocation invocation
;
1277 invocation
.thread
= current_thread();
1280 willNotify
= (0 != (kIOServiceNotifyEnable
& notify
->state
));
1283 queue_enter( ¬ify
->handlerInvocations
, &invocation
,
1284 _IOServiceNotifierInvocation
*, link
);
1290 ret
= (*notify
->handler
)( notify
->target
, notify
->ref
,
1291 type
, this, argument
, argSize
);
1294 queue_remove( ¬ify
->handlerInvocations
, &invocation
,
1295 _IOServiceNotifierInvocation
*, link
);
1296 if( kIOServiceNotifyWaiter
& notify
->state
) {
1297 notify
->state
&= ~kIOServiceNotifyWaiter
;
1298 WAKEUPNOTIFY( notify
);
1303 ret
= kIOReturnSuccess
;
1306 ret
= kIOReturnBadArgument
;
1312 applyToInterestNotifiers(const IORegistryEntry
*target
,
1313 const OSSymbol
* typeOfInterest
,
1314 OSObjectApplierFunction applier
,
1317 OSArray
* copyArray
= 0;
1321 IOCommand
*notifyList
=
1322 OSDynamicCast( IOCommand
, target
->getProperty( typeOfInterest
));
1325 copyArray
= OSArray::withCapacity(1);
1327 // iterate over queue, entry is set to each element in the list
1328 iterqueue(¬ifyList
->fCommandChain
, entry
) {
1329 _IOServiceInterestNotifier
* notify
;
1331 queue_element(entry
, notify
, _IOServiceInterestNotifier
*, chain
);
1332 copyArray
->setObject(notify
);
1341 for( index
= 0; (next
= copyArray
->getObject( index
)); index
++)
1342 (*applier
)(next
, context
);
1343 copyArray
->release();
1347 void IOService::applyToInterested( const OSSymbol
* typeOfInterest
,
1348 OSObjectApplierFunction applier
,
1351 applyToClients( (IOServiceApplierFunction
) applier
, context
);
1352 applyToInterestNotifiers(this, typeOfInterest
, applier
, context
);
1355 struct MessageClientsContext
{
1356 IOService
* service
;
1363 static void messageClientsApplier( OSObject
* object
, void * ctx
)
1366 MessageClientsContext
* context
= (MessageClientsContext
*) ctx
;
1368 ret
= context
->service
->messageClient( context
->type
,
1369 object
, context
->argument
, context
->argSize
);
1370 if( kIOReturnSuccess
!= ret
)
1374 // send a message to all clients
1375 IOReturn
IOService::messageClients( UInt32 type
,
1376 void * argument
, vm_size_t argSize
)
1378 MessageClientsContext context
;
1380 context
.service
= this;
1381 context
.type
= type
;
1382 context
.argument
= argument
;
1383 context
.argSize
= argSize
;
1384 context
.ret
= kIOReturnSuccess
;
1386 applyToInterested( gIOGeneralInterest
,
1387 &messageClientsApplier
, &context
);
1389 return( context
.ret
);
1392 IOReturn
IOService::acknowledgeNotification( IONotificationRef notification
,
1393 IOOptionBits response
)
1395 return( kIOReturnUnsupported
);
1398 IONotifier
* IOService::registerInterest( const OSSymbol
* typeOfInterest
,
1399 IOServiceInterestHandler handler
, void * target
, void * ref
)
1401 _IOServiceInterestNotifier
* notify
= 0;
1403 if( (typeOfInterest
!= gIOGeneralInterest
)
1404 && (typeOfInterest
!= gIOBusyInterest
)
1405 && (typeOfInterest
!= gIOAppPowerStateInterest
)
1406 && (typeOfInterest
!= gIOPriorityPowerStateInterest
))
1409 lockForArbitration();
1410 if( 0 == (__state
[0] & kIOServiceInactiveState
)) {
1412 notify
= new _IOServiceInterestNotifier
;
1413 if( notify
&& !notify
->init()) {
1419 notify
->handler
= handler
;
1420 notify
->target
= target
;
1422 notify
->state
= kIOServiceNotifyEnable
;
1423 queue_init( ¬ify
->handlerInvocations
);
1429 // Get the head of the notifier linked list
1430 IOCommand
*notifyList
= (IOCommand
*) getProperty( typeOfInterest
);
1431 if (!notifyList
|| !OSDynamicCast(IOCommand
, notifyList
)) {
1432 notifyList
= OSTypeAlloc(IOCommand
);
1435 setProperty( typeOfInterest
, notifyList
);
1436 notifyList
->release();
1441 enqueue(¬ifyList
->fCommandChain
, ¬ify
->chain
);
1442 notify
->retain(); // ref'ed while in list
1448 unlockForArbitration();
1453 static void cleanInterestList( OSObject
* head
)
1455 IOCommand
*notifyHead
= OSDynamicCast(IOCommand
, head
);
1460 while ( queue_entry_t entry
= dequeue(¬ifyHead
->fCommandChain
) ) {
1461 queue_next(entry
) = queue_prev(entry
) = 0;
1463 _IOServiceInterestNotifier
* notify
;
1465 queue_element(entry
, notify
, _IOServiceInterestNotifier
*, chain
);
1471 void IOService::unregisterAllInterest( void )
1473 cleanInterestList( getProperty( gIOGeneralInterest
));
1474 cleanInterestList( getProperty( gIOBusyInterest
));
1475 cleanInterestList( getProperty( gIOAppPowerStateInterest
));
1476 cleanInterestList( getProperty( gIOPriorityPowerStateInterest
));
1480 * _IOServiceInterestNotifier
1483 // wait for all threads, other than the current one,
1484 // to exit the handler
1486 void _IOServiceInterestNotifier::wait()
1488 _IOServiceNotifierInvocation
* next
;
1493 queue_iterate( &handlerInvocations
, next
,
1494 _IOServiceNotifierInvocation
*, link
) {
1495 if( next
->thread
!= current_thread() ) {
1501 state
|= kIOServiceNotifyWaiter
;
1508 void _IOServiceInterestNotifier::free()
1510 assert( queue_empty( &handlerInvocations
));
1514 void _IOServiceInterestNotifier::remove()
1518 if( queue_next( &chain
)) {
1519 remqueue( 0, &chain
);
1520 queue_next( &chain
) = queue_prev( &chain
) = 0;
1524 state
&= ~kIOServiceNotifyEnable
;
1533 bool _IOServiceInterestNotifier::disable()
1539 ret
= (0 != (kIOServiceNotifyEnable
& state
));
1540 state
&= ~kIOServiceNotifyEnable
;
1549 void _IOServiceInterestNotifier::enable( bool was
)
1553 state
|= kIOServiceNotifyEnable
;
1555 state
&= ~kIOServiceNotifyEnable
;
1559 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1565 #define tailQ(o) setObject(o)
1566 #define headQ(o) setObject(0, o)
1567 #define TLOG(fmt, args...) { if(kIOLogYield & gIOKitDebug) IOLog(fmt, ## args); }
1569 inline void _workLoopAction( IOWorkLoop::Action action
,
1570 IOService
* service
,
1571 void * p0
= 0, void * p1
= 0,
1572 void * p2
= 0, void * p3
= 0 )
1576 if( (wl
= service
->getWorkLoop())) {
1578 wl
->runAction( action
, service
, p0
, p1
, p2
, p3
);
1581 (*action
)( service
, p0
, p1
, p2
, p3
);
1584 bool IOService::requestTerminate( IOService
* provider
, IOOptionBits options
)
1588 // if its our only provider
1589 ok
= isParent( provider
, gIOServicePlane
, true);
1593 provider
->terminateClient( this, options
| kIOServiceRecursing
);
1594 ok
= (0 != (__state
[1] & kIOServiceRecursing
));
1601 bool IOService::terminatePhase1( IOOptionBits options
)
1606 OSArray
* makeInactive
;
1609 bool startPhase2
= false;
1611 TLOG("%s::terminatePhase1(%08lx)\n", getName(), options
);
1614 if( options
& kIOServiceRecursing
) {
1615 __state
[1] |= kIOServiceRecursing
;
1620 makeInactive
= OSArray::withCapacity( 16 );
1629 didInactive
= victim
->lockForArbitration( true );
1631 didInactive
= (0 == (victim
->__state
[0] & kIOServiceInactiveState
));
1633 victim
->__state
[0] |= kIOServiceInactiveState
;
1634 victim
->__state
[0] &= ~(kIOServiceRegisteredState
| kIOServiceMatchedState
1635 | kIOServiceFirstPublishState
| kIOServiceFirstMatchState
);
1636 victim
->_adjustBusy( 1 );
1638 victim
->unlockForArbitration();
1641 startPhase2
= didInactive
;
1644 victim
->deliverNotification( gIOTerminatedNotification
, 0, 0xffffffff );
1645 IOUserClient::destroyUserReferences( victim
);
1647 iter
= victim
->getClientIterator();
1649 while( (client
= (IOService
*) iter
->getNextObject())) {
1650 TLOG("%s::requestTerminate(%s, %08lx)\n",
1651 client
->getName(), victim
->getName(), options
);
1652 ok
= client
->requestTerminate( victim
, options
);
1653 TLOG("%s::requestTerminate(%s, ok = %d)\n",
1654 client
->getName(), victim
->getName(), ok
);
1656 makeInactive
->setObject( client
);
1662 victim
= (IOService
*) makeInactive
->getObject(0);
1665 makeInactive
->removeObject(0);
1669 makeInactive
->release();
1672 scheduleTerminatePhase2( options
);
1677 void IOService::scheduleTerminatePhase2( IOOptionBits options
)
1679 AbsoluteTime deadline
;
1680 int waitResult
= THREAD_AWAKENED
;
1681 bool wait
, haveDeadline
= false;
1683 options
|= kIOServiceRequired
;
1687 IOLockLock( gJobsLock
);
1689 if( (options
& kIOServiceSynchronous
)
1690 && (current_thread() != gIOTerminateThread
)) {
1693 wait
= (gIOTerminateThread
!= 0);
1695 // wait to become the terminate thread
1696 IOLockSleep( gJobsLock
, &gIOTerminateThread
, THREAD_UNINT
);
1700 gIOTerminateThread
= current_thread();
1701 gIOTerminatePhase2List
->setObject( this );
1705 while( gIOTerminateWork
)
1706 terminateWorker( options
);
1707 wait
= (0 != (__state
[1] & kIOServiceBusyStateMask
));
1709 // wait for the victim to go non-busy
1710 if( !haveDeadline
) {
1711 clock_interval_to_deadline( 15, kSecondScale
, &deadline
);
1712 haveDeadline
= true;
1714 waitResult
= IOLockSleepDeadline( gJobsLock
, &gIOTerminateWork
,
1715 deadline
, THREAD_UNINT
);
1716 if( waitResult
== THREAD_TIMED_OUT
) {
1717 TLOG("%s::terminate(kIOServiceSynchronous) timeout", getName());
1720 } while(gIOTerminateWork
|| (wait
&& (waitResult
!= THREAD_TIMED_OUT
)));
1722 gIOTerminateThread
= 0;
1723 IOLockWakeup( gJobsLock
, (event_t
) &gIOTerminateThread
, /* one-thread */ false);
1726 // ! kIOServiceSynchronous
1728 gIOTerminatePhase2List
->setObject( this );
1729 if( 0 == gIOTerminateWork
++) {
1730 if( !gIOTerminateThread
)
1731 gIOTerminateThread
= IOCreateThread( &terminateThread
, (void *) options
);
1733 IOLockWakeup(gJobsLock
, (event_t
) &gIOTerminateWork
, /* one-thread */ false );
1737 IOLockUnlock( gJobsLock
);
1742 void IOService::terminateThread( void * arg
)
1744 IOLockLock( gJobsLock
);
1746 while (gIOTerminateWork
)
1747 terminateWorker( (IOOptionBits
) arg
);
1749 gIOTerminateThread
= 0;
1750 IOLockWakeup( gJobsLock
, (event_t
) &gIOTerminateThread
, /* one-thread */ false);
1752 IOLockUnlock( gJobsLock
);
1755 void IOService::scheduleStop( IOService
* provider
)
1757 TLOG("%s::scheduleStop(%s)\n", getName(), provider
->getName());
1759 IOLockLock( gJobsLock
);
1760 gIOStopList
->tailQ( this );
1761 gIOStopProviderList
->tailQ( provider
);
1763 if( 0 == gIOTerminateWork
++) {
1764 if( !gIOTerminateThread
)
1765 gIOTerminateThread
= IOCreateThread( &terminateThread
, (void *) 0 );
1767 IOLockWakeup(gJobsLock
, (event_t
) &gIOTerminateWork
, /* one-thread */ false );
1770 IOLockUnlock( gJobsLock
);
1773 void IOService::scheduleFinalize( void )
1775 TLOG("%s::scheduleFinalize\n", getName());
1777 IOLockLock( gJobsLock
);
1778 gIOFinalizeList
->tailQ( this );
1780 if( 0 == gIOTerminateWork
++) {
1781 if( !gIOTerminateThread
)
1782 gIOTerminateThread
= IOCreateThread( &terminateThread
, (void *) 0 );
1784 IOLockWakeup(gJobsLock
, (event_t
) &gIOTerminateWork
, /* one-thread */ false );
1787 IOLockUnlock( gJobsLock
);
1790 bool IOService::willTerminate( IOService
* provider
, IOOptionBits options
)
1795 bool IOService::didTerminate( IOService
* provider
, IOOptionBits options
, bool * defer
)
1797 if( false == *defer
) {
1799 if( lockForArbitration( true )) {
1800 if( false == provider
->handleIsOpen( this ))
1801 scheduleStop( provider
);
1804 message( kIOMessageServiceIsRequestingClose
, provider
, (void *) options
);
1805 if( false == provider
->handleIsOpen( this ))
1806 scheduleStop( provider
);
1809 unlockForArbitration();
1816 void IOService::actionWillTerminate( IOService
* victim
, IOOptionBits options
,
1817 OSArray
* doPhase2List
)
1823 iter
= victim
->getClientIterator();
1825 while( (client
= (IOService
*) iter
->getNextObject())) {
1826 TLOG("%s::willTerminate(%s, %08lx)\n",
1827 client
->getName(), victim
->getName(), options
);
1828 ok
= client
->willTerminate( victim
, options
);
1829 doPhase2List
->tailQ( client
);
1835 void IOService::actionDidTerminate( IOService
* victim
, IOOptionBits options
)
1841 victim
->messageClients( kIOMessageServiceIsTerminated
, (void *) options
);
1843 iter
= victim
->getClientIterator();
1845 while( (client
= (IOService
*) iter
->getNextObject())) {
1846 TLOG("%s::didTerminate(%s, %08lx)\n",
1847 client
->getName(), victim
->getName(), options
);
1848 client
->didTerminate( victim
, options
, &defer
);
1849 TLOG("%s::didTerminate(%s, defer %d)\n",
1850 client
->getName(), victim
->getName(), defer
);
1856 void IOService::actionFinalize( IOService
* victim
, IOOptionBits options
)
1858 TLOG("%s::finalize(%08lx)\n", victim
->getName(), options
);
1859 victim
->finalize( options
);
1862 void IOService::actionStop( IOService
* provider
, IOService
* client
)
1864 TLOG("%s::stop(%s)\n", client
->getName(), provider
->getName());
1865 client
->stop( provider
);
1866 if( provider
->isOpen( client
))
1867 provider
->close( client
);
1868 TLOG("%s::detach(%s)\n", client
->getName(), provider
->getName());
1869 client
->detach( provider
);
1872 void IOService::terminateWorker( IOOptionBits options
)
1874 OSArray
* doPhase2List
;
1875 OSArray
* didPhase2List
;
1880 IOService
* provider
;
1886 options
|= kIOServiceRequired
;
1888 doPhase2List
= OSArray::withCapacity( 16 );
1889 didPhase2List
= OSArray::withCapacity( 16 );
1890 freeList
= OSSet::withCapacity( 16 );
1891 if( (0 == doPhase2List
) || (0 == didPhase2List
) || (0 == freeList
))
1895 workDone
= gIOTerminateWork
;
1897 while( (victim
= (IOService
*) gIOTerminatePhase2List
->getObject(0) )) {
1900 gIOTerminatePhase2List
->removeObject(0);
1901 IOLockUnlock( gJobsLock
);
1905 doPhase2
= victim
->lockForArbitration( true );
1907 doPhase2
= (0 != (kIOServiceInactiveState
& victim
->__state
[0]));
1909 doPhase2
= (0 == (victim
->__state
[1] & kIOServiceTermPhase2State
))
1910 && (0 == (victim
->__state
[1] & kIOServiceConfigState
));
1912 victim
->__state
[1] |= kIOServiceTermPhase2State
;
1914 victim
->unlockForArbitration();
1917 if( 0 == victim
->getClient()) {
1918 // no clients - will go to finalize
1919 IOLockLock( gJobsLock
);
1920 gIOFinalizeList
->tailQ( victim
);
1921 IOLockUnlock( gJobsLock
);
1923 _workLoopAction( (IOWorkLoop::Action
) &actionWillTerminate
,
1924 victim
, (void *) options
, (void *) doPhase2List
);
1926 didPhase2List
->headQ( victim
);
1929 victim
= (IOService
*) doPhase2List
->getObject(0);
1932 doPhase2List
->removeObject(0);
1936 while( (victim
= (IOService
*) didPhase2List
->getObject(0)) ) {
1938 if( victim
->lockForArbitration( true )) {
1939 victim
->__state
[1] |= kIOServiceTermPhase3State
;
1940 victim
->unlockForArbitration();
1942 _workLoopAction( (IOWorkLoop::Action
) &actionDidTerminate
,
1943 victim
, (void *) options
);
1944 didPhase2List
->removeObject(0);
1946 IOLockLock( gJobsLock
);
1953 while( (victim
= (IOService
*) gIOFinalizeList
->getObject(0))) {
1955 IOLockUnlock( gJobsLock
);
1956 _workLoopAction( (IOWorkLoop::Action
) &actionFinalize
,
1957 victim
, (void *) options
);
1958 IOLockLock( gJobsLock
);
1960 freeList
->setObject( victim
);
1961 // safe if finalize list is append only
1962 gIOFinalizeList
->removeObject(0);
1966 (!doPhase3
) && (client
= (IOService
*) gIOStopList
->getObject(idx
)); ) {
1968 provider
= (IOService
*) gIOStopProviderList
->getObject(idx
);
1971 if( !provider
->isChild( client
, gIOServicePlane
)) {
1972 // may be multiply queued - nop it
1973 TLOG("%s::nop stop(%s)\n", client
->getName(), provider
->getName());
1975 // not ready for stop if it has clients, skip it
1976 if( (client
->__state
[1] & kIOServiceTermPhase3State
) && client
->getClient()) {
1977 TLOG("%s::defer stop(%s)\n", client
->getName(), provider
->getName());
1982 IOLockUnlock( gJobsLock
);
1983 _workLoopAction( (IOWorkLoop::Action
) &actionStop
,
1984 provider
, (void *) client
);
1985 IOLockLock( gJobsLock
);
1986 // check the finalize list now
1990 freeList
->setObject( client
);
1991 freeList
->setObject( provider
);
1993 // safe if stop list is append only
1994 gIOStopList
->removeObject( idx
);
1995 gIOStopProviderList
->removeObject( idx
);
1999 } while( doPhase3
);
2001 gIOTerminateWork
-= workDone
;
2002 moreToDo
= (gIOTerminateWork
!= 0);
2005 TLOG("iokit terminate done, %d stops remain\n", gIOStopList
->getCount());
2008 } while( moreToDo
);
2010 IOLockUnlock( gJobsLock
);
2012 freeList
->release();
2013 doPhase2List
->release();
2014 didPhase2List
->release();
2016 IOLockLock( gJobsLock
);
2019 bool IOService::finalize( IOOptionBits options
)
2022 IOService
* provider
;
2024 iter
= getProviderIterator();
2028 while( (provider
= (IOService
*) iter
->getNextObject())) {
2031 if( 0 == (__state
[1] & kIOServiceTermPhase3State
)) {
2032 /* we come down here on programmatic terminate */
2034 if( provider
->isOpen( this ))
2035 provider
->close( this );
2039 if( provider
->lockForArbitration( true )) {
2040 if( 0 == (provider
->__state
[1] & kIOServiceTermPhase3State
))
2041 scheduleStop( provider
);
2042 provider
->unlockForArbitration();
2059 void IOService::doServiceTerminate( IOOptionBits options
)
2063 // a method in case someone needs to override it
2064 bool IOService::terminateClient( IOService
* client
, IOOptionBits options
)
2068 if( client
->isParent( this, gIOServicePlane
, true))
2069 // we are the clients only provider
2070 ok
= client
->terminate( options
);
2077 bool IOService::terminate( IOOptionBits options
)
2079 options
|= kIOServiceTerminate
;
2081 return( terminatePhase1( options
));
2084 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2090 struct ServiceOpenMessageContext
2092 IOService
* service
;
2094 IOService
* excludeClient
;
2095 IOOptionBits options
;
2098 static void serviceOpenMessageApplier( OSObject
* object
, void * ctx
)
2100 ServiceOpenMessageContext
* context
= (ServiceOpenMessageContext
*) ctx
;
2102 if( object
!= context
->excludeClient
)
2103 context
->service
->messageClient( context
->type
, object
, (void *) context
->options
);
2106 bool IOService::open( IOService
* forClient
,
2107 IOOptionBits options
,
2111 ServiceOpenMessageContext context
;
2113 context
.service
= this;
2114 context
.type
= kIOMessageServiceIsAttemptingOpen
;
2115 context
.excludeClient
= forClient
;
2116 context
.options
= options
;
2118 applyToInterested( gIOGeneralInterest
,
2119 &serviceOpenMessageApplier
, &context
);
2121 if( false == lockForArbitration(false) )
2124 ok
= (0 == (__state
[0] & kIOServiceInactiveState
));
2126 ok
= handleOpen( forClient
, options
, arg
);
2128 unlockForArbitration();
2133 void IOService::close( IOService
* forClient
,
2134 IOOptionBits options
)
2139 lockForArbitration();
2141 wasClosed
= handleIsOpen( forClient
);
2143 handleClose( forClient
, options
);
2144 last
= (__state
[1] & kIOServiceTermPhase3State
);
2147 unlockForArbitration();
2150 forClient
->scheduleStop( this );
2152 else if( wasClosed
) {
2154 ServiceOpenMessageContext context
;
2156 context
.service
= this;
2157 context
.type
= kIOMessageServiceWasClosed
;
2158 context
.excludeClient
= forClient
;
2159 context
.options
= options
;
2161 applyToInterested( gIOGeneralInterest
,
2162 &serviceOpenMessageApplier
, &context
);
2166 bool IOService::isOpen( const IOService
* forClient
) const
2168 IOService
* self
= (IOService
*) this;
2171 self
->lockForArbitration();
2173 ok
= handleIsOpen( forClient
);
2175 self
->unlockForArbitration();
2180 bool IOService::handleOpen( IOService
* forClient
,
2181 IOOptionBits options
,
2186 ok
= (0 == __owner
);
2188 __owner
= forClient
;
2190 else if( options
& kIOServiceSeize
) {
2191 ok
= (kIOReturnSuccess
== messageClient( kIOMessageServiceIsRequestingClose
,
2192 __owner
, (void *) options
));
2193 if( ok
&& (0 == __owner
))
2194 __owner
= forClient
;
2201 void IOService::handleClose( IOService
* forClient
,
2202 IOOptionBits options
)
2204 if( __owner
== forClient
)
2208 bool IOService::handleIsOpen( const IOService
* forClient
) const
2211 return( __owner
== forClient
);
2213 return( __owner
!= forClient
);
2217 * Probing & starting
2219 static SInt32
IONotifyOrdering( const OSMetaClassBase
* inObj1
, const OSMetaClassBase
* inObj2
, void * ref
)
2221 const _IOServiceNotifier
* obj1
= (const _IOServiceNotifier
*) inObj1
;
2222 const _IOServiceNotifier
* obj2
= (const _IOServiceNotifier
*) inObj2
;
2230 val1
= obj1
->priority
;
2233 val2
= obj2
->priority
;
2235 return ( val1
- val2
);
2238 static SInt32
IOServiceObjectOrder( const OSObject
* entry
, void * ref
)
2240 OSDictionary
* dict
;
2241 IOService
* service
;
2242 _IOServiceNotifier
* notify
;
2243 OSSymbol
* key
= (OSSymbol
*) ref
;
2246 if( (notify
= OSDynamicCast( _IOServiceNotifier
, entry
)))
2247 return( notify
->priority
);
2249 else if( (service
= OSDynamicCast( IOService
, entry
)))
2250 offset
= OSDynamicCast(OSNumber
, service
->getProperty( key
));
2251 else if( (dict
= OSDynamicCast( OSDictionary
, entry
)))
2252 offset
= OSDynamicCast(OSNumber
, dict
->getObject( key
));
2259 return( (SInt32
) offset
->unsigned32BitValue());
2261 return( kIODefaultProbeScore
);
2264 SInt32
IOServiceOrdering( const OSMetaClassBase
* inObj1
, const OSMetaClassBase
* inObj2
, void * ref
)
2266 const OSObject
* obj1
= (const OSObject
*) inObj1
;
2267 const OSObject
* obj2
= (const OSObject
*) inObj2
;
2275 val1
= IOServiceObjectOrder( obj1
, ref
);
2278 val2
= IOServiceObjectOrder( obj2
, ref
);
2280 return ( val1
- val2
);
2283 IOService
* IOService::getClientWithCategory( const OSSymbol
* category
)
2285 IOService
* service
= 0;
2287 const OSSymbol
* nextCat
;
2289 iter
= getClientIterator();
2291 while( (service
= (IOService
*) iter
->getNextObject())) {
2292 if( kIOServiceInactiveState
& service
->__state
[0])
2294 nextCat
= (const OSSymbol
*) OSDynamicCast( OSSymbol
,
2295 service
->getProperty( gIOMatchCategoryKey
));
2296 if( category
== nextCat
)
2304 bool IOService::invokeNotifer( _IOServiceNotifier
* notify
)
2306 _IOServiceNotifierInvocation invocation
;
2310 invocation
.thread
= current_thread();
2313 willNotify
= (0 != (kIOServiceNotifyEnable
& notify
->state
));
2316 queue_enter( ¬ify
->handlerInvocations
, &invocation
,
2317 _IOServiceNotifierInvocation
*, link
);
2323 ret
= (*notify
->handler
)( notify
->target
, notify
->ref
, this );
2326 queue_remove( ¬ify
->handlerInvocations
, &invocation
,
2327 _IOServiceNotifierInvocation
*, link
);
2328 if( kIOServiceNotifyWaiter
& notify
->state
) {
2329 notify
->state
&= ~kIOServiceNotifyWaiter
;
2330 WAKEUPNOTIFY( notify
);
2339 * Alloc and probe matching classes,
2340 * called on the provider instance
2343 void IOService::probeCandidates( OSOrderedSet
* matches
)
2345 OSDictionary
* match
= 0;
2348 IOService
* newInst
;
2349 OSDictionary
* props
;
2352 OSOrderedSet
* familyMatches
= 0;
2353 OSOrderedSet
* startList
;
2354 OSDictionary
* startDict
= 0;
2355 const OSSymbol
* category
;
2357 _IOServiceNotifier
* notify
;
2358 OSObject
* nextMatch
= 0;
2360 bool needReloc
= false;
2366 while( !needReloc
&& (nextMatch
= matches
->getFirstObject())) {
2368 nextMatch
->retain();
2369 matches
->removeObject(nextMatch
);
2371 if( (notify
= OSDynamicCast( _IOServiceNotifier
, nextMatch
))) {
2373 lockForArbitration();
2374 if( 0 == (__state
[0] & kIOServiceInactiveState
))
2375 invokeNotifer( notify
);
2376 unlockForArbitration();
2377 nextMatch
->release();
2381 } else if( !(match
= OSDynamicCast( OSDictionary
, nextMatch
))) {
2382 nextMatch
->release();
2389 debugFlags
= getDebugFlags( match
);
2393 category
= OSDynamicCast( OSSymbol
,
2394 match
->getObject( gIOMatchCategoryKey
));
2396 category
= gIODefaultMatchCategoryKey
;
2398 if( getClientWithCategory( category
)) {
2400 if( debugFlags
& kIOLogMatch
)
2401 LOG("%s: match category %s exists\n", getName(),
2402 category
->getCStringNoCopy());
2404 nextMatch
->release();
2409 // create a copy now in case its modified during matching
2410 props
= OSDictionary::withDictionary( match
, match
->getCount());
2413 props
->setCapacityIncrement(1);
2415 // check the nub matches
2416 if( false == passiveMatch( props
, true ))
2419 // Check to see if driver reloc has been loaded.
2420 needReloc
= (false == gIOCatalogue
->isModuleLoaded( match
));
2423 if( debugFlags
& kIOLogCatalogue
)
2424 LOG("%s: stalling for module\n", getName());
2426 // If reloc hasn't been loaded, exit;
2427 // reprobing will occur after reloc has been loaded.
2431 // reorder on family matchPropertyTable score.
2432 if( 0 == familyMatches
)
2433 familyMatches
= OSOrderedSet::withCapacity( 1,
2434 IOServiceOrdering
, (void *) gIOProbeScoreKey
);
2436 familyMatches
->setObject( props
);
2441 nextMatch
->release();
2450 if( familyMatches
) {
2453 && (props
= (OSDictionary
*) familyMatches
->getFirstObject())) {
2456 familyMatches
->removeObject( props
);
2461 debugFlags
= getDebugFlags( props
);
2464 symbol
= OSDynamicCast( OSSymbol
,
2465 props
->getObject( gIOClassKey
));
2469 // alloc the driver instance
2470 inst
= (IOService
*) OSMetaClass::allocClassWithName( symbol
);
2473 IOLog("Couldn't alloc class \"%s\"\n",
2474 symbol
->getCStringNoCopy());
2478 // init driver instance
2479 if( !(inst
->init( props
))) {
2481 if( debugFlags
& kIOLogStart
)
2482 IOLog("%s::init fails\n", symbol
->getCStringNoCopy());
2486 if( __state
[1] & kIOServiceSynchronousState
)
2487 inst
->__state
[1] |= kIOServiceSynchronousState
;
2489 // give the driver the default match category if not specified
2490 category
= OSDynamicCast( OSSymbol
,
2491 props
->getObject( gIOMatchCategoryKey
));
2493 category
= gIODefaultMatchCategoryKey
;
2494 inst
->setProperty( gIOMatchCategoryKey
, (OSObject
*) category
);
2496 // attach driver instance
2497 if( !(inst
->attach( this )))
2500 // pass in score from property table
2501 score
= familyMatches
->orderObject( props
);
2503 // & probe the new driver instance
2505 if( debugFlags
& kIOLogProbe
)
2506 LOG("%s::probe(%s)\n",
2507 inst
->getMetaClass()->getClassName(), getName());
2510 newInst
= inst
->probe( this, &score
);
2511 inst
->detach( this );
2514 if( debugFlags
& kIOLogProbe
)
2515 IOLog("%s::probe fails\n", symbol
->getCStringNoCopy());
2521 newPri
= OSNumber::withNumber( score
, 32 );
2523 newInst
->setProperty( gIOProbeScoreKey
, newPri
);
2527 // add to start list for the match category
2529 startDict
= OSDictionary::withCapacity( 1 );
2530 assert( startDict
);
2531 startList
= (OSOrderedSet
*)
2532 startDict
->getObject( category
);
2533 if( 0 == startList
) {
2534 startList
= OSOrderedSet::withCapacity( 1,
2535 IOServiceOrdering
, (void *) gIOProbeScoreKey
);
2536 if( startDict
&& startList
) {
2537 startDict
->setObject( category
, startList
);
2538 startList
->release();
2541 assert( startList
);
2543 startList
->setObject( newInst
);
2551 familyMatches
->release();
2555 // start the best (until success) of each category
2557 iter
= OSCollectionIterator::withCollection( startDict
);
2559 while( (category
= (const OSSymbol
*) iter
->getNextObject())) {
2561 startList
= (OSOrderedSet
*) startDict
->getObject( category
);
2562 assert( startList
);
2567 while( true // (!started)
2568 && (inst
= (IOService
*)startList
->getFirstObject())) {
2571 startList
->removeObject(inst
);
2574 debugFlags
= getDebugFlags( inst
->getPropertyTable() );
2576 if( debugFlags
& kIOLogStart
) {
2578 LOG( "match category exists, skipping " );
2579 LOG( "%s::start(%s) <%d>\n", inst
->getName(),
2580 getName(), inst
->getRetainCount());
2583 if( false == started
)
2584 started
= startCandidate( inst
);
2586 if( (debugFlags
& kIOLogStart
) && (false == started
))
2587 LOG( "%s::start(%s) <%d> failed\n", inst
->getName(), getName(),
2588 inst
->getRetainCount());
2597 // adjust the busy count by -1 if matching is stalled for a module,
2598 // or +1 if a previously stalled matching is complete.
2599 lockForArbitration();
2602 adjBusy
= (__state
[1] & kIOServiceModuleStallState
) ? 0 : 1;
2604 __state
[1] |= kIOServiceModuleStallState
;
2606 } else if( __state
[1] & kIOServiceModuleStallState
) {
2607 __state
[1] &= ~kIOServiceModuleStallState
;
2611 _adjustBusy( adjBusy
);
2612 unlockForArbitration();
2615 startDict
->release();
2619 * Start a previously attached & probed instance,
2620 * called on exporting object instance
2623 bool IOService::startCandidate( IOService
* service
)
2627 ok
= service
->attach( this );
2631 if (this != gIOResources
)
2633 // stall for any nub resources
2635 // stall for any driver resources
2636 service
->checkResources();
2639 AbsoluteTime startTime
;
2640 AbsoluteTime endTime
;
2643 if (kIOLogStart
& gIOKitDebug
)
2644 clock_get_uptime(&startTime
);
2646 ok
= service
->start(this);
2648 if (kIOLogStart
& gIOKitDebug
)
2650 clock_get_uptime(&endTime
);
2652 if (CMP_ABSOLUTETIME(&endTime
, &startTime
) > 0)
2654 SUB_ABSOLUTETIME(&endTime
, &startTime
);
2655 absolutetime_to_nanoseconds(endTime
, &nano
);
2656 if (nano
> 500000000ULL)
2657 IOLog("%s::start took %ld ms\n", service
->getName(), (UInt32
)(nano
/ 1000000ULL));
2661 service
->detach( this );
2666 IOService
* IOService::resources( void )
2668 return( gIOResources
);
2671 void IOService::publishResource( const char * key
, OSObject
* value
)
2673 const OSSymbol
* sym
;
2675 if( (sym
= OSSymbol::withCString( key
))) {
2676 publishResource( sym
, value
);
2681 void IOService::publishResource( const OSSymbol
* key
, OSObject
* value
)
2684 value
= (OSObject
*) gIOServiceKey
;
2686 gIOResources
->setProperty( key
, value
);
2688 if( IORecursiveLockHaveLock( gNotificationLock
))
2691 gIOResourceGenerationCount
++;
2692 gIOResources
->registerService();
2695 bool IOService::addNeededResource( const char * key
)
2697 OSObject
* resourcesProp
;
2702 resourcesProp
= getProperty( gIOResourceMatchKey
);
2704 newKey
= OSString::withCString( key
);
2705 if( (0 == resourcesProp
) || (0 == newKey
))
2708 set
= OSDynamicCast( OSSet
, resourcesProp
);
2710 set
= OSSet::withCapacity( 1 );
2712 set
->setObject( resourcesProp
);
2717 set
->setObject( newKey
);
2719 ret
= setProperty( gIOResourceMatchKey
, set
);
2725 bool IOService::checkResource( OSObject
* matching
)
2728 OSDictionary
* table
;
2730 if( (str
= OSDynamicCast( OSString
, matching
))) {
2731 if( gIOResources
->getProperty( str
))
2736 table
= resourceMatching( str
);
2737 else if( (table
= OSDynamicCast( OSDictionary
, matching
)))
2740 IOLog("%s: Can't match using: %s\n", getName(),
2741 matching
->getMetaClass()->getClassName());
2742 /* false would stall forever */
2746 if( gIOKitDebug
& kIOLogConfig
)
2747 LOG("config(%x): stalling %s\n", (int) IOThreadSelf(), getName());
2749 waitForService( table
);
2751 if( gIOKitDebug
& kIOLogConfig
)
2752 LOG("config(%x): waking\n", (int) IOThreadSelf() );
2757 bool IOService::checkResources( void )
2759 OSObject
* resourcesProp
;
2764 resourcesProp
= getProperty( gIOResourceMatchKey
);
2765 if( 0 == resourcesProp
)
2768 if( (set
= OSDynamicCast( OSSet
, resourcesProp
))) {
2770 iter
= OSCollectionIterator::withCollection( set
);
2772 while( ok
&& (resourcesProp
= iter
->getNextObject()) )
2773 ok
= checkResource( resourcesProp
);
2778 ok
= checkResource( resourcesProp
);
2784 void _IOConfigThread::configThread( void )
2786 _IOConfigThread
* inst
;
2789 if( !(inst
= new _IOConfigThread
))
2793 if( !(IOCreateThread((IOThreadFunc
) &_IOConfigThread::main
, inst
)))
2806 void _IOConfigThread::free( void )
2811 void IOService::doServiceMatch( IOOptionBits options
)
2813 _IOServiceNotifier
* notify
;
2815 OSOrderedSet
* matches
;
2816 SInt32 catalogGeneration
;
2817 bool keepGuessing
= true;
2818 bool reRegistered
= true;
2820 // job->nub->deliverNotification( gIOPublishNotification,
2821 // kIOServiceRegisteredState, 0xffffffff );
2823 while( keepGuessing
) {
2825 matches
= gIOCatalogue
->findDrivers( this, &catalogGeneration
);
2826 // the matches list should always be created by findDrivers()
2829 lockForArbitration();
2830 if( 0 == (__state
[0] & kIOServiceFirstPublishState
))
2831 deliverNotification( gIOFirstPublishNotification
,
2832 kIOServiceFirstPublishState
, 0xffffffff );
2834 __state
[1] &= ~kIOServiceNeedConfigState
;
2835 __state
[1] |= kIOServiceConfigState
;
2836 __state
[0] |= kIOServiceRegisteredState
;
2838 if( reRegistered
&& (0 == (__state
[0] & kIOServiceInactiveState
))) {
2840 iter
= OSCollectionIterator::withCollection( (OSOrderedSet
*)
2841 gNotifications
->getObject( gIOPublishNotification
) );
2843 while((notify
= (_IOServiceNotifier
*)
2844 iter
->getNextObject())) {
2846 if( passiveMatch( notify
->matching
)
2847 && (kIOServiceNotifyEnable
& notify
->state
))
2848 matches
->setObject( notify
);
2855 unlockForArbitration();
2857 if( matches
->getCount() && (kIOReturnSuccess
== getResources()))
2858 probeCandidates( matches
);
2863 lockForArbitration();
2864 reRegistered
= (0 != (__state
[1] & kIOServiceNeedConfigState
));
2866 (reRegistered
|| (catalogGeneration
!=
2867 gIOCatalogue
->getGenerationCount()))
2868 && (0 == (__state
[0] & kIOServiceInactiveState
));
2871 unlockForArbitration();
2874 if( (0 == (__state
[0] & kIOServiceInactiveState
))
2875 && (0 == (__state
[1] & kIOServiceModuleStallState
)) ) {
2876 deliverNotification( gIOMatchedNotification
,
2877 kIOServiceMatchedState
, 0xffffffff );
2878 if( 0 == (__state
[0] & kIOServiceFirstMatchState
))
2879 deliverNotification( gIOFirstMatchNotification
,
2880 kIOServiceFirstMatchState
, 0xffffffff );
2883 __state
[1] &= ~kIOServiceConfigState
;
2884 if( __state
[0] & kIOServiceInactiveState
)
2885 scheduleTerminatePhase2();
2888 unlockForArbitration();
2891 UInt32
IOService::_adjustBusy( SInt32 delta
)
2896 bool wasQuiet
, nowQuiet
, needWake
;
2899 result
= __state
[1] & kIOServiceBusyStateMask
;
2903 next
->lockForArbitration();
2904 count
= next
->__state
[1] & kIOServiceBusyStateMask
;
2905 assert( count
< kIOServiceBusyMax
);
2906 wasQuiet
= (0 == count
);
2907 assert( (!wasQuiet
) || (delta
> 0));
2908 next
->__state
[1] += delta
;
2909 nowQuiet
= (0 == (next
->__state
[1] & kIOServiceBusyStateMask
));
2910 needWake
= (0 != (kIOServiceBusyWaiterState
& next
->__state
[1]));
2913 next
->__state
[1] &= ~kIOServiceBusyWaiterState
;
2914 IOLockLock( gIOServiceBusyLock
);
2915 thread_wakeup( (event_t
) next
);
2916 IOLockUnlock( gIOServiceBusyLock
);
2919 next
->unlockForArbitration();
2921 if( (wasQuiet
|| nowQuiet
) ) {
2922 MessageClientsContext context
;
2924 context
.service
= next
;
2925 context
.type
= kIOMessageServiceBusyStateChange
;
2926 context
.argument
= (void *) wasQuiet
; // busy now
2927 context
.argSize
= 0;
2929 applyToInterestNotifiers( next
, gIOBusyInterest
,
2930 &messageClientsApplier
, &context
);
2932 if( nowQuiet
&& (next
== gIOServiceRoot
))
2933 OSMetaClass::considerUnloads();
2936 delta
= nowQuiet
? -1 : +1;
2938 } while( (wasQuiet
|| nowQuiet
) && (next
= next
->getProvider()));
2943 void IOService::adjustBusy( SInt32 delta
)
2945 lockForArbitration();
2946 _adjustBusy( delta
);
2947 unlockForArbitration();
2950 UInt32
IOService::getBusyState( void )
2952 return( __state
[1] & kIOServiceBusyStateMask
);
2955 IOReturn
IOService::waitForState( UInt32 mask
, UInt32 value
,
2956 mach_timespec_t
* timeout
)
2959 int waitResult
= THREAD_AWAKENED
;
2960 bool computeDeadline
= true;
2961 AbsoluteTime abstime
;
2964 lockForArbitration();
2965 IOLockLock( gIOServiceBusyLock
);
2966 wait
= (value
!= (__state
[1] & mask
));
2968 __state
[1] |= kIOServiceBusyWaiterState
;
2969 unlockForArbitration();
2971 if( computeDeadline
) {
2972 AbsoluteTime nsinterval
;
2973 clock_interval_to_absolutetime_interval(
2974 timeout
->tv_sec
, kSecondScale
, &abstime
);
2975 clock_interval_to_absolutetime_interval(
2976 timeout
->tv_nsec
, kNanosecondScale
, &nsinterval
);
2977 ADD_ABSOLUTETIME( &abstime
, &nsinterval
);
2978 clock_absolutetime_interval_to_deadline(
2979 abstime
, &abstime
);
2980 computeDeadline
= false;
2983 assert_wait_deadline((event_t
)this, THREAD_UNINT
, __OSAbsoluteTime(abstime
));
2986 assert_wait((event_t
)this, THREAD_UNINT
);
2988 unlockForArbitration();
2989 IOLockUnlock( gIOServiceBusyLock
);
2991 waitResult
= thread_block(THREAD_CONTINUE_NULL
);
2993 } while( wait
&& (waitResult
!= THREAD_TIMED_OUT
));
2995 if( waitResult
== THREAD_TIMED_OUT
)
2996 return( kIOReturnTimeout
);
2998 return( kIOReturnSuccess
);
3001 IOReturn
IOService::waitQuiet( mach_timespec_t
* timeout
)
3003 return( waitForState( kIOServiceBusyStateMask
, 0, timeout
));
3006 bool IOService::serializeProperties( OSSerialize
* s
) const
3009 ((IOService
*)this)->setProperty( ((IOService
*)this)->__state
,
3010 sizeof( __state
), "__state");
3012 return( super::serializeProperties(s
) );
3016 void _IOConfigThread::main( _IOConfigThread
* self
)
3018 _IOServiceJob
* job
;
3026 semaphore_wait( gJobsSemaphore
);
3028 IOTakeLock( gJobsLock
);
3029 job
= (_IOServiceJob
*) gJobs
->getFirstObject();
3031 gJobs
->removeObject(job
);
3034 // gNumConfigThreads--; // we're out of service
3035 gNumWaitingThreads
--; // we're out of service
3037 IOUnlock( gJobsLock
);
3043 if( gIOKitDebug
& kIOLogConfig
)
3044 LOG("config(%x): starting on %s, %d\n",
3045 (int) IOThreadSelf(), job
->nub
->getName(), job
->type
);
3047 switch( job
->type
) {
3050 nub
->doServiceMatch( job
->options
);
3054 LOG("config(%x): strange type (%d)\n",
3055 (int) IOThreadSelf(), job
->type
);
3062 IOTakeLock( gJobsLock
);
3063 alive
= (gOutstandingJobs
> gNumWaitingThreads
);
3065 gNumWaitingThreads
++; // back in service
3066 // gNumConfigThreads++;
3068 if( 0 == --gNumConfigThreads
) {
3069 // IOLog("MATCH IDLE\n");
3070 IOLockWakeup( gJobsLock
, (event_t
) &gNumConfigThreads
, /* one-thread */ false );
3073 IOUnlock( gJobsLock
);
3078 if( gIOKitDebug
& kIOLogConfig
)
3079 LOG("config(%x): terminating\n", (int) IOThreadSelf() );
3084 IOReturn
IOService::waitMatchIdle( UInt32 msToWait
)
3087 int waitResult
= THREAD_AWAKENED
;
3088 bool computeDeadline
= true;
3089 AbsoluteTime abstime
;
3091 IOLockLock( gJobsLock
);
3093 wait
= (0 != gNumConfigThreads
);
3096 if( computeDeadline
) {
3097 clock_interval_to_absolutetime_interval(
3098 msToWait
, kMillisecondScale
, &abstime
);
3099 clock_absolutetime_interval_to_deadline(
3100 abstime
, &abstime
);
3101 computeDeadline
= false;
3103 waitResult
= IOLockSleepDeadline( gJobsLock
, &gNumConfigThreads
,
3104 abstime
, THREAD_UNINT
);
3106 waitResult
= IOLockSleep( gJobsLock
, &gNumConfigThreads
,
3110 } while( wait
&& (waitResult
!= THREAD_TIMED_OUT
));
3111 IOLockUnlock( gJobsLock
);
3113 if( waitResult
== THREAD_TIMED_OUT
)
3114 return( kIOReturnTimeout
);
3116 return( kIOReturnSuccess
);
3119 void _IOServiceJob::pingConfig( _IOServiceJob
* job
)
3126 IOTakeLock( gJobsLock
);
3129 gJobs
->setLastObject( job
);
3131 count
= gNumWaitingThreads
;
3132 // if( gNumConfigThreads) count++;// assume we're called from a config thread
3134 create
= ( (gOutstandingJobs
> count
)
3135 && (gNumConfigThreads
< kMaxConfigThreads
) );
3137 gNumConfigThreads
++;
3138 gNumWaitingThreads
++;
3141 IOUnlock( gJobsLock
);
3146 if( gIOKitDebug
& kIOLogConfig
)
3147 LOG("config(%d): creating\n", gNumConfigThreads
- 1);
3148 _IOConfigThread::configThread();
3151 semaphore_signal( gJobsSemaphore
);
3154 // internal - call with gNotificationLock
3155 OSObject
* IOService::getExistingServices( OSDictionary
* matching
,
3156 IOOptionBits inState
, IOOptionBits options
)
3158 OSObject
* current
= 0;
3160 IOService
* service
;
3167 && (obj
= matching
->getObject(gIOProviderClassKey
))
3169 && gIOResourcesKey
->isEqualTo(obj
)
3170 && (service
= gIOResources
))
3172 if( (inState
== (service
->__state
[0] & inState
))
3173 && (0 == (service
->__state
[0] & kIOServiceInactiveState
))
3174 && service
->passiveMatch( matching
))
3176 if( options
& kIONotifyOnce
)
3179 current
= OSSet::withObjects(
3180 (const OSObject
**) &service
, 1, 1 );
3185 iter
= IORegistryIterator::iterateOver( gIOServicePlane
,
3186 kIORegistryIterateRecursively
);
3190 while( (service
= (IOService
*) iter
->getNextObject())) {
3191 if( (inState
== (service
->__state
[0] & inState
))
3192 && (0 == (service
->__state
[0] & kIOServiceInactiveState
))
3193 && service
->passiveMatch( matching
)) {
3195 if( options
& kIONotifyOnce
) {
3200 ((OSSet
*)current
)->setObject( service
);
3202 current
= OSSet::withObjects(
3203 (const OSObject
**) &service
, 1, 1 );
3206 } while( !service
&& !iter
->isValid());
3211 if( current
&& (0 == (options
& (kIONotifyOnce
| kIOServiceExistingSet
)))) {
3212 iter
= OSCollectionIterator::withCollection( (OSSet
*)current
);
3221 OSIterator
* IOService::getMatchingServices( OSDictionary
* matching
)
3225 // is a lock even needed?
3228 iter
= (OSIterator
*) getExistingServices( matching
,
3229 kIOServiceMatchedState
);
3237 // internal - call with gNotificationLock
3238 IONotifier
* IOService::setNotification(
3239 const OSSymbol
* type
, OSDictionary
* matching
,
3240 IOServiceNotificationHandler handler
, void * target
, void * ref
,
3243 _IOServiceNotifier
* notify
= 0;
3249 notify
= new _IOServiceNotifier
;
3250 if( notify
&& !notify
->init()) {
3256 notify
->matching
= matching
;
3257 notify
->handler
= handler
;
3258 notify
->target
= target
;
3260 notify
->priority
= priority
;
3261 notify
->state
= kIOServiceNotifyEnable
;
3262 queue_init( ¬ify
->handlerInvocations
);
3266 if( 0 == (set
= (OSOrderedSet
*) gNotifications
->getObject( type
))) {
3267 set
= OSOrderedSet::withCapacity( 1,
3268 IONotifyOrdering
, 0 );
3270 gNotifications
->setObject( type
, set
);
3274 notify
->whence
= set
;
3276 set
->setObject( notify
);
3282 // internal - call with gNotificationLock
3283 IONotifier
* IOService::doInstallNotification(
3284 const OSSymbol
* type
, OSDictionary
* matching
,
3285 IOServiceNotificationHandler handler
,
3286 void * target
, void * ref
,
3287 SInt32 priority
, OSIterator
** existing
)
3290 IONotifier
* notify
;
3291 IOOptionBits inState
;
3296 if( type
== gIOPublishNotification
)
3297 inState
= kIOServiceRegisteredState
;
3299 else if( type
== gIOFirstPublishNotification
)
3300 inState
= kIOServiceFirstPublishState
;
3302 else if( (type
== gIOMatchedNotification
)
3303 || (type
== gIOFirstMatchNotification
))
3304 inState
= kIOServiceMatchedState
;
3305 else if( type
== gIOTerminatedNotification
)
3310 notify
= setNotification( type
, matching
, handler
, target
, ref
, priority
);
3313 // get the current set
3314 exist
= (OSIterator
*) getExistingServices( matching
, inState
);
3324 IONotifier
* IOService::installNotification(
3325 const OSSymbol
* type
, OSDictionary
* matching
,
3326 IOServiceNotificationHandler handler
,
3327 void * target
, void * ref
,
3328 SInt32 priority
, OSIterator
** existing
)
3330 IONotifier
* notify
;
3334 notify
= doInstallNotification( type
, matching
, handler
, target
, ref
,
3335 priority
, existing
);
3342 IONotifier
* IOService::addNotification(
3343 const OSSymbol
* type
, OSDictionary
* matching
,
3344 IOServiceNotificationHandler handler
,
3345 void * target
, void * ref
,
3348 OSIterator
* existing
;
3349 _IOServiceNotifier
* notify
;
3352 notify
= (_IOServiceNotifier
*) installNotification( type
, matching
,
3353 handler
, target
, ref
, priority
, &existing
);
3355 // send notifications for existing set
3358 notify
->retain(); // in case handler remove()s
3359 while( (next
= (IOService
*) existing
->getNextObject())) {
3361 next
->lockForArbitration();
3362 if( 0 == (next
->__state
[0] & kIOServiceInactiveState
))
3363 next
->invokeNotifer( notify
);
3364 next
->unlockForArbitration();
3367 existing
->release();
3373 struct SyncNotifyVars
{
3374 semaphore_port_t waitHere
;
3378 bool IOService::syncNotificationHandler(
3379 void * /* target */, void * ref
,
3380 IOService
* newService
)
3383 // result may get written more than once before the
3384 // notification is removed!
3385 ((SyncNotifyVars
*) ref
)->result
= newService
;
3386 semaphore_signal( ((SyncNotifyVars
*) ref
)->waitHere
);
3391 IOService
* IOService::waitForService( OSDictionary
* matching
,
3392 mach_timespec_t
* timeout
)
3394 IONotifier
* notify
= 0;
3395 // priority doesn't help us much since we need a thread wakeup
3396 SInt32 priority
= 0;
3397 SyncNotifyVars state
;
3398 kern_return_t err
= kIOReturnBadArgument
;
3410 state
.result
= (IOService
*) getExistingServices( matching
,
3411 kIOServiceMatchedState
, kIONotifyOnce
);
3415 err
= semaphore_create( kernel_task
, &state
.waitHere
,
3416 SYNC_POLICY_FIFO
, 0 );
3417 if( KERN_SUCCESS
!= err
)
3420 notify
= IOService::setNotification( gIOMatchedNotification
, matching
,
3421 &IOService::syncNotificationHandler
, (void *) 0,
3422 (void *) &state
, priority
);
3430 err
= semaphore_timedwait( state
.waitHere
, *timeout
);
3432 err
= semaphore_wait( state
.waitHere
);
3436 notify
->remove(); // dequeues
3438 matching
->release();
3440 semaphore_destroy( kernel_task
, state
.waitHere
);
3442 return( state
.result
);
3445 void IOService::deliverNotification( const OSSymbol
* type
,
3446 IOOptionBits orNewState
, IOOptionBits andNewState
)
3448 _IOServiceNotifier
* notify
;
3450 OSArray
* willSend
= 0;
3452 lockForArbitration();
3454 if( (0 == (__state
[0] & kIOServiceInactiveState
))
3455 || (type
== gIOTerminatedNotification
)) {
3459 iter
= OSCollectionIterator::withCollection( (OSOrderedSet
*)
3460 gNotifications
->getObject( type
) );
3463 while( (notify
= (_IOServiceNotifier
*) iter
->getNextObject())) {
3465 if( passiveMatch( notify
->matching
)
3466 && (kIOServiceNotifyEnable
& notify
->state
)) {
3468 willSend
= OSArray::withCapacity(8);
3470 willSend
->setObject( notify
);
3476 __state
[0] = (__state
[0] | orNewState
) & andNewState
;
3482 for( unsigned int idx
= 0;
3483 (notify
= (_IOServiceNotifier
*) willSend
->getObject(idx
));
3485 invokeNotifer( notify
);
3487 willSend
->release();
3489 unlockForArbitration();
3492 IOOptionBits
IOService::getState( void ) const
3494 return( __state
[0] );
3498 * Helpers to make matching objects for simple cases
3501 OSDictionary
* IOService::serviceMatching( const OSString
* name
,
3502 OSDictionary
* table
)
3505 table
= OSDictionary::withCapacity( 2 );
3507 table
->setObject(gIOProviderClassKey
, (OSObject
*)name
);
3512 OSDictionary
* IOService::serviceMatching( const char * name
,
3513 OSDictionary
* table
)
3515 const OSString
* str
;
3517 str
= OSSymbol::withCString( name
);
3521 table
= serviceMatching( str
, table
);
3526 OSDictionary
* IOService::nameMatching( const OSString
* name
,
3527 OSDictionary
* table
)
3530 table
= OSDictionary::withCapacity( 2 );
3532 table
->setObject( gIONameMatchKey
, (OSObject
*)name
);
3537 OSDictionary
* IOService::nameMatching( const char * name
,
3538 OSDictionary
* table
)
3540 const OSString
* str
;
3542 str
= OSSymbol::withCString( name
);
3546 table
= nameMatching( str
, table
);
3551 OSDictionary
* IOService::resourceMatching( const OSString
* str
,
3552 OSDictionary
* table
)
3554 table
= serviceMatching( gIOResourcesKey
, table
);
3556 table
->setObject( gIOResourceMatchKey
, (OSObject
*) str
);
3561 OSDictionary
* IOService::resourceMatching( const char * name
,
3562 OSDictionary
* table
)
3564 const OSSymbol
* str
;
3566 str
= OSSymbol::withCString( name
);
3570 table
= resourceMatching( str
, table
);
3577 * _IOServiceNotifier
3580 // wait for all threads, other than the current one,
3581 // to exit the handler
3583 void _IOServiceNotifier::wait()
3585 _IOServiceNotifierInvocation
* next
;
3590 queue_iterate( &handlerInvocations
, next
,
3591 _IOServiceNotifierInvocation
*, link
) {
3592 if( next
->thread
!= current_thread() ) {
3598 state
|= kIOServiceNotifyWaiter
;
3605 void _IOServiceNotifier::free()
3607 assert( queue_empty( &handlerInvocations
));
3611 void _IOServiceNotifier::remove()
3616 whence
->removeObject( (OSObject
*) this );
3620 matching
->release();
3624 state
&= ~kIOServiceNotifyEnable
;
3633 bool _IOServiceNotifier::disable()
3639 ret
= (0 != (kIOServiceNotifyEnable
& state
));
3640 state
&= ~kIOServiceNotifyEnable
;
3649 void _IOServiceNotifier::enable( bool was
)
3653 state
|= kIOServiceNotifyEnable
;
3655 state
&= ~kIOServiceNotifyEnable
;
3663 IOService
* IOResources::resources( void )
3667 inst
= new IOResources
;
3668 if( inst
&& !inst
->init()) {
3676 IOWorkLoop
* IOResources::getWorkLoop() const
3678 // If we are the resource root then bringe over to the
3679 // platform to get its workloop
3680 if (this == (IOResources
*) gIOResources
)
3681 return getPlatform()->getWorkLoop();
3683 return IOService::getWorkLoop();
3686 bool IOResources::matchPropertyTable( OSDictionary
* table
)
3694 prop
= table
->getObject( gIOResourceMatchKey
);
3695 str
= OSDynamicCast( OSString
, prop
);
3697 ok
= (0 != getProperty( str
));
3699 else if( (set
= OSDynamicCast( OSSet
, prop
))) {
3701 iter
= OSCollectionIterator::withCollection( set
);
3703 while( ok
&& (str
= OSDynamicCast( OSString
, iter
->getNextObject()) ))
3704 ok
= (0 != getProperty( str
));
3713 IOReturn
IOResources::setProperties( OSObject
* properties
)
3716 const OSSymbol
* key
;
3717 OSDictionary
* dict
;
3718 OSCollectionIterator
* iter
;
3720 err
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
3721 if ( kIOReturnSuccess
!= err
)
3724 dict
= OSDynamicCast(OSDictionary
, properties
);
3726 return( kIOReturnBadArgument
);
3728 iter
= OSCollectionIterator::withCollection( dict
);
3730 return( kIOReturnBadArgument
);
3732 while( (key
= OSDynamicCast(OSSymbol
, iter
->getNextObject()))) {
3734 if (gIOConsoleUsersKey
== key
)
3736 IORegistryEntry::getRegistryRoot()->setProperty(key
, dict
->getObject(key
));
3737 OSIncrementAtomic( &gIOConsoleUsersSeed
);
3738 publishResource( gIOConsoleUsersSeedKey
, gIOConsoleUsersSeedValue
);
3742 publishResource( key
, dict
->getObject(key
) );
3747 return( kIOReturnSuccess
);
3751 * Helpers for matching dictionaries.
3752 * Keys existing in matching are checked in properties.
3753 * Keys may be a string or OSCollection of IOStrings
3756 bool IOService::compareProperty( OSDictionary
* matching
,
3762 value
= matching
->getObject( key
);
3764 ok
= value
->isEqualTo( getProperty( key
));
3772 bool IOService::compareProperty( OSDictionary
* matching
,
3773 const OSString
* key
)
3778 value
= matching
->getObject( key
);
3780 ok
= value
->isEqualTo( getProperty( key
));
3787 bool IOService::compareProperties( OSDictionary
* matching
,
3788 OSCollection
* keys
)
3790 OSCollectionIterator
* iter
;
3791 const OSString
* key
;
3794 if( !matching
|| !keys
)
3797 iter
= OSCollectionIterator::withCollection( keys
);
3800 while( ok
&& (key
= OSDynamicCast( OSString
, iter
->getNextObject())))
3801 ok
= compareProperty( matching
, key
);
3805 keys
->release(); // !! consume a ref !!
3810 /* Helper to add a location matching dict to the table */
3812 OSDictionary
* IOService::addLocation( OSDictionary
* table
)
3814 OSDictionary
* dict
;
3819 dict
= OSDictionary::withCapacity( 1 );
3821 table
->setObject( gIOLocationMatchKey
, dict
);
3829 * Go looking for a provider to match a location dict.
3832 IOService
* IOService::matchLocation( IOService
* /* client */ )
3836 parent
= getProvider();
3839 parent
= parent
->matchLocation( this );
3844 bool IOService::passiveMatch( OSDictionary
* table
, bool changesOK
)
3850 IORegistryEntry
* entry
;
3855 bool matchParent
= false;
3866 str
= OSDynamicCast( OSString
, table
->getObject( gIOProviderClassKey
));
3869 match
= (0 != where
->metaCast( str
));
3874 obj
= table
->getObject( gIONameMatchKey
);
3877 match
= where
->compareNames( obj
, changesOK
? &matched
: 0 );
3880 if( changesOK
&& matched
) {
3881 // leave a hint as to which name matched
3882 table
->setObject( gIONameMatchedKey
, matched
);
3887 str
= OSDynamicCast( OSString
, table
->getObject( gIOLocationMatchKey
));
3890 const OSSymbol
* sym
;
3894 sym
= where
->copyLocation();
3896 match
= sym
->isEqualTo( str
);
3903 obj
= table
->getObject( gIOPropertyMatchKey
);
3906 OSDictionary
* dict
;
3907 OSDictionary
* nextDict
;
3912 dict
= where
->dictionaryWithProperties();
3914 nextDict
= OSDynamicCast( OSDictionary
, obj
);
3918 iter
= OSCollectionIterator::withCollection(
3919 OSDynamicCast(OSCollection
, obj
));
3922 || (iter
&& (0 != (nextDict
= OSDynamicCast(OSDictionary
,
3923 iter
->getNextObject()))))) {
3924 match
= dict
->isEqualTo( nextDict
, nextDict
);
3937 str
= OSDynamicCast( OSString
, table
->getObject( gIOPathMatchKey
));
3940 entry
= IORegistryEntry::fromPath( str
->getCStringNoCopy() );
3941 match
= (where
== entry
);
3948 num
= OSDynamicCast( OSNumber
, table
->getObject( gIOMatchedServiceCountKey
));
3952 IOService
* service
= 0;
3953 UInt32 serviceCount
= 0;
3956 iter
= where
->getClientIterator();
3958 while( (service
= (IOService
*) iter
->getNextObject())) {
3959 if( kIOServiceInactiveState
& service
->__state
[0])
3961 if( 0 == service
->getProperty( gIOMatchCategoryKey
))
3967 match
= (serviceCount
== num
->unsigned32BitValue());
3972 if( done
== table
->getCount()) {
3973 // don't call family if we've done all the entries in the table
3974 matchParent
= false;
3978 // pass in score from property table
3979 score
= IOServiceObjectOrder( table
, (void *) gIOProbeScoreKey
);
3981 // do family specific matching
3982 match
= where
->matchPropertyTable( table
, &score
);
3986 if( kIOLogMatch
& getDebugFlags( table
))
3987 LOG("%s: family specific matching fails\n", where
->getName());
3994 newPri
= OSNumber::withNumber( score
, 32 );
3996 table
->setObject( gIOProbeScoreKey
, newPri
);
4001 if( !(match
= where
->compareProperty( table
, kIOBSDNameKey
)))
4004 matchParent
= false;
4006 obj
= OSDynamicCast( OSDictionary
,
4007 table
->getObject( gIOParentMatchKey
));
4011 table
= (OSDictionary
*) obj
;
4015 table
= OSDynamicCast( OSDictionary
,
4016 table
->getObject( gIOLocationMatchKey
));
4019 where
= where
->getProvider();
4021 where
= where
->matchLocation( where
);
4024 } while( table
&& where
);
4026 } while( matchParent
&& (where
= where
->getProvider()) );
4028 if( kIOLogMatch
& gIOKitDebug
)
4030 LOG("match parent @ %s = %d\n",
4031 where
->getName(), match
);
4037 IOReturn
IOService::newUserClient( task_t owningTask
, void * securityID
,
4038 UInt32 type
, OSDictionary
* properties
,
4039 IOUserClient
** handler
)
4041 const OSSymbol
*userClientClass
= 0;
4042 IOUserClient
*client
;
4045 if (kIOReturnSuccess
== newUserClient( owningTask
, securityID
, type
, handler
))
4046 return kIOReturnSuccess
;
4048 // First try my own properties for a user client class name
4049 temp
= getProperty(gIOUserClientClassKey
);
4051 if (OSDynamicCast(OSSymbol
, temp
))
4052 userClientClass
= (const OSSymbol
*) temp
;
4053 else if (OSDynamicCast(OSString
, temp
)) {
4054 userClientClass
= OSSymbol::withString((OSString
*) temp
);
4055 if (userClientClass
)
4056 setProperty(kIOUserClientClassKey
,
4057 (OSObject
*) userClientClass
);
4061 // Didn't find one so lets just bomb out now without further ado.
4062 if (!userClientClass
)
4063 return kIOReturnUnsupported
;
4065 // This reference is consumed by the IOServiceOpen call
4066 temp
= OSMetaClass::allocClassWithName(userClientClass
);
4068 return kIOReturnNoMemory
;
4070 if (OSDynamicCast(IOUserClient
, temp
))
4071 client
= (IOUserClient
*) temp
;
4074 return kIOReturnUnsupported
;
4077 if ( !client
->initWithTask(owningTask
, securityID
, type
, properties
) ) {
4079 return kIOReturnBadArgument
;
4082 if ( !client
->attach(this) ) {
4084 return kIOReturnUnsupported
;
4087 if ( !client
->start(this) ) {
4088 client
->detach(this);
4090 return kIOReturnUnsupported
;
4094 return kIOReturnSuccess
;
4097 IOReturn
IOService::newUserClient( task_t owningTask
, void * securityID
,
4098 UInt32 type
, IOUserClient
** handler
)
4100 return( kIOReturnUnsupported
);
4103 IOReturn
IOService::requestProbe( IOOptionBits options
)
4105 return( kIOReturnUnsupported
);
4109 * Convert an IOReturn to text. Subclasses which add additional
4110 * IOReturn's should override this method and call
4111 * super::stringFromReturn if the desired value is not found.
4114 const char * IOService::stringFromReturn( IOReturn rtn
)
4116 static const IONamedValue IOReturn_values
[] = {
4117 {kIOReturnSuccess
, "success" },
4118 {kIOReturnError
, "general error" },
4119 {kIOReturnNoMemory
, "memory allocation error" },
4120 {kIOReturnNoResources
, "resource shortage" },
4121 {kIOReturnIPCError
, "Mach IPC failure" },
4122 {kIOReturnNoDevice
, "no such device" },
4123 {kIOReturnNotPrivileged
, "privilege violation" },
4124 {kIOReturnBadArgument
, "invalid argument" },
4125 {kIOReturnLockedRead
, "device is read locked" },
4126 {kIOReturnLockedWrite
, "device is write locked" },
4127 {kIOReturnExclusiveAccess
, "device is exclusive access" },
4128 {kIOReturnBadMessageID
, "bad IPC message ID" },
4129 {kIOReturnUnsupported
, "unsupported function" },
4130 {kIOReturnVMError
, "virtual memory error" },
4131 {kIOReturnInternalError
, "internal driver error" },
4132 {kIOReturnIOError
, "I/O error" },
4133 {kIOReturnCannotLock
, "cannot acquire lock" },
4134 {kIOReturnNotOpen
, "device is not open" },
4135 {kIOReturnNotReadable
, "device is not readable" },
4136 {kIOReturnNotWritable
, "device is not writeable" },
4137 {kIOReturnNotAligned
, "alignment error" },
4138 {kIOReturnBadMedia
, "media error" },
4139 {kIOReturnStillOpen
, "device is still open" },
4140 {kIOReturnRLDError
, "rld failure" },
4141 {kIOReturnDMAError
, "DMA failure" },
4142 {kIOReturnBusy
, "device is busy" },
4143 {kIOReturnTimeout
, "I/O timeout" },
4144 {kIOReturnOffline
, "device is offline" },
4145 {kIOReturnNotReady
, "device is not ready" },
4146 {kIOReturnNotAttached
, "device/channel is not attached" },
4147 {kIOReturnNoChannels
, "no DMA channels available" },
4148 {kIOReturnNoSpace
, "no space for data" },
4149 {kIOReturnPortExists
, "device port already exists" },
4150 {kIOReturnCannotWire
, "cannot wire physical memory" },
4151 {kIOReturnNoInterrupt
, "no interrupt attached" },
4152 {kIOReturnNoFrames
, "no DMA frames enqueued" },
4153 {kIOReturnMessageTooLarge
, "message is too large" },
4154 {kIOReturnNotPermitted
, "operation is not permitted" },
4155 {kIOReturnNoPower
, "device is without power" },
4156 {kIOReturnNoMedia
, "media is not present" },
4157 {kIOReturnUnformattedMedia
, "media is not formatted" },
4158 {kIOReturnUnsupportedMode
, "unsupported mode" },
4159 {kIOReturnUnderrun
, "data underrun" },
4160 {kIOReturnOverrun
, "data overrun" },
4161 {kIOReturnDeviceError
, "device error" },
4162 {kIOReturnNoCompletion
, "no completion routine" },
4163 {kIOReturnAborted
, "operation was aborted" },
4164 {kIOReturnNoBandwidth
, "bus bandwidth would be exceeded" },
4165 {kIOReturnNotResponding
, "device is not responding" },
4166 {kIOReturnInvalid
, "unanticipated driver error" },
4170 return IOFindNameForValue(rtn
, IOReturn_values
);
4174 * Convert an IOReturn to an errno.
4176 int IOService::errnoFromReturn( IOReturn rtn
)
4180 case kIOReturnSuccess
:
4182 case kIOReturnNoMemory
:
4184 case kIOReturnNoDevice
:
4186 case kIOReturnVMError
:
4188 case kIOReturnNotPermitted
:
4190 case kIOReturnNotPrivileged
:
4192 case kIOReturnIOError
:
4194 case kIOReturnNotWritable
:
4196 case kIOReturnBadArgument
:
4198 case kIOReturnUnsupported
:
4202 case kIOReturnNoPower
:
4204 case kIOReturnDeviceError
:
4206 case kIOReturnTimeout
:
4208 case kIOReturnMessageTooLarge
:
4210 case kIOReturnNoSpace
:
4212 case kIOReturnCannotLock
:
4216 case kIOReturnBadMessageID
:
4217 case kIOReturnNoCompletion
:
4218 case kIOReturnNotAligned
:
4220 case kIOReturnNotReady
:
4222 case kIOReturnRLDError
:
4224 case kIOReturnPortExists
:
4225 case kIOReturnStillOpen
:
4227 case kIOReturnExclusiveAccess
:
4228 case kIOReturnLockedRead
:
4229 case kIOReturnLockedWrite
:
4230 case kIOReturnNotAttached
:
4231 case kIOReturnNotOpen
:
4232 case kIOReturnNotReadable
:
4234 case kIOReturnCannotWire
:
4235 case kIOReturnNoResources
:
4237 case kIOReturnAborted
:
4238 case kIOReturnOffline
:
4239 case kIOReturnNotResponding
:
4241 case kIOReturnBadMedia
:
4242 case kIOReturnNoMedia
:
4243 case kIOReturnUnformattedMedia
:
4244 return(ENXIO
); // (media error)
4245 case kIOReturnDMAError
:
4246 case kIOReturnOverrun
:
4247 case kIOReturnUnderrun
:
4248 return(EIO
); // (transfer error)
4249 case kIOReturnNoBandwidth
:
4250 case kIOReturnNoChannels
:
4251 case kIOReturnNoFrames
:
4252 case kIOReturnNoInterrupt
:
4253 return(EIO
); // (hardware error)
4254 case kIOReturnError
:
4255 case kIOReturnInternalError
:
4256 case kIOReturnInvalid
:
4257 return(EIO
); // (generic error)
4258 case kIOReturnIPCError
:
4259 return(EIO
); // (ipc error)
4261 return(EIO
); // (all other errors)
4265 IOReturn
IOService::message( UInt32 type
, IOService
* provider
,
4269 * Generic entry point for calls from the provider. A return value of
4270 * kIOReturnSuccess indicates that the message was received, and where
4271 * applicable, that it was successful.
4274 return kIOReturnUnsupported
;
4281 IOItemCount
IOService::getDeviceMemoryCount( void )
4286 array
= OSDynamicCast( OSArray
, getProperty( gIODeviceMemoryKey
));
4288 count
= array
->getCount();
4295 IODeviceMemory
* IOService::getDeviceMemoryWithIndex( unsigned int index
)
4298 IODeviceMemory
* range
;
4300 array
= OSDynamicCast( OSArray
, getProperty( gIODeviceMemoryKey
));
4302 range
= (IODeviceMemory
*) array
->getObject( index
);
4309 IOMemoryMap
* IOService::mapDeviceMemoryWithIndex( unsigned int index
,
4310 IOOptionBits options
)
4312 IODeviceMemory
* range
;
4315 range
= getDeviceMemoryWithIndex( index
);
4317 map
= range
->map( options
);
4324 OSArray
* IOService::getDeviceMemory( void )
4326 return( OSDynamicCast( OSArray
, getProperty( gIODeviceMemoryKey
)));
4330 void IOService::setDeviceMemory( OSArray
* array
)
4332 setProperty( gIODeviceMemoryKey
, array
);
4336 * For machines where the transfers on an I/O bus can stall because
4337 * the CPU is in an idle mode, These APIs allow a driver to specify
4338 * the maximum bus stall that they can handle. 0 indicates no limit.
4341 setCPUSnoopDelay(UInt32 __unused ns
)
4344 ml_set_maxsnoop(ns
);
4345 #endif /* __i386__ */
4352 return ml_get_maxsnoop();
4355 #endif /* __i386__ */
4359 requireMaxBusStall(UInt32 __unused ns
)
4362 static const UInt kNoReplace
= -1U; // Must be an illegal index
4363 UInt replace
= kNoReplace
;
4365 IOLockLock(sBusStallLock
);
4367 UInt count
= sBusStall
->getLength() / sizeof(BusStallEntry
);
4368 BusStallEntry
*entries
= (BusStallEntry
*) sBusStall
->getBytesNoCopy();
4371 const BusStallEntry ne
= {this, ns
};
4373 // Set Maximum bus delay.
4374 for (UInt i
= 0; i
< count
; i
++) {
4375 const IOService
*thisService
= entries
[i
].fService
;
4376 if (this == thisService
)
4378 else if (!thisService
) {
4379 if (kNoReplace
== replace
)
4383 const UInt32 thisMax
= entries
[i
].fMaxDelay
;
4389 // Must be safe to call from locked context
4390 ml_set_maxbusdelay(ns
);
4392 if (kNoReplace
== replace
)
4393 sBusStall
->appendBytes(&ne
, sizeof(ne
));
4395 entries
[replace
] = ne
;
4398 ns
= -1U; // Set to max unsigned, i.e. no restriction
4400 for (UInt i
= 0; i
< count
; i
++) {
4401 // Clear a maximum bus delay.
4402 const IOService
*thisService
= entries
[i
].fService
;
4403 UInt32 thisMax
= entries
[i
].fMaxDelay
;
4404 if (this == thisService
)
4406 else if (thisService
&& thisMax
< ns
)
4410 // Check if entry found
4411 if (kNoReplace
!= replace
) {
4412 entries
[replace
].fService
= 0; // Null the entry
4413 ml_set_maxbusdelay(ns
);
4417 IOLockUnlock(sBusStallLock
);
4418 #endif /* __i386__ */
4425 IOReturn
IOService::resolveInterrupt(IOService
*nub
, int source
)
4427 IOInterruptController
*interruptController
;
4430 OSSymbol
*interruptControllerName
;
4432 IOInterruptSource
*interruptSources
;
4434 // Get the parents list from the nub.
4435 array
= OSDynamicCast(OSArray
, nub
->getProperty(gIOInterruptControllersKey
));
4436 if (array
== 0) return kIOReturnNoResources
;
4438 // Allocate space for the IOInterruptSources if needed... then return early.
4439 if (nub
->_interruptSources
== 0) {
4440 numSources
= array
->getCount();
4441 interruptSources
= (IOInterruptSource
*)IOMalloc(numSources
* sizeof(IOInterruptSource
));
4442 if (interruptSources
== 0) return kIOReturnNoMemory
;
4444 bzero(interruptSources
, numSources
* sizeof(IOInterruptSource
));
4446 nub
->_numInterruptSources
= numSources
;
4447 nub
->_interruptSources
= interruptSources
;
4448 return kIOReturnSuccess
;
4451 interruptControllerName
= OSDynamicCast(OSSymbol
,array
->getObject(source
));
4452 if (interruptControllerName
== 0) return kIOReturnNoResources
;
4454 interruptController
= getPlatform()->lookUpInterruptController(interruptControllerName
);
4455 if (interruptController
== 0) return kIOReturnNoResources
;
4457 // Get the interrupt numbers from the nub.
4458 array
= OSDynamicCast(OSArray
, nub
->getProperty(gIOInterruptSpecifiersKey
));
4459 if (array
== 0) return kIOReturnNoResources
;
4460 data
= OSDynamicCast(OSData
, array
->getObject(source
));
4461 if (data
== 0) return kIOReturnNoResources
;
4463 // Set the interruptController and interruptSource in the nub's table.
4464 interruptSources
= nub
->_interruptSources
;
4465 interruptSources
[source
].interruptController
= interruptController
;
4466 interruptSources
[source
].vectorData
= data
;
4468 return kIOReturnSuccess
;
4471 IOReturn
IOService::lookupInterrupt(int source
, bool resolve
, IOInterruptController
**interruptController
)
4475 /* Make sure the _interruptSources are set */
4476 if (_interruptSources
== 0) {
4477 ret
= resolveInterrupt(this, source
);
4478 if (ret
!= kIOReturnSuccess
) return ret
;
4481 /* Make sure the local source number is valid */
4482 if ((source
< 0) || (source
>= _numInterruptSources
))
4483 return kIOReturnNoInterrupt
;
4485 /* Look up the contoller for the local source */
4486 *interruptController
= _interruptSources
[source
].interruptController
;
4488 if (*interruptController
== NULL
) {
4489 if (!resolve
) return kIOReturnNoInterrupt
;
4491 /* Try to reslove the interrupt */
4492 ret
= resolveInterrupt(this, source
);
4493 if (ret
!= kIOReturnSuccess
) return ret
;
4495 *interruptController
= _interruptSources
[source
].interruptController
;
4498 return kIOReturnSuccess
;
4501 IOReturn
IOService::registerInterrupt(int source
, OSObject
*target
,
4502 IOInterruptAction handler
,
4505 IOInterruptController
*interruptController
;
4508 ret
= lookupInterrupt(source
, true, &interruptController
);
4509 if (ret
!= kIOReturnSuccess
) return ret
;
4511 /* Register the source */
4512 return interruptController
->registerInterrupt(this, source
, target
,
4513 (IOInterruptHandler
)handler
,
4517 IOReturn
IOService::unregisterInterrupt(int source
)
4519 IOInterruptController
*interruptController
;
4522 ret
= lookupInterrupt(source
, false, &interruptController
);
4523 if (ret
!= kIOReturnSuccess
) return ret
;
4525 /* Unregister the source */
4526 return interruptController
->unregisterInterrupt(this, source
);
4529 IOReturn
IOService::getInterruptType(int source
, int *interruptType
)
4531 IOInterruptController
*interruptController
;
4534 ret
= lookupInterrupt(source
, true, &interruptController
);
4535 if (ret
!= kIOReturnSuccess
) return ret
;
4537 /* Return the type */
4538 return interruptController
->getInterruptType(this, source
, interruptType
);
4541 IOReturn
IOService::enableInterrupt(int source
)
4543 IOInterruptController
*interruptController
;
4546 ret
= lookupInterrupt(source
, false, &interruptController
);
4547 if (ret
!= kIOReturnSuccess
) return ret
;
4549 /* Enable the source */
4550 return interruptController
->enableInterrupt(this, source
);
4553 IOReturn
IOService::disableInterrupt(int source
)
4555 IOInterruptController
*interruptController
;
4558 ret
= lookupInterrupt(source
, false, &interruptController
);
4559 if (ret
!= kIOReturnSuccess
) return ret
;
4561 /* Disable the source */
4562 return interruptController
->disableInterrupt(this, source
);
4565 IOReturn
IOService::causeInterrupt(int source
)
4567 IOInterruptController
*interruptController
;
4570 ret
= lookupInterrupt(source
, false, &interruptController
);
4571 if (ret
!= kIOReturnSuccess
) return ret
;
4573 /* Cause an interrupt for the source */
4574 return interruptController
->causeInterrupt(this, source
);
4577 OSMetaClassDefineReservedUsed(IOService
, 0);
4578 OSMetaClassDefineReservedUsed(IOService
, 1);
4579 OSMetaClassDefineReservedUsed(IOService
, 2);
4580 OSMetaClassDefineReservedUsed(IOService
, 3);
4582 OSMetaClassDefineReservedUnused(IOService
, 4);
4583 OSMetaClassDefineReservedUnused(IOService
, 5);
4584 OSMetaClassDefineReservedUnused(IOService
, 6);
4585 OSMetaClassDefineReservedUnused(IOService
, 7);
4586 OSMetaClassDefineReservedUnused(IOService
, 8);
4587 OSMetaClassDefineReservedUnused(IOService
, 9);
4588 OSMetaClassDefineReservedUnused(IOService
, 10);
4589 OSMetaClassDefineReservedUnused(IOService
, 11);
4590 OSMetaClassDefineReservedUnused(IOService
, 12);
4591 OSMetaClassDefineReservedUnused(IOService
, 13);
4592 OSMetaClassDefineReservedUnused(IOService
, 14);
4593 OSMetaClassDefineReservedUnused(IOService
, 15);
4594 OSMetaClassDefineReservedUnused(IOService
, 16);
4595 OSMetaClassDefineReservedUnused(IOService
, 17);
4596 OSMetaClassDefineReservedUnused(IOService
, 18);
4597 OSMetaClassDefineReservedUnused(IOService
, 19);
4598 OSMetaClassDefineReservedUnused(IOService
, 20);
4599 OSMetaClassDefineReservedUnused(IOService
, 21);
4600 OSMetaClassDefineReservedUnused(IOService
, 22);
4601 OSMetaClassDefineReservedUnused(IOService
, 23);
4602 OSMetaClassDefineReservedUnused(IOService
, 24);
4603 OSMetaClassDefineReservedUnused(IOService
, 25);
4604 OSMetaClassDefineReservedUnused(IOService
, 26);
4605 OSMetaClassDefineReservedUnused(IOService
, 27);
4606 OSMetaClassDefineReservedUnused(IOService
, 28);
4607 OSMetaClassDefineReservedUnused(IOService
, 29);
4608 OSMetaClassDefineReservedUnused(IOService
, 30);
4609 OSMetaClassDefineReservedUnused(IOService
, 31);
4610 OSMetaClassDefineReservedUnused(IOService
, 32);
4611 OSMetaClassDefineReservedUnused(IOService
, 33);
4612 OSMetaClassDefineReservedUnused(IOService
, 34);
4613 OSMetaClassDefineReservedUnused(IOService
, 35);
4614 OSMetaClassDefineReservedUnused(IOService
, 36);
4615 OSMetaClassDefineReservedUnused(IOService
, 37);
4616 OSMetaClassDefineReservedUnused(IOService
, 38);
4617 OSMetaClassDefineReservedUnused(IOService
, 39);
4618 OSMetaClassDefineReservedUnused(IOService
, 40);
4619 OSMetaClassDefineReservedUnused(IOService
, 41);
4620 OSMetaClassDefineReservedUnused(IOService
, 42);
4621 OSMetaClassDefineReservedUnused(IOService
, 43);
4622 OSMetaClassDefineReservedUnused(IOService
, 44);
4623 OSMetaClassDefineReservedUnused(IOService
, 45);
4624 OSMetaClassDefineReservedUnused(IOService
, 46);
4625 OSMetaClassDefineReservedUnused(IOService
, 47);
4628 OSMetaClassDefineReservedUnused(IOService
, 48);
4629 OSMetaClassDefineReservedUnused(IOService
, 49);
4630 OSMetaClassDefineReservedUnused(IOService
, 50);
4631 OSMetaClassDefineReservedUnused(IOService
, 51);
4632 OSMetaClassDefineReservedUnused(IOService
, 52);
4633 OSMetaClassDefineReservedUnused(IOService
, 53);
4634 OSMetaClassDefineReservedUnused(IOService
, 54);
4635 OSMetaClassDefineReservedUnused(IOService
, 55);
4636 OSMetaClassDefineReservedUnused(IOService
, 56);
4637 OSMetaClassDefineReservedUnused(IOService
, 57);
4638 OSMetaClassDefineReservedUnused(IOService
, 58);
4639 OSMetaClassDefineReservedUnused(IOService
, 59);
4640 OSMetaClassDefineReservedUnused(IOService
, 60);
4641 OSMetaClassDefineReservedUnused(IOService
, 61);
4642 OSMetaClassDefineReservedUnused(IOService
, 62);
4643 OSMetaClassDefineReservedUnused(IOService
, 63);