X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/de355530ae67247cbd0da700edb3a2a1dae884c2..8f6c56a50524aa785f7e596d52dddfb331e18961:/iokit/Kernel/IOService.cpp diff --git a/iokit/Kernel/IOService.cpp b/iokit/Kernel/IOService.cpp index 919ea16fa..7feca38f6 100644 --- a/iokit/Kernel/IOService.cpp +++ b/iokit/Kernel/IOService.cpp @@ -1,34 +1,29 @@ /* * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1991-1999 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * - * 29-Jan-91 Portions from IODevice.m, Doug Mitchell at NeXT, Created. - * 18-Jun-98 start IOKit objc - * 10-Nov-98 start iokit cpp - * 25-Feb-99 sdouglas, add threads and locks to ensure deadlock - * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #include @@ -37,13 +32,14 @@ #include #include #include +#include #include #include #include #include #include #include -#include +#include #include #include #include @@ -106,6 +102,12 @@ const OSSymbol * gIOKitDebugKey; const OSSymbol * gIOCommandPoolSizeKey; +const OSSymbol * gIOConsoleUsersKey; +const OSSymbol * gIOConsoleSessionUIDKey; +const OSSymbol * gIOConsoleUsersSeedKey; +const OSSymbol * gIOConsoleSessionOnConsoleKey; +const OSSymbol * gIOConsoleSessionSecureInputPIDKey; + static int gIOResourceGenerationCount; const OSSymbol * gIOServiceKey; @@ -141,6 +143,9 @@ static OSArray * gIOStopList; static OSArray * gIOStopProviderList; static OSArray * gIOFinalizeList; +static SInt32 gIOConsoleUsersSeed; +static OSData * gIOConsoleUsersSeedValue; + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define LOCKREADNOTIFY() \ @@ -162,6 +167,19 @@ static OSArray * gIOFinalizeList; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#define queue_element(entry, element, type, field) do { \ + vm_address_t __ele = (vm_address_t) (entry); \ + __ele -= -4 + ((size_t)(&((type) 4)->field)); \ + (element) = (type) __ele; \ + } while(0) + +#define iterqueue(que, elt) \ + for (queue_entry_t elt = queue_first(que); \ + !queue_end(que, elt); \ + elt = queue_next(elt)) + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + struct ArbitrationLockQueueElement { queue_chain_t link; IOThread thread; @@ -235,6 +253,13 @@ void IOService::initialize( void ) kIOTerminatedNotification ); gIOServiceKey = OSSymbol::withCStringNoCopy( kIOServiceClass); + gIOConsoleUsersKey = OSSymbol::withCStringNoCopy( kIOConsoleUsersKey); + gIOConsoleSessionUIDKey = OSSymbol::withCStringNoCopy( kIOConsoleSessionUIDKey); + gIOConsoleUsersSeedKey = OSSymbol::withCStringNoCopy( kIOConsoleUsersSeedKey); + gIOConsoleSessionOnConsoleKey = OSSymbol::withCStringNoCopy( kIOConsoleSessionOnConsoleKey); + gIOConsoleSessionSecureInputPIDKey = OSSymbol::withCStringNoCopy( kIOConsoleSessionSecureInputPIDKey); + gIOConsoleUsersSeedValue = OSData::withBytesNoCopy(&gIOConsoleUsersSeed, sizeof(gIOConsoleUsersSeed)); + gNotificationLock = IORecursiveLockAlloc(); assert( gIOServicePlane && gIODeviceMemoryKey @@ -243,7 +268,10 @@ void IOService::initialize( void ) && gIOProviderClassKey && gIONameMatchKey && gIONameMatchedKey && gIOMatchCategoryKey && gIODefaultMatchCategoryKey && gIOPublishNotification && gIOMatchedNotification - && gIOTerminatedNotification && gIOServiceKey ); + && gIOTerminatedNotification && gIOServiceKey + && gIOConsoleUsersKey && gIOConsoleSessionUIDKey + && gIOConsoleSessionOnConsoleKey && gIOConsoleSessionSecureInputPIDKey + && gIOConsoleUsersSeedKey && gIOConsoleUsersSeedValue); gJobsLock = IOLockAlloc(); gJobs = OSOrderedSet::withCapacity( 10 ); @@ -398,7 +426,7 @@ void IOService::detach( IOService * provider ) * Register instance - publish it for matching */ -void IOService::registerService( IOOptionBits options = 0 ) +void IOService::registerService( IOOptionBits options ) { char * pathBuf; const char * path; @@ -451,7 +479,7 @@ void IOService::registerService( IOOptionBits options = 0 ) startMatching( options ); } -void IOService::startMatching( IOOptionBits options = 0 ) +void IOService::startMatching( IOOptionBits options ) { IOService * provider; UInt32 prevBusy = 0; @@ -509,7 +537,7 @@ void IOService::startMatching( IOOptionBits options = 0 ) lockForArbitration(); IOLockLock( gIOServiceBusyLock ); - waitAgain = (prevBusy != (__state[1] & kIOServiceBusyStateMask)); + waitAgain = (prevBusy < (__state[1] & kIOServiceBusyStateMask)); if( waitAgain) __state[1] |= kIOServiceSyncPubState | kIOServiceBusyWaiterState; else @@ -531,7 +559,8 @@ void IOService::startMatching( IOOptionBits options = 0 ) IOReturn IOService::catalogNewDrivers( OSOrderedSet * newTables ) { OSDictionary * table; - OSIterator * iter; + OSSet * set; + OSSet * allSet = 0; IOService * service; #if IOMATCHDEBUG SInt32 count = 0; @@ -542,18 +571,23 @@ IOReturn IOService::catalogNewDrivers( OSOrderedSet * newTables ) while( (table = (OSDictionary *) newTables->getFirstObject())) { LOCKWRITENOTIFY(); - iter = (OSIterator *) getExistingServices( table, - kIOServiceRegisteredState ); + set = (OSSet *) getExistingServices( table, + kIOServiceRegisteredState, + kIOServiceExistingSet); UNLOCKNOTIFY(); - if( iter) { - while( (service = (IOService *) iter->getNextObject())) { - service->startMatching(kIOServiceAsynchronous); + if( set) { + #if IOMATCHDEBUG - count++; + count += set->getCount(); #endif + if (allSet) { + allSet->merge((const OSSet *) set); + set->release(); } - iter->release(); + else + allSet = set; } + #if IOMATCHDEBUG if( getDebugFlags( table ) & kIOLogMatch) LOG("Matching service count = %ld\n", count); @@ -561,13 +595,21 @@ IOReturn IOService::catalogNewDrivers( OSOrderedSet * newTables ) newTables->removeObject(table); } + if (allSet) { + while( (service = (IOService *) allSet->getAnyObject())) { + service->startMatching(kIOServiceAsynchronous); + allSet->removeObject(service); + } + allSet->release(); + } + newTables->release(); return( kIOReturnSuccess ); } _IOServiceJob * _IOServiceJob::startJob( IOService * nub, int type, - IOOptionBits options = 0 ) + IOOptionBits options ) { _IOServiceJob * job; @@ -812,7 +854,7 @@ void IOService::setPMRootDomain( class IOPMrootDomain * rootDomain) * Stacking change */ -bool IOService::lockForArbitration( bool isSuccessRequired = true ) +bool IOService::lockForArbitration( bool isSuccessRequired ) { bool found; bool success; @@ -1199,7 +1241,7 @@ void IOService::applyToClients( IOServiceApplierFunction applier, // send a message to a client or interested party of this service IOReturn IOService::messageClient( UInt32 type, OSObject * client, - void * argument = 0, vm_size_t argSize = 0 ) + void * argument, vm_size_t argSize ) { IOReturn ret; IOService * service; @@ -1247,32 +1289,48 @@ IOReturn IOService::messageClient( UInt32 type, OSObject * client, return( ret ); } +static void +applyToInterestNotifiers(const IORegistryEntry *target, + const OSSymbol * typeOfInterest, + OSObjectApplierFunction applier, + void * context ) +{ + OSArray * copyArray = 0; + + LOCKREADNOTIFY(); + + IOCommand *notifyList = + OSDynamicCast( IOCommand, target->getProperty( typeOfInterest )); + + if( notifyList) { + copyArray = OSArray::withCapacity(1); + + // iterate over queue, entry is set to each element in the list + iterqueue(¬ifyList->fCommandChain, entry) { + _IOServiceInterestNotifier * notify; + + queue_element(entry, notify, _IOServiceInterestNotifier *, chain); + copyArray->setObject(notify); + } + } + UNLOCKNOTIFY(); + + if( copyArray) { + unsigned int index; + OSObject * next; + + for( index = 0; (next = copyArray->getObject( index )); index++) + (*applier)(next, context); + copyArray->release(); + } +} + void IOService::applyToInterested( const OSSymbol * typeOfInterest, OSObjectApplierFunction applier, void * context ) { - OSArray * array; - unsigned int index; - OSObject * next; - OSArray * copyArray; - applyToClients( (IOServiceApplierFunction) applier, context ); - - LOCKREADNOTIFY(); - array = OSDynamicCast( OSArray, getProperty( typeOfInterest )); - if( array) { - copyArray = OSArray::withArray( array ); - UNLOCKNOTIFY(); - if( copyArray) { - for( index = 0; - (next = array->getObject( index )); - index++) { - (*applier)(next, context); - } - copyArray->release(); - } - } else - UNLOCKNOTIFY(); + applyToInterestNotifiers(this, typeOfInterest, applier, context); } struct MessageClientsContext { @@ -1296,7 +1354,7 @@ static void messageClientsApplier( OSObject * object, void * ctx ) // send a message to all clients IOReturn IOService::messageClients( UInt32 type, - void * argument = 0, vm_size_t argSize = 0 ) + void * argument, vm_size_t argSize ) { MessageClientsContext context; @@ -1322,7 +1380,6 @@ IONotifier * IOService::registerInterest( const OSSymbol * typeOfInterest, IOServiceInterestHandler handler, void * target, void * ref ) { _IOServiceInterestNotifier * notify = 0; - OSArray * set; if( (typeOfInterest != gIOGeneralInterest) && (typeOfInterest != gIOBusyInterest) @@ -1349,16 +1406,23 @@ IONotifier * IOService::registerInterest( const OSSymbol * typeOfInterest, ////// queue LOCKWRITENOTIFY(); - if( 0 == (set = (OSArray *) getProperty( typeOfInterest ))) { - set = OSArray::withCapacity( 1 ); - if( set) { - setProperty( typeOfInterest, set ); - set->release(); - } - } - notify->whence = set; - if( set) - set->setObject( notify ); + + // Get the head of the notifier linked list + IOCommand *notifyList = (IOCommand *) getProperty( typeOfInterest ); + if (!notifyList || !OSDynamicCast(IOCommand, notifyList)) { + notifyList = OSTypeAlloc(IOCommand); + if (notifyList) { + notifyList->init(); + setProperty( typeOfInterest, notifyList); + notifyList->release(); + } + } + + if (notifyList) { + enqueue(¬ifyList->fCommandChain, ¬ify->chain); + notify->retain(); // ref'ed while in list + } + UNLOCKNOTIFY(); } } @@ -1367,30 +1431,30 @@ IONotifier * IOService::registerInterest( const OSSymbol * typeOfInterest, return( notify ); } -static void cleanInterestArray( OSObject * object ) +static void cleanInterestList( OSObject * head ) { - OSArray * array; - unsigned int index; - _IOServiceInterestNotifier * next; - - if( (array = OSDynamicCast( OSArray, object))) { - LOCKWRITENOTIFY(); - for( index = 0; - (next = (_IOServiceInterestNotifier *) - array->getObject( index )); - index++) { - next->whence = 0; - } - UNLOCKNOTIFY(); + IOCommand *notifyHead = OSDynamicCast(IOCommand, head); + if (!notifyHead) + return; + + LOCKWRITENOTIFY(); + while ( queue_entry_t entry = dequeue(¬ifyHead->fCommandChain) ) { + queue_next(entry) = queue_prev(entry) = 0; + + _IOServiceInterestNotifier * notify; + + queue_element(entry, notify, _IOServiceInterestNotifier *, chain); + notify->release(); } + UNLOCKNOTIFY(); } void IOService::unregisterAllInterest( void ) { - cleanInterestArray( getProperty( gIOGeneralInterest )); - cleanInterestArray( getProperty( gIOBusyInterest )); - cleanInterestArray( getProperty( gIOAppPowerStateInterest )); - cleanInterestArray( getProperty( gIOPriorityPowerStateInterest )); + cleanInterestList( getProperty( gIOGeneralInterest )); + cleanInterestList( getProperty( gIOBusyInterest )); + cleanInterestList( getProperty( gIOAppPowerStateInterest )); + cleanInterestList( getProperty( gIOPriorityPowerStateInterest )); } /* @@ -1432,10 +1496,10 @@ void _IOServiceInterestNotifier::remove() { LOCKWRITENOTIFY(); - if( whence) { - whence->removeObject(whence->getNextIndexOfObject( - (OSObject *) this, 0 )); - whence = 0; + if( queue_next( &chain )) { + remqueue( 0, &chain); + queue_next( &chain) = queue_prev( &chain) = 0; + release(); } state &= ~kIOServiceNotifyEnable; @@ -1515,7 +1579,7 @@ bool IOService::requestTerminate( IOService * provider, IOOptionBits options ) return( ok ); } -bool IOService::terminatePhase1( IOOptionBits options = 0 ) +bool IOService::terminatePhase1( IOOptionBits options ) { IOService * victim; IOService * client; @@ -1560,7 +1624,6 @@ bool IOService::terminatePhase1( IOOptionBits options = 0 ) victim->deliverNotification( gIOTerminatedNotification, 0, 0xffffffff ); IOUserClient::destroyUserReferences( victim ); - victim->unregisterAllInterest(); iter = victim->getClientIterator(); if( iter) { @@ -1592,10 +1655,10 @@ bool IOService::terminatePhase1( IOOptionBits options = 0 ) return( true ); } -void IOService::scheduleTerminatePhase2( IOOptionBits options = 0 ) +void IOService::scheduleTerminatePhase2( IOOptionBits options ) { AbsoluteTime deadline; - int waitResult; + int waitResult = THREAD_AWAKENED; bool wait, haveDeadline = false; options |= kIOServiceRequired; @@ -1620,7 +1683,8 @@ void IOService::scheduleTerminatePhase2( IOOptionBits options = 0 ) gIOTerminateWork++; do { - terminateWorker( options ); + while( gIOTerminateWork ) + terminateWorker( options ); wait = (0 != (__state[1] & kIOServiceBusyStateMask)); if( wait) { // wait for the victim to go non-busy @@ -1632,20 +1696,23 @@ void IOService::scheduleTerminatePhase2( IOOptionBits options = 0 ) deadline, THREAD_UNINT ); if( waitResult == THREAD_TIMED_OUT) { TLOG("%s::terminate(kIOServiceSynchronous) timeout", getName()); - } else - thread_cancel_timer(); + } } - } while( wait && (waitResult != THREAD_TIMED_OUT)); + } while(gIOTerminateWork || (wait && (waitResult != THREAD_TIMED_OUT))); - gIOTerminateThread = 0; - IOLockWakeup( gJobsLock, (event_t) &gIOTerminateThread, /* one-thread */ false); + gIOTerminateThread = 0; + IOLockWakeup( gJobsLock, (event_t) &gIOTerminateThread, /* one-thread */ false); } else { // ! kIOServiceSynchronous gIOTerminatePhase2List->setObject( this ); - if( 0 == gIOTerminateWork++) - gIOTerminateThread = IOCreateThread( &terminateThread, (void *) options ); + if( 0 == gIOTerminateWork++) { + if( !gIOTerminateThread) + gIOTerminateThread = IOCreateThread( &terminateThread, (void *) options ); + else + IOLockWakeup(gJobsLock, (event_t) &gIOTerminateWork, /* one-thread */ false ); + } } IOLockUnlock( gJobsLock ); @@ -1657,7 +1724,8 @@ void IOService::terminateThread( void * arg ) { IOLockLock( gJobsLock ); - terminateWorker( (IOOptionBits) arg ); + while (gIOTerminateWork) + terminateWorker( (IOOptionBits) arg ); gIOTerminateThread = 0; IOLockWakeup( gJobsLock, (event_t) &gIOTerminateThread, /* one-thread */ false); @@ -1962,8 +2030,8 @@ bool IOService::finalize( IOOptionBits options ) return( true ); } -#undef tailQ(o) -#undef headQ(o) +#undef tailQ +#undef headQ /* * Terminate @@ -1987,7 +2055,7 @@ bool IOService::terminateClient( IOService * client, IOOptionBits options ) return( ok ); } -bool IOService::terminate( IOOptionBits options = 0 ) +bool IOService::terminate( IOOptionBits options ) { options |= kIOServiceTerminate; @@ -2017,8 +2085,8 @@ static void serviceOpenMessageApplier( OSObject * object, void * ctx ) } bool IOService::open( IOService * forClient, - IOOptionBits options = 0, - void * arg = 0 ) + IOOptionBits options, + void * arg ) { bool ok; ServiceOpenMessageContext context; @@ -2044,7 +2112,7 @@ bool IOService::open( IOService * forClient, } void IOService::close( IOService * forClient, - IOOptionBits options = 0 ) + IOOptionBits options ) { bool wasClosed; bool last = false; @@ -2076,7 +2144,7 @@ void IOService::close( IOService * forClient, } } -bool IOService::isOpen( const IOService * forClient = 0 ) const +bool IOService::isOpen( const IOService * forClient ) const { IOService * self = (IOService *) this; bool ok; @@ -2539,14 +2607,37 @@ bool IOService::startCandidate( IOService * service ) ok = service->attach( this ); - if( ok) { - // stall for any nub resources - checkResources(); - // stall for any driver resources - service->checkResources(); + if( ok) + { + if (this != gIOResources) + { + // stall for any nub resources + checkResources(); + // stall for any driver resources + service->checkResources(); + } + + AbsoluteTime startTime; + AbsoluteTime endTime; + UInt64 nano; + + if (kIOLogStart & gIOKitDebug) + clock_get_uptime(&startTime); + ok = service->start(this); - ok = service->start( this ); + if (kIOLogStart & gIOKitDebug) + { + clock_get_uptime(&endTime); + + if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) + { + SUB_ABSOLUTETIME(&endTime, &startTime); + absolutetime_to_nanoseconds(endTime, &nano); + if (nano > 500000000ULL) + IOLog("%s::start took %ld ms\n", service->getName(), (UInt32)(nano / 1000000ULL)); + } + } if( !ok) service->detach( this ); } @@ -2558,7 +2649,7 @@ IOService * IOService::resources( void ) return( gIOResources ); } -void IOService::publishResource( const char * key, OSObject * value = 0 ) +void IOService::publishResource( const char * key, OSObject * value ) { const OSSymbol * sym; @@ -2568,35 +2659,38 @@ void IOService::publishResource( const char * key, OSObject * value = 0 ) } } -void IOService::publishResource( const OSSymbol * key, OSObject * value = 0 ) +void IOService::publishResource( const OSSymbol * key, OSObject * value ) { if( 0 == value) value = (OSObject *) gIOServiceKey; gIOResources->setProperty( key, value); + if( IORecursiveLockHaveLock( gNotificationLock)) + return; + gIOResourceGenerationCount++; gIOResources->registerService(); } bool IOService::addNeededResource( const char * key ) { - OSObject * resources; + OSObject * resourcesProp; OSSet * set; OSString * newKey; bool ret; - resources = getProperty( gIOResourceMatchKey ); + resourcesProp = getProperty( gIOResourceMatchKey ); newKey = OSString::withCString( key ); - if( (0 == resources) || (0 == newKey)) + if( (0 == resourcesProp) || (0 == newKey)) return( false); - set = OSDynamicCast( OSSet, resources ); + set = OSDynamicCast( OSSet, resourcesProp ); if( !set) { set = OSSet::withCapacity( 1 ); if( set) - set->setObject( resources ); + set->setObject( resourcesProp ); } else set->retain(); @@ -2643,32 +2737,32 @@ bool IOService::checkResource( OSObject * matching ) bool IOService::checkResources( void ) { - OSObject * resources; + OSObject * resourcesProp; OSSet * set; OSIterator * iter; bool ok; - resources = getProperty( gIOResourceMatchKey ); - if( 0 == resources) + resourcesProp = getProperty( gIOResourceMatchKey ); + if( 0 == resourcesProp) return( true ); - if( (set = OSDynamicCast( OSSet, resources ))) { + if( (set = OSDynamicCast( OSSet, resourcesProp ))) { iter = OSCollectionIterator::withCollection( set ); ok = (0 != iter); - while( ok && (resources = iter->getNextObject()) ) - ok = checkResource( resources ); + while( ok && (resourcesProp = iter->getNextObject()) ) + ok = checkResource( resourcesProp ); if( iter) iter->release(); } else - ok = checkResource( resources ); + ok = checkResource( resourcesProp ); return( ok ); } -_IOConfigThread * _IOConfigThread::configThread( void ) +void _IOConfigThread::configThread( void ) { _IOConfigThread * inst; @@ -2677,18 +2771,17 @@ _IOConfigThread * _IOConfigThread::configThread( void ) continue; if( !inst->init()) continue; - if( !(inst->thread = IOCreateThread - ( (IOThreadFunc) &_IOConfigThread::main, inst ))) + if( !(IOCreateThread((IOThreadFunc) &_IOConfigThread::main, inst ))) continue; - return( inst ); + return; } while( false); if( inst) inst->release(); - return( 0 ); + return; } void _IOConfigThread::free( void ) @@ -2807,21 +2900,15 @@ UInt32 IOService::_adjustBusy( SInt32 delta ) next->unlockForArbitration(); if( (wasQuiet || nowQuiet) ) { - OSArray * array; - unsigned int index; - OSObject * interested; - - array = OSDynamicCast( OSArray, next->getProperty( gIOBusyInterest )); - if( array) { - LOCKREADNOTIFY(); - for( index = 0; - (interested = array->getObject( index )); - index++) { - next->messageClient(kIOMessageServiceBusyStateChange, - interested, (void *) wasQuiet /* busy now */); - } - UNLOCKNOTIFY(); - } + MessageClientsContext context; + + context.service = next; + context.type = kIOMessageServiceBusyStateChange; + context.argument = (void *) wasQuiet; // busy now + context.argSize = 0; + + applyToInterestNotifiers( next, gIOBusyInterest, + &messageClientsApplier, &context ); if( nowQuiet && (next == gIOServiceRoot)) OSMetaClass::considerUnloads(); @@ -2847,7 +2934,7 @@ UInt32 IOService::getBusyState( void ) } IOReturn IOService::waitForState( UInt32 mask, UInt32 value, - mach_timespec_t * timeout = 0 ) + mach_timespec_t * timeout ) { bool wait; int waitResult = THREAD_AWAKENED; @@ -2861,7 +2948,6 @@ IOReturn IOService::waitForState( UInt32 mask, UInt32 value, if( wait) { __state[1] |= kIOServiceBusyWaiterState; unlockForArbitration(); - assert_wait( (event_t) this, THREAD_UNINT ); if( timeout ) { if( computeDeadline ) { AbsoluteTime nsinterval; @@ -2874,16 +2960,16 @@ IOReturn IOService::waitForState( UInt32 mask, UInt32 value, abstime, &abstime ); computeDeadline = false; } - thread_set_timer_deadline( abstime ); + + assert_wait_deadline((event_t)this, THREAD_UNINT, __OSAbsoluteTime(abstime)); } + else + assert_wait((event_t)this, THREAD_UNINT ); } else unlockForArbitration(); IOLockUnlock( gIOServiceBusyLock ); - if( wait) { + if( wait) waitResult = thread_block(THREAD_CONTINUE_NULL); - if( timeout && (waitResult != THREAD_TIMED_OUT)) - thread_cancel_timer(); - } } while( wait && (waitResult != THREAD_TIMED_OUT)); @@ -2893,7 +2979,7 @@ IOReturn IOService::waitForState( UInt32 mask, UInt32 value, return( kIOReturnSuccess ); } -IOReturn IOService::waitQuiet( mach_timespec_t * timeout = 0 ) +IOReturn IOService::waitQuiet( mach_timespec_t * timeout ) { return( waitForState( kIOServiceBusyStateMask, 0, timeout )); } @@ -3046,44 +3132,64 @@ void _IOServiceJob::pingConfig( _IOServiceJob * job ) semaphore_signal( gJobsSemaphore ); } - // internal - call with gNotificationLock OSObject * IOService::getExistingServices( OSDictionary * matching, - IOOptionBits inState, IOOptionBits options = 0 ) + IOOptionBits inState, IOOptionBits options ) { OSObject * current = 0; OSIterator * iter; IOService * service; + OSObject * obj; if( !matching) return( 0 ); - iter = IORegistryIterator::iterateOver( gIOServicePlane, - kIORegistryIterateRecursively ); - if( iter) { - do { - iter->reset(); - while( (service = (IOService *) iter->getNextObject())) { - if( (inState == (service->__state[0] & inState)) - && (0 == (service->__state[0] & kIOServiceInactiveState)) - && service->passiveMatch( matching )) { - - if( options & kIONotifyOnce) { - current = service; - break; - } - if( current) - ((OSSet *)current)->setObject( service ); - else - current = OSSet::withObjects( - & (const OSObject *) service, 1, 1 ); - } - } - } while( !service && !iter->isValid()); - iter->release(); + if(true + && (obj = matching->getObject(gIOProviderClassKey)) + && gIOResourcesKey + && gIOResourcesKey->isEqualTo(obj) + && (service = gIOResources)) + { + if( (inState == (service->__state[0] & inState)) + && (0 == (service->__state[0] & kIOServiceInactiveState)) + && service->passiveMatch( matching )) + { + if( options & kIONotifyOnce) + current = service; + else + current = OSSet::withObjects( + (const OSObject **) &service, 1, 1 ); + } + } + else + { + iter = IORegistryIterator::iterateOver( gIOServicePlane, + kIORegistryIterateRecursively ); + if( iter) { + do { + iter->reset(); + while( (service = (IOService *) iter->getNextObject())) { + if( (inState == (service->__state[0] & inState)) + && (0 == (service->__state[0] & kIOServiceInactiveState)) + && service->passiveMatch( matching )) { + + if( options & kIONotifyOnce) { + current = service; + break; + } + if( current) + ((OSSet *)current)->setObject( service ); + else + current = OSSet::withObjects( + (const OSObject **) &service, 1, 1 ); + } + } + } while( !service && !iter->isValid()); + iter->release(); + } } - if( current && (0 == (options & kIONotifyOnce))) { + if( current && (0 == (options & (kIONotifyOnce | kIOServiceExistingSet)))) { iter = OSCollectionIterator::withCollection( (OSSet *)current ); current->release(); current = iter; @@ -3113,7 +3219,7 @@ OSIterator * IOService::getMatchingServices( OSDictionary * matching ) IONotifier * IOService::setNotification( const OSSymbol * type, OSDictionary * matching, IOServiceNotificationHandler handler, void * target, void * ref, - SInt32 priority = 0 ) + SInt32 priority ) { _IOServiceNotifier * notify = 0; OSOrderedSet * set; @@ -3217,8 +3323,8 @@ IONotifier * IOService::installNotification( IONotifier * IOService::addNotification( const OSSymbol * type, OSDictionary * matching, IOServiceNotificationHandler handler, - void * target, void * ref = 0, - SInt32 priority = 0 ) + void * target, void * ref, + SInt32 priority ) { OSIterator * existing; _IOServiceNotifier * notify; @@ -3264,7 +3370,7 @@ bool IOService::syncNotificationHandler( } IOService * IOService::waitForService( OSDictionary * matching, - mach_timespec_t * timeout = 0 ) + mach_timespec_t * timeout ) { IONotifier * notify = 0; // priority doesn't help us much since we need a thread wakeup @@ -3374,7 +3480,7 @@ IOOptionBits IOService::getState( void ) const */ OSDictionary * IOService::serviceMatching( const OSString * name, - OSDictionary * table = 0 ) + OSDictionary * table ) { if( !table) table = OSDictionary::withCapacity( 2 ); @@ -3385,7 +3491,7 @@ OSDictionary * IOService::serviceMatching( const OSString * name, } OSDictionary * IOService::serviceMatching( const char * name, - OSDictionary * table = 0 ) + OSDictionary * table ) { const OSString * str; @@ -3399,7 +3505,7 @@ OSDictionary * IOService::serviceMatching( const char * name, } OSDictionary * IOService::nameMatching( const OSString * name, - OSDictionary * table = 0 ) + OSDictionary * table ) { if( !table) table = OSDictionary::withCapacity( 2 ); @@ -3410,7 +3516,7 @@ OSDictionary * IOService::nameMatching( const OSString * name, } OSDictionary * IOService::nameMatching( const char * name, - OSDictionary * table = 0 ) + OSDictionary * table ) { const OSString * str; @@ -3424,7 +3530,7 @@ OSDictionary * IOService::nameMatching( const char * name, } OSDictionary * IOService::resourceMatching( const OSString * str, - OSDictionary * table = 0 ) + OSDictionary * table ) { table = serviceMatching( gIOResourcesKey, table ); if( table) @@ -3434,7 +3540,7 @@ OSDictionary * IOService::resourceMatching( const OSString * str, } OSDictionary * IOService::resourceMatching( const char * name, - OSDictionary * table = 0 ) + OSDictionary * table ) { const OSSymbol * str; @@ -3605,6 +3711,15 @@ IOReturn IOResources::setProperties( OSObject * properties ) return( kIOReturnBadArgument); while( (key = OSDynamicCast(OSSymbol, iter->getNextObject()))) { + + if (gIOConsoleUsersKey == key) + { + IORegistryEntry::getRegistryRoot()->setProperty(key, dict->getObject(key)); + OSIncrementAtomic( &gIOConsoleUsersSeed ); + publishResource( gIOConsoleUsersSeedKey, gIOConsoleUsersSeedValue ); + continue; + } + publishResource( key, dict->getObject(key) ); } @@ -4058,7 +4173,7 @@ int IOService::errnoFromReturn( IOReturn rtn ) case kIOReturnBadArgument: return(EINVAL); case kIOReturnUnsupported: - return(EOPNOTSUPP); + return(ENOTSUP); case kIOReturnBusy: return(EBUSY); case kIOReturnNoPower: @@ -4169,7 +4284,7 @@ IODeviceMemory * IOService::getDeviceMemoryWithIndex( unsigned int index ) } IOMemoryMap * IOService::mapDeviceMemoryWithIndex( unsigned int index, - IOOptionBits options = 0 ) + IOOptionBits options ) { IODeviceMemory * range; IOMemoryMap * map; @@ -4353,8 +4468,8 @@ IOReturn IOService::causeInterrupt(int source) OSMetaClassDefineReservedUsed(IOService, 0); OSMetaClassDefineReservedUsed(IOService, 1); OSMetaClassDefineReservedUsed(IOService, 2); +OSMetaClassDefineReservedUsed(IOService, 3); -OSMetaClassDefineReservedUnused(IOService, 3); OSMetaClassDefineReservedUnused(IOService, 4); OSMetaClassDefineReservedUnused(IOService, 5); OSMetaClassDefineReservedUnused(IOService, 6);