Loading...
iokit/Kernel/IOService.cpp xnu-12377.101.15 xnu-201
--- xnu/xnu-12377.101.15/iokit/Kernel/IOService.cpp
+++ xnu/xnu-201/iokit/Kernel/IOService.cpp
@@ -1,85 +1,60 @@
 /*
- * Copyright (c) 1998-2021 Apple Inc. All rights reserved.
+ * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * 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.
- *
- * 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
+ * @APPLE_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 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, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE 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. 
  *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ * 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
+ *
  */
-
+ 
 #include <IOKit/system.h>
+
 #include <IOKit/IOService.h>
-#include <libkern/OSDebug.h>
-#include <libkern/c++/OSAllocation.h>
 #include <libkern/c++/OSContainers.h>
-#include <libkern/c++/OSKext.h>
 #include <libkern/c++/OSUnserialize.h>
-#include <libkern/c++/OSKext.h>
-#include <libkern/c++/OSSharedPtr.h>
-#include <libkern/Block.h>
 #include <IOKit/IOCatalogue.h>
-#include <IOKit/IOCommand.h>
-#include <IOKit/IODeviceTreeSupport.h>
 #include <IOKit/IODeviceMemory.h>
 #include <IOKit/IOInterrupts.h>
 #include <IOKit/IOInterruptController.h>
 #include <IOKit/IOPlatformExpert.h>
 #include <IOKit/IOMessage.h>
 #include <IOKit/IOLib.h>
-#include <IOKit/IOKitKeysPrivate.h>
+#include <IOKit/IOKitKeys.h>
 #include <IOKit/IOBSD.h>
 #include <IOKit/IOUserClient.h>
-#include <IOKit/IOUserServer.h>
 #include <IOKit/IOWorkLoop.h>
-#include <IOKit/IOTimeStamp.h>
-#include <IOKit/IOHibernatePrivate.h>
-#include <IOKit/IOInterruptAccountingPrivate.h>
-#include <IOKit/IOKernelReporters.h>
-#include <IOKit/AppleKeyStoreInterface.h>
-#include <IOKit/pwr_mgt/RootDomain.h>
-#include <IOKit/IOCPU.h>
-#include <Exclaves/Exclaves.h>
-#include <kern/cs_blobs.h>
 #include <mach/sync_policy.h>
-#include <mach/thread_info.h>
-#include <machine/atomic.h>
 #include <IOKit/assert.h>
 #include <sys/errno.h>
-#include <sys/kdebug.h>
-#include <string.h>
-
-#include <machine/pal_routines.h>
-
-#define LOG kprintf
-//#define LOG IOLog
-#define MATCH_DEBUG     0
-#define IOSERVICE_OBFUSCATE(x) ((void *)(VM_KERNEL_ADDRPERM(x)))
-
-// disabled since lockForArbitration() can be held externally
-#define DEBUG_NOTIFIER_LOCKED   0
+
+//#define LOG kprintf
+#define LOG IOLog
 
 #include "IOServicePrivate.h"
-#include "IOServicePMPrivate.h"
-#include "IOKitKernelInternal.h"
 
 // take lockForArbitration before LOCKNOTIFY
 
@@ -90,7 +65,6 @@
 OSDefineMetaClassAndStructors(IOService, IORegistryEntry)
 
 OSDefineMetaClassAndStructors(_IOServiceNotifier, IONotifier)
-OSDefineMetaClassAndStructors(_IOServiceNullNotifier, IONotifier)
 
 OSDefineMetaClassAndStructors(_IOServiceInterestNotifier, IONotifier)
 
@@ -99,251 +73,97 @@
 OSDefineMetaClassAndStructors(_IOServiceJob, OSObject)
 
 OSDefineMetaClassAndStructors(IOResources, IOService)
-OSDefineMetaClassAndStructors(IOUserResources, IOService)
-OSDefineMetaClassAndStructors(IOExclaveProxy, IOService)
 
 OSDefineMetaClassAndStructors(_IOOpenServiceIterator, OSIterator)
 
-OSDefineMetaClassAndStructors(_IOServiceStateNotification, IOService)
-
 OSDefineMetaClassAndAbstractStructors(IONotifier, OSObject)
 
-OSDefineMetaClassAndStructors(IOServiceCompatibility, IOService)
-
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-static IOPlatformExpert *       gIOPlatform;
-class IOPMrootDomain *          gIOPMRootDomain;
-const IORegistryPlane *         gIOServicePlane;
-const IORegistryPlane *         gIOPowerPlane;
-const OSSymbol *                gIODeviceMemoryKey;
-const OSSymbol *                gIOInterruptControllersKey;
-const OSSymbol *                gIOInterruptSpecifiersKey;
-
-const OSSymbol *                gIOResourcesKey;
-const OSSymbol *                gIOUserResourcesKey;
-const OSSymbol *                gIOResourceMatchKey;
-const OSSymbol *                gIOResourceMatchedKey;
-const OSSymbol *                gIOResourceIOKitKey;
-
-const OSSymbol *                gIOProviderClassKey;
-const OSSymbol *                gIONameMatchKey;
-const OSSymbol *                gIONameMatchedKey;
-const OSSymbol *                gIOPropertyMatchKey;
-const OSSymbol *                gIOPropertyExistsMatchKey;
-const OSSymbol *                gIOLocationMatchKey;
-const OSSymbol *                gIOParentMatchKey;
-const OSSymbol *                gIOPathMatchKey;
-const OSSymbol *                gIOMatchCategoryKey;
-const OSSymbol *                gIODefaultMatchCategoryKey;
-const OSSymbol *                gIOMatchedAtBootKey;
-const OSSymbol *                gIOMatchedServiceCountKey;
-const OSSymbol *                gIOMatchedPersonalityKey;
-const OSSymbol *                gIORematchPersonalityKey;
-const OSSymbol *                gIORematchCountKey;
-const OSSymbol *                gIODEXTMatchCountKey;
-const OSSymbol *                gIOSupportedPropertiesKey;
-const OSSymbol *                gIOUserServicePropertiesKey;
-#if defined(XNU_TARGET_OS_OSX)
-const OSSymbol *                gIOServiceLegacyMatchingRegistryIDKey;
-#endif /* defined(XNU_TARGET_OS_OSX) */
-
-const OSSymbol *                gIOCompatibilityMatchKey;
-const OSSymbol *                gIOCompatibilityPropertiesKey;
-const OSSymbol *                gIOPathKey;
-
-const OSSymbol *                gIOMapperIDKey;
-const OSSymbol *                gIOUserClientClassKey;
-
-const OSSymbol *                gIOUserClassKey;
-const OSSymbol *                gIOUserClassesKey;
-const OSSymbol *                gIOUserServerClassKey;
-const OSSymbol *                gIOUserServerNameKey;
-const OSSymbol *                gIOUserServerTagKey;
-const OSSymbol *                gIOUserUserClientKey;
-const OSSymbol *                gIOUserServerOneProcessKey;
-const OSSymbol *                gIOUserServerPreserveUserspaceRebootKey;
-
-const OSSymbol *                gIOKitDebugKey;
-
-const OSSymbol *                gIOCommandPoolSizeKey;
-
-const OSSymbol *                gIOConsoleLockedKey;
-const OSSymbol *                gIOConsoleUsersKey;
-const OSSymbol *                gIOConsoleSessionUIDKey;
-const OSSymbol *                gIOConsoleSessionAuditIDKey;
-const OSSymbol *                gIOConsoleUsersSeedKey;
-const OSSymbol *                gIOConsoleSessionOnConsoleKey;
-const OSSymbol *                gIOConsoleSessionLoginDoneKey;
-const OSSymbol *                gIOConsoleSessionSecureInputPIDKey;
-const OSSymbol *                gIOConsoleSessionScreenLockedTimeKey;
-const OSSymbol *                gIOConsoleSessionScreenIsLockedKey;
-clock_sec_t                     gIOConsoleLockTime;
-static bool                     gIOConsoleLoggedIn;
-#if HIBERNATION
-static OSBoolean *              gIOConsoleBooterLockState;
-static uint32_t                 gIOScreenLockState;
-#endif
-static IORegistryEntry *        gIOChosenEntry;
-
-static int                      gIOResourceGenerationCount;
-
-const OSSymbol *                gIOServiceKey;
-const OSSymbol *                gIOPublishNotification;
-const OSSymbol *                gIOFirstPublishNotification;
-const OSSymbol *                gIOMatchedNotification;
-const OSSymbol *                gIOFirstMatchNotification;
-const OSSymbol *                gIOTerminatedNotification;
-const OSSymbol *                gIOWillTerminateNotification;
-
-const OSSymbol *                gIOUserClientEntitlementsKey;
-const OSSymbol *                gIOServiceDEXTEntitlementsKey;
-const OSSymbol *                gIODriverKitEntitlementKey;
-const OSSymbol *                gIODriverKitUserClientEntitlementsKey;
-const OSSymbol *                gIODriverKitUserClientEntitlementAllowAnyKey;
-const OSSymbol *                gIODriverKitRequiredEntitlementsKey;
-const OSSymbol *                gIODriverKitTestDriverEntitlementKey;
-const OSSymbol *                gIODriverKitUserClientEntitlementCommunicatesWithDriversKey;
-const OSSymbol *                gIODriverKitUserClientEntitlementAllowThirdPartyUserClientsKey;
-const OSSymbol *                gIOMatchDeferKey;
-const OSSymbol *                gIOServiceMatchDeferredKey;
-const OSSymbol *                gIOServiceNotificationUserKey;
-
-const OSSymbol *                gIOExclaveAssignedKey;
-const OSSymbol *                gIOExclaveProxyKey;
-
-const OSSymbol *                gIOPrimaryDriverTerminateOptionsKey;
-const OSSymbol *                gIOMediaKey;
-const OSSymbol *                gIOBlockStorageDriverKey;
-static const OSSymbol *         gPhysicalInterconnectKey;
-static const OSSymbol *         gVirtualInterfaceKey;
-
-const OSSymbol *                gIOAllCPUInitializedKey;
-
-const OSSymbol *                gIOGeneralInterest;
-const OSSymbol *                gIOBusyInterest;
-const OSSymbol *                gIOAppPowerStateInterest;
-const OSSymbol *                gIOPriorityPowerStateInterest;
-const OSSymbol *                gIOConsoleSecurityInterest;
-
-const OSSymbol *                gIOBSDKey;
-const OSSymbol *                gIOBSDNameKey;
-const OSSymbol *                gIOBSDMajorKey;
-const OSSymbol *                gIOBSDMinorKey;
-const OSSymbol *                gIOBSDUnitKey;
-
-const  OSSymbol *               gAKSGetKey;
-#if defined(__i386__) || defined(__x86_64__)
-const OSSymbol *                gIOCreateEFIDevicePathSymbol;
-#endif
-
-static OSDictionary *           gNotifications;
-static IORecursiveLock *        gNotificationLock;
-
-static IOService *              gIOResources;
-static IOService *              gIOUserResources;
-static IOService *              gIOServiceRoot;
-
-static OSOrderedSet *           gJobs;
-static semaphore_port_t         gJobsSemaphore;
-static IOLock *                 gJobsLock;
-static int                      gOutstandingJobs;
-static int                      gNumConfigThreads;
-static int                      gHighNumConfigThreads;
-static int                      gMaxConfigThreads = kMaxConfigThreads;
-static int                      gNumWaitingThreads;
-static IOLock *                 gIOServiceBusyLock;
-bool                            gCPUsRunning;
-bool                            gIOKitWillTerminate;
-atomic_bool                     gInUserspaceReboot;
-
-#define kIOServiceRootMediaParentInvalid ((IOService *) -1UL)
-#if NO_KEXTD
-static bool                     gIOServiceHideIOMedia = false;
-static IOService *              gIOServiceRootMediaParent = NULL;
-#else /* NO_KEXTD */
-static bool                     gIOServiceHideIOMedia = true;
-static IOService *              gIOServiceRootMediaParent = kIOServiceRootMediaParentInvalid;
-#endif /* !NO_KEXTD */
-
-static thread_t                 gIOTerminateThread;
-static thread_t                 gIOTerminateWorkerThread;
-static UInt32                   gIOTerminateWork;
-static OSArray *                gIOTerminatePhase2List;
-static OSArray *                gIOStopList;
-static OSArray *                gIOStopProviderList;
-static OSArray *                gIOFinalizeList;
-
-#if !NO_KEXTD
-static OSArray *                gIOMatchDeferList;
-#endif
-
-static SInt32                   gIOConsoleUsersSeed;
-static OSData *                 gIOConsoleUsersSeedValue;
-
-extern const OSSymbol *         gIODTPHandleKey;
-
-const OSSymbol *                gIOPlatformFunctionHandlerSet;
-
-
-static IOLock *                 gIOConsoleUsersLock;
-static thread_call_t            gIOConsoleLockCallout;
-static IONotifier *             gIOServiceNullNotifier;
-
-static SECURITY_READ_ONLY_LATE(uint32_t) gIODextRelaunchMax;
-
-IORecursiveLock               * gDriverKitLaunchLock;
-OSSet                         * gDriverKitLaunches;
-const OSSymbol                * gIOAssociatedServicesKey;
+static IOPlatformExpert *	gIOPlatform;
+static class IOPMrootDomain *	gIOPMRootDomain;
+const IORegistryPlane *		gIOServicePlane;
+const IORegistryPlane *		gIOPowerPlane;
+const OSSymbol *		gIODeviceMemoryKey;
+const OSSymbol *		gIOInterruptControllersKey;
+const OSSymbol *		gIOInterruptSpecifiersKey;
+
+const OSSymbol *		gIOResourcesKey;
+const OSSymbol *		gIOResourceMatchKey;
+const OSSymbol *		gIOProviderClassKey;
+const OSSymbol * 		gIONameMatchKey;
+const OSSymbol *		gIONameMatchedKey;
+const OSSymbol *		gIOPropertyMatchKey;
+const OSSymbol *		gIOLocationMatchKey;
+const OSSymbol *		gIOPathMatchKey;
+const OSSymbol *		gIOMatchCategoryKey;
+const OSSymbol *		gIODefaultMatchCategoryKey;
+const OSSymbol *		gIOMatchedServiceCountKey;
+
+const OSSymbol *		gIOUserClientClassKey;
+const OSSymbol *		gIOKitDebugKey;
+
+const OSSymbol *		gIOCommandPoolSizeKey;
+
+static int			gIOResourceGenerationCount;
+
+const OSSymbol *		gIOServiceKey;
+const OSSymbol *		gIOPublishNotification;
+const OSSymbol *		gIOFirstPublishNotification;
+const OSSymbol *		gIOMatchedNotification;
+const OSSymbol *		gIOFirstMatchNotification;
+const OSSymbol *		gIOTerminatedNotification;
+
+const OSSymbol *		gIOGeneralInterest;
+const OSSymbol *		gIOBusyInterest;
+const OSSymbol *		gIOAppPowerStateInterest;
+const OSSymbol *		gIOPriorityPowerStateInterest;
+
+static OSDictionary * 		gNotifications;
+static IORecursiveLock *	gNotificationLock;
+
+static IOService *		gIOResources;
+static IOService * 		gIOServiceRoot;
+
+static OSOrderedSet *		gJobs;
+static semaphore_port_t		gJobsSemaphore;
+static IOLock *			gJobsLock;
+static int			gOutstandingJobs;
+static int			gNumConfigThreads;
+static int			gNumWaitingThreads;
+static IOLock *			gIOServiceBusyLock;
+
+static thread_t			gIOTerminateThread;
+static UInt32			gIOTerminateWork;
+static OSArray *		gIOTerminatePhase2List;
+static OSArray *		gIOStopList;
+static OSArray *		gIOStopProviderList;
+static OSArray *		gIOFinalizeList;
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-#define LOCKREADNOTIFY()        \
+#define LOCKREADNOTIFY()	\
     IORecursiveLockLock( gNotificationLock )
-#define LOCKWRITENOTIFY()       \
+#define LOCKWRITENOTIFY()	\
     IORecursiveLockLock( gNotificationLock )
 #define LOCKWRITE2READNOTIFY()
-#define UNLOCKNOTIFY()          \
+#define UNLOCKNOTIFY()		\
     IORecursiveLockUnlock( gNotificationLock )
-#define SLEEPNOTIFY(event) \
-    IORecursiveLockSleep( gNotificationLock, (void *)(event), THREAD_UNINT )
-#define SLEEPNOTIFYTO(event, deadline) \
-    IORecursiveLockSleepDeadline( gNotificationLock, (void *)(event), deadline, THREAD_UNINT )
-#define WAKEUPNOTIFY(event) \
-	IORecursiveLockWakeup( gNotificationLock, (void *)(event), /* wake one */ false )
-
-#define randomDelay()   \
-	int del = read_processor_clock();                               \
-	del = (((int)IOThreadSelf()) ^ del ^ (del >> 10)) & 0x3ff;      \
-	IOSleep( del );
+
+#define randomDelay()	\
+        int del = read_processor_clock();				\
+        del = (((int)IOThreadSelf()) ^ del ^ (del >> 10)) & 0x3ff;	\
+        IOSleep( del );
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-#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 IOInterruptAccountingReporter {
-	IOSimpleReporter * reporter; /* Reporter responsible for communicating the statistics */
-	IOInterruptAccountingData * statistics; /* The live statistics values, if any */
-};
-
 struct ArbitrationLockQueueElement {
-	queue_chain_t link;
-	IOThread      thread;
-	IOService *   service;
-	unsigned      count;
-	bool          required;
-	bool          aborted;
+    queue_chain_t link;
+    IOThread      thread;
+    IOService *   service;
+    unsigned      count;
+    bool          required;
+    bool          aborted;
 };
 
 static queue_head_t gArbitrationLockQueueActive;
@@ -351,415 +171,113 @@
 static queue_head_t gArbitrationLockQueueFree;
 static IOLock *     gArbitrationLockQueueLock;
 
-bool
-IOService::isInactive( void ) const
-{
-	return 0 != (kIOServiceInactiveState & getState());
-}
-
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-// Only used by the intel implementation of
-//     IOService::requireMaxBusStall(UInt32 ns)
-//     IOService::requireMaxInterruptDelay(uint32_t ns)
-struct CpuDelayEntry {
-	IOService * fService;
-	UInt32      fMaxDelay;
-	UInt32      fDelayType;
-};
-
-enum {
-	kCpuDelayBusStall,
-#if defined(__x86_64__)
-	kCpuDelayInterrupt,
-#endif /* defined(__x86_64__) */
-	kCpuNumDelayTypes
-};
-
-static OSData          *sCpuDelayData = OSData::withCapacity(8 * sizeof(CpuDelayEntry));
-static IORecursiveLock *sCpuDelayLock = IORecursiveLockAlloc();
-static OSArray         *sCpuLatencyHandlers[kCpuNumDelayTypes];
-const OSSymbol         *sCPULatencyFunctionName[kCpuNumDelayTypes];
-static OSNumber * sCPULatencyHolder[kCpuNumDelayTypes];
-static char sCPULatencyHolderName[kCpuNumDelayTypes][128];
-static OSNumber * sCPULatencySet[kCpuNumDelayTypes];
-
-static void
-requireMaxCpuDelay(IOService * service, UInt32 ns, UInt32 delayType);
-static IOReturn
-setLatencyHandler(UInt32 delayType, IOService * target, bool enable);
-
-static bool IOServiceMatchingNotificationHandlerToBlock(void * target __unused,
-    void * refCon, IOService * newService, IONotifier * notifier);
+void IOService::initialize( void )
+{
+    kern_return_t	err;
+
+    gIOServicePlane	= IORegistryEntry::makePlane( kIOServicePlane );
+    gIOPowerPlane 	= IORegistryEntry::makePlane( kIOPowerPlane );
+
+    gIOProviderClassKey = OSSymbol::withCStringNoCopy( kIOProviderClassKey );
+    gIONameMatchKey	= OSSymbol::withCStringNoCopy( kIONameMatchKey );
+    gIONameMatchedKey	= OSSymbol::withCStringNoCopy( kIONameMatchedKey );
+    gIOPropertyMatchKey	= OSSymbol::withCStringNoCopy( kIOPropertyMatchKey );
+    gIOPathMatchKey 	= OSSymbol::withCStringNoCopy( kIOPathMatchKey );
+    gIOLocationMatchKey = OSSymbol::withCStringNoCopy( kIOLocationMatchKey );
+
+    gIOMatchCategoryKey	= OSSymbol::withCStringNoCopy( kIOMatchCategoryKey );
+    gIODefaultMatchCategoryKey	= OSSymbol::withCStringNoCopy( 
+					kIODefaultMatchCategoryKey );
+    gIOMatchedServiceCountKey	= OSSymbol::withCStringNoCopy( 
+					kIOMatchedServiceCountKey );
+
+    gIOUserClientClassKey = OSSymbol::withCStringNoCopy( kIOUserClientClassKey );
+
+    gIOResourcesKey	= OSSymbol::withCStringNoCopy( kIOResourcesClass );
+    gIOResourceMatchKey	= OSSymbol::withCStringNoCopy( kIOResourceMatchKey );
+
+    gIODeviceMemoryKey	= OSSymbol::withCStringNoCopy( "IODeviceMemory" );
+    gIOInterruptControllersKey
+	= OSSymbol::withCStringNoCopy("IOInterruptControllers");
+    gIOInterruptSpecifiersKey
+	= OSSymbol::withCStringNoCopy("IOInterruptSpecifiers");
+
+    gIOKitDebugKey	= OSSymbol::withCStringNoCopy( kIOKitDebugKey );
+
+    gIOCommandPoolSizeKey	= OSSymbol::withCStringNoCopy( kIOCommandPoolSizeKey );
+
+    gIOGeneralInterest 		= OSSymbol::withCStringNoCopy( kIOGeneralInterest );
+    gIOBusyInterest   		= OSSymbol::withCStringNoCopy( kIOBusyInterest );
+    gIOAppPowerStateInterest   	= OSSymbol::withCStringNoCopy( kIOAppPowerStateInterest );
+    gIOPriorityPowerStateInterest   	= OSSymbol::withCStringNoCopy( kIOPriorityPowerStateInterest );
+
+    gNotifications		= OSDictionary::withCapacity( 1 );
+    gIOPublishNotification	= OSSymbol::withCStringNoCopy(
+						 kIOPublishNotification );
+    gIOFirstPublishNotification	= OSSymbol::withCStringNoCopy(
+                                                 kIOFirstPublishNotification );
+    gIOMatchedNotification	= OSSymbol::withCStringNoCopy(
+						 kIOMatchedNotification );
+    gIOFirstMatchNotification	= OSSymbol::withCStringNoCopy(
+						 kIOFirstMatchNotification );
+    gIOTerminatedNotification	= OSSymbol::withCStringNoCopy(
+						 kIOTerminatedNotification );
+    gIOServiceKey		= OSSymbol::withCStringNoCopy( kIOServiceClass);
+
+    gNotificationLock	 	= IORecursiveLockAlloc();
+
+    assert( gIOServicePlane && gIODeviceMemoryKey
+        && gIOInterruptControllersKey && gIOInterruptSpecifiersKey
+        && gIOResourcesKey && gNotifications && gNotificationLock
+        && gIOProviderClassKey && gIONameMatchKey && gIONameMatchedKey
+	&& gIOMatchCategoryKey && gIODefaultMatchCategoryKey
+        && gIOPublishNotification && gIOMatchedNotification
+        && gIOTerminatedNotification && gIOServiceKey );
+
+    gJobsLock	= IOLockAlloc();
+    gJobs 	= OSOrderedSet::withCapacity( 10 );
+
+    gIOServiceBusyLock = IOLockAlloc();
+
+    err = semaphore_create(kernel_task, &gJobsSemaphore, SYNC_POLICY_FIFO, 0);
+
+    assert( gIOServiceBusyLock && gJobs && gJobsLock && (err == KERN_SUCCESS) );
+
+    gIOResources = IOResources::resources();
+    assert( gIOResources );
+
+    gArbitrationLockQueueLock = IOLockAlloc();
+    queue_init(&gArbitrationLockQueueActive);
+    queue_init(&gArbitrationLockQueueWaiting);
+    queue_init(&gArbitrationLockQueueFree);
+
+    assert( gArbitrationLockQueueLock );
+
+    gIOTerminatePhase2List = OSArray::withCapacity( 2 );
+    gIOStopList            = OSArray::withCapacity( 16 );
+    gIOStopProviderList    = OSArray::withCapacity( 16 );
+    gIOFinalizeList	   = OSArray::withCapacity( 16 );
+    assert( gIOTerminatePhase2List && gIOStopList && gIOStopProviderList && gIOFinalizeList );
+}
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-IOCoreAnalyticsSendEventProc gIOCoreAnalyticsSendEventProc;
-
-kern_return_t
-IOSetCoreAnalyticsSendEventProc(IOCoreAnalyticsSendEventProc proc)
-{
-	if (gIOCoreAnalyticsSendEventProc) {
-		return kIOReturnNotPermitted;
-	}
-	gIOCoreAnalyticsSendEventProc = proc;
-
-	return kIOReturnSuccess;
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-
-static IOMessage  sSystemPower;
-extern "C" bool restore_boot;
-
-namespace IOServicePH
-{
-IONotifier          * fRootNotifier;
-OSArray             * fUserServers;
-OSArray             * fUserServersWait;
-OSArray             * fMatchingWork;
-OSArray             * fMatchingDelayed;
-IOService           * fSystemPowerAckTo;
-uint32_t              fSystemPowerAckRef;
-IOService           * fSystemPowerAckTo2;
-uint8_t               fSystemState = kIOServiceSystemStateOn;
-uint8_t               fUserServerSystemState;
-bool                  fWaitingUserServers;
-thread_call_t         fUserServerAckTimer;
-
-void lock();
-void unlock();
-
-void init(IOPMrootDomain * root);
-
-void systemPowerChange(uint8_t newState,
-    IOService * ackTo,
-    uint32_t ackRef,
-    uint32_t * pMaxWaitForReply);
-IOReturn systemPowerChange(
-	void * target,
-	void * refCon,
-	UInt32 messageType, IOService * service,
-	void * messageArgument, vm_size_t argSize);
-IOReturn rootWillChangeTo(IOPMPowerFlags flags, unsigned long state);
-bool matchingStart(IOService * service);
-void matchingEnd(IOService * service);
-void userServerAckTimerExpired(void *, void *);
-};
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-void
-IOService::initialize( void )
-{
-	kern_return_t       err;
-
-	gIOServicePlane     = IORegistryEntry::makePlane( kIOServicePlane );
-	gIOPowerPlane       = IORegistryEntry::makePlane( kIOPowerPlane );
-
-	gIOProviderClassKey = OSSymbol::withCStringNoCopy( kIOProviderClassKey );
-	gIONameMatchKey     = OSSymbol::withCStringNoCopy( kIONameMatchKey );
-	gIONameMatchedKey   = OSSymbol::withCStringNoCopy( kIONameMatchedKey );
-	gIOPropertyMatchKey = OSSymbol::withCStringNoCopy( kIOPropertyMatchKey );
-	gIOPropertyExistsMatchKey = OSSymbol::withCStringNoCopy( kIOPropertyExistsMatchKey );
-	gIOPathMatchKey     = OSSymbol::withCStringNoCopy( kIOPathMatchKey );
-	gIOLocationMatchKey = OSSymbol::withCStringNoCopy( kIOLocationMatchKey );
-	gIOParentMatchKey   = OSSymbol::withCStringNoCopy( kIOParentMatchKey );
-
-	gIOMatchCategoryKey = OSSymbol::withCStringNoCopy( kIOMatchCategoryKey );
-	gIODefaultMatchCategoryKey  = OSSymbol::withCStringNoCopy(
-		kIODefaultMatchCategoryKey );
-	gIOMatchedAtBootKey  = OSSymbol::withCStringNoCopy(
-		kIOMatchedAtBootKey );
-
-	gIOMatchedServiceCountKey   = OSSymbol::withCStringNoCopy(
-		kIOMatchedServiceCountKey );
-	gIOMatchedPersonalityKey = OSSymbol::withCStringNoCopy(
-		kIOMatchedPersonalityKey );
-	gIORematchPersonalityKey = OSSymbol::withCStringNoCopy(
-		kIORematchPersonalityKey );
-	gIORematchCountKey = OSSymbol::withCStringNoCopy(
-		kIORematchCountKey );
-	gIODEXTMatchCountKey = OSSymbol::withCStringNoCopy(
-		kIODEXTMatchCountKey );
-
-#if defined(XNU_TARGET_OS_OSX)
-	gIOServiceLegacyMatchingRegistryIDKey = OSSymbol::withCStringNoCopy(
-		kIOServiceLegacyMatchingRegistryIDKey );
-#endif /* defined(XNU_TARGET_OS_OSX) */
-
-	if (!PE_parse_boot_argn("dextrelaunch", &gIODextRelaunchMax, sizeof(gIODextRelaunchMax))) {
-		if (restore_boot) {
-			// Limit dext relaunches in the restore environment
-			gIODextRelaunchMax = 10;
-		} else {
-			gIODextRelaunchMax = 1000;
-		}
-	}
-	PE_parse_boot_argn("iocthreads", &gMaxConfigThreads, sizeof(gMaxConfigThreads));
-
-	gIOUserClientClassKey = OSSymbol::withCStringNoCopy( kIOUserClientClassKey );
-
-	gIOUserClassKey       = OSSymbol::withCStringNoCopy(kIOUserClassKey);
-	gIOUserClassesKey     = OSSymbol::withCStringNoCopy(kIOUserClassesKey);
-
-	gIOUserServerClassKey  = OSSymbol::withCStringNoCopy(kIOUserServerClassKey);
-	gIOUserServerNameKey   = OSSymbol::withCStringNoCopy(kIOUserServerNameKey);
-	gIOUserServerTagKey    = OSSymbol::withCStringNoCopy(kIOUserServerTagKey);
-	gIOUserUserClientKey   = OSSymbol::withCStringNoCopy(kIOUserUserClientKey);
-
-	gIOUserServerOneProcessKey = OSSymbol::withCStringNoCopy(kIOUserServerOneProcessKey);
-
-	gIOUserServerPreserveUserspaceRebootKey = OSSymbol::withCStringNoCopy(kIOUserServerPreserveUserspaceRebootKey);
-
-	gIOResourcesKey       = OSSymbol::withCStringNoCopy( kIOResourcesClass );
-	gIOResourceMatchKey   = OSSymbol::withCStringNoCopy( kIOResourceMatchKey );
-	gIOResourceMatchedKey = OSSymbol::withCStringNoCopy( kIOResourceMatchedKey );
-	gIOResourceIOKitKey   = OSSymbol::withCStringNoCopy("IOKit");
-
-	gIODeviceMemoryKey  = OSSymbol::withCStringNoCopy( "IODeviceMemory" );
-	gIOInterruptControllersKey
-	        = OSSymbol::withCStringNoCopy("IOInterruptControllers");
-	gIOInterruptSpecifiersKey
-	        = OSSymbol::withCStringNoCopy("IOInterruptSpecifiers");
-
-	gIOCompatibilityMatchKey = OSSymbol::withCStringNoCopy(kIOCompatibilityMatchKey);
-	gIOCompatibilityPropertiesKey = OSSymbol::withCStringNoCopy(kIOCompatibilityPropertiesKey);
-	gIOPathKey = OSSymbol::withCStringNoCopy(kIOPathKey);
-	gIOSupportedPropertiesKey = OSSymbol::withCStringNoCopy(kIOSupportedPropertiesKey);
-	gIOUserServicePropertiesKey = OSSymbol::withCStringNoCopy(kIOUserServicePropertiesKey);
-
-	gIOMapperIDKey = OSSymbol::withCStringNoCopy(kIOMapperIDKey);
-
-	gIOKitDebugKey      = OSSymbol::withCStringNoCopy( kIOKitDebugKey );
-
-	gIOCommandPoolSizeKey       = OSSymbol::withCStringNoCopy( kIOCommandPoolSizeKey );
-
-	gIOGeneralInterest          = OSSymbol::withCStringNoCopy( kIOGeneralInterest );
-	gIOBusyInterest             = OSSymbol::withCStringNoCopy( kIOBusyInterest );
-	gIOAppPowerStateInterest    = OSSymbol::withCStringNoCopy( kIOAppPowerStateInterest );
-	gIOPriorityPowerStateInterest       = OSSymbol::withCStringNoCopy( kIOPriorityPowerStateInterest );
-	gIOConsoleSecurityInterest  = OSSymbol::withCStringNoCopy( kIOConsoleSecurityInterest );
-
-	gIOBSDKey      = OSSymbol::withCStringNoCopy(kIOBSDKey);
-	gIOBSDNameKey  = OSSymbol::withCStringNoCopy(kIOBSDNameKey);
-	gIOBSDMajorKey = OSSymbol::withCStringNoCopy(kIOBSDMajorKey);
-	gIOBSDMinorKey = OSSymbol::withCStringNoCopy(kIOBSDMinorKey);
-	gIOBSDUnitKey  = OSSymbol::withCStringNoCopy(kIOBSDUnitKey);
-
-	gNotifications              = OSDictionary::withCapacity( 1 );
-	gIOPublishNotification      = OSSymbol::withCStringNoCopy(
-		kIOPublishNotification );
-	gIOFirstPublishNotification = OSSymbol::withCStringNoCopy(
-		kIOFirstPublishNotification );
-	gIOMatchedNotification      = OSSymbol::withCStringNoCopy(
-		kIOMatchedNotification );
-	gIOFirstMatchNotification   = OSSymbol::withCStringNoCopy(
-		kIOFirstMatchNotification );
-	gIOTerminatedNotification   = OSSymbol::withCStringNoCopy(
-		kIOTerminatedNotification );
-	gIOWillTerminateNotification = OSSymbol::withCStringNoCopy(
-		kIOWillTerminateNotification );
-	gIOServiceKey               = OSSymbol::withCStringNoCopy( kIOServiceClass);
-
-
-	gIOConsoleLockedKey         = OSSymbol::withCStringNoCopy( kIOConsoleLockedKey);
-	gIOConsoleUsersKey          = OSSymbol::withCStringNoCopy( kIOConsoleUsersKey);
-	gIOConsoleSessionUIDKey     = OSSymbol::withCStringNoCopy( kIOConsoleSessionUIDKey);
-	gIOConsoleSessionAuditIDKey = OSSymbol::withCStringNoCopy( kIOConsoleSessionAuditIDKey);
-
-	gIOConsoleUsersSeedKey               = OSSymbol::withCStringNoCopy(kIOConsoleUsersSeedKey);
-	gIOConsoleSessionOnConsoleKey        = OSSymbol::withCStringNoCopy(kIOConsoleSessionOnConsoleKey);
-	gIOConsoleSessionLoginDoneKey        = OSSymbol::withCStringNoCopy(kIOConsoleSessionLoginDoneKey);
-	gIOConsoleSessionSecureInputPIDKey   = OSSymbol::withCStringNoCopy(kIOConsoleSessionSecureInputPIDKey);
-	gIOConsoleSessionScreenLockedTimeKey = OSSymbol::withCStringNoCopy(kIOConsoleSessionScreenLockedTimeKey);
-	gIOConsoleSessionScreenIsLockedKey   = OSSymbol::withCStringNoCopy(kIOConsoleSessionScreenIsLockedKey);
-
-	gIOConsoleUsersSeedValue           = OSData::withValueNoCopy(gIOConsoleUsersSeed);
-
-	gIOUserClientEntitlementsKey           = OSSymbol::withCStringNoCopy( kIOUserClientEntitlementsKey );
-	gIOServiceDEXTEntitlementsKey           = OSSymbol::withCStringNoCopy( kIOServiceDEXTEntitlementsKey );
-	gIODriverKitEntitlementKey             = OSSymbol::withCStringNoCopy( kIODriverKitEntitlementKey );
-	gIODriverKitUserClientEntitlementsKey   = OSSymbol::withCStringNoCopy( kIODriverKitUserClientEntitlementsKey );
-#if XNU_TARGET_OS_OSX
-	gIODriverKitUserClientEntitlementAllowAnyKey   = OSSymbol::withCStringNoCopy( kIODriverKitUserClientEntitlementAllowAnyKey );
-#else
-	gIODriverKitUserClientEntitlementAllowAnyKey   = NULL;
-#endif
-	gIODriverKitRequiredEntitlementsKey   = OSSymbol::withCStringNoCopy( kIODriverKitRequiredEntitlementsKey );
-	gIODriverKitTestDriverEntitlementKey  = OSSymbol::withCStringNoCopy( kIODriverKitTestDriverEntitlementKey );
-	gIODriverKitUserClientEntitlementCommunicatesWithDriversKey = OSSymbol::withCStringNoCopy(kIODriverKitUserClientEntitlementCommunicatesWithDriversKey);
-	gIODriverKitUserClientEntitlementAllowThirdPartyUserClientsKey = OSSymbol::withCStringNoCopy(kIODriverKitUserClientEntitlementAllowThirdPartyUserClientsKey);
-
-	gIOMatchDeferKey                    = OSSymbol::withCStringNoCopy( kIOMatchDeferKey );
-	gIOServiceMatchDeferredKey          = OSSymbol::withCStringNoCopy( kIOServiceMatchDeferredKey );
-	gIOServiceNotificationUserKey       = OSSymbol::withCStringNoCopy( kIOServiceNotificationUserKey );
-	gIOExclaveAssignedKey               = OSSymbol::withCStringNoCopy(kIOExclaveAssignedKey);
-	gIOExclaveProxyKey                  = OSSymbol::withCStringNoCopy(kIOExclaveProxyKey);
-
-	gIOPrimaryDriverTerminateOptionsKey = OSSymbol::withCStringNoCopy(kIOPrimaryDriverTerminateOptionsKey);
-	gIOMediaKey                         = OSSymbol::withCStringNoCopy("IOMedia");
-	gIOBlockStorageDriverKey            = OSSymbol::withCStringNoCopy("IOBlockStorageDriver");
-	gPhysicalInterconnectKey            = OSSymbol::withCStringNoCopy("Physical Interconnect");
-	gVirtualInterfaceKey                = OSSymbol::withCStringNoCopy("Virtual Interface");
-
-	gIOAllCPUInitializedKey                 = OSSymbol::withCStringNoCopy( kIOAllCPUInitializedKey );
-
-	gIOPlatformFunctionHandlerSet               = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerSet);
-	sCPULatencyFunctionName[kCpuDelayBusStall]  = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerMaxBusDelay);
-#if defined(__x86_64__)
-	sCPULatencyFunctionName[kCpuDelayInterrupt] = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerMaxInterruptDelay);
-#endif /* defined(__x86_64__) */
-	uint32_t  idx;
-	for (idx = 0; idx < kCpuNumDelayTypes; idx++) {
-		sCPULatencySet[idx]    = OSNumber::withNumber(UINT_MAX, 32);
-		sCPULatencyHolder[idx] = OSNumber::withNumber(0ULL, 64);
-		assert(sCPULatencySet[idx] && sCPULatencyHolder[idx]);
-	}
-
-#if defined(__x86_64__)
-	gIOCreateEFIDevicePathSymbol = OSSymbol::withCString("CreateEFIDevicePath");
-#endif /* defined(__x86_64__) */
-
-	gNotificationLock           = IORecursiveLockAlloc();
-
-	gAKSGetKey                   = OSSymbol::withCStringNoCopy(AKS_PLATFORM_FUNCTION_GETKEY);
-
-#if CONFIG_EXCLAVES
-	gExclaveProxyStates          = OSDictionary::withCapacity( 1 );
-
-	gExclaveProxyStateLock           = IORecursiveLockAlloc();
-	assert( gExclaveProxyStates && gExclaveProxyStateLock);
-#endif /* CONFIG_EXCLAVES */
-
-	assert( gIOServicePlane && gIODeviceMemoryKey
-	    && gIOInterruptControllersKey && gIOInterruptSpecifiersKey
-	    && gIOResourcesKey && gNotifications && gNotificationLock
-	    && gIOProviderClassKey && gIONameMatchKey && gIONameMatchedKey
-	    && gIOMatchCategoryKey && gIODefaultMatchCategoryKey
-	    && gIOPublishNotification && gIOMatchedNotification
-	    && gIOTerminatedNotification && gIOServiceKey
-	    && gIOConsoleUsersKey && gIOConsoleSessionUIDKey
-	    && gIOConsoleSessionOnConsoleKey && gIOConsoleSessionSecureInputPIDKey
-	    && gIOConsoleUsersSeedKey && gIOConsoleUsersSeedValue);
-
-	gJobsLock   = IOLockAlloc();
-	gJobs       = OSOrderedSet::withCapacity( 10 );
-
-	gIOServiceBusyLock = IOLockAlloc();
-
-	gIOConsoleUsersLock = IOLockAlloc();
-
-	err = semaphore_create(kernel_task, &gJobsSemaphore, SYNC_POLICY_FIFO, 0);
-
-	gIOConsoleLockCallout = thread_call_allocate(&IOService::consoleLockTimer, NULL);
-
-	IORegistryEntry::getRegistryRoot()->setProperty(gIOConsoleLockedKey, kOSBooleanTrue);
-
-	assert( gIOServiceBusyLock && gJobs && gJobsLock && gIOConsoleUsersLock
-	    && gIOConsoleLockCallout && (err == KERN_SUCCESS));
-
-	gIOResources = IOResources::resources();
-	gIOUserResources = IOUserResources::resources();
-	assert( gIOResources && gIOUserResources );
-
-	gIOServiceNullNotifier = OSTypeAlloc(_IOServiceNullNotifier);
-	assert(gIOServiceNullNotifier);
-
-	gArbitrationLockQueueLock = IOLockAlloc();
-	queue_init(&gArbitrationLockQueueActive);
-	queue_init(&gArbitrationLockQueueWaiting);
-	queue_init(&gArbitrationLockQueueFree);
-
-	assert( gArbitrationLockQueueLock );
-
-	allocPMInitLock();
-
-	gIOTerminatePhase2List = OSArray::withCapacity( 2 );
-	gIOStopList            = OSArray::withCapacity( 16 );
-	gIOStopProviderList    = OSArray::withCapacity( 16 );
-	gIOFinalizeList        = OSArray::withCapacity( 16 );
-#if !NO_KEXTD
-	if (OSKext::iokitDaemonAvailable()) {
-		gIOMatchDeferList      = OSArray::withCapacity( 16 );
-	} else {
-		gIOMatchDeferList      = NULL;
-	}
-#endif
-	assert( gIOTerminatePhase2List && gIOStopList && gIOStopProviderList && gIOFinalizeList );
-
-	gDriverKitLaunches = OSSet::withCapacity(0);
-	gDriverKitLaunchLock = IORecursiveLockAlloc();
-	gIOAssociatedServicesKey = OSSymbol::withCStringNoCopy( "IOAssociatedServices" );
-#if CONFIG_EXCLAVES
-	gDARTMapperFunctionSetActive = OSSymbol::withCStringNoCopy("setActive");
-#endif /* CONFIG_EXCLAVES */
-
-	// worker thread that is responsible for terminating / cleaning up threads
-	kernel_thread_start(&terminateThread, NULL, &gIOTerminateWorkerThread);
-	assert(gIOTerminateWorkerThread);
-	thread_set_thread_name(gIOTerminateWorkerThread, "IOServiceTerminateThread");
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-#if defined(__x86_64__)
-extern "C" {
-const char *getCpuDelayBusStallHolderName(void);
-const char *
-getCpuDelayBusStallHolderName(void)
-{
-	return sCPULatencyHolderName[kCpuDelayBusStall];
-}
-
-const char *getCpuInterruptDelayHolderName(void);
-const char *
-getCpuInterruptDelayHolderName(void)
-{
-	return sCPULatencyHolderName[kCpuDelayInterrupt];
-}
-}
-#endif /* defined(__x86_64__) */
-
-
-
 #if IOMATCHDEBUG
-static UInt64
-getDebugFlags( OSDictionary * props )
-{
-	OSNumber *  debugProp;
-	UInt64      debugFlags;
-
-	debugProp = OSDynamicCast( OSNumber,
-	    props->getObject( gIOKitDebugKey ));
-	if (debugProp) {
-		debugFlags = debugProp->unsigned64BitValue();
-	} else {
-		debugFlags = gIOKitDebug;
-	}
-
-	return debugFlags;
-}
-
-static UInt64
-getDebugFlags( IOService * inst )
-{
-	OSObject *  prop;
-	OSNumber *  debugProp;
-	UInt64      debugFlags;
-
-	prop = inst->copyProperty(gIOKitDebugKey);
-	debugProp = OSDynamicCast(OSNumber, prop);
-	if (debugProp) {
-		debugFlags = debugProp->unsigned64BitValue();
-	} else {
-		debugFlags = gIOKitDebug;
-	}
-
-	OSSafeReleaseNULL(prop);
-
-	return debugFlags;
+static UInt64 getDebugFlags( OSDictionary * props )
+{
+    OSNumber *	debugProp;
+    UInt64	debugFlags;
+
+    debugProp = OSDynamicCast( OSNumber,
+		props->getObject( gIOKitDebugKey ));
+    if( debugProp)
+	debugFlags = debugProp->unsigned64BitValue();
+    else
+	debugFlags = gIOKitDebug;
+
+    return( debugFlags );
 }
 #endif
 
@@ -769,554 +287,296 @@
 // The default score is from the property table, & may be altered
 // during probe to change the start order.
 
-IOService *
-IOService::probe(   IOService * provider,
-    SInt32    * score )
-{
-	return this;
-}
-
-bool
-IOService::start( IOService * provider )
-{
-	return true;
-}
-
-void
-IOService::stop( IOService * provider )
-{
-	if (reserved->uvars && reserved->uvars->userServer) {
-		reserved->uvars->userServer->serviceStop(this, provider);
-	}
-}
-
-bool
-IOService::init( OSDictionary * dictionary )
-{
-	bool ret;
-
-	ret = super::init(dictionary);
-	if (!ret) {
-		return false;
-	}
-	if (reserved) {
-		return true;
-	}
-
-	reserved = IOMallocType(ExpansionData);
-	IOLockInlineInit(&reserved->interruptStatisticsLock);
-	return true;
-}
-
-bool
-IOService::init( IORegistryEntry * from,
-    const IORegistryPlane * inPlane )
-{
-	bool ret;
-
-	ret = super::init(from, inPlane);
-	if (!ret) {
-		return false;
-	}
-	if (reserved) {
-		return true;
-	}
-
-	reserved = IOMallocType(ExpansionData);
-	IOLockInlineInit(&reserved->interruptStatisticsLock);
-
-	return true;
-}
-
-void
-IOService::free( void )
-{
-	IOInterruptSourcePrivate *sourcesPrivate = NULL;
-	int i = 0;
-	requireMaxBusStall(0);
-#if defined(__x86_64__)
-	requireMaxInterruptDelay(0);
-#endif /* defined(__x86_64__) */
-	if (getPropertyTable()) {
-		unregisterAllInterest();
-	}
-	PMfree();
-
-	if (reserved) {
-		if (reserved->interruptStatisticsArray) {
-			for (i = 0; i < reserved->interruptStatisticsArrayCount; i++) {
-				if (reserved->interruptStatisticsArray[i].reporter) {
-					reserved->interruptStatisticsArray[i].reporter->release();
-				}
-			}
-
-			IODelete(reserved->interruptStatisticsArray, IOInterruptAccountingReporter, reserved->interruptStatisticsArrayCount);
-		}
-
-		if (reserved->uvars && reserved->uvars->userServer) {
-			reserved->uvars->userServer->serviceFree(this);
-		}
-		sourcesPrivate = reserved->interruptSourcesPrivate;
-		IOLockInlineDestroy(&reserved->interruptStatisticsLock);
-		IOFreeType(reserved, ExpansionData);
-	}
-
-	if (_numInterruptSources && _interruptSources) {
-		assert(sourcesPrivate);
-		for (i = 0; i < _numInterruptSources; i++) {
-			void * block = sourcesPrivate[i].vectorBlock;
-			if (block) {
-				Block_release(block);
-			}
-		}
-		IODelete(_interruptSources, IOInterruptSource, _numInterruptSources);
-		_interruptSources = NULL;
-		IODelete(sourcesPrivate, IOInterruptSourcePrivate, _numInterruptSources);
-	}
-
-	super::free();
+IOService * IOService::probe(	IOService * provider,
+				SInt32	  * score )
+{
+    return( this );
+}
+
+bool IOService::start( IOService * provider )
+{
+    return( true );
+}
+
+void IOService::stop( IOService * provider )
+{
+}
+
+void IOService::free( void )
+{
+    if( getPropertyTable())
+        unregisterAllInterest();
+    PMfree();
+    super::free();
 }
 
 /*
  * Attach in service plane
  */
-bool
-IOService::attach( IOService * provider )
-{
-	bool         ok;
-	uint32_t     count;
-	AbsoluteTime deadline;
-	int          waitResult = THREAD_AWAKENED;
-	bool         wait, computeDeadline = true;
-
-	if (provider) {
-		if (gIOKitDebug & kIOLogAttach) {
-			LOG( "%s[0x%qx]::attach(%s[0x%qx])\n", getName(), getRegistryEntryID(),
-			    provider->getName(), provider->getRegistryEntryID());
-		}
-
-		ok   = false;
-		do{
-			wait = false;
-			provider->lockForArbitration();
-			if (provider->__state[0] & kIOServiceInactiveState) {
-				ok = false;
-			} else {
-				count = provider->getChildCount(gIOServicePlane);
-				wait = (count > (kIOServiceBusyMax - 4));
-				if (!wait) {
-					ok = attachToParent(provider, gIOServicePlane);
-				} else {
-					IOLog("stalling for detach from %s\n", provider->getName());
-					IOLockLock( gIOServiceBusyLock );
-					provider->__state[1] |= kIOServiceWaitDetachState;
-				}
-			}
-			provider->unlockForArbitration();
-			if (wait) {
-				if (computeDeadline) {
-					clock_interval_to_deadline(15, kSecondScale, &deadline);
-					computeDeadline = false;
-				}
-				assert_wait_deadline((event_t)&provider->__provider, THREAD_UNINT, deadline);
-				IOLockUnlock( gIOServiceBusyLock );
-				waitResult = thread_block(THREAD_CONTINUE_NULL);
-				wait = (waitResult != THREAD_TIMED_OUT);
-			}
-		}while (wait);
-	} else {
-		gIOServiceRoot = this;
-		ok = attachToParent( getRegistryRoot(), gIOServicePlane);
-	}
-
-	if (ok && !__provider) {
-		(void) getProvider();
-	}
-
-	return ok;
-}
-
-IOService *
-IOService::getServiceRoot( void )
-{
-	return gIOServiceRoot;
-}
-
-void
-IOService::detach( IOService * provider )
-{
-	IOService * newProvider = NULL;
-	SInt32      busy;
-	bool        adjParent;
-
-	if (gIOKitDebug & kIOLogAttach) {
-		LOG("%s[0x%qx]::detach(%s[0x%qx])\n", getName(), getRegistryEntryID(), provider->getName(), provider->getRegistryEntryID());
-	}
-
-#if !NO_KEXTD
-	IOLockLock(gJobsLock);
-	if (gIOMatchDeferList) {
-		auto idx = gIOMatchDeferList->getNextIndexOfObject(this, 0);
-		if (-1U != idx) {
-			gIOMatchDeferList->removeObject(idx);
-		}
-	}
-	if (IOServicePH::fMatchingDelayed) {
-		auto idx = IOServicePH::fMatchingDelayed->getNextIndexOfObject(this, 0);
-		if (-1U != idx) {
-			IOServicePH::fMatchingDelayed->removeObject(idx);
-		}
-	}
-	IOLockUnlock(gJobsLock);
-#endif /* NO_KEXTD */
-
-	lockForArbitration();
-
-	uint64_t regID1 = provider->getRegistryEntryID();
-	uint64_t regID2 = getRegistryEntryID();
-	IOServiceTrace(
-		IOSERVICE_DETACH,
-		(uintptr_t) regID1,
-		(uintptr_t) (regID1 >> 32),
-		(uintptr_t) regID2,
-		(uintptr_t) (regID2 >> 32));
-
-	adjParent = ((busy = (__state[1] & kIOServiceBusyStateMask))
-	    && (provider == getProvider()));
-
-	detachFromParent( provider, gIOServicePlane );
-
-	if (busy) {
-		newProvider = getProvider();
-		if (busy && (__state[1] & kIOServiceTermPhase3State) && (NULL == newProvider)) {
-			_adjustBusy( -busy );
-		}
-	}
-
-	if (kIOServiceInactiveState & __state[0]) {
-		getMetaClass()->removeInstance(this);
-		IORemoveServicePlatformActions(this);
-	}
-
-	unlockForArbitration();
-
-	if (newProvider && adjParent) {
-		newProvider->lockForArbitration();
-		newProvider->_adjustBusy(1);
-		newProvider->unlockForArbitration();
-	}
-
-	// check for last client detach from a terminated service
-	if (provider->lockForArbitration( true )) {
-		if (kIOServiceStartState & __state[1]) {
-			provider->scheduleTerminatePhase2();
-		}
-		if (adjParent) {
-			provider->_adjustBusy( -1 );
-		}
-		if ((provider->__state[1] & kIOServiceTermPhase3State)
-		    && (NULL == provider->getClient())) {
-			provider->scheduleFinalize(false);
-		}
-
-		IOLockLock( gIOServiceBusyLock );
-		if (kIOServiceWaitDetachState & provider->__state[1]) {
-			provider->__state[1] &= ~kIOServiceWaitDetachState;
-			thread_wakeup(&provider->__provider);
-		}
-		IOLockUnlock( gIOServiceBusyLock );
-
-		provider->unlockForArbitration();
-	}
-
-	if (kIOServiceRematchOnDetach & __state[1] && !IOUserServer::shouldLeakObjects()) {
-		// kIOServiceRematchOnDetach isn't just for dexts
-		// but if IOUserServer already starts leaking objects, it doesn't matter anymore
-		provider->registerService();
-	}
+bool IOService::attach( IOService * provider )
+{
+    bool	ok;
+
+    if( provider) {
+
+	if( gIOKitDebug & kIOLogAttach)
+            LOG( "%s::attach(%s)\n", getName(),
+                    provider->getName());
+
+        provider->lockForArbitration();
+        if( provider->__state[0] & kIOServiceInactiveState)
+            ok = false;
+        else
+            ok = attachToParent( provider, gIOServicePlane);
+        provider->unlockForArbitration();
+
+    } else {
+	gIOServiceRoot = this;
+	ok = attachToParent( getRegistryRoot(), gIOServicePlane);
+    }
+
+    return( ok );
+}
+
+IOService * IOService::getServiceRoot( void )
+{
+    return( gIOServiceRoot );
+}
+
+void IOService::detach( IOService * provider )
+{
+    IOService * newProvider = 0;
+    SInt32	busy;
+    bool	adjParent;
+
+    if( gIOKitDebug & kIOLogAttach)
+        LOG("%s::detach(%s)\n", getName(), provider->getName());
+
+    lockForArbitration();
+
+    adjParent = ((busy = (__state[1] & kIOServiceBusyStateMask))
+               && (provider == getProvider()));
+
+    detachFromParent( provider, gIOServicePlane );
+
+    if( busy) {
+        newProvider = getProvider();
+        if( busy && (__state[1] & kIOServiceTermPhase3State) && (0 == newProvider))
+            _adjustBusy( -busy );
+    }
+
+    unlockForArbitration();
+
+    if( newProvider) {
+        newProvider->lockForArbitration();
+        newProvider->_adjustBusy(1);
+        newProvider->unlockForArbitration();
+    }
+
+    // check for last client detach from a terminated service
+    if( provider->lockForArbitration( true )) {
+        if( adjParent)
+            provider->_adjustBusy( -1 );
+        if( (provider->__state[1] & kIOServiceTermPhase3State)
+         && (0 == provider->getClient())) {
+            provider->scheduleFinalize();
+        }
+        provider->unlockForArbitration();
+    }
 }
 
 /*
  * Register instance - publish it for matching
  */
 
-void
-IOService::registerService( IOOptionBits options )
-{
-	OSDataAllocation<char> pathBuf;
-	const char *        path;
-	const char *        skip;
-	int                 len;
-	enum { kMaxPathLen  = 256 };
-	enum { kMaxChars    = 63 };
-
-	IORegistryEntry * parent = this;
-	IORegistryEntry * root = getRegistryRoot();
-	while (parent && (parent != root)) {
-		parent = parent->getParentEntry( gIOServicePlane);
-	}
-
-	if (parent != root) {
-		IOLog("%s: not registry member at registerService()\n", getName());
-		return;
-	}
-
-	// Allow the Platform Expert to adjust this node.
-	if (gIOPlatform && (!gIOPlatform->platformAdjustService(this))) {
-		return;
-	}
-
-#if DEBUG || DEVELOPMENT
-	__patchProperties();
-#endif /* DEBUG || DEVELOPMENT */
-
-	IOInstallServicePlatformActions(this);
-	IOInstallServiceSleepPlatformActions(this);
-
-	if ((this != gIOResources)
-	    && (kIOLogRegister & gIOKitDebug)) {
-		pathBuf = OSDataAllocation<char>( kMaxPathLen, OSAllocateMemory );
-
-		IOLog( "Registering: " );
-
-		len = kMaxPathLen;
-		if (pathBuf && getPath( pathBuf.data(), &len, gIOServicePlane)) {
-			path = pathBuf.data();
-			if (len > kMaxChars) {
-				IOLog("..");
-				len -= kMaxChars;
-				path += len;
-				if ((skip = strchr( path, '/'))) {
-					path = skip;
-				}
-			}
-		} else {
-			path = getName();
-		}
-
-		IOLog( "%s\n", path );
-	}
-
-	startMatching( options );
-}
-
-void
-IOService::startMatching( IOOptionBits options )
-{
-	IOService * provider;
-	UInt32      prevBusy = 0;
-	bool        needConfig;
-	bool        needWake = false;
-	bool        sync;
-	bool        waitAgain;
-	bool        releaseAssertion = false;
-
-	if (options & kIOServiceDextRequirePowerForMatching) {
-		bool ok = gIOPMRootDomain->acquireDriverKitMatchingAssertion() == kIOReturnSuccess;
-		if (!ok) {
-			panic("%s: Failed to acquire power assertion for matching", getName());
-		}
-		releaseAssertion = true;
-	}
-
-	lockForArbitration();
-
-	sync = (options & kIOServiceSynchronous)
-	    || ((provider = getProvider())
-	    && (provider->__state[1] & kIOServiceSynchronousState));
-
-	if (options & kIOServiceAsynchronous) {
-		sync = false;
-	}
-
-	needConfig =  (0 == (__state[1] & (kIOServiceNeedConfigState | kIOServiceConfigRunning)))
-	    && (0 == (__state[0] & kIOServiceInactiveState));
-
-	__state[1] |= kIOServiceNeedConfigState;
+void IOService::registerService( IOOptionBits options = 0 )
+{
+    char *		pathBuf;
+    const char *	path;
+    char *		skip;
+    int			len;
+    enum { kMaxPathLen	= 256 };
+    enum { kMaxChars	= 63 };
+
+    IORegistryEntry * parent = this;
+    IORegistryEntry * root = getRegistryRoot();
+    while( parent && (parent != root))
+        parent = parent->getParentEntry( gIOServicePlane);
+
+    if( parent != root) {
+        IOLog("%s: not registry member at registerService()\n", getName());
+        return;
+    }
+
+    // Allow the Platform Expert to adjust this node.
+    if( gIOPlatform && (!gIOPlatform->platformAdjustService(this)))
+	return;
+
+    if( (this != gIOResources)
+     && (kIOLogRegister & gIOKitDebug)) {
+
+        pathBuf = (char *) IOMalloc( kMaxPathLen );
+
+        IOLog( "Registering: " );
+
+        len = kMaxPathLen;
+        if( pathBuf && getPath( pathBuf, &len, gIOServicePlane)) {
+
+            path = pathBuf;
+            if( len > kMaxChars) {
+                IOLog("..");
+                len -= kMaxChars;
+                path += len;
+                if( (skip = strchr( path, '/')))
+                    path = skip;
+            }
+        } else
+            path = getName();
+
+        IOLog( "%s\n", path );
+
+	if( pathBuf)
+	    IOFree( pathBuf, kMaxPathLen );
+    }
+
+    startMatching( options );
+}
+
+void IOService::startMatching( IOOptionBits options = 0 )
+{
+    IOService *	provider;
+    UInt32	prevBusy = 0;
+    bool	needConfig;
+    bool	needWake = false;
+    bool	ok;
+    bool	sync;
+    bool	waitAgain;
+
+    lockForArbitration();
+
+    sync = (options & kIOServiceSynchronous)
+	|| ((provider = getProvider())
+		&& (provider->__state[1] & kIOServiceSynchronousState));
+
+
+    needConfig =  (0 == (__state[1] & (kIOServiceNeedConfigState | kIOServiceConfigState)))
+	       && (0 == (__state[0] & kIOServiceInactiveState));
+
+    __state[1] |= kIOServiceNeedConfigState;
 
 //    __state[0] &= ~kIOServiceInactiveState;
 
 //    if( sync) LOG("OSKernelStackRemaining = %08x @ %s\n",
 //			OSKernelStackRemaining(), getName());
 
-	if (needConfig) {
-		needWake = (0 != (kIOServiceSyncPubState & __state[1]));
+    if( needConfig) {
+	prevBusy = _adjustBusy( 1 );
+        needWake = (0 != (kIOServiceSyncPubState & __state[1]));
+    }
+
+    if( sync)
+	__state[1] |= kIOServiceSynchronousState;
+    else
+	__state[1] &= ~kIOServiceSynchronousState;
+
+    unlockForArbitration();
+
+    if( needConfig) {
+
+        if( needWake) {
+            IOLockLock( gIOServiceBusyLock );
+            thread_wakeup( (event_t) this/*&__state[1]*/ );
+            IOLockUnlock( gIOServiceBusyLock );
+
+        } else if( !sync || (kIOServiceAsynchronous & options)) {
+
+            ok = (0 != _IOServiceJob::startJob( this, kMatchNubJob, options ));
+    
+        } else do {
+
+            if( (__state[1] & kIOServiceNeedConfigState))
+                doServiceMatch( options );
+
+            lockForArbitration();
+            IOLockLock( gIOServiceBusyLock );
+
+            waitAgain = (prevBusy != (__state[1] & kIOServiceBusyStateMask));
+            if( waitAgain)
+                __state[1] |= kIOServiceSyncPubState | kIOServiceBusyWaiterState;
+            else
+                __state[1] &= ~kIOServiceSyncPubState;
+
+            unlockForArbitration();
+
+            if( waitAgain)
+                assert_wait( (event_t) this/*&__state[1]*/, THREAD_UNINT);
+
+            IOLockUnlock( gIOServiceBusyLock );
+            if( waitAgain)
+                thread_block((void (*)(void)) 0);
+
+        } while( waitAgain );
+    }
+}
+
+IOReturn IOService::catalogNewDrivers( OSOrderedSet * newTables )
+{
+    OSDictionary *	table;
+    OSIterator *	iter;
+    IOService *		service;
+#if IOMATCHDEBUG
+    SInt32		count = 0;
+#endif
+
+    newTables->retain();
+    
+    while( (table = (OSDictionary *) newTables->getFirstObject())) {
+
+	LOCKWRITENOTIFY();
+        iter = (OSIterator *) getExistingServices( table,
+                                                    kIOServiceRegisteredState );
+	UNLOCKNOTIFY();
+	if( iter) {
+	    while( (service = (IOService *) iter->getNextObject())) {
+                service->startMatching(kIOServiceAsynchronous);
+#if IOMATCHDEBUG
+		count++;
+#endif
+	    }
+	    iter->release();
 	}
-
-	if (sync) {
-		__state[1] |= kIOServiceSynchronousState;
-	} else {
-		__state[1] &= ~kIOServiceSynchronousState;
-	}
-
-	if (needConfig) {
-		prevBusy = _adjustBusy( 1 );
-	}
-
-	unlockForArbitration();
-
-	if (needConfig) {
-		if (needWake) {
-			IOLockLock( gIOServiceBusyLock );
-			thread_wakeup((event_t) this /*&__state[1]*/ );
-			IOLockUnlock( gIOServiceBusyLock );
-		} else if (!sync || (kIOServiceAsynchronous & options)) {
-			// assertion will be released when matching job is complete
-			releaseAssertion = false;
-			_IOServiceJob::startJob( this, kMatchNubJob, options );
-		} else {
-			do {
-				if ((__state[1] & kIOServiceNeedConfigState)) {
-					doServiceMatch( options );
-				}
-
-				lockForArbitration();
-				IOLockLock( gIOServiceBusyLock );
-
-				waitAgain = ((prevBusy < (__state[1] & kIOServiceBusyStateMask))
-				    && (0 == (__state[0] & kIOServiceInactiveState)));
-
-				if (waitAgain) {
-					__state[1] |= kIOServiceSyncPubState | kIOServiceBusyWaiterState;
-				} else {
-					__state[1] &= ~kIOServiceSyncPubState;
-				}
-
-				unlockForArbitration();
-
-				if (waitAgain) {
-					assert_wait((event_t) this /*&__state[1]*/, THREAD_UNINT);
-				}
-
-				IOLockUnlock( gIOServiceBusyLock );
-				if (waitAgain) {
-					thread_block(THREAD_CONTINUE_NULL);
-				}
-			} while (waitAgain);
-		}
-	}
-
-	if (releaseAssertion) {
-		gIOPMRootDomain->releaseDriverKitMatchingAssertion();
-	}
-}
-
-
-void
-IOService::startDeferredMatches(void)
-{
-#if !NO_KEXTD
-	OSArray * array;
-
-	IOLockLock(gJobsLock);
-	array = gIOMatchDeferList;
-	gIOMatchDeferList = NULL;
-	IOLockUnlock(gJobsLock);
-
-	if (array) {
-		IOLog("deferred rematching count %d\n", array->getCount());
-		array->iterateObjects(^bool (OSObject * obj)
-		{
-			((IOService *)obj)->startMatching(kIOServiceAsynchronous);
-			return false;
-		});
-		array->release();
-	}
-#endif /* !NO_KEXTD */
-}
-
-void
-IOService::iokitDaemonLaunched(void)
-{
-#if !NO_KEXTD
-	if (!OSKext::iokitDaemonAvailable()) {
-		panic(kIOKitDaemonName " is unavailable in this environment, but it was launched");
-	}
-	IOServiceTrace(IOSERVICE_KEXTD_READY, 0, 0, 0, 0);
-	startDeferredMatches();
-	getServiceRoot()->adjustBusy(-1);
-	IOService::publishUserResource(gIOResourceIOKitKey);
-#endif /* !NO_KEXTD */
-}
-
-/*
- * Possibly called with IORWLock from IOCatalog held.
- * This means that no calls to OSKext that could take
- * sKextLock can be performed from this function.
- */
-IOReturn
-IOService::catalogNewDrivers( OSOrderedSet * newTables )
-{
-	OSDictionary *      table;
-	OSSet *             set;
-	OSSet *             allSet = NULL;
-	IOService *         service;
 #if IOMATCHDEBUG
-	SInt32              count = 0;
+	if( getDebugFlags( table ) & kIOLogMatch)
+	    LOG("Matching service count = %ld\n", count);
 #endif
-
-	newTables->retain();
-
-	while ((table = (OSDictionary *) newTables->getFirstObject())) {
-		LOCKWRITENOTIFY();
-		set = (OSSet *) copyExistingServices( table,
-		    kIOServiceRegisteredState,
-		    kIOServiceExistingSet);
-		UNLOCKNOTIFY();
-		if (set) {
-#if IOMATCHDEBUG
-			count += set->getCount();
-#endif
-			if (allSet) {
-				allSet->merge((const OSSet *) set);
-				set->release();
-			} else {
-				allSet = set;
-			}
-		}
-
-#if IOMATCHDEBUG
-		if (getDebugFlags( table ) & kIOLogMatch) {
-			LOG("Matching service count = %ld\n", (long)count);
-		}
-#endif
-		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 )
-{
-	_IOServiceJob *     job;
-
-	job = new _IOServiceJob;
-	if (job && !job->init()) {
-		job->release();
-		job = NULL;
-	}
-
-	if (job) {
-		job->type       = type;
-		job->nub        = nub;
-		job->options    = options;
-		nub->retain();          // thread will release()
-		pingConfig( job );
-	}
-
-	return job;
+	newTables->removeObject(table);
+    }
+
+    newTables->release();
+
+    return( kIOReturnSuccess );
+}
+
+ _IOServiceJob * _IOServiceJob::startJob( IOService * nub, int type,
+						IOOptionBits options = 0 )
+{
+    _IOServiceJob *	job;
+
+    job = new _IOServiceJob;
+    if( job && !job->init()) {
+        job->release();
+        job = 0;
+    }
+
+    if( job) {
+        job->type	= type;
+        job->nub	= nub;
+	job->options	= options;
+        nub->retain();			// thread will release()
+        pingConfig( job );
+    }
+
+    return( job );
 }
 
 /*
@@ -1324,16 +584,14 @@
  * a property table.
  */
 
-bool
-IOService::matchPropertyTable( OSDictionary * table, SInt32 * score )
-{
-	return matchPropertyTable(table);
-}
-
-bool
-IOService::matchPropertyTable( OSDictionary * table )
-{
-	return true;
+bool IOService::matchPropertyTable( OSDictionary * table, SInt32 * score )
+{
+    return( matchPropertyTable(table) );
+}
+
+bool IOService::matchPropertyTable( OSDictionary * table )
+{
+    return( true );
 }
 
 /*
@@ -1341,223 +599,172 @@
  * before first driver is attached.
  */
 
-IOReturn
-IOService::getResources( void )
-{
-	return kIOReturnSuccess;
+IOReturn IOService::getResources( void )
+{
+    return( kIOReturnSuccess);
 }
 
 /*
  * Client/provider accessors
  */
 
-IOService *
-IOService::getProvider( void ) const
-{
-	IOService * self = (IOService *) this;
-	IOService * parent;
-	SInt32      generation;
-
-	generation = getRegistryEntryParentGenerationCount();
-	if (__providerGeneration == generation) {
-		return __provider;
-	}
-
-	parent = (IOService *) getParentEntry( gIOServicePlane);
-	if (parent == IORegistryEntry::getRegistryRoot()) {
-		/* root is not an IOService */
-		parent = NULL;
-	}
-
-	self->__provider = parent;
-	OSMemoryBarrier();
-	// save the count from before call to getParentEntry()
-	self->__providerGeneration = generation;
-
-	return parent;
-}
-
-IOWorkLoop *
-IOService::getWorkLoop() const
-{
-	IOService *provider = getProvider();
-
-	if (provider) {
-		return provider->getWorkLoop();
-	} else {
-		return NULL;
-	}
-}
-
-OSIterator *
-IOService::getProviderIterator( void ) const
-{
-	return getParentIterator( gIOServicePlane);
-}
-
-IOService *
-IOService::getClient( void ) const
-{
-	return (IOService *) getChildEntry( gIOServicePlane);
-}
-
-OSIterator *
-IOService::getClientIterator( void ) const
-{
-	return getChildIterator( gIOServicePlane);
-}
-
-OSIterator *
-_IOOpenServiceIterator::iterator( OSIterator * _iter,
-    const IOService * client,
-    const IOService * provider )
-{
-	_IOOpenServiceIterator * inst;
-
-	if (!_iter) {
-		return NULL;
-	}
-
-	inst = new _IOOpenServiceIterator;
-
-	if (inst && !inst->init()) {
-		inst->release();
-		inst = NULL;
-	}
-	if (inst) {
-		inst->iter = _iter;
-		inst->client = client;
-		inst->provider = provider;
-	} else {
-		OSSafeReleaseNULL(_iter);
-	}
-
-	return inst;
-}
-
-void
-_IOOpenServiceIterator::free()
-{
-	iter->release();
-	if (last) {
-		last->unlockForArbitration();
-	}
-	OSIterator::free();
-}
-
-OSObject *
-_IOOpenServiceIterator::getNextObject()
-{
-	IOService * next;
-
-	if (last) {
-		last->unlockForArbitration();
-	}
-
-	while ((next = (IOService *) iter->getNextObject())) {
-		next->lockForArbitration();
-		if ((client && (next->isOpen( client )))
-		    || (provider && (provider->isOpen( next )))) {
-			break;
-		}
-		next->unlockForArbitration();
-	}
-
-	last = next;
-
-	return next;
-}
-
-bool
-_IOOpenServiceIterator::isValid()
-{
-	return iter->isValid();
-}
-
-void
-_IOOpenServiceIterator::reset()
-{
-	if (last) {
-		last->unlockForArbitration();
-		last = NULL;
-	}
-	iter->reset();
-}
-
-OSIterator *
-IOService::getOpenProviderIterator( void ) const
-{
-	return _IOOpenServiceIterator::iterator( getProviderIterator(), this, NULL );
-}
-
-OSIterator *
-IOService::getOpenClientIterator( void ) const
-{
-	return _IOOpenServiceIterator::iterator( getClientIterator(), NULL, this );
-}
-
-
-IOReturn
-IOService::callPlatformFunction( const OSSymbol * functionName,
-    bool waitForFunction,
-    void *param1, void *param2,
-    void *param3, void *param4 )
-{
-	IOReturn  result = kIOReturnUnsupported;
-	IOService *provider;
-
-	if (functionName == gIOPlatformQuiesceActionKey ||
-	    functionName == gIOPlatformActiveActionKey ||
-	    functionName == gIOPlatformPanicActionKey) {
-		/*
-		 * Services which register for IOPlatformQuiesceAction / IOPlatformActiveAction / IOPlatformPanicAction
-		 * must consume that event themselves, without passing it up to super/IOService.
-		 */
-		if (gEnforcePlatformActionSafety) {
-			panic("Class %s passed the %s action to IOService",
-			    getMetaClass()->getClassName(), functionName->getCStringNoCopy());
-		}
-	}
-
-	if (gIOPlatformFunctionHandlerSet == functionName) {
-		const OSSymbol * functionHandlerName = (const OSSymbol *) param1;
-		IOService *      target              = (IOService *) param2;
-		bool             enable              = (param3 != NULL);
-
-		if (sCPULatencyFunctionName[kCpuDelayBusStall] == functionHandlerName) {
-			result = setLatencyHandler(kCpuDelayBusStall, target, enable);
-		}
-#if defined(__x86_64__)
-		else if (sCPULatencyFunctionName[kCpuDelayInterrupt] == param1) {
-			result = setLatencyHandler(kCpuDelayInterrupt, target, enable);
-		}
-#endif /* defined(__x86_64__) */
-	}
-
-	if ((kIOReturnUnsupported == result) && (provider = getProvider())) {
-		result = provider->callPlatformFunction(functionName, waitForFunction,
-		    param1, param2, param3, param4);
-	}
-
-	return result;
-}
-
-IOReturn
-IOService::callPlatformFunction( const char * functionName,
-    bool waitForFunction,
-    void *param1, void *param2,
-    void *param3, void *param4 )
-{
-	IOReturn result = kIOReturnNoMemory;
-	const OSSymbol *functionSymbol = OSSymbol::withCString(functionName);
-
-	if (functionSymbol != NULL) {
-		result = callPlatformFunction(functionSymbol, waitForFunction,
-		    param1, param2, param3, param4);
-		functionSymbol->release();
-	}
-
-	return result;
+IOService * IOService::getProvider( void ) const
+{
+    IOService *	self = (IOService *) this;
+    IOService *	parent;
+    SInt32	generation;
+
+    parent = __provider;
+    generation = getGenerationCount();
+    if( __providerGeneration == generation)
+	return( parent );
+
+    parent = (IOService *) getParentEntry( gIOServicePlane);
+    if( parent == IORegistryEntry::getRegistryRoot())
+	/* root is not an IOService */
+	parent = 0;
+
+    self->__provider = parent;
+    // save the count before getParentEntry()
+    self->__providerGeneration = generation;
+
+    return( parent );
+}
+
+IOWorkLoop * IOService::getWorkLoop() const
+{ 
+    IOService *provider = getProvider();
+
+    if (provider)
+	return provider->getWorkLoop();
+    else
+	return 0;
+}
+
+OSIterator * IOService::getProviderIterator( void ) const
+{
+    return( getParentIterator( gIOServicePlane));
+}
+
+IOService * IOService::getClient( void ) const
+{
+    return( (IOService *) getChildEntry( gIOServicePlane));
+}
+
+OSIterator * IOService::getClientIterator( void ) const
+{
+    return( getChildIterator( gIOServicePlane));
+}
+
+OSIterator * _IOOpenServiceIterator::iterator( OSIterator * _iter,
+						const IOService * client,
+						const IOService * provider )
+{
+    _IOOpenServiceIterator * inst;
+
+    if( !_iter)
+	return( 0 );
+
+    inst = new _IOOpenServiceIterator;
+
+    if( inst && !inst->init()) {
+	inst->release();
+	inst = 0;
+    }
+    if( inst) {
+	inst->iter = _iter;
+	inst->client = client;
+	inst->provider = provider;
+    }
+
+    return( inst );
+}
+
+void _IOOpenServiceIterator::free()
+{
+    iter->release();
+    if( last)
+	last->unlockForArbitration();
+    OSIterator::free();
+}
+
+OSObject * _IOOpenServiceIterator::getNextObject()
+{
+    IOService * next;
+
+    if( last)
+	last->unlockForArbitration();
+
+    while( (next = (IOService *) iter->getNextObject())) {
+
+	next->lockForArbitration();
+	if( (client && (next->isOpen( client )))
+	 || (provider && (provider->isOpen( next ))) )
+            break;
+	next->unlockForArbitration();
+    }
+
+    last = next;
+
+    return( next );
+}
+
+bool _IOOpenServiceIterator::isValid()
+{
+    return( iter->isValid() );
+}
+
+void _IOOpenServiceIterator::reset()
+{
+    if( last) {
+	last->unlockForArbitration();
+	last = 0;
+    }
+    iter->reset();
+}
+
+OSIterator * IOService::getOpenProviderIterator( void ) const
+{
+    return( _IOOpenServiceIterator::iterator( getProviderIterator(), this, 0 ));
+}
+
+OSIterator * IOService::getOpenClientIterator( void ) const
+{
+    return( _IOOpenServiceIterator::iterator( getClientIterator(), 0, this ));
+}
+
+
+IOReturn IOService::callPlatformFunction( const OSSymbol * functionName,
+					  bool waitForFunction,
+					  void *param1, void *param2,
+					  void *param3, void *param4 )
+{
+  IOReturn  result = kIOReturnUnsupported;
+  IOService *provider = getProvider();
+  
+  if (provider != 0) {
+    result = provider->callPlatformFunction(functionName, waitForFunction,
+					    param1, param2, param3, param4);
+  }
+  
+  return result;
+}
+
+IOReturn IOService::callPlatformFunction( const char * functionName,
+					  bool waitForFunction,
+					  void *param1, void *param2,
+					  void *param3, void *param4 )
+{
+  IOReturn result = kIOReturnNoMemory;
+  const OSSymbol *functionSymbol = OSSymbol::withCString(functionName);
+  
+  if (functionSymbol != 0) {
+    result = callPlatformFunction(functionSymbol, waitForFunction,
+				  param1, param2, param3, param4);
+    functionSymbol->release();
+  }
+  
+  return result;
 }
 
 
@@ -1565,531 +772,410 @@
  * Accessors for global services
  */
 
-IOPlatformExpert *
-IOService::getPlatform( void )
-{
-	return gIOPlatform;
-}
-
-class IOPMrootDomain *
-	IOService::getPMRootDomain( void )
-{
-	return gIOPMRootDomain;
-}
-
-IOService *
-IOService::getResourceService( void )
-{
-	return gIOResources;
-}
-
-IOService * gIOSystemStateNotificationService;
-
-IOService *
-IOService::getSystemStateNotificationService(void)
-{
-	return gIOSystemStateNotificationService;
-}
-
-void
-IOService::setPlatform( IOPlatformExpert * platform)
-{
-	gIOPlatform = platform;
-	gIOResources->attachToParent( gIOServiceRoot, gIOServicePlane );
-
-	gIOUserResources->attachToParent( gIOServiceRoot, gIOServicePlane );
-
-#if DEVELOPMENT || DEBUG
-	// Test object that will be terminated for dext to match
-	{
-		IOService * ios;
-		ios = OSTypeAlloc(IOService);
-		ios->init();
-		ios->attach(gIOUserResources);
-		ios->setProperty(gIOMatchCategoryKey->getCStringNoCopy(), "com.apple.iokit.test");
-		ios->setProperty(gIOModuleIdentifierKey->getCStringNoCopy(), "com.apple.kpi.iokit");
-		ios->setProperty(gIOMatchedAtBootKey, kOSBooleanTrue);
-		ios->setProperty(gIOPrimaryDriverTerminateOptionsKey, kOSBooleanTrue);
-		ios->release();
-	}
-#endif
-
-	gIOSystemStateNotificationService = IOSystemStateNotification::initialize();
-	gIOSystemStateNotificationService->attachToParent(platform, gIOServicePlane);
-	gIOSystemStateNotificationService->registerService();
-
-	static const char * keys[kCpuNumDelayTypes] = {
-		kIOPlatformMaxBusDelay,
-#if defined(__x86_64__)
-		kIOPlatformMaxInterruptDelay
-#endif /* defined(__x86_64__) */
-	};
-	const OSObject * objs[2];
-	OSArray * array;
-	uint32_t  idx;
-
-	for (idx = 0; idx < kCpuNumDelayTypes; idx++) {
-		objs[0] = sCPULatencySet[idx];
-		objs[1] = sCPULatencyHolder[idx];
-		array   = OSArray::withObjects(objs, 2);
-		if (!array) {
-			break;
-		}
-		platform->setProperty(keys[idx], array);
-		array->release();
-	}
-}
-
-void
-IOService::setPMRootDomain( class IOPMrootDomain * rootDomain)
-{
-	gIOPMRootDomain = rootDomain;
-}
-
-void
-IOService::publishPMRootDomain( void )
-{
-	assert(getPMRootDomain() != NULL);
-	publishResource(gIOResourceIOKitKey);
-#if NO_KEXTD
-	// Publish IOUserResources now since there is no IOKit daemon.
-	publishUserResource(gIOResourceIOKitKey);
-#endif
-	IOServicePH::init(getPMRootDomain());
+IOPlatformExpert * IOService::getPlatform( void )
+{
+    return( gIOPlatform);
+}
+
+class IOPMrootDomain * IOService::getPMRootDomain( void )
+{
+    return( gIOPMRootDomain);
+}
+
+IOService * IOService::getResourceService( void )
+{
+    return( gIOResources );
+}
+
+void IOService::setPlatform( IOPlatformExpert * platform)
+{
+    gIOPlatform = platform;
+    gIOResources->attachToParent( gIOServiceRoot, gIOServicePlane );
+}
+
+void IOService::setPMRootDomain( class IOPMrootDomain * rootDomain)
+{
+    gIOPMRootDomain = rootDomain;
+    publishResource("IOKit");
 }
 
 /*
  * Stacking change
  */
 
-bool
-IOService::lockForArbitration( bool isSuccessRequired )
-{
-	bool                          found;
-	bool                          success;
-	ArbitrationLockQueueElement * element;
-	ArbitrationLockQueueElement * owner;
-	ArbitrationLockQueueElement * active;
-	ArbitrationLockQueueElement * waiting;
-
-	enum { kPutOnFreeQueue, kPutOnActiveQueue, kPutOnWaitingQueue } action;
-
-	// lock global access
-	IOTakeLock( gArbitrationLockQueueLock );
-
-	// obtain an unused queue element
-	if (!queue_empty( &gArbitrationLockQueueFree )) {
-		queue_remove_first( &gArbitrationLockQueueFree,
-		    element,
-		    ArbitrationLockQueueElement *,
-		    link );
-	} else {
-		element = IOMallocType(ArbitrationLockQueueElement);
-		assert( element );
-	}
-
-	// prepare the queue element
-	element->thread   = IOThreadSelf();
-	element->service  = this;
-	element->count    = 1;
-	element->required = isSuccessRequired;
-	element->aborted  = false;
-
-	// determine whether this object is already locked (ie. on active queue)
-	found = false;
-	queue_iterate( &gArbitrationLockQueueActive,
-	    owner,
-	    ArbitrationLockQueueElement *,
-	    link )
-	{
-		if (owner->service == element->service) {
-			found = true;
-			break;
-		}
-	}
-
-	if (found) { // this object is already locked
-		active = owner;
-		// determine whether it is the same or a different thread trying to lock
-		if (active->thread != element->thread) { // it is a different thread
-			ArbitrationLockQueueElement * victim = NULL;
-
-			// before placing this new thread on the waiting queue, we look for
-			// a deadlock cycle...
-
-			while (1) {
-				// determine whether the active thread holding the object we
-				// want is waiting for another object to be unlocked
-				found = false;
-				queue_iterate( &gArbitrationLockQueueWaiting,
-				    waiting,
-				    ArbitrationLockQueueElement *,
-				    link )
-				{
-					if (waiting->thread == active->thread) {
-						assert( false == waiting->aborted );
-						found = true;
-						break;
-					}
-				}
-
-				if (found) { // yes, active thread waiting for another object
-					// this may be a candidate for rejection if the required
-					// flag is not set, should we detect a deadlock later on
-					if (false == waiting->required) {
-						victim = waiting;
-					}
-
-					// find the thread that is holding this other object, that
-					// is blocking the active thread from proceeding (fun :-)
-					found = false;
-					queue_iterate( &gArbitrationLockQueueActive,
-					    active, // (reuse active queue element)
-					    ArbitrationLockQueueElement *,
-					    link )
-					{
-						if (active->service == waiting->service) {
-							found = true;
-							break;
-						}
-					}
-
-					// someone must be holding it or it wouldn't be waiting
-					assert( found );
-
-					if (active->thread == element->thread) {
-						// doh, it's waiting for the thread that originated
-						// this whole lock (ie. current thread) -> deadlock
-						if (false == element->required) { // willing to fail?
-							// the originating thread doesn't have the required
-							// flag, so it can fail
-							success = false; // (fail originating lock request)
-							break; // (out of while)
-						} else { // originating thread is not willing to fail
-							// see if we came across a waiting thread that did
-							// not have the 'required' flag set: we'll fail it
-							if (victim) {
-								// we do have a willing victim, fail it's lock
-								victim->aborted = true;
-
-								// take the victim off the waiting queue
-								queue_remove( &gArbitrationLockQueueWaiting,
-								    victim,
-								    ArbitrationLockQueueElement *,
-								    link );
-
-								// wake the victim
-								wakeup_thread_with_inheritor(&victim->service->__machPortHoldDestroy, // event
-								    THREAD_AWAKENED, LCK_WAKE_DEFAULT, victim->thread);
-
-								// allow this thread to proceed (ie. wait)
-								success = true; // (put request on wait queue)
-								break; // (out of while)
-							} else {
-								// all the waiting threads we came across in
-								// finding this loop had the 'required' flag
-								// set, so we've got a deadlock we can't avoid
-								panic("I/O Kit: Unrecoverable deadlock.");
-							}
-						}
-					} else {
-						// repeat while loop, redefining active thread to be the
-						// thread holding "this other object" (see above), and
-						// looking for threads waiting on it; note the active
-						// variable points to "this other object" already... so
-						// there nothing to do in this else clause.
-					}
-				} else { // no, active thread is not waiting for another object
-					success = true; // (put request on wait queue)
-					break; // (out of while)
-				}
-			} // while forever
-
-			if (success) { // put the request on the waiting queue?
-				kern_return_t wait_result;
-
-				// place this thread on the waiting queue and put it to sleep;
-				// we place it at the tail of the queue...
-				queue_enter( &gArbitrationLockQueueWaiting,
-				    element,
-				    ArbitrationLockQueueElement *,
-				    link );
-
-				// declare that this thread will wait for a given event
-restart_sleep:
-				// unlock global access
-				// & put thread to sleep, waiting for our event to fire...
-				wait_result = IOLockSleepWithInheritor(gArbitrationLockQueueLock,
-				    LCK_SLEEP_UNLOCK,
-				    &element->service->__machPortHoldDestroy,     // event
-				    owner->thread,
-				    element->required ? THREAD_UNINT : THREAD_INTERRUPTIBLE, TIMEOUT_WAIT_FOREVER);
-
-				// ...and we've been woken up; we might be in one of two states:
-				// (a) we've been aborted and our queue element is not on
-				//     any of the three queues, but is floating around
-				// (b) we're allowed to proceed with the lock and we have
-				//     already been moved from the waiting queue to the
-				//     active queue.
-				// ...plus a 3rd state, should the thread have been interrupted:
-				// (c) we're still on the waiting queue
-
-				// determine whether we were interrupted out of our sleep
-				if (THREAD_INTERRUPTED == wait_result) {
-					// re-lock global access
-					IOTakeLock( gArbitrationLockQueueLock );
-
-					// determine whether we're still on the waiting queue
-					found = false;
-					queue_iterate( &gArbitrationLockQueueWaiting,
-					    waiting, // (reuse waiting queue element)
-					    ArbitrationLockQueueElement *,
-					    link )
-					{
-						if (waiting == element) {
-							found = true;
-							break;
-						}
-					}
-
-					if (found) { // yes, we're still on the waiting queue
-						// determine whether we're willing to fail
-						if (false == element->required) {
-							// mark us as aborted
-							element->aborted = true;
-
-							// take us off the waiting queue
-							queue_remove( &gArbitrationLockQueueWaiting,
-							    element,
-							    ArbitrationLockQueueElement *,
-							    link );
-						} else { // we are not willing to fail
-							// ignore interruption, go back to sleep
-							goto restart_sleep;
-						}
-					}
-
-					// unlock global access
-					IOUnlock( gArbitrationLockQueueLock );
-
-					// proceed as though this were a normal wake up
-					wait_result = THREAD_AWAKENED;
-				}
-
-				assert( THREAD_AWAKENED == wait_result );
-
-				// determine whether we've been aborted while we were asleep
-				if (element->aborted) {
-					assert( false == element->required );
-					// re-lock global access
-					IOTakeLock( gArbitrationLockQueueLock );
-
-					action = kPutOnFreeQueue;
-					success = false;
-				} else { // we weren't aborted, so we must be ready to go :-)
-					// we've already been moved from waiting to active queue
-					return true;
-				}
-			} else { // the lock request is to be failed
-				// return unused queue element to queue
-				action = kPutOnFreeQueue;
-			}
-		} else { // it is the same thread, recursive access is allowed
-			// add one level of recursion
-			active->count++;
-
-			// return unused queue element to queue
-			action = kPutOnFreeQueue;
-			success = true;
-		}
-	} else { // this object is not already locked, so let this thread through
-		action = kPutOnActiveQueue;
-		success = true;
-	}
-
-	// put the new element on a queue
-	if (kPutOnActiveQueue == action) {
-		queue_enter( &gArbitrationLockQueueActive,
-		    element,
-		    ArbitrationLockQueueElement *,
-		    link );
-	} else if (kPutOnFreeQueue == action) {
-		queue_enter( &gArbitrationLockQueueFree,
-		    element,
-		    ArbitrationLockQueueElement *,
-		    link );
-	} else {
-		assert( 0 ); // kPutOnWaitingQueue never occurs, handled specially above
-	}
-
-	// unlock global access
-	IOUnlock( gArbitrationLockQueueLock );
-
-	return success;
-}
-
-void
-IOService::unlockForArbitration( void )
-{
-	bool                          found;
-	ArbitrationLockQueueElement * element;
-
-	// lock global access
-	IOTakeLock( gArbitrationLockQueueLock );
-
-	// find the lock element for this object (ie. on active queue)
-	found = false;
-	queue_iterate( &gArbitrationLockQueueActive,
-	    element,
-	    ArbitrationLockQueueElement *,
-	    link )
-	{
-		if (element->service == this) {
-			found = true;
-			break;
-		}
-	}
-
-	assert( found );
-
-	// determine whether the lock has been taken recursively
-	if (element->count > 1) {
-		// undo one level of recursion
-		element->count--;
-	} else {
-		// remove it from the active queue
-		queue_remove( &gArbitrationLockQueueActive,
-		    element,
-		    ArbitrationLockQueueElement *,
-		    link );
-
-		// put it on the free queue
-		queue_enter( &gArbitrationLockQueueFree,
-		    element,
-		    ArbitrationLockQueueElement *,
-		    link );
-
-		// determine whether a thread is waiting for object
-		thread_t woken;
-		kern_return_t kr =
-		    wakeup_one_with_inheritor(&__machPortHoldDestroy, // event
-		    THREAD_AWAKENED, LCK_WAKE_DEFAULT, &woken);
-
-		if (KERN_SUCCESS == kr) {
-			found = false;
-			queue_iterate( &gArbitrationLockQueueWaiting,
-			    element,
-			    ArbitrationLockQueueElement *,
-			    link )
-			{
-				if (element->thread == woken) {
-					found = true;
-					break;
-				}
-			}
-			assert(found); // we found an interested thread on waiting queue
-			// remove it from the waiting queue
-			queue_remove( &gArbitrationLockQueueWaiting,
-			    element,
-			    ArbitrationLockQueueElement *,
-			    link );
-
-			// put it on the active queue
-			queue_enter( &gArbitrationLockQueueActive,
-			    element,
-			    ArbitrationLockQueueElement *,
-			    link );
-
-			thread_deallocate(woken);
-		}
-	}
-
-	// unlock global access
-	IOUnlock( gArbitrationLockQueueLock );
-}
-
-uint32_t
-IOService::isLockedForArbitration(IOService * service)
-{
-#if DEBUG_NOTIFIER_LOCKED
-	uint32_t                      count;
-	ArbitrationLockQueueElement * active;
-
-	// lock global access
-	IOLockLock(gArbitrationLockQueueLock);
-
-	// determine whether this object is already locked (ie. on active queue)
-	count = 0;
-	queue_iterate(&gArbitrationLockQueueActive,
-	    active,
-	    ArbitrationLockQueueElement *,
-	    link)
-	{
-		if ((active->thread == IOThreadSelf())
-		    && (!service || (active->service == service))) {
-			count += 0x10000;
-			count += active->count;
-		}
-	}
-
-	IOLockUnlock(gArbitrationLockQueueLock);
-
-	return count;
-
-#else /* DEBUG_NOTIFIER_LOCKED */
-
-	return 0;
-
-#endif /* DEBUG_NOTIFIER_LOCKED */
-}
-
-void
-IOService::setMachPortHoldDestroy(bool holdDestroy)
-{
-	__machPortHoldDestroy = holdDestroy;
-}
-
-bool
-IOService::machPortHoldDestroy()
-{
-	return __machPortHoldDestroy;
-}
-
-void
-IOService::applyToProviders( IOServiceApplierFunction applier,
-    void * context )
-{
-	applyToParents((IORegistryEntryApplierFunction) applier,
-	    context, gIOServicePlane );
-}
-
-void
-IOService::applyToClients( IOServiceApplierFunction applier,
-    void * context )
-{
-	applyToChildren((IORegistryEntryApplierFunction) applier,
-	    context, gIOServicePlane );
-}
-
-
-static void
-IOServiceApplierToBlock(IOService * next, void * context)
-{
-	IOServiceApplierBlock block = (IOServiceApplierBlock) context;
-	block(next);
-}
-
-void
-IOService::applyToProviders(IOServiceApplierBlock applier)
-{
-	applyToProviders(&IOServiceApplierToBlock, applier);
-}
-
-void
-IOService::applyToClients(IOServiceApplierBlock applier)
-{
-	applyToClients(&IOServiceApplierToBlock, applier);
-}
+bool IOService::lockForArbitration( bool isSuccessRequired = true )
+{
+    bool                          found;
+    bool                          success;
+    ArbitrationLockQueueElement * element;
+    ArbitrationLockQueueElement * active;
+    ArbitrationLockQueueElement * waiting;
+
+    enum { kPutOnFreeQueue, kPutOnActiveQueue, kPutOnWaitingQueue } action;
+
+    // lock global access
+    IOTakeLock( gArbitrationLockQueueLock );
+
+    // obtain an unused queue element
+    if( !queue_empty( &gArbitrationLockQueueFree )) {
+        queue_remove_first( &gArbitrationLockQueueFree,
+                            element,
+                            ArbitrationLockQueueElement *,
+                            link );
+    } else {
+        element = IONew( ArbitrationLockQueueElement, 1 );
+        assert( element );
+    }
+
+    // prepare the queue element
+    element->thread   = IOThreadSelf();
+    element->service  = this;
+    element->count    = 1;
+    element->required = isSuccessRequired;
+    element->aborted  = false;
+
+    // determine whether this object is already locked (ie. on active queue)
+    found = false;
+    queue_iterate( &gArbitrationLockQueueActive,
+                    active,
+                    ArbitrationLockQueueElement *,
+                    link )
+    {
+        if( active->service == element->service ) {
+            found = true;
+            break;
+        }
+    }
+
+    if( found ) { // this object is already locked
+
+        // determine whether it is the same or a different thread trying to lock
+        if( active->thread != element->thread ) { // it is a different thread
+
+            ArbitrationLockQueueElement * victim = 0;
+
+            // before placing this new thread on the waiting queue, we look for
+            // a deadlock cycle...
+
+            while( 1 ) {
+                // determine whether the active thread holding the object we
+                // want is waiting for another object to be unlocked
+                found = false;
+                queue_iterate( &gArbitrationLockQueueWaiting,
+                               waiting,
+                               ArbitrationLockQueueElement *,
+                               link )
+                {
+                    if( waiting->thread == active->thread ) {
+                        assert( false == waiting->aborted );
+                        found = true;
+                        break;
+                    }
+                }
+
+                if( found ) { // yes, active thread waiting for another object
+
+                    // this may be a candidate for rejection if the required
+                    // flag is not set, should we detect a deadlock later on
+                    if( false == waiting->required )
+                        victim = waiting;
+
+                    // find the thread that is holding this other object, that
+                    // is blocking the active thread from proceeding (fun :-)
+                    found = false;
+                    queue_iterate( &gArbitrationLockQueueActive,
+                                   active,      // (reuse active queue element)
+                                   ArbitrationLockQueueElement *,
+                                   link )
+                    {
+                        if( active->service == waiting->service ) {
+                            found = true;
+                            break;
+                        }
+                    }
+
+                    // someone must be holding it or it wouldn't be waiting
+                    assert( found );
+
+                    if( active->thread == element->thread ) {
+
+                        // doh, it's waiting for the thread that originated
+                        // this whole lock (ie. current thread) -> deadlock
+                        if( false == element->required ) { // willing to fail?
+
+                            // the originating thread doesn't have the required
+                            // flag, so it can fail
+                            success = false; // (fail originating lock request)
+                            break; // (out of while)
+
+                        } else { // originating thread is not willing to fail
+
+                            // see if we came across a waiting thread that did
+                            // not have the 'required' flag set: we'll fail it
+                            if( victim ) {
+
+                                // we do have a willing victim, fail it's lock
+                                victim->aborted = true;
+
+                                // take the victim off the waiting queue
+                                queue_remove( &gArbitrationLockQueueWaiting,
+                                              victim,
+                                              ArbitrationLockQueueElement *,
+                                              link );
+
+                                // wake the victim
+                                thread_wakeup_one(victim);
+
+                                // allow this thread to proceed (ie. wait)
+                                success = true; // (put request on wait queue)
+                                break; // (out of while)
+                            } else {
+
+                                // all the waiting threads we came across in
+                                // finding this loop had the 'required' flag
+                                // set, so we've got a deadlock we can't avoid
+                                panic("I/O Kit: Unrecoverable deadlock.");
+                            }
+                        }
+                    } else {
+                        // repeat while loop, redefining active thread to be the
+                        // thread holding "this other object" (see above), and
+                        // looking for threads waiting on it; note the active
+                        // variable points to "this other object" already... so
+                        // there nothing to do in this else clause.
+                    }
+                } else { // no, active thread is not waiting for another object
+                      
+                    success = true; // (put request on wait queue)
+                    break; // (out of while)
+                }
+            } // while forever
+
+            if( success ) { // put the request on the waiting queue?
+                kern_return_t wait_result;
+
+                // place this thread on the waiting queue and put it to sleep;
+                // we place it at the tail of the queue...
+                queue_enter( &gArbitrationLockQueueWaiting,
+                             element,
+                             ArbitrationLockQueueElement *,
+                             link );
+
+                // declare that this thread will wait for a given event
+restart_sleep:  assert_wait( element,
+                             element->required ? THREAD_UNINT
+                                               : THREAD_INTERRUPTIBLE );
+
+                // unlock global access
+                IOUnlock( gArbitrationLockQueueLock );
+
+                // put thread to sleep, waiting for our event to fire...
+                wait_result = thread_block((void (*)(void)) 0);
+
+                // ...and we've been woken up; we might be in one of two states:
+                // (a) we've been aborted and our queue element is not on
+                //     any of the three queues, but is floating around
+                // (b) we're allowed to proceed with the lock and we have
+                //     already been moved from the waiting queue to the
+                //     active queue.
+                // ...plus a 3rd state, should the thread have been interrupted:
+                // (c) we're still on the waiting queue
+
+                // determine whether we were interrupted out of our sleep
+                if( THREAD_INTERRUPTED == wait_result ) {
+
+                    // re-lock global access
+                    IOTakeLock( gArbitrationLockQueueLock );
+
+                    // determine whether we're still on the waiting queue
+                    found = false;
+                    queue_iterate( &gArbitrationLockQueueWaiting,
+                                   waiting,     // (reuse waiting queue element)
+                                   ArbitrationLockQueueElement *,
+                                   link )
+                    {
+                        if( waiting == element ) {
+                            found = true;
+                            break;
+                        }
+                    }
+
+                    if( found ) { // yes, we're still on the waiting queue
+
+                        // determine whether we're willing to fail
+                        if( false == element->required ) {
+
+                            // mark us as aborted
+                            element->aborted = true;
+
+                            // take us off the waiting queue
+                            queue_remove( &gArbitrationLockQueueWaiting,
+                                          element,
+                                          ArbitrationLockQueueElement *,
+                                          link );
+                        } else { // we are not willing to fail
+
+                            // ignore interruption, go back to sleep
+                            goto restart_sleep;
+                        }
+                    }
+
+                    // unlock global access
+                    IOUnlock( gArbitrationLockQueueLock );
+
+                    // proceed as though this were a normal wake up
+                    wait_result = THREAD_AWAKENED;
+                }
+
+                assert( THREAD_AWAKENED == wait_result );
+
+                // determine whether we've been aborted while we were asleep
+                if( element->aborted ) {
+                    assert( false == element->required );
+
+                    // re-lock global access
+                    IOTakeLock( gArbitrationLockQueueLock );
+
+                    action = kPutOnFreeQueue;
+                    success = false;
+                } else { // we weren't aborted, so we must be ready to go :-)
+
+                    // we've already been moved from waiting to active queue
+                    return true;
+                }
+
+            } else { // the lock request is to be failed
+
+                // return unused queue element to queue
+                action = kPutOnFreeQueue;
+            }
+        } else { // it is the same thread, recursive access is allowed
+
+            // add one level of recursion
+            active->count++;
+
+            // return unused queue element to queue
+            action = kPutOnFreeQueue;
+            success = true;
+        }
+    } else { // this object is not already locked, so let this thread through
+        action = kPutOnActiveQueue;
+        success = true;
+    }
+
+    // put the new element on a queue
+    if( kPutOnActiveQueue == action ) {
+        queue_enter( &gArbitrationLockQueueActive,
+                     element,
+                     ArbitrationLockQueueElement *,
+                     link );
+    } else if( kPutOnFreeQueue == action ) {
+        queue_enter( &gArbitrationLockQueueFree,
+                     element,
+                     ArbitrationLockQueueElement *,
+                     link );
+    } else {
+        assert( 0 ); // kPutOnWaitingQueue never occurs, handled specially above
+    }
+
+    // unlock global access
+    IOUnlock( gArbitrationLockQueueLock );
+
+    return( success );
+}
+
+void IOService::unlockForArbitration( void )
+{
+    bool                          found;
+    ArbitrationLockQueueElement * element;
+
+    // lock global access
+    IOTakeLock( gArbitrationLockQueueLock );
+
+    // find the lock element for this object (ie. on active queue)
+    found = false;
+    queue_iterate( &gArbitrationLockQueueActive,
+                    element,
+                    ArbitrationLockQueueElement *,
+                    link )
+    {
+        if( element->service == this ) {
+            found = true;
+            break;
+        }
+    }
+
+    assert( found );
+
+    // determine whether the lock has been taken recursively
+    if( element->count > 1 ) {
+        // undo one level of recursion
+        element->count--;
+
+    } else {
+
+        // remove it from the active queue
+        queue_remove( &gArbitrationLockQueueActive,
+                      element,
+                      ArbitrationLockQueueElement *,
+                      link );
+
+        // put it on the free queue
+        queue_enter( &gArbitrationLockQueueFree,
+                     element,
+                     ArbitrationLockQueueElement *,
+                     link );
+
+        // determine whether a thread is waiting for object (head to tail scan)
+        found = false;
+        queue_iterate( &gArbitrationLockQueueWaiting,
+                       element,
+                       ArbitrationLockQueueElement *,
+                       link )
+        {
+            if( element->service == this ) {
+                found = true;
+                break;
+            }
+        }
+
+        if ( found ) { // we found an interested thread on waiting queue
+
+            // remove it from the waiting queue
+            queue_remove( &gArbitrationLockQueueWaiting,
+                          element,
+                          ArbitrationLockQueueElement *,
+                          link );
+
+            // put it on the active queue
+            queue_enter( &gArbitrationLockQueueActive,
+                         element,
+                         ArbitrationLockQueueElement *,
+                         link );
+
+            // wake the waiting thread
+            thread_wakeup_one(element);
+        }
+    }
+
+    // unlock global access
+    IOUnlock( gArbitrationLockQueueLock );
+}
+
+void IOService::applyToProviders( IOServiceApplierFunction applier,
+                                  void * context )
+{
+    applyToParents( (IORegistryEntryApplierFunction) applier,
+                    context, gIOServicePlane );
+}
+
+void IOService::applyToClients( IOServiceApplierFunction applier,
+                                void * context )
+{
+    applyToChildren( (IORegistryEntryApplierFunction) applier,
+                     context, gIOServicePlane );
+}
+
 
 /*
  * Client messages
@@ -2097,308 +1183,199 @@
 
 
 // send a message to a client or interested party of this service
-IOReturn
-IOService::messageClient( UInt32 type, OSObject * client,
-    void * argument, vm_size_t argSize )
-{
-	IOReturn                            ret;
-	IOService *                         service;
-	_IOServiceInterestNotifier *        notify;
-
-	if ((service = OSDynamicCast( IOService, client))) {
-		ret = service->message( type, this, argument );
-	} else if ((notify = OSDynamicCast( _IOServiceInterestNotifier, client))) {
-		_IOServiceNotifierInvocation invocation;
-		bool                     willNotify;
-
-		invocation.thread = current_thread();
-
-		LOCKWRITENOTIFY();
-		willNotify = (0 != (kIOServiceNotifyEnable & notify->state));
-
-		if (willNotify) {
-			queue_enter( &notify->handlerInvocations, &invocation,
-			    _IOServiceNotifierInvocation *, link );
-		}
-		UNLOCKNOTIFY();
-
-		if (willNotify) {
-			ret = (*notify->handler)( notify->target, notify->ref,
-			    type, this, argument, argSize );
-
-			LOCKWRITENOTIFY();
-			queue_remove( &notify->handlerInvocations, &invocation,
-			    _IOServiceNotifierInvocation *, link );
-			if (kIOServiceNotifyWaiter & notify->state) {
-				notify->state &= ~kIOServiceNotifyWaiter;
-				WAKEUPNOTIFY( notify );
-			}
-			UNLOCKNOTIFY();
-		} else {
-			ret = kIOReturnSuccess;
-		}
-	} else {
-		ret = kIOReturnBadArgument;
-	}
-
-	return ret;
-}
-
-static void
-applyToInterestNotifiers(const IORegistryEntry *target,
-    const OSSymbol * typeOfInterest,
-    OSObjectApplierFunction applier,
-    void * context )
-{
-	OSArray *  copyArray = NULL;
-	OSObject * prop;
-
-	LOCKREADNOTIFY();
-
-	prop = target->copyProperty(typeOfInterest);
-	IOCommand *notifyList = OSDynamicCast(IOCommand, prop);
-
-	if (notifyList) {
-		copyArray = OSArray::withCapacity(1);
-
-		// iterate over queue, entry is set to each element in the list
-		iterqueue(&notifyList->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();
-	}
-
-	OSSafeReleaseNULL(prop);
-}
-
-void
-IOService::applyToInterested( const OSSymbol * typeOfInterest,
-    OSObjectApplierFunction applier,
-    void * context )
-{
-	if (gIOGeneralInterest == typeOfInterest) {
-		applyToClients((IOServiceApplierFunction) applier, context );
-	}
-	applyToInterestNotifiers(this, typeOfInterest, applier, context);
+IOReturn IOService::messageClient( UInt32 type, OSObject * client,
+                                   void * argument = 0, vm_size_t argSize = 0 )
+{
+    IOReturn 				ret;
+    IOService * 			service;
+    _IOServiceInterestNotifier *	notify;
+
+    if( (service = OSDynamicCast( IOService, client)))
+        ret = service->message( type, this, argument );
+    
+    else if( (notify = OSDynamicCast( _IOServiceInterestNotifier, client))) {
+
+        _IOServiceNotifierInvocation invocation;
+        bool			 willNotify;
+    
+        invocation.thread = current_thread();
+    
+        LOCKWRITENOTIFY();
+        willNotify = (0 != (kIOServiceNotifyEnable & notify->state));
+    
+        if( willNotify) {
+            queue_enter( &notify->handlerInvocations, &invocation,
+                            _IOServiceNotifierInvocation *, link );
+        }
+        UNLOCKNOTIFY();
+    
+        if( willNotify) {
+
+            ret = (*notify->handler)( notify->target, notify->ref,
+                                          type, this, argument, argSize );
+    
+            LOCKWRITENOTIFY();
+            queue_remove( &notify->handlerInvocations, &invocation,
+                            _IOServiceNotifierInvocation *, link );
+            if( kIOServiceNotifyWaiter & notify->state) {
+                notify->state &= ~kIOServiceNotifyWaiter;
+                thread_wakeup( (event_t) notify);
+            }
+            UNLOCKNOTIFY();
+
+        } else
+            ret = kIOReturnSuccess;
+
+    } else
+        ret = kIOReturnBadArgument;
+
+    return( ret );
+}
+
+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();
 }
 
 struct MessageClientsContext {
-	IOService * service;
-	UInt32      type;
-	void *      argument;
-	vm_size_t   argSize;
-	IOReturn    ret;
+    IOService *	service;
+    UInt32	type;
+    void *	argument;
+    vm_size_t	argSize;
+    IOReturn	ret;
 };
 
-static void
-messageClientsApplier( OSObject * object, void * ctx )
-{
-	IOReturn                ret;
-	MessageClientsContext * context = (MessageClientsContext *) ctx;
-
-	ret = context->service->messageClient( context->type,
-	    object, context->argument, context->argSize );
-	if (kIOReturnSuccess != ret) {
-		context->ret = ret;
-	}
+static void messageClientsApplier( OSObject * object, void * ctx )
+{
+    IOReturn		    ret;
+    MessageClientsContext * context = (MessageClientsContext *) ctx;
+
+    ret = context->service->messageClient( context->type,
+                                           object, context->argument, context->argSize );    
+    if( kIOReturnSuccess != ret)
+        context->ret = ret;
 }
 
 // send a message to all clients
-IOReturn
-IOService::messageClients( UInt32 type,
-    void * argument, vm_size_t argSize )
-{
-	MessageClientsContext       context;
-
-	context.service     = this;
-	context.type        = type;
-	context.argument    = argument;
-	context.argSize     = argSize;
-	context.ret         = kIOReturnSuccess;
-
-	applyToInterested( gIOGeneralInterest,
-	    &messageClientsApplier, &context );
-
-	return context.ret;
-}
-
-IOReturn
-IOService::acknowledgeNotification( IONotificationRef notification,
-    IOOptionBits response )
-{
-	return kIOReturnUnsupported;
-}
-
-IONotifier *
-IOService::registerInterest( const OSSymbol * typeOfInterest,
-    IOServiceInterestHandler handler, void * target, void * ref )
-{
-	_IOServiceInterestNotifier * notify = NULL;
-	IOReturn rc = kIOReturnError;
-
-	notify = new _IOServiceInterestNotifier;
-	if (!notify) {
-		return NULL;
-	}
-
-	if (notify->init()) {
-		rc = registerInterestForNotifier(notify, typeOfInterest,
-		    handler, target, ref);
-	}
-
-	if (rc != kIOReturnSuccess) {
-		notify->release();
-		notify = NULL;
-	}
-
-	return notify;
-}
-
-
-
-static IOReturn
-IOServiceInterestHandlerToBlock( void * target __unused, void * refCon,
-    UInt32 messageType, IOService * provider,
-    void * messageArgument, vm_size_t argSize )
-{
-	return ((IOServiceInterestHandlerBlock) refCon)(messageType, provider, messageArgument, argSize);
-}
-
-IONotifier *
-IOService::registerInterest(const OSSymbol * typeOfInterest,
-    IOServiceInterestHandlerBlock handler)
-{
-	IONotifier * notify;
-
-	notify = registerInterest(typeOfInterest, &IOServiceInterestHandlerToBlock, NULL, handler);
-	return notify;
-}
-
-IOReturn
-IOService::registerInterestForNotifier( IONotifier *svcNotify, const OSSymbol * typeOfInterest,
-    IOServiceInterestHandler handler, void * target, void * ref )
-{
-	IOReturn rc = kIOReturnSuccess;
-	_IOServiceInterestNotifier  *notify = NULL;
-
-
-	if (!svcNotify || !(notify = OSDynamicCast(_IOServiceInterestNotifier, svcNotify)) || !handler) {
-		return kIOReturnBadArgument;
-	}
-
-	notify->handler = handler;
-	notify->target = target;
-	if (handler == &IOServiceInterestHandlerToBlock) {
-		notify->ref = Block_copy(ref);
-	} else {
-		notify->ref = ref;
-	}
-
-	if ((typeOfInterest != gIOGeneralInterest)
-	    && (typeOfInterest != gIOBusyInterest)
-	    && (typeOfInterest != gIOAppPowerStateInterest)
-	    && (typeOfInterest != gIOConsoleSecurityInterest)
-	    && (typeOfInterest != gIOPriorityPowerStateInterest)) {
-		return kIOReturnBadArgument;
-	}
-
-	lockForArbitration();
-	if (0 == (__state[0] & kIOServiceInactiveState)) {
-		notify->state = kIOServiceNotifyEnable;
-
-		////// queue
-
-		LOCKWRITENOTIFY();
-
-		// Get the head of the notifier linked list
-		IOCommand * notifyList;
-		OSObject  * obj = copyProperty( typeOfInterest );
-		if (!(notifyList = OSDynamicCast(IOCommand, obj))) {
-			notifyList = OSTypeAlloc(IOCommand);
-			if (notifyList) {
-				notifyList->init();
-				bool ok = setProperty( typeOfInterest, notifyList);
-				notifyList->release();
-				if (!ok) {
-					notifyList = NULL;
-				}
-			}
-		}
-		if (obj) {
-			obj->release();
-		}
-
-		if (notifyList) {
-			enqueue(&notifyList->fCommandChain, &notify->chain);
-			notify->retain(); // ref'ed while in list
-		}
-
-		UNLOCKNOTIFY();
-	} else {
-		rc = kIOReturnNotReady;
-	}
-	unlockForArbitration();
-
-	return rc;
-}
-
-static void
-cleanInterestList( OSObject * head )
-{
-	IOCommand *notifyHead = OSDynamicCast(IOCommand, head);
-	if (!notifyHead) {
-		return;
-	}
-
-	LOCKWRITENOTIFY();
-	while (queue_entry_t entry = dequeue(&notifyHead->fCommandChain)) {
-		queue_next(entry) = queue_prev(entry) = NULL;
-
-		_IOServiceInterestNotifier * notify;
-
-		queue_element(entry, notify, _IOServiceInterestNotifier *, chain);
-		notify->release();
-	}
-	UNLOCKNOTIFY();
-}
-
-void
-IOService::unregisterAllInterest( void )
-{
-	OSObject * prop;
-
-	prop = copyProperty(gIOGeneralInterest);
-	cleanInterestList(prop);
-	OSSafeReleaseNULL(prop);
-
-	prop = copyProperty(gIOBusyInterest);
-	cleanInterestList(prop);
-	OSSafeReleaseNULL(prop);
-
-	prop = copyProperty(gIOAppPowerStateInterest);
-	cleanInterestList(prop);
-	OSSafeReleaseNULL(prop);
-
-	prop = copyProperty(gIOPriorityPowerStateInterest);
-	cleanInterestList(prop);
-	OSSafeReleaseNULL(prop);
-
-	prop = copyProperty(gIOConsoleSecurityInterest);
-	cleanInterestList(prop);
-	OSSafeReleaseNULL(prop);
+IOReturn IOService::messageClients( UInt32 type,
+                                    void * argument = 0, vm_size_t argSize = 0 )
+{
+    MessageClientsContext	context;
+
+    context.service	= this;
+    context.type	= type;
+    context.argument	= argument;
+    context.argSize	= argSize;
+    context.ret		= kIOReturnSuccess;
+
+    applyToInterested( gIOGeneralInterest,
+                       &messageClientsApplier, &context );
+
+    return( context.ret );
+}
+
+IOReturn IOService::acknowledgeNotification( IONotificationRef notification,
+                                              IOOptionBits response )
+{
+    return( kIOReturnUnsupported );
+}
+
+IONotifier * IOService::registerInterest( const OSSymbol * typeOfInterest,
+                  IOServiceInterestHandler handler, void * target, void * ref )
+{
+    _IOServiceInterestNotifier * notify = 0;
+    OSArray *			 set;
+
+    if( (typeOfInterest != gIOGeneralInterest)
+     && (typeOfInterest != gIOBusyInterest)
+     && (typeOfInterest != gIOAppPowerStateInterest)
+     && (typeOfInterest != gIOPriorityPowerStateInterest))
+        return( 0 );
+
+    lockForArbitration();
+    if( 0 == (__state[0] & kIOServiceInactiveState)) {
+
+        notify = new _IOServiceInterestNotifier;
+        if( notify && !notify->init()) {
+            notify->release();
+            notify = 0;
+        }
+
+        if( notify) {
+            notify->handler = handler;
+            notify->target = target;
+            notify->ref = ref;
+            notify->state = kIOServiceNotifyEnable;
+            queue_init( &notify->handlerInvocations );
+
+            ////// 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 );
+            UNLOCKNOTIFY();
+        }
+    }
+    unlockForArbitration();
+
+    return( notify );
+}
+
+static void cleanInterestArray( OSObject * object )
+{
+    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();
+    }
+}
+
+void IOService::unregisterAllInterest( void )
+{
+    cleanInterestArray( getProperty( gIOGeneralInterest ));
+    cleanInterestArray( getProperty( gIOBusyInterest ));
+    cleanInterestArray( getProperty( gIOAppPowerStateInterest ));
+    cleanInterestArray( getProperty( gIOPriorityPowerStateInterest ));
 }
 
 /*
@@ -2408,1091 +1385,607 @@
 // wait for all threads, other than the current one,
 //  to exit the handler
 
-void
-_IOServiceInterestNotifier::wait()
-{
-	_IOServiceNotifierInvocation * next;
-	bool doWait;
-
-	do {
-		doWait = false;
-		queue_iterate( &handlerInvocations, next,
-		    _IOServiceNotifierInvocation *, link) {
-			if (next->thread != current_thread()) {
-				doWait = true;
-				break;
-			}
-		}
-		if (doWait) {
-			state |= kIOServiceNotifyWaiter;
-			SLEEPNOTIFY(this);
-		}
-	} while (doWait);
-}
-
-void
-_IOServiceInterestNotifier::free()
-{
-	assert( queue_empty( &handlerInvocations ));
-
-	if (handler == &IOServiceInterestHandlerToBlock) {
-		Block_release(ref);
-	}
-
-	OSObject::free();
-}
-
-void
-_IOServiceInterestNotifier::remove()
-{
-	LOCKWRITENOTIFY();
-
-	if (queue_next( &chain )) {
-		remqueue(&chain);
-		queue_next( &chain) = queue_prev( &chain) = NULL;
-		release();
-	}
-
-	state &= ~kIOServiceNotifyEnable;
-
-	wait();
-
-	UNLOCKNOTIFY();
-
-	release();
-}
-
-bool
-_IOServiceInterestNotifier::disable()
-{
-	bool        ret;
-
-	LOCKWRITENOTIFY();
-
-	ret = (0 != (kIOServiceNotifyEnable & state));
-	state &= ~kIOServiceNotifyEnable;
-	if (ret) {
-		wait();
-	}
-
-	UNLOCKNOTIFY();
-
-	return ret;
-}
-
-void
-_IOServiceInterestNotifier::enable( bool was )
-{
-	LOCKWRITENOTIFY();
-	if (was) {
-		state |= kIOServiceNotifyEnable;
-	} else {
-		state &= ~kIOServiceNotifyEnable;
-	}
-	UNLOCKNOTIFY();
-}
-
-bool
-_IOServiceInterestNotifier::init()
-{
-	queue_init( &handlerInvocations );
-	return OSObject::init();
-}
+void _IOServiceInterestNotifier::wait()
+{
+    _IOServiceNotifierInvocation * next;
+    bool doWait;
+
+    do {
+        doWait = false;
+        queue_iterate( &handlerInvocations, next,
+                        _IOServiceNotifierInvocation *, link) {
+            if( next->thread != current_thread() ) {
+                doWait = true;
+                break;
+            }
+        }
+        if( doWait) {
+            state |= kIOServiceNotifyWaiter;
+            assert_wait( this, THREAD_UNINT);
+            UNLOCKNOTIFY();
+            thread_block((void (*)(void)) 0);
+            LOCKWRITENOTIFY();
+        }
+
+    } while( doWait );
+}
+
+void _IOServiceInterestNotifier::free()
+{
+    assert( queue_empty( &handlerInvocations ));
+    OSObject::free();
+}
+
+void _IOServiceInterestNotifier::remove()
+{
+    LOCKWRITENOTIFY();
+
+    if( whence) {
+        whence->removeObject(whence->getNextIndexOfObject(
+                                       (OSObject *) this, 0 ));
+        whence = 0;
+    }
+
+    state &= ~kIOServiceNotifyEnable;
+
+    wait();
+
+    UNLOCKNOTIFY();
+    
+    release();
+}
+
+bool _IOServiceInterestNotifier::disable()
+{
+    bool	ret;
+
+    LOCKWRITENOTIFY();
+
+    ret = (0 != (kIOServiceNotifyEnable & state));
+    state &= ~kIOServiceNotifyEnable;
+    if( ret)
+        wait();
+
+    UNLOCKNOTIFY();
+
+    return( ret );
+}
+
+void _IOServiceInterestNotifier::enable( bool was )
+{
+    LOCKWRITENOTIFY();
+    if( was)
+        state |= kIOServiceNotifyEnable;
+    else
+        state &= ~kIOServiceNotifyEnable;
+    UNLOCKNOTIFY();
+}
+
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 /*
  * Termination
  */
 
-#define tailQ(o)                setObject(o)
-#define headQ(o)                setObject(0, o)
-#define TLOG(fmt, args...)      { if(kIOLogYield & gIOKitDebug) { IOLog("[%llx] ", thread_tid(current_thread())); IOLog(fmt, ## args); }}
-
-static void
-_workLoopAction( IOWorkLoop::Action action,
-    IOService * service,
-    void * p0 = NULL, void * p1 = NULL,
-    void * p2 = NULL, void * p3 = NULL )
-{
-	IOWorkLoop * wl;
-
-	if ((wl = service->getWorkLoop())) {
-		wl->retain();
-		wl->runAction( action, service, p0, p1, p2, p3 );
-		wl->release();
-	} else {
-		(*action)( service, p0, p1, p2, p3 );
-	}
-}
-
-bool
-IOService::requestTerminate( IOService * provider, IOOptionBits options )
-{
-	bool ok;
-
-	// if its our only provider
-	ok = isParent( provider, gIOServicePlane, true);
-
-	// -- compat
-	if (ok) {
-		provider->terminateClient( this, options | kIOServiceRecursing );
-		ok = (0 != (kIOServiceInactiveState & __state[0]));
-	}
-	// --
-
-	return ok;
-}
-
-bool
-IOService::terminatePhase1( IOOptionBits options )
-{
-	IOService *  victim;
-	IOService *  client;
-	IOService *  rematchProvider;
-	OSIterator * iter;
-	OSArray *    makeInactive;
-	OSArray *    waitingInactive;
-	IOOptionBits callerOptions;
-	int          waitResult = THREAD_AWAKENED;
-	bool         wait;
-	bool                 ok;
-	bool                 didInactive;
-	bool                 startPhase2 = false;
-
-	TLOG("%s[0x%qx]::terminatePhase1(%08llx)\n", getName(), getRegistryEntryID(), (long long)options);
-
-	callerOptions = options;
-	rematchProvider = NULL;
-	uint64_t regID = getRegistryEntryID();
-	IOServiceTrace(
-		IOSERVICE_TERMINATE_PHASE1,
-		(uintptr_t) regID,
-		(uintptr_t) (regID >> 32),
-		(uintptr_t) this,
-		(uintptr_t) options);
-
-	// -- compat
-	if (options & kIOServiceRecursing) {
-		lockForArbitration();
-		if (0 == (kIOServiceInactiveState & __state[0])) {
-			__state[0] |= kIOServiceInactiveState;
-			__state[1] |= kIOServiceRecursing | kIOServiceTermPhase1State;
-		}
-		unlockForArbitration();
-
-		return true;
-	}
-	// --
-
-	makeInactive    = OSArray::withCapacity( 16 );
-	waitingInactive = OSArray::withCapacity( 16 );
-	if (!makeInactive || !waitingInactive) {
-		OSSafeReleaseNULL(makeInactive);
-		OSSafeReleaseNULL(waitingInactive);
-		return false;
-	}
-
-	victim = this;
-	victim->retain();
-
-	while (victim) {
-		didInactive = victim->lockForArbitration( true );
-		if (didInactive) {
-			uint64_t regID1 = victim->getRegistryEntryID();
-			IOServiceTrace(IOSERVICE_TERM_SET_INACTIVE,
-			    (uintptr_t) regID1,
-			    (uintptr_t) (regID1 >> 32),
-			    (uintptr_t) victim->__state[1],
-			    (uintptr_t) 0);
-
-			enum { kRP1 = kIOServiceRecursing | kIOServiceTermPhase1State };
-			didInactive = (kRP1 == (victim->__state[1] & kRP1))
-			    || (0 == (victim->__state[0] & kIOServiceInactiveState));
-
-			if (!didInactive) {
-				// a multiply attached IOService can be visited twice
-				if (-1U == waitingInactive->getNextIndexOfObject(victim, 0)) {
-					do{
-						IOLockLock(gIOServiceBusyLock);
-						wait = (victim->__state[1] & kIOServiceTermPhase1State);
-						if (wait) {
-							TLOG("%s[0x%qx]::waitPhase1(%s[0x%qx])\n",
-							    getName(), getRegistryEntryID(), victim->getName(), victim->getRegistryEntryID());
-							victim->__state[1] |= kIOServiceTerm1WaiterState;
-							victim->unlockForArbitration();
-							assert_wait((event_t)&victim->__state[1], THREAD_UNINT);
-						}
-						IOLockUnlock(gIOServiceBusyLock);
-						if (wait) {
-							waitResult = thread_block(THREAD_CONTINUE_NULL);
-							TLOG("%s[0x%qx]::did waitPhase1(%s[0x%qx])\n",
-							    getName(), getRegistryEntryID(), victim->getName(), victim->getRegistryEntryID());
-							victim->lockForArbitration();
-						}
-					}while (wait && (waitResult != THREAD_TIMED_OUT));
-				}
-			} else {
-				victim->__state[0] |= kIOServiceInactiveState;
-				victim->__state[0] &= ~(kIOServiceRegisteredState | kIOServiceMatchedState
-				    | kIOServiceFirstPublishState | kIOServiceFirstMatchState);
-				victim->__state[1] &= ~kIOServiceRecursing;
-				victim->__state[1] |= kIOServiceTermPhase1State;
-				waitingInactive->headQ(victim);
-				if (victim == this) {
-					if (kIOServiceTerminateNeedWillTerminate & options) {
-						victim->__state[1] |= kIOServiceNeedWillTerminate;
-					}
-				}
-				victim->_adjustBusy( 1 );
-
-				if ((options & kIOServiceTerminateWithRematch) && (victim == this)) {
-					if ((options & kIOServiceTerminateWithRematchCurrentDext)) {
-						OSObject     * obj;
-						OSObject     * rematchProps;
-						OSNumber     * num;
-						uint32_t       count;
-
-						rematchProvider = getProvider();
-						if (rematchProvider) {
-							obj = rematchProvider->copyProperty(gIORematchCountKey);
-							num = OSDynamicCast(OSNumber, obj);
-							count = 0;
-							if (num) {
-								count = num->unsigned32BitValue();
-								count++;
-							}
-							num = OSNumber::withNumber(count, 32);
-							rematchProvider->setProperty(gIORematchCountKey, num);
-							rematchProps = copyProperty(gIOMatchedPersonalityKey);
-							rematchProvider->setProperty(gIORematchPersonalityKey, rematchProps);
-							OSSafeReleaseNULL(num);
-							OSSafeReleaseNULL(rematchProps);
-							OSSafeReleaseNULL(obj);
-						}
-					}
-					victim->__state[1] |= kIOServiceRematchOnDetach;
-				}
-			}
-			victim->unlockForArbitration();
-		}
-		if (victim == this) {
-			options &= ~(kIOServiceTerminateWithRematch | kIOServiceTerminateWithRematchCurrentDext);
-			startPhase2 = didInactive;
-		}
-		if (didInactive) {
-			OSArray * notifiers;
-			notifiers = victim->copyNotifiers(gIOTerminatedNotification, 0, 0xffffffff);
-			victim->invokeNotifiers(&notifiers);
-
-			IOUserClient::destroyUserReferences( victim );
-
-			iter = victim->getClientIterator();
-			if (iter) {
-				while ((client = (IOService *) iter->getNextObject())) {
-					TLOG("%s[0x%qx]::requestTerminate(%s[0x%qx], %08llx)\n",
-					    client->getName(), client->getRegistryEntryID(),
-					    victim->getName(), victim->getRegistryEntryID(), (long long)options);
-					ok = client->requestTerminate( victim, options );
-					TLOG("%s[0x%qx]::requestTerminate(%s[0x%qx], ok = %d)\n",
-					    client->getName(), client->getRegistryEntryID(),
-					    victim->getName(), victim->getRegistryEntryID(), ok);
-
-					uint64_t regID1 = client->getRegistryEntryID();
-					uint64_t regID2 = victim->getRegistryEntryID();
-					IOServiceTrace(
-						(ok ? IOSERVICE_TERMINATE_REQUEST_OK
-						: IOSERVICE_TERMINATE_REQUEST_FAIL),
-						(uintptr_t) regID1,
-						(uintptr_t) (regID1 >> 32),
-						(uintptr_t) regID2,
-						(uintptr_t) (regID2 >> 32));
-
-					if (ok) {
-						makeInactive->setObject( client );
-					}
-				}
-				iter->release();
-			}
-		}
-		victim->release();
-		victim = (IOService *) makeInactive->getObject(0);
-		if (victim) {
-			victim->retain();
-			makeInactive->removeObject(0);
-		}
-	}
-
-	makeInactive->release();
-
-	while ((victim = (IOService *) waitingInactive->getObject(0))) {
-		victim->retain();
-		waitingInactive->removeObject(0);
-
-		victim->lockForArbitration();
-		victim->__state[1] &= ~kIOServiceTermPhase1State;
-		if (kIOServiceTerm1WaiterState & victim->__state[1]) {
-			victim->__state[1] &= ~kIOServiceTerm1WaiterState;
-			TLOG("%s[0x%qx]::wakePhase1\n", victim->getName(), victim->getRegistryEntryID());
-			IOLockLock( gIOServiceBusyLock );
-			thread_wakeup((event_t) &victim->__state[1]);
-			IOLockUnlock( gIOServiceBusyLock );
-		}
-		victim->unlockForArbitration();
-		victim->release();
-	}
-
-	waitingInactive->release();
-
-	if (startPhase2) {
-		retain();
-		lockForArbitration();
-		__state[1] |= kIOServiceTermPhase2ReadyState;
-		scheduleTerminatePhase2(options);
-		unlockForArbitration();
-		release();
-	}
-
-	if (rematchProvider) {
-		DKLOG(DKS " rematching after dext crash\n", DKN(rematchProvider));
-	}
-
-	return true;
-}
-
-void
-IOService::setTerminateDefer(IOService * provider, bool defer)
-{
-	lockForArbitration();
-	if (defer) {
-		__state[1] |= kIOServiceStartState;
-	} else {
-		__state[1] &= ~kIOServiceStartState;
-	}
-	unlockForArbitration();
-
-	if (provider && !defer) {
-		provider->lockForArbitration();
-		provider->scheduleTerminatePhase2();
-		provider->unlockForArbitration();
-	}
-}
-
-// Must call this while holding gJobsLock
-void
-IOService::waitToBecomeTerminateThread(void)
-{
-	IOLockAssert(gJobsLock, kIOLockAssertOwned);
-	bool wait;
-	do {
-		wait = (gIOTerminateThread != THREAD_NULL);
-		if (wait) {
-			IOLockSleepWithInheritor(
-				gJobsLock,
-				LCK_SLEEP_DEFAULT,
-				&gIOTerminateThread,
-				gIOTerminateThread,
-				THREAD_UNINT,
-				TIMEOUT_WAIT_FOREVER);
-		}
-	} while (wait);
-	gIOTerminateThread = current_thread();
-}
-
-// call with lockForArbitration
-void
-IOService::scheduleTerminatePhase2( IOOptionBits options )
-{
-	AbsoluteTime        deadline;
-	uint64_t            regID1;
-	int                 waitResult = THREAD_AWAKENED;
-	bool                wait = false, haveDeadline = false;
-
-	if (!(__state[0] & kIOServiceInactiveState)) {
-		return;
-	}
-
-	regID1 = getRegistryEntryID();
-	IOServiceTrace(
-		IOSERVICE_TERM_SCHED_PHASE2,
-		(uintptr_t) regID1,
-		(uintptr_t) (regID1 >> 32),
-		(uintptr_t) __state[1],
-		(uintptr_t) options);
-
-	if (0 == (__state[1] & kIOServiceTermPhase2ReadyState)) {
-		return;
-	}
-
-	retain();
-	unlockForArbitration();
-	options |= kIOServiceRequired;
-	IOLockLock( gJobsLock );
-
-	if ((options & kIOServiceSynchronous)
-	    && (current_thread() != gIOTerminateThread)) {
-		waitToBecomeTerminateThread();
-		gIOTerminatePhase2List->setObject( this );
-		gIOTerminateWork++;
-
-		do {
-			while (gIOTerminateWork) {
-				terminateWorker( options );
-			}
-			wait = (0 != (__state[1] & kIOServiceBusyStateMask));
-			if (wait) {
-				/* wait for the victim to go non-busy */
-				if (!haveDeadline) {
-					clock_interval_to_deadline( 15, kSecondScale, &deadline );
-					haveDeadline = true;
-				}
-				/* let others do work while we wait */
-				gIOTerminateThread = NULL;
-				IOLockWakeupAllWithInheritor(gJobsLock, &gIOTerminateThread);
-				waitResult = IOLockSleepDeadline( gJobsLock, &gIOTerminateWork,
-				    deadline, THREAD_UNINT );
-				if (__improbable(waitResult == THREAD_TIMED_OUT)) {
-					IOLog("%s[0x%qx]::terminate(kIOServiceSynchronous): THREAD_TIMED_OUT. "
-					    "Attempting to auto-resolve your deadlock. PLEASE FIX!\n", getName(), getRegistryEntryID());
-				}
-				waitToBecomeTerminateThread();
-			}
-		} while (gIOTerminateWork || (wait && (waitResult != THREAD_TIMED_OUT)));
-
-		gIOTerminateThread = NULL;
-		IOLockWakeupAllWithInheritor(gJobsLock, &gIOTerminateThread);
-	} else {
-		// ! kIOServiceSynchronous
-
-		gIOTerminatePhase2List->setObject( this );
-		if (0 == gIOTerminateWork++) {
-			assert(gIOTerminateWorkerThread);
-			IOLockWakeup(gJobsLock, (event_t)&gIOTerminateWork, /* one-thread */ false );
-		}
-	}
-
-	IOLockUnlock( gJobsLock );
-	lockForArbitration();
-	release();
-}
-
-__attribute__((__noreturn__))
-void
-IOService::terminateThread( void * arg, wait_result_t waitResult )
-{
-	// IOLockSleep re-acquires the lock on wakeup, so we only need to do this once
-	IOLockLock(gJobsLock);
-	while (true) {
-		if (gIOTerminateThread != gIOTerminateWorkerThread) {
-			waitToBecomeTerminateThread();
-		}
-
-		while (gIOTerminateWork) {
-			terminateWorker((IOOptionBits)(uintptr_t)arg );
-		}
-
-		gIOTerminateThread = NULL;
-		IOLockWakeupAllWithInheritor(gJobsLock, &gIOTerminateThread);
-		IOLockSleep(gJobsLock, &gIOTerminateWork, THREAD_UNINT);
-	}
-}
-
-void
-IOService::scheduleStop( IOService * provider )
-{
-	uint64_t regID1 = getRegistryEntryID();
-	uint64_t regID2 = provider->getRegistryEntryID();
-
-	TLOG("%s[0x%qx]::scheduleStop(%s[0x%qx])\n", getName(), regID1, provider->getName(), regID2);
-	IOServiceTrace(
-		IOSERVICE_TERMINATE_SCHEDULE_STOP,
-		(uintptr_t) regID1,
-		(uintptr_t) (regID1 >> 32),
-		(uintptr_t) regID2,
-		(uintptr_t) (regID2 >> 32));
-
-	IOLockLock( gJobsLock );
-	gIOStopList->tailQ( this );
-	gIOStopProviderList->tailQ( provider );
-
-	if (0 == gIOTerminateWork++) {
-		assert(gIOTerminateWorkerThread);
-		IOLockWakeup(gJobsLock, (event_t)&gIOTerminateWork, /* one-thread */ false );
-	}
-
-	IOLockUnlock( gJobsLock );
-}
-
-void
-IOService::scheduleFinalize(bool now)
-{
-	uint64_t regID1 = getRegistryEntryID();
-
-	TLOG("%s[0x%qx]::scheduleFinalize\n", getName(), regID1);
-	IOServiceTrace(
-		IOSERVICE_TERMINATE_SCHEDULE_FINALIZE,
-		(uintptr_t) regID1,
-		(uintptr_t) (regID1 >> 32),
-		0, 0);
-
-	if (now || IOUserClient::finalizeUserReferences(this)) {
-		IOLockLock( gJobsLock );
-		gIOFinalizeList->tailQ(this);
-		if (0 == gIOTerminateWork++) {
-			assert(gIOTerminateWorkerThread);
-			IOLockWakeup(gJobsLock, (event_t)&gIOTerminateWork, /* one-thread */ false );
-		}
-		IOLockUnlock( gJobsLock );
-	}
-}
-
-bool
-IOService::willTerminate( IOService * provider, IOOptionBits options )
-{
-	if (reserved->uvars) {
-		IOUserServer::serviceWillTerminate(this, provider, options);
-	} else if (kIODKLogSetup & gIODKDebug) {
-		DKLOG("%s[0x%qx]::willTerminate serviceWillTerminate not called\n", getName(), getRegistryEntryID());
-	}
-	return true;
-}
-
-bool
-IOService::didTerminate( IOService * provider, IOOptionBits options, bool * defer )
-{
-	if (reserved->uvars) {
-		IOUserServer::serviceDidTerminate(this, provider, options, defer);
-	}
-
-	if (false == *defer) {
-		if (lockForArbitration( true )) {
-			if (false == provider->handleIsOpen( this )) {
-				scheduleStop( provider );
-			}
-			// -- compat
-			else {
-				message( kIOMessageServiceIsRequestingClose, provider, (void *)(uintptr_t) options );
-				if (false == provider->handleIsOpen( this )) {
-					scheduleStop( provider );
-				}
-			}
-			// --
-			unlockForArbitration();
-		}
-	}
-
-	return true;
-}
-
-void
-IOService::actionWillTerminate( IOService * victim, IOOptionBits options,
-    OSArray * doPhase2List,
-    bool user,
-    void *unused3 __unused)
-{
-	OSIterator * iter;
-	IOService *  client;
-	bool         ok;
-	uint64_t     regID1, regID2 = victim->getRegistryEntryID();
-
-	iter = victim->getClientIterator();
-	if (iter) {
-		while ((client = (IOService *) iter->getNextObject())) {
-			if (user != (NULL != client->reserved->uvars)) {
-				continue;
-			}
-			regID1 = client->getRegistryEntryID();
-			TLOG("%s[0x%qx]::willTerminate(%s[0x%qx], %08llx)\n",
-			    client->getName(), regID1,
-			    victim->getName(), regID2, (long long)options);
-			IOServiceTrace(
-				IOSERVICE_TERMINATE_WILL,
-				(uintptr_t) regID1,
-				(uintptr_t) (regID1 >> 32),
-				(uintptr_t) regID2,
-				(uintptr_t) (regID2 >> 32));
-
-			ok = client->willTerminate( victim, options );
-			doPhase2List->tailQ( client );
-		}
-		iter->release();
-	}
-}
-
-void
-IOService::actionDidTerminate( IOService * victim, IOOptionBits options,
-    void *unused1 __unused, void *unused2 __unused,
-    void *unused3 __unused )
-{
-	OSIterator * iter;
-	IOService *  client;
-	bool         defer;
-	uint64_t     regID1, regID2 = victim->getRegistryEntryID();
-
-	victim->messageClients( kIOMessageServiceIsTerminated, (void *)(uintptr_t) options );
-
-	iter = victim->getClientIterator();
-	if (iter) {
-		while ((client = (IOService *) iter->getNextObject())) {
-			regID1 = client->getRegistryEntryID();
-			TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], %08llx)\n",
-			    client->getName(), regID1,
-			    victim->getName(), regID2, (long long)options);
-			defer = false;
-			client->didTerminate( victim, options, &defer );
-
-			IOServiceTrace(
-				(defer ? IOSERVICE_TERMINATE_DID_DEFER
-				: IOSERVICE_TERMINATE_DID),
-				(uintptr_t) regID1,
-				(uintptr_t) (regID1 >> 32),
-				(uintptr_t) regID2,
-				(uintptr_t) (regID2 >> 32));
-
-			TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], defer %d)\n",
-			    client->getName(), regID1,
-			    victim->getName(), regID2, defer);
-		}
-		iter->release();
-	}
-}
-
-
-void
-IOService::actionWillStop( IOService * victim, IOOptionBits options,
-    void *unused1 __unused, void *unused2 __unused,
-    void *unused3 __unused )
-{
-	OSIterator * iter;
-	IOService *  provider;
-	bool         ok;
-	uint64_t     regID1, regID2 = victim->getRegistryEntryID();
-
-	iter = victim->getProviderIterator();
-	if (iter) {
-		while ((provider = (IOService *) iter->getNextObject())) {
-			regID1 = provider->getRegistryEntryID();
-			TLOG("%s[0x%qx]::willTerminate(%s[0x%qx], %08llx)\n",
-			    victim->getName(), regID2,
-			    provider->getName(), regID1, (long long)options);
-			IOServiceTrace(
-				IOSERVICE_TERMINATE_WILL,
-				(uintptr_t) regID2,
-				(uintptr_t) (regID2 >> 32),
-				(uintptr_t) regID1,
-				(uintptr_t) (regID1 >> 32));
-
-			ok = victim->willTerminate( provider, options );
-		}
-		iter->release();
-	}
-}
-
-void
-IOService::actionDidStop( IOService * victim, IOOptionBits options,
-    void *unused1 __unused, void *unused2 __unused,
-    void *unused3 __unused )
-{
-	OSIterator * iter;
-	IOService *  provider;
-	bool defer = false;
-	uint64_t     regID1, regID2 = victim->getRegistryEntryID();
-
-	iter = victim->getProviderIterator();
-	if (iter) {
-		while ((provider = (IOService *) iter->getNextObject())) {
-			regID1 = provider->getRegistryEntryID();
-			TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], %08llx)\n",
-			    victim->getName(), regID2,
-			    provider->getName(), regID1, (long long)options);
-			victim->didTerminate( provider, options, &defer );
-
-			IOServiceTrace(
-				(defer ? IOSERVICE_TERMINATE_DID_DEFER
-				: IOSERVICE_TERMINATE_DID),
-				(uintptr_t) regID2,
-				(uintptr_t) (regID2 >> 32),
-				(uintptr_t) regID1,
-				(uintptr_t) (regID1 >> 32));
-
-			TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], defer %d)\n",
-			    victim->getName(), regID2,
-			    provider->getName(), regID1, defer);
-		}
-		iter->release();
-	}
-}
-
-
-void
-IOService::actionFinalize( IOService * victim, IOOptionBits options,
-    void *unused1 __unused, void *unused2 __unused,
-    void *unused3 __unused )
-{
-	uint64_t regID1 = victim->getRegistryEntryID();
-	TLOG("%s[0x%qx]::finalize(%08llx)\n", victim->getName(), regID1, (long long)options);
-	IOServiceTrace(
-		IOSERVICE_TERMINATE_FINALIZE,
-		(uintptr_t) regID1,
-		(uintptr_t) (regID1 >> 32),
-		0, 0);
-
-	victim->finalize( options );
-}
-
-void
-IOService::actionStop( IOService * provider, IOService * client,
-    void *unused1 __unused, void *unused2 __unused,
-    void *unused3 __unused )
-{
-	uint64_t regID1 = provider->getRegistryEntryID();
-	uint64_t regID2 = client->getRegistryEntryID();
-
-	TLOG("%s[0x%qx]::stop(%s[0x%qx])\n", client->getName(), regID2, provider->getName(), regID1);
-	IOServiceTrace(
-		IOSERVICE_TERMINATE_STOP,
-		(uintptr_t) regID1,
-		(uintptr_t) (regID1 >> 32),
-		(uintptr_t) regID2,
-		(uintptr_t) (regID2 >> 32));
-
-	client->stop( provider );
-	if (provider->isOpen( client )) {
-		provider->close( client );
-	}
-
-	TLOG("%s[0x%qx]::detach(%s[0x%qx])\n", client->getName(), regID2, provider->getName(), regID1);
-	client->detach( provider );
-}
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wcast-function-type"
-
-void
-IOService::terminateWorker( IOOptionBits options )
-{
-	OSArray *           doPhase2List;
-	OSArray *           didPhase2List;
-	OSSet *             freeList;
-	OSIterator *        iter;
-	UInt32              workDone;
-	IOService *         victim;
-	IOService *         client;
-	IOService *         provider;
-	unsigned int        idx;
-	bool                moreToDo;
-	bool                doPhase2;
-	bool                doPhase3;
-
-	options |= kIOServiceRequired;
-
-	doPhase2List  = OSArray::withCapacity( 16 );
-	didPhase2List = OSArray::withCapacity( 16 );
-	freeList      = OSSet::withCapacity( 16 );
-	if ((NULL == doPhase2List) || (NULL == didPhase2List) || (NULL == freeList)) {
-		OSSafeReleaseNULL(doPhase2List);
-		OSSafeReleaseNULL(didPhase2List);
-		OSSafeReleaseNULL(freeList);
-		return;
-	}
-
-	do {
-		workDone = gIOTerminateWork;
-
-		while ((victim = (IOService *) gIOTerminatePhase2List->getObject(0))) {
-			victim->retain();
-			gIOTerminatePhase2List->removeObject(0);
-			IOLockUnlock( gJobsLock );
-
-			uint64_t regID1 = victim->getRegistryEntryID();
-			IOServiceTrace(
-				IOSERVICE_TERM_START_PHASE2,
-				(uintptr_t) regID1,
-				(uintptr_t) (regID1 >> 32),
-				(uintptr_t) 0,
-				(uintptr_t) 0);
-
-			while (victim) {
-				doPhase2 = victim->lockForArbitration( true );
-				if (doPhase2) {
-					doPhase2 = (0 != (kIOServiceInactiveState & victim->__state[0]));
-					if (doPhase2) {
-						victim->__state[1] |= kIOServiceTermPhase2ReadyState;
-
-						uint64_t regID1 = victim->getRegistryEntryID();
-						IOServiceTrace(
-							IOSERVICE_TERM_TRY_PHASE2,
-							(uintptr_t) regID1,
-							(uintptr_t) (regID1 >> 32),
-							(uintptr_t) victim->__state[1],
-							(uintptr_t) 0);
-
-						doPhase2 = (0 == (victim->__state[1] &
-						    (kIOServiceTermPhase1State
-						    | kIOServiceTermPhase2State
-						    | kIOServiceConfigState)));
-
-						if (doPhase2 && (iter = victim->getClientIterator())) {
-							while (doPhase2 && (client = (IOService *) iter->getNextObject())) {
-								doPhase2 = (0 == (client->__state[1] & kIOServiceStartState));
-								if (!doPhase2) {
-									uint64_t regID1 = client->getRegistryEntryID();
-									IOServiceTrace(
-										IOSERVICE_TERM_UC_DEFER,
-										(uintptr_t) regID1,
-										(uintptr_t) (regID1 >> 32),
-										(uintptr_t) client->__state[1],
-										(uintptr_t) 0);
-									TLOG("%s[0x%qx]::defer phase2(%s[0x%qx])\n",
-									    victim->getName(), victim->getRegistryEntryID(),
-									    client->getName(), client->getRegistryEntryID());
-								}
-							}
-							iter->release();
-						}
-						if (doPhase2) {
-							victim->__state[1] |= kIOServiceTermPhase2State;
-						}
-					}
-					victim->unlockForArbitration();
-				}
-				if (doPhase2) {
-					if (kIOServiceNeedWillTerminate & victim->__state[1]) {
-						if (NULL == victim->reserved->uvars) {
-							_workLoopAction((IOWorkLoop::Action) &actionWillStop,
-							    victim, (void *)(uintptr_t) options);
-						} else {
-							actionWillStop(victim, options, NULL, NULL, NULL);
-						}
-					}
-
-					OSArray * notifiers;
-					notifiers = victim->copyNotifiers(gIOWillTerminateNotification, 0, 0xffffffff);
-					victim->invokeNotifiers(&notifiers);
-
-					_workLoopAction((IOWorkLoop::Action) &actionWillTerminate,
-					    victim,
-					    (void *)(uintptr_t) options,
-					    (void *)(uintptr_t) doPhase2List,
-					    (void *)(uintptr_t) false);
-
-					actionWillTerminate(
-						victim, options, doPhase2List, true, NULL);
-
-					didPhase2List->headQ( victim );
-				}
-				victim->release();
-				victim = (IOService *) doPhase2List->getObject(0);
-				if (victim) {
-					victim->retain();
-					doPhase2List->removeObject(0);
-				}
-			}
-
-			while ((victim = (IOService *) didPhase2List->getObject(0))) {
-				bool scheduleFinalize = false;
-				if (victim->lockForArbitration( true )) {
-					victim->__state[1] |= kIOServiceTermPhase3State;
-					scheduleFinalize = (NULL == victim->getClient());
-					victim->unlockForArbitration();
-				}
-				_workLoopAction((IOWorkLoop::Action) &actionDidTerminate,
-				    victim, (void *)(uintptr_t) options );
-				if (kIOServiceNeedWillTerminate & victim->__state[1]) {
-					_workLoopAction((IOWorkLoop::Action) &actionDidStop,
-					    victim, (void *)(uintptr_t) options, NULL );
-				}
-				// no clients - will go to finalize
-				if (scheduleFinalize) {
-					victim->scheduleFinalize(false);
-				}
-				didPhase2List->removeObject(0);
-			}
-			IOLockLock( gJobsLock );
-		}
-
-		// phase 3
-		do {
-			doPhase3 = false;
-			// finalize leaves
-			while ((victim = (IOService *) gIOFinalizeList->getObject(0))) {
-				bool sendFinal = false;
-				IOLockUnlock( gJobsLock );
-				if (victim->lockForArbitration(true)) {
-					sendFinal = (0 == (victim->__state[1] & kIOServiceFinalized));
-					if (sendFinal) {
-						victim->__state[1] |= kIOServiceFinalized;
-					}
-					victim->unlockForArbitration();
-				}
-				if (sendFinal) {
-					_workLoopAction((IOWorkLoop::Action) &actionFinalize,
-					    victim, (void *)(uintptr_t) options );
-				}
-				IOLockLock( gJobsLock );
-				// hold off free
-				freeList->setObject( victim );
-				// safe if finalize list is append only
-				gIOFinalizeList->removeObject(0);
-			}
-
-			for (idx = 0;
-			    (!doPhase3) && (client = (IOService *) gIOStopList->getObject(idx));) {
-				provider = (IOService *) gIOStopProviderList->getObject(idx);
-				assert( provider );
-
-				uint64_t regID1 = provider->getRegistryEntryID();
-				uint64_t regID2 = client->getRegistryEntryID();
-
-				if (!provider->isChild( client, gIOServicePlane )) {
-					// may be multiply queued - nop it
-					TLOG("%s[0x%qx]::nop stop(%s[0x%qx])\n", client->getName(), regID2, provider->getName(), regID1);
-					IOServiceTrace(
-						IOSERVICE_TERMINATE_STOP_NOP,
-						(uintptr_t) regID1,
-						(uintptr_t) (regID1 >> 32),
-						(uintptr_t) regID2,
-						(uintptr_t) (regID2 >> 32));
-				} else {
-					// a terminated client is not ready for stop if it has clients, skip it
-					bool deferStop = (0 != (kIOServiceInactiveState & client->__state[0]));
-					IOLockUnlock( gJobsLock );
-					if (deferStop && client->lockForArbitration(true)) {
-						deferStop = (0 == (client->__state[1] & kIOServiceFinalized));
-						//deferStop = (!deferStop && (0 != client->getClient()));
-						//deferStop = (0 != client->getClient());
-						client->unlockForArbitration();
-						if (deferStop) {
-							TLOG("%s[0x%qx]::defer stop()\n", client->getName(), regID2);
-							IOServiceTrace(IOSERVICE_TERMINATE_STOP_DEFER,
-							    (uintptr_t) regID1,
-							    (uintptr_t) (regID1 >> 32),
-							    (uintptr_t) regID2,
-							    (uintptr_t) (regID2 >> 32));
-
-							idx++;
-							IOLockLock( gJobsLock );
-							continue;
-						}
-					}
-					_workLoopAction((IOWorkLoop::Action) &actionStop,
-					    provider, (void *) client );
-					IOLockLock( gJobsLock );
-					// check the finalize list now
-					doPhase3 = true;
-				}
-				// hold off free
-				freeList->setObject( client );
-				freeList->setObject( provider );
-
-				// safe if stop list is append only
-				gIOStopList->removeObject( idx );
-				gIOStopProviderList->removeObject( idx );
-				idx = 0;
-			}
-		} while (doPhase3);
-
-		gIOTerminateWork -= workDone;
-		moreToDo = (gIOTerminateWork != 0);
-
-		if (!moreToDo) {
-			TLOG("iokit terminate done, %d stops remain\n", gIOStopList->getCount());
-			IOServiceTrace(
-				IOSERVICE_TERMINATE_DONE,
-				(uintptr_t) gIOStopList->getCount(), 0, 0, 0);
-		}
-	} while (moreToDo);
-
-	IOLockUnlock( gJobsLock );
-
-	freeList->release();
-	doPhase2List->release();
-	didPhase2List->release();
-
-	IOLockLock( gJobsLock );
-}
-
-#pragma clang diagnostic pop
-
-bool
-IOService::finalize( IOOptionBits options )
-{
-	OSIterator *  iter;
-	IOService *   provider;
-	uint64_t      regID1, regID2 = getRegistryEntryID();
-
-	iter = getProviderIterator();
-	assert( iter );
-
-	if (iter) {
-		while ((provider = (IOService *) iter->getNextObject())) {
-			// -- compat
-			if (0 == (__state[1] & kIOServiceTermPhase3State)) {
-				/* we come down here on programmatic terminate */
-
-				regID1 = provider->getRegistryEntryID();
-				TLOG("%s[0x%qx]::stop1(%s[0x%qx])\n", getName(), regID2, provider->getName(), regID1);
-				IOServiceTrace(
-					IOSERVICE_TERMINATE_STOP,
-					(uintptr_t) regID1,
-					(uintptr_t) (regID1 >> 32),
-					(uintptr_t) regID2,
-					(uintptr_t) (regID2 >> 32));
-
-				stop( provider );
-				if (provider->isOpen( this )) {
-					provider->close( this );
-				}
-				detach( provider );
-			} else {
-				//--
-				if (provider->lockForArbitration( true )) {
-					if (0 == (provider->__state[1] & kIOServiceTermPhase3State)) {
-						scheduleStop( provider );
-					}
-					provider->unlockForArbitration();
-				}
-			}
-		}
-		iter->release();
-	}
-
-	return true;
-}
-
-#undef tailQ
-#undef headQ
+#define tailQ(o)		setObject(o)
+#define headQ(o)		setObject(0, o)
+#define TLOG(fmt, args...)  	{ if(kIOLogYield & gIOKitDebug) IOLog(fmt, ## args); }
+
+inline void _workLoopAction( IOWorkLoop::Action action,
+                             IOService * service,
+                             void * p0 = 0, void * p1 = 0,
+                             void * p2 = 0, void * p3 = 0 )
+{
+    IOWorkLoop * wl;
+
+    if( (wl = service->getWorkLoop())) {
+        wl->retain();
+        wl->runAction( action, service, p0, p1, p2, p3 );
+        wl->release();
+    } else
+        (*action)( service, p0, p1, p2, p3 );
+}
+
+bool IOService::requestTerminate( IOService * provider, IOOptionBits options )
+{
+    bool ok;
+
+    // if its our only provider
+    ok = isParent( provider, gIOServicePlane, true);
+
+    // -- compat
+    if( ok) {
+        provider->terminateClient( this, options | kIOServiceRecursing );
+        ok = (0 != (__state[1] & kIOServiceRecursing));
+    }
+    // --
+
+    return( ok );
+}
+
+bool IOService::terminatePhase1( IOOptionBits options = 0 )
+{
+    IOService *		victim;
+    IOService *		client;
+    OSIterator *	iter;
+    OSArray *		makeInactive;
+    bool		ok;
+    bool		didInactive;
+    bool		startPhase2 = false;
+
+    TLOG("%s::terminatePhase1(%08lx)\n", getName(), options);
+
+    // -- compat
+    if( options & kIOServiceRecursing) {
+        __state[1] |= kIOServiceRecursing;
+        return( true );
+    }
+    // -- 
+
+    makeInactive = OSArray::withCapacity( 16 );
+    if( !makeInactive)
+        return( false );
+
+    victim = this;
+    victim->retain();
+
+    while( victim ) {
+
+        didInactive = victim->lockForArbitration( true );
+        if( didInactive) {
+            didInactive = (0 == (victim->__state[0] & kIOServiceInactiveState));
+            if( didInactive) {
+                victim->__state[0] |= kIOServiceInactiveState;
+                victim->__state[0] &= ~(kIOServiceRegisteredState | kIOServiceMatchedState
+                                        | kIOServiceFirstPublishState | kIOServiceFirstMatchState);
+                victim->_adjustBusy( 1 );
+            }
+            victim->unlockForArbitration();
+        }
+        if( victim == this)
+            startPhase2 = didInactive;
+        if( didInactive) {
+
+            victim->deliverNotification( gIOTerminatedNotification, 0, 0xffffffff );
+            IOUserClient::destroyUserReferences( victim );
+            victim->unregisterAllInterest();
+
+            iter = victim->getClientIterator();
+            if( iter) {
+                while( (client = (IOService *) iter->getNextObject())) {
+                    TLOG("%s::requestTerminate(%s, %08lx)\n",
+                            client->getName(), victim->getName(), options);
+                    ok = client->requestTerminate( victim, options );
+                    TLOG("%s::requestTerminate(%s, ok = %d)\n",
+                            client->getName(), victim->getName(), ok);
+                    if( ok)
+                        makeInactive->setObject( client );
+                }
+                iter->release();
+            }
+        }
+        victim->release();
+        victim = (IOService *) makeInactive->getObject(0);
+        if( victim) {
+            victim->retain();
+            makeInactive->removeObject(0);
+        }
+    }
+
+    makeInactive->release();
+
+    if( startPhase2)
+        scheduleTerminatePhase2( options );
+
+    return( true );
+}
+
+void IOService::scheduleTerminatePhase2( IOOptionBits options = 0 )
+{
+    AbsoluteTime	deadline;
+    int			waitResult;
+    bool		wait, haveDeadline = false;
+
+    options |= kIOServiceRequired;
+
+    retain();
+
+    IOLockLock( gJobsLock );
+
+    if( (options & kIOServiceSynchronous)
+        && (current_thread() != gIOTerminateThread)) {
+
+        do {
+            wait = (gIOTerminateThread != 0);
+            if( wait) {
+                // wait to become the terminate thread
+                assert_wait( (event_t) &gIOTerminateThread, THREAD_UNINT );
+                IOLockUnlock( gJobsLock );
+                thread_block((void (*)(void)) 0);
+                IOLockLock( gJobsLock );
+            }
+        } while( wait );
+
+        gIOTerminateThread = current_thread();
+        gIOTerminatePhase2List->setObject( this );
+        gIOTerminateWork++;
+
+        do {
+            terminateWorker( options );
+            wait = (0 != (__state[1] & kIOServiceBusyStateMask));
+            if( wait) {
+                // wait for the victim to go non-busy
+                assert_wait( (event_t) &gIOTerminateWork, THREAD_UNINT );
+                if( !haveDeadline) {
+                    clock_interval_to_deadline( 15, kSecondScale, &deadline );
+                    haveDeadline = true;
+                }
+                thread_set_timer_deadline( deadline );
+                IOLockUnlock( gJobsLock );
+                waitResult = thread_block((void (*)(void)) 0);
+                if( waitResult == THREAD_TIMED_OUT) {
+                    TLOG("%s::terminate(kIOServiceSynchronous) timeout", getName());
+                } else
+                    thread_cancel_timer();
+                IOLockLock( gJobsLock );
+            }
+        } while( wait && (waitResult != THREAD_TIMED_OUT));
+
+        gIOTerminateThread = 0;
+        thread_wakeup( (event_t) &gIOTerminateThread );
+
+    } else {
+        // ! kIOServiceSynchronous
+
+        gIOTerminatePhase2List->setObject( this );
+        if( 0 == gIOTerminateWork++)
+            gIOTerminateThread = IOCreateThread( &terminateThread, (void *) options );
+    }
+
+    IOLockUnlock( gJobsLock );
+
+    release();
+}
+
+void IOService::terminateThread( void * arg )
+{
+    IOLockLock( gJobsLock );
+
+    terminateWorker( (IOOptionBits) arg );
+
+    gIOTerminateThread = 0;
+    thread_wakeup( (event_t) &gIOTerminateThread );
+
+    IOLockUnlock( gJobsLock );
+}
+
+void IOService::scheduleStop( IOService * provider )
+{
+    TLOG("%s::scheduleStop(%s)\n", getName(), provider->getName());
+
+    IOLockLock( gJobsLock );
+    gIOStopList->tailQ( this );
+    gIOStopProviderList->tailQ( provider );
+
+    if( 0 == gIOTerminateWork++) {
+        if( !gIOTerminateThread)
+            gIOTerminateThread = IOCreateThread( &terminateThread, (void *) 0 );
+        else
+            thread_wakeup( (event_t) &gIOTerminateWork );
+    }
+
+    IOLockUnlock( gJobsLock );
+}
+
+void IOService::scheduleFinalize( void )
+{
+    TLOG("%s::scheduleFinalize\n", getName());
+
+    IOLockLock( gJobsLock );
+    gIOFinalizeList->tailQ( this );
+
+    if( 0 == gIOTerminateWork++) {
+        if( !gIOTerminateThread)
+            gIOTerminateThread = IOCreateThread( &terminateThread, (void *) 0 );
+        else
+            thread_wakeup( (event_t) &gIOTerminateWork );
+    }
+
+    IOLockUnlock( gJobsLock );
+}
+
+bool IOService::willTerminate( IOService * provider, IOOptionBits options )
+{
+    return( true );
+}
+
+bool IOService::didTerminate( IOService * provider, IOOptionBits options, bool * defer )
+{
+    if( false == *defer) {
+
+        if( lockForArbitration( true )) {
+            if( false == provider->handleIsOpen( this ))
+                scheduleStop( provider );
+            // -- compat
+            else {
+                message( kIOMessageServiceIsRequestingClose, provider, (void *) options );
+                if( false == provider->handleIsOpen( this ))
+                    scheduleStop( provider );
+            }
+            // --
+            unlockForArbitration();
+        }
+    }
+
+    return( true );
+}
+
+void IOService::actionWillTerminate( IOService * victim, IOOptionBits options, 
+                                    OSArray * doPhase2List )
+{
+    OSIterator * iter;
+    IOService *	 client;
+    bool	 ok;
+
+    iter = victim->getClientIterator();
+    if( iter) {
+        while( (client = (IOService *) iter->getNextObject())) {
+            TLOG("%s::willTerminate(%s, %08lx)\n",
+                    client->getName(), victim->getName(), options);
+            ok = client->willTerminate( victim, options );
+            doPhase2List->tailQ( client );
+        }
+        iter->release();
+    }
+}
+
+void IOService::actionDidTerminate( IOService * victim, IOOptionBits options )
+{
+    OSIterator * iter;
+    IOService *	 client;
+    bool defer = false;
+
+    victim->messageClients( kIOMessageServiceIsTerminated, (void *) options );
+
+    iter = victim->getClientIterator();
+    if( iter) {
+        while( (client = (IOService *) iter->getNextObject())) {
+            TLOG("%s::didTerminate(%s, %08lx)\n",
+                    client->getName(), victim->getName(), options);
+            client->didTerminate( victim, options, &defer );
+            TLOG("%s::didTerminate(%s, defer %d)\n",
+                    client->getName(), victim->getName(), defer);
+        }
+        iter->release();
+    }
+}
+
+void IOService::actionFinalize( IOService * victim, IOOptionBits options )
+{
+    TLOG("%s::finalize(%08lx)\n", victim->getName(), options);
+    victim->finalize( options );
+}
+
+void IOService::actionStop( IOService * provider, IOService * client )
+{
+    TLOG("%s::stop(%s)\n", client->getName(), provider->getName());
+    client->stop( provider );
+    if( provider->isOpen( client ))
+        provider->close( client );
+    TLOG("%s::detach(%s)\n", client->getName(), provider->getName());
+    client->detach( provider );
+}
+
+void IOService::terminateWorker( IOOptionBits options )
+{
+    OSArray *		doPhase2List;
+    OSArray *		didPhase2List;
+    OSSet *		freeList;
+    UInt32		workDone;
+    IOService * 	victim;
+    IOService * 	client;
+    IOService * 	provider;
+    unsigned int	idx;
+    bool		moreToDo;
+    bool		doPhase2;
+    bool		doPhase3;
+
+    options |= kIOServiceRequired;
+
+    doPhase2List  = OSArray::withCapacity( 16 );
+    didPhase2List = OSArray::withCapacity( 16 );
+    freeList	  = OSSet::withCapacity( 16 );
+    if( (0 == doPhase2List) || (0 == didPhase2List) || (0 == freeList))
+        return;
+
+    do {
+        workDone = gIOTerminateWork;
+
+        while( (victim = (IOService *) gIOTerminatePhase2List->getObject(0) )) {
+    
+            victim->retain();
+            gIOTerminatePhase2List->removeObject(0);
+            IOLockUnlock( gJobsLock );
+
+            while( victim ) {
+        
+                doPhase2 = victim->lockForArbitration( true );
+                if( doPhase2) {
+                    doPhase2 = (0 != (kIOServiceInactiveState & victim->__state[0]));
+                    if( doPhase2) {
+                        doPhase2 = (0 == (victim->__state[1] & kIOServiceTermPhase2State))
+                                && (0 == (victim->__state[1] & kIOServiceConfigState));
+                        if( doPhase2)
+                            victim->__state[1] |= kIOServiceTermPhase2State;
+                    }
+                    victim->unlockForArbitration();
+                }
+                if( doPhase2) {
+                    if( 0 == victim->getClient()) {
+                        // no clients - will go to finalize
+                        IOLockLock( gJobsLock );
+                        gIOFinalizeList->tailQ( victim );
+                        IOLockUnlock( gJobsLock );
+                    } else {
+                        _workLoopAction( (IOWorkLoop::Action) &actionWillTerminate,
+                                            victim, (void *) options, (void *) doPhase2List );
+                    }
+                    didPhase2List->headQ( victim );
+                }
+                victim->release();
+                victim = (IOService *) doPhase2List->getObject(0);
+                if( victim) {
+                    victim->retain();
+                    doPhase2List->removeObject(0);
+                }
+            }
+        
+            while( (victim = (IOService *) didPhase2List->getObject(0)) ) {
+    
+                if( victim->lockForArbitration( true )) {
+                    victim->__state[1] |= kIOServiceTermPhase3State;
+                    victim->unlockForArbitration();
+                }
+                _workLoopAction( (IOWorkLoop::Action) &actionDidTerminate,
+                                    victim, (void *) options );
+                didPhase2List->removeObject(0);
+            }
+            IOLockLock( gJobsLock );
+        }
+
+        // phase 3
+        do {
+            doPhase3 = false;
+            // finalize leaves
+            while( (victim = (IOService *) gIOFinalizeList->getObject(0))) {
+    
+                IOLockUnlock( gJobsLock );
+                _workLoopAction( (IOWorkLoop::Action) &actionFinalize,
+                                    victim, (void *) options );
+                IOLockLock( gJobsLock );
+                // hold off free
+                freeList->setObject( victim );
+                // safe if finalize list is append only
+                gIOFinalizeList->removeObject(0);
+            }
+        
+            for( idx = 0;
+                 (!doPhase3) && (client = (IOService *) gIOStopList->getObject(idx)); ) {
+        
+                provider = (IOService *) gIOStopProviderList->getObject(idx);
+                assert( provider );
+        
+                if( !provider->isChild( client, gIOServicePlane )) {
+                    // may be multiply queued - nop it
+                    TLOG("%s::nop stop(%s)\n", client->getName(), provider->getName());
+                } else {
+                    // not ready for stop if it has clients, skip it
+                    if( (client->__state[1] & kIOServiceTermPhase3State) && client->getClient()) {
+                        TLOG("%s::defer stop(%s)\n", client->getName(), provider->getName());
+                        idx++;
+                        continue;
+                    }
+        
+                    IOLockUnlock( gJobsLock );
+                    _workLoopAction( (IOWorkLoop::Action) &actionStop,
+                                     provider, (void *) client );
+                    IOLockLock( gJobsLock );
+                    // check the finalize list now
+                    doPhase3 = true;
+                }
+                // hold off free
+                freeList->setObject( client );
+                freeList->setObject( provider );
+
+                // safe if stop list is append only
+                gIOStopList->removeObject( idx );
+                gIOStopProviderList->removeObject( idx );
+                idx = 0;
+            }
+
+        } while( doPhase3 );
+
+        gIOTerminateWork -= workDone;
+        moreToDo = (gIOTerminateWork != 0);
+
+        if( !moreToDo) {
+            TLOG("iokit terminate done, %d stops remain\n", gIOStopList->getCount());
+        }
+
+    } while( moreToDo );
+
+    IOLockUnlock( gJobsLock );
+
+    freeList->release();
+    doPhase2List->release();
+    didPhase2List->release();
+
+    IOLockLock( gJobsLock );
+}
+
+bool IOService::finalize( IOOptionBits options )
+{
+    OSIterator *	iter;
+    IOService *		provider;
+
+    iter = getProviderIterator();
+    assert( iter );
+
+    if( iter) {
+        while( (provider = (IOService *) iter->getNextObject())) {
+
+            // -- compat
+            if( 0 == (__state[1] & kIOServiceTermPhase3State)) {
+                /* we come down here on programmatic terminate */
+                stop( provider );
+                if( provider->isOpen( this ))
+                    provider->close( this );
+                detach( provider );
+            } else {
+            //--
+                if( provider->lockForArbitration( true )) {
+                    if( 0 == (provider->__state[1] & kIOServiceTermPhase3State))
+                        scheduleStop( provider );
+                    provider->unlockForArbitration();
+                }
+            }
+        }
+        iter->release();
+    }
+
+    return( true );
+}
+
+#undef tailQ(o)
+#undef headQ(o)
 
 /*
  * Terminate
  */
 
-void
-IOService::doServiceTerminate( IOOptionBits options )
+void IOService::doServiceTerminate( IOOptionBits options )
 {
 }
 
 // a method in case someone needs to override it
-bool
-IOService::terminateClient( IOService * client, IOOptionBits options )
-{
-	bool ok;
-
-	if (client->isParent( this, gIOServicePlane, true)) {
-		// we are the clients only provider
-		ok = client->terminate( options );
-	} else {
-		ok = true;
-	}
-
-	return ok;
-}
-
-bool
-IOService::terminate( IOOptionBits options )
-{
-	options |= kIOServiceTerminate;
-
-	return terminatePhase1( options );
+bool IOService::terminateClient( IOService * client, IOOptionBits options )
+{
+    bool ok;
+
+    if( client->isParent( this, gIOServicePlane, true))
+        // we are the clients only provider
+        ok = client->terminate( options );
+    else
+	ok = true;
+
+    return( ok );
+}
+
+bool IOService::terminate( IOOptionBits options = 0 )
+{
+    options |= kIOServiceTerminate;
+
+    return( terminatePhase1( options ));
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -3501,3668 +1994,1456 @@
  * Open & close
  */
 
-struct ServiceOpenMessageContext {
-	IOService *  service;
-	UInt32       type;
-	IOService *  excludeClient;
-	IOOptionBits options;
+struct ServiceOpenMessageContext
+{
+    IOService *	 service;
+    UInt32	 type;
+    IOService *  excludeClient;
+    IOOptionBits options;
 };
 
-static void
-serviceOpenMessageApplier( OSObject * object, void * ctx )
-{
-	ServiceOpenMessageContext * context = (ServiceOpenMessageContext *) ctx;
-
-	if (object != context->excludeClient) {
-		context->service->messageClient( context->type, object, (void *)(uintptr_t) context->options );
-	}
-}
-
-bool
-IOService::open(   IOService *     forClient,
-    IOOptionBits    options,
-    void *          arg )
-{
-	bool                        ok;
-	kern_return_t               ret = kIOReturnSuccess;
-	ServiceOpenMessageContext   context;
-
-	context.service             = this;
-	context.type                = kIOMessageServiceIsAttemptingOpen;
-	context.excludeClient       = forClient;
-	context.options             = options;
-
-	applyToInterested( gIOGeneralInterest,
-	    &serviceOpenMessageApplier, &context );
-
-	if (false == lockForArbitration(false)) {
-		return false;
-	}
-
-	ok = (0 == (__state[0] & kIOServiceInactiveState));
-
-	if (ok && forClient && forClient->reserved->uvars && forClient->reserved->uvars->userServer) {
-		ret = forClient->reserved->uvars->userServer->serviceOpen(this, forClient);
-		if (ret != kIOReturnSuccess) {
-			ok = false;
-		}
-	}
-
-	if (ok) {
-		ok = handleOpen( forClient, options, arg );
-
-		if (!ok && forClient && forClient->reserved->uvars && forClient->reserved->uvars->userServer) {
-			forClient->reserved->uvars->userServer->serviceClose(this, forClient);
-		}
-	}
-
-	unlockForArbitration();
-
-	return ok;
-}
-
-void
-IOService::close(  IOService *     forClient,
-    IOOptionBits    options )
-{
-	bool                wasClosed;
-	bool                last = false;
-
-	lockForArbitration();
-
-	wasClosed = handleIsOpen( forClient );
-	if (wasClosed) {
-		handleClose( forClient, options );
-		last = (__state[1] & kIOServiceTermPhase3State);
-
-		if (forClient && forClient->reserved->uvars && forClient->reserved->uvars->userServer) {
-			forClient->reserved->uvars->userServer->serviceClose(this, forClient);
-		}
-	}
-
-	unlockForArbitration();
-
-	if (last) {
-		forClient->scheduleStop( this );
-	} else if (wasClosed) {
-		ServiceOpenMessageContext context;
-
-		context.service         = this;
-		context.type            = kIOMessageServiceWasClosed;
-		context.excludeClient   = forClient;
-		context.options         = options;
-
-		applyToInterested( gIOGeneralInterest,
-		    &serviceOpenMessageApplier, &context );
-	}
-}
-
-bool
-IOService::isOpen( const IOService * forClient ) const
-{
-	IOService * self = (IOService *) this;
-	bool ok;
-
-	self->lockForArbitration();
-
-	ok = handleIsOpen( forClient );
-
-	self->unlockForArbitration();
-
-	return ok;
-}
-
-bool
-IOService::handleOpen(     IOService *     forClient,
-    IOOptionBits    options,
-    void *          arg )
-{
-	bool        ok;
-
-	ok = (NULL == __owner);
-	if (ok) {
-		__owner = forClient;
-	} else if (options & kIOServiceSeize) {
-		ok = (kIOReturnSuccess == messageClient( kIOMessageServiceIsRequestingClose,
-		    __owner, (void *)(uintptr_t) options ));
-		if (ok && (NULL == __owner)) {
-			__owner = forClient;
-		} else {
-			ok = false;
-		}
-	}
-	return ok;
-}
-
-void
-IOService::handleClose(    IOService *     forClient,
-    IOOptionBits    options )
-{
-	if (__owner == forClient) {
-		__owner = NULL;
-	}
-}
-
-bool
-IOService::handleIsOpen(   const IOService * forClient ) const
-{
-	if (forClient) {
-		return __owner == forClient;
-	} else {
-		return __owner != forClient;
-	}
+static void serviceOpenMessageApplier( OSObject * object, void * ctx )
+{
+    ServiceOpenMessageContext * context = (ServiceOpenMessageContext *) ctx;
+
+    if( object != context->excludeClient)
+        context->service->messageClient( context->type, object, (void *) context->options );    
+}
+
+bool IOService::open( 	IOService *	forClient,
+                        IOOptionBits	options = 0,
+                        void *		arg = 0 )
+{
+    bool			ok;
+    ServiceOpenMessageContext	context;
+
+    context.service		= this;
+    context.type		= kIOMessageServiceIsAttemptingOpen;
+    context.excludeClient	= forClient;
+    context.options		= options;
+
+    applyToInterested( gIOGeneralInterest,
+                        &serviceOpenMessageApplier, &context );
+
+    if( false == lockForArbitration(false) )
+        return false;
+
+    ok = (0 == (__state[0] & kIOServiceInactiveState));
+    if( ok)
+        ok = handleOpen( forClient, options, arg );
+
+    unlockForArbitration();
+
+    return( ok );
+}
+
+void IOService::close( 	IOService *	forClient,
+                        IOOptionBits	options = 0 )
+{
+    bool		wasClosed;
+    bool		last = false;
+
+    lockForArbitration();
+
+    wasClosed = handleIsOpen( forClient );
+    if( wasClosed) {
+        handleClose( forClient, options );
+	last = (__state[1] & kIOServiceTermPhase3State);
+    }
+
+    unlockForArbitration();
+
+    if( last)
+        forClient->scheduleStop( this );
+
+    else if( wasClosed) {
+
+        ServiceOpenMessageContext context;
+    
+        context.service		= this;
+        context.type		= kIOMessageServiceWasClosed;
+        context.excludeClient	= forClient;
+        context.options		= options;
+
+        applyToInterested( gIOGeneralInterest,
+                            &serviceOpenMessageApplier, &context );
+    }
+}
+
+bool IOService::isOpen( const IOService * forClient = 0 ) const
+{
+    IOService *	self = (IOService *) this;
+    bool ok;
+
+    self->lockForArbitration();
+
+    ok = handleIsOpen( forClient );
+
+    self->unlockForArbitration();
+
+    return( ok );
+}
+
+bool IOService::handleOpen( 	IOService *	forClient,
+                                IOOptionBits	options,
+                                void *		arg )
+{
+    bool	ok;
+
+    ok = (0 == __owner);
+    if( ok )
+        __owner = forClient;
+
+    else if( options & kIOServiceSeize ) {
+        ok = (kIOReturnSuccess == messageClient( kIOMessageServiceIsRequestingClose,
+                                __owner, (void *) options ));
+        if( ok && (0 == __owner ))
+            __owner = forClient;
+        else
+            ok = false;
+    }
+    return( ok );
+}
+
+void IOService::handleClose( 	IOService *	forClient,
+                                IOOptionBits	options )
+{
+    if( __owner == forClient)
+        __owner = 0;
+}
+
+bool IOService::handleIsOpen( 	const IOService * forClient ) const
+{
+    if( forClient)
+	return( __owner == forClient );
+    else
+	return( __owner != forClient );
 }
 
 /*
  * Probing & starting
  */
-static SInt32
-IONotifyOrdering( const OSMetaClassBase * inObj1, const OSMetaClassBase * inObj2, void * ref )
-{
-	const _IOServiceNotifier * obj1 = (const _IOServiceNotifier *) inObj1;
-	const _IOServiceNotifier * obj2 = (const _IOServiceNotifier *) inObj2;
-	SInt32             val1;
-	SInt32             val2;
-
-	val1 = 0;
-	val2 = 0;
-	if (obj1) {
-		val1 = obj1->priority;
+static SInt32 IONotifyOrdering( const OSMetaClassBase * inObj1, const OSMetaClassBase * inObj2, void * ref )
+{
+    const _IOServiceNotifier * obj1 = (const _IOServiceNotifier *) inObj1;
+    const _IOServiceNotifier * obj2 = (const _IOServiceNotifier *) inObj2;
+    SInt32             val1;
+    SInt32             val2;
+
+    val1 = 0;
+    val2 = 0;
+
+    if ( obj1 )
+        val1 = obj1->priority;
+
+    if ( obj2 )
+        val2 = obj2->priority;
+
+    return ( val1 - val2 );
+}
+
+static SInt32 IOServiceObjectOrder( const OSObject * entry, void * ref)
+{
+    OSDictionary *	dict;
+    IOService *		service;
+    _IOServiceNotifier * notify;
+    OSSymbol *		key = (OSSymbol *) ref;
+    OSNumber *		offset;
+
+    if( (notify = OSDynamicCast( _IOServiceNotifier, entry)))
+	return( notify->priority );
+
+    else if( (service = OSDynamicCast( IOService, entry)))
+        offset = OSDynamicCast(OSNumber, service->getProperty( key ));
+    else if( (dict = OSDynamicCast( OSDictionary, entry)))
+        offset = OSDynamicCast(OSNumber, dict->getObject( key ));
+    else {
+	assert( false );
+	offset = 0;
+    }
+
+    if( offset)
+        return( (SInt32) offset->unsigned32BitValue());
+    else
+        return( kIODefaultProbeScore );
+}
+
+SInt32 IOServiceOrdering( const OSMetaClassBase * inObj1, const OSMetaClassBase * inObj2, void * ref )
+{
+    const OSObject *	obj1 = (const OSObject *) inObj1;
+    const OSObject *	obj2 = (const OSObject *) inObj2;
+    SInt32               val1;
+    SInt32               val2;
+
+    val1 = 0;
+    val2 = 0;
+
+    if ( obj1 )
+        val1 = IOServiceObjectOrder( obj1, ref );
+
+    if ( obj2 )
+        val2 = IOServiceObjectOrder( obj2, ref );
+
+    return ( val1 - val2 );
+}
+
+IOService * IOService::getClientWithCategory( const OSSymbol * category )
+{
+    IOService *		service = 0;
+    OSIterator *	iter;
+    const OSSymbol *	nextCat;
+
+    iter = getClientIterator();
+    if( iter) {
+	while( (service = (IOService *) iter->getNextObject())) {
+	    if( kIOServiceInactiveState & service->__state[0])
+		continue;
+            nextCat = (const OSSymbol *) OSDynamicCast( OSSymbol,
+			service->getProperty( gIOMatchCategoryKey ));
+	    if( category == nextCat)
+		break;
 	}
-	if (obj2) {
-		val2 = obj2->priority;
-	}
-	if (val1 > val2) {
-		return 1;
-	}
-	if (val1 < val2) {
-		return -1;
-	}
-	return 0;
-}
-
-static SInt32
-IOServiceObjectOrder( const OSObject * entry, void * ref)
-{
-	OSDictionary *      dict;
-	IOService *         service;
-	_IOServiceNotifier * notify;
-	OSSymbol *          key = (OSSymbol *) ref;
-	OSNumber *          offset;
-	OSObject *          prop;
-	SInt32              result;
-
-	prop = NULL;
-	result = kIODefaultProbeScore;
-	if ((dict = OSDynamicCast( OSDictionary, entry))) {
-		offset = OSDynamicCast(OSNumber, dict->getObject( key ));
-	} else if ((notify = OSDynamicCast( _IOServiceNotifier, entry))) {
-		return notify->priority;
-	} else if ((service = OSDynamicCast( IOService, entry))) {
-		prop = service->copyProperty(key);
-		offset = OSDynamicCast(OSNumber, prop);
-	} else {
-		assert( false );
-		offset = NULL;
-	}
-
-	if (offset) {
-		result = offset->unsigned32BitValue();
-	}
-
-	OSSafeReleaseNULL(prop);
-
-	return result;
-}
-
-__attribute__((no_sanitize("signed-integer-overflow"))) SInt32
-IOServiceOrdering( const OSMetaClassBase * inObj1, const OSMetaClassBase * inObj2, void * ref )
-{
-	const OSObject *    obj1 = (const OSObject *) inObj1;
-	const OSObject *    obj2 = (const OSObject *) inObj2;
-	SInt32               val1;
-	SInt32               val2;
-
-	val1 = 0;
-	val2 = 0;
-
-	if (obj1) {
-		val1 = IOServiceObjectOrder( obj1, ref );
-	}
-
-	if (obj2) {
-		val2 = IOServiceObjectOrder( obj2, ref );
-	}
-
-	return val1 - val2;
-}
-
-IOService *
-IOService::copyClientWithCategory( const OSSymbol * category )
-{
-	IOService *         service = NULL;
-	OSIterator *        iter;
-	const OSSymbol *    nextCat;
-
-	iter = getClientIterator();
-	if (iter) {
-		while ((service = (IOService *) iter->getNextObject())) {
-			if (kIOServiceInactiveState & service->__state[0]) {
-				if (!(kIOServiceRematchOnDetach & service->__state[1])) {
-					continue;
-				}
-			}
-			nextCat = (const OSSymbol *) OSDynamicCast( OSSymbol,
-			    service->getProperty( gIOMatchCategoryKey ));
-			if (category == nextCat) {
-				service->retain();
-				break;
-			}
-		}
-		iter->release();
-	}
-	return service;
-}
-
-IOService *
-IOService::getClientWithCategory( const OSSymbol * category )
-{
-	IOService *
-	    service = copyClientWithCategory(category);
-	if (service) {
-		service->release();
-	}
-	return service;
-}
-
-bool
-IOService::invokeNotifier( _IOServiceNotifier * notify )
-{
-	_IOServiceNotifierInvocation invocation;
-	bool                         willNotify;
-	bool                         ret = true;
-	invocation.thread = current_thread();
-
-#if DEBUG_NOTIFIER_LOCKED
-	uint32_t count;
-	if ((count = isLockedForArbitration(0))) {
-		IOLog("[%s, 0x%x]\n", notify->type->getCStringNoCopy(), count);
-		panic("[%s, 0x%x]", notify->type->getCStringNoCopy(), count);
-	}
-#endif /* DEBUG_NOTIFIER_LOCKED */
-
-	LOCKWRITENOTIFY();
-	willNotify = (0 != (kIOServiceNotifyEnable & notify->state));
-
-	if (willNotify) {
-		queue_enter( &notify->handlerInvocations, &invocation,
-		    _IOServiceNotifierInvocation *, link );
-	}
-	UNLOCKNOTIFY();
-
-	if (willNotify) {
-		ret = (*notify->handler)(notify->target, notify->ref, this, notify);
-
-		LOCKWRITENOTIFY();
-		queue_remove( &notify->handlerInvocations, &invocation,
-		    _IOServiceNotifierInvocation *, link );
-		if (kIOServiceNotifyWaiter & notify->state) {
-			notify->state &= ~kIOServiceNotifyWaiter;
-			WAKEUPNOTIFY( notify );
-		}
-		UNLOCKNOTIFY();
-	}
-
-	return ret;
-}
-
-bool
-IOService::invokeNotifiers(OSArray * willSend[])
-{
-	OSArray *            array;
-	_IOServiceNotifier * notify;
-	bool                 ret = true;
-
-	array = *willSend;
-	if (!array) {
-		return true;
-	}
-	*willSend = NULL;
-
-	for (unsigned int idx = 0;
-	    (notify = (_IOServiceNotifier *) array->getObject(idx));
-	    idx++) {
-		ret &= invokeNotifier(notify);
-	}
-	array->release();
-
-	return ret;
-}
-
-
-TUNABLE(bool, iokit_print_verbose_match_logs, "iokit_print_verbose_match_logs", false);
+	iter->release();
+    }
+    return( service );
+}
+
+bool IOService::invokeNotifer( _IOServiceNotifier * notify )
+{
+    _IOServiceNotifierInvocation invocation;
+    bool			 willNotify;
+    bool			 ret = true;
+
+    invocation.thread = current_thread();
+
+    LOCKWRITENOTIFY();
+    willNotify = (0 != (kIOServiceNotifyEnable & notify->state));
+
+    if( willNotify) {
+        queue_enter( &notify->handlerInvocations, &invocation,
+                        _IOServiceNotifierInvocation *, link );
+    }
+    UNLOCKNOTIFY();
+
+    if( willNotify) {
+
+        ret = (*notify->handler)( notify->target, notify->ref, this );
+
+        LOCKWRITENOTIFY();
+        queue_remove( &notify->handlerInvocations, &invocation,
+                        _IOServiceNotifierInvocation *, link );
+        if( kIOServiceNotifyWaiter & notify->state) {
+            notify->state &= ~kIOServiceNotifyWaiter;
+            thread_wakeup( (event_t) notify);
+        }
+        UNLOCKNOTIFY();
+    }
+
+    return( ret );
+}
 
 /*
  * Alloc and probe matching classes,
  * called on the provider instance
  */
 
-void
-IOService::probeCandidates( OSOrderedSet * matches )
-{
-	OSDictionary        *       match = NULL;
-	OSSymbol            *       symbol;
-	IOService           *       inst;
-	IOService           *       newInst;
-	OSDictionary        *       props;
-	SInt32                      score;
-	OSNumber            *       newPri;
-	OSOrderedSet        *       familyMatches = NULL;
-	OSOrderedSet        *       startList;
-	OSSet               *       kexts = NULL;
-	OSObject            *       kextRef;
-
-	OSDictionary        *       startDict = NULL;
-	const OSSymbol      *       category;
-	OSIterator          *       iter;
-	_IOServiceNotifier  *       notify;
-	OSObject            *       nextMatch = NULL;
-	bool                        started;
-	bool                        needReloc = false;
-	bool                        matchDeferred = false;
+void IOService::probeCandidates( OSOrderedSet * matches )
+{
+    OSDictionary 	*	match = 0;
+    OSSymbol 		*	symbol;
+    IOService 		*	inst;
+    IOService 		*	newInst;
+    OSDictionary 	*	props;
+    SInt32			score;
+    OSNumber 		*	newPri;
+    OSOrderedSet 	*	familyMatches = 0;
+    OSOrderedSet 	*	startList;
+    OSDictionary	*	startDict = 0;
+    const OSSymbol	* 	category;
+    OSIterator		*	iter;
+    _IOServiceNotifier 	*		notify;
+    OSObject 		*	nextMatch = 0;
+    bool			started;
+    bool			needReloc = false;
 #if IOMATCHDEBUG
-	SInt64                      debugFlags;
+    SInt64			debugFlags;
 #endif
-	IOService           *       client = NULL;
-	OSObject            *       prop1;
-	OSObject            *       rematchCountProp;
-	OSDictionary        *       rematchPersonality;
-	OSNumber            *       num;
-	uint32_t                    count;
-	uint32_t                    dextCount;
-	bool                        isDext;
-	bool                        categoryConsumed;
-
-	rematchCountProp = NULL;
-	count = 0;
-	prop1 = copyProperty(gIORematchPersonalityKey);
-	rematchPersonality = OSDynamicCast(OSDictionary, prop1);
-	if (rematchPersonality) {
-		rematchCountProp = copyProperty(gIORematchCountKey);
-		num = OSDynamicCast(OSNumber, rematchCountProp);
-		if (num) {
-			count = num->unsigned32BitValue();
-		}
-		removeProperty(gIORematchPersonalityKey);
+
+    assert( matches );
+    while( !needReloc && (nextMatch = matches->getFirstObject())) {
+
+        nextMatch->retain();
+        matches->removeObject(nextMatch);
+        
+        if( (notify = OSDynamicCast( _IOServiceNotifier, nextMatch ))) {
+
+            lockForArbitration();
+            if( 0 == (__state[0] & kIOServiceInactiveState))
+                invokeNotifer( notify );
+            unlockForArbitration();
+            nextMatch->release();
+            nextMatch = 0;
+            continue;
+
+        } else if( !(match = OSDynamicCast( OSDictionary, nextMatch ))) {
+            nextMatch->release();
+            nextMatch = 0;
+            continue;
 	}
-	dextCount = 0;
-
-	assert( matches );
-	while (!needReloc
-	    && (nextMatch = matches->getFirstObject())) {
-		nextMatch->retain();
-		matches->removeObject(nextMatch);
-
-		if ((notify = OSDynamicCast( _IOServiceNotifier, nextMatch ))) {
-			if (0 == (__state[0] & kIOServiceInactiveState)) {
-				invokeNotifier( notify );
-			}
-			nextMatch->release();
-			nextMatch = NULL;
-			continue;
-		} else if (!(match = OSDynamicCast( OSDictionary, nextMatch ))) {
-			nextMatch->release();
-			nextMatch = NULL;
-			continue;
-		}
-
-		props = NULL;
+
+	props = 0;
 #if IOMATCHDEBUG
-		debugFlags = getDebugFlags( match );
+        debugFlags = getDebugFlags( match );
 #endif
 
-		bool newIsBoot = false;
-		bool existingIsBoot = false;
-		bool isReplacementCandidate = false;
-
-		do {
-			client = NULL;
-			isDext = (NULL != match->getObject(gIOUserServerNameKey));
-			if (isDext && !(kIODKEnable & gIODKDebug)) {
-				continue;
-			}
-			if (isDext && !OSKext::iokitDaemonAvailable()) {
-				continue;
-			}
-			if (isDext && !gIODextRelaunchMax && rematchCountProp) {
-				continue;
-			}
-			if (isDext && isInactive()) {
-				continue;
-			}
-			newIsBoot = gIOCatalogue->personalityIsBoot(match);
-
-			category = OSDynamicCast( OSSymbol,
-			    match->getObject( gIOMatchCategoryKey ));
-			if (NULL == category) {
-				category = gIODefaultMatchCategoryKey;
-			}
-			client = copyClientWithCategory(category);
-
-			categoryConsumed = (client != NULL);
-			if (categoryConsumed) {
+        do {
+            category = OSDynamicCast( OSSymbol,
+			match->getObject( gIOMatchCategoryKey ));
+	    if( 0 == category)
+		category = gIODefaultMatchCategoryKey;
+
+	    if( getClientWithCategory( category )) {
 #if IOMATCHDEBUG
-				if ((debugFlags & kIOLogMatch) && (this != gIOResources)) {
-					LOG("%s: match category %s exists\n", getName(),
-					    category->getCStringNoCopy());
-				}
+		if( debugFlags & kIOLogMatch)
+		    LOG("%s: match category %s exists\n", getName(),
+				category->getCStringNoCopy());
 #endif
-				existingIsBoot = client->propertyExists(gIOMatchedAtBootKey);
-				isReplacementCandidate = existingIsBoot && !newIsBoot;
-				if (!isDext && !isReplacementCandidate) {
-					break;
-				}
-			}
-
-			// create a copy now in case its modified during matching
-			props = OSDictionary::withDictionary(match, match->getCount());
-			if (NULL == props) {
-				break;
-			}
-			props->setCapacityIncrement(1);
-
-			// check the nub matches
-			if (false == matchPassive(props, kIOServiceChangesOK | kIOServiceClassDone)) {
-				break;
-			}
-			if (isReplacementCandidate) {
-				if (canTerminateForReplacement(client)) {
-					client->terminate(kIOServiceTerminateNeedWillTerminate | kIOServiceTerminateWithRematch);
-					break;
-				}
-			}
-
-			if (isDext || isReplacementCandidate) {
-				if (isDext) {
-					dextCount++;
-				}
-				if (categoryConsumed) {
-					break;
-				}
-			}
-			if (rematchPersonality) {
-				bool personalityMatch = match->isEqualTo(rematchPersonality);
-				if (count > gIODextRelaunchMax) {
-					personalityMatch = !personalityMatch;
-				}
-				if (!personalityMatch) {
-					break;
-				}
-			}
-
-			// Check to see if driver reloc has been loaded.
-			needReloc = (false == gIOCatalogue->isModuleLoaded( match, &kextRef ));
-			if (needReloc) {
+                nextMatch->release();
+                nextMatch = 0;
+                continue;
+	    }
+
+            // create a copy now in case its modified during matching
+            props = OSDictionary::withDictionary( match, match->getCount());
+            if( 0 == props)
+                continue;
+	    props->setCapacityIncrement(1);		
+
+	    // check the nub matches
+	    if( false == passiveMatch( props, true ))
+		continue;
+
+            // Check to see if driver reloc has been loaded.
+            needReloc = (false == gIOCatalogue->isModuleLoaded( match ));
+            if( needReloc) {
 #if IOMATCHDEBUG
-				if (debugFlags & kIOLogCatalogue) {
-					LOG("%s: stalling for module\n", getName());
-				}
+		if( debugFlags & kIOLogCatalogue)
+		    LOG("%s: stalling for module\n", getName());
 #endif
-				// If reloc hasn't been loaded, exit;
-				// reprobing will occur after reloc has been loaded.
-				break;
-			}
-			if (kextRef) {
-				if (NULL == kexts) {
-					kexts = OSSet::withCapacity(1);
-				}
-				if (kexts) {
-					kexts->setObject(kextRef);
-					kextRef->release();
-				}
-			}
-			if (newIsBoot) {
-				props->setObject(gIOMatchedAtBootKey, kOSBooleanTrue);
-			}
-			if (isDext) {
-				// copy saved for rematchng
-				props->setObject(gIOMatchedPersonalityKey, match);
-			}
-			// reorder on family matchPropertyTable score.
-			if (NULL == familyMatches) {
-				familyMatches = OSOrderedSet::withCapacity( 1,
-				    IOServiceOrdering, (void *) gIOProbeScoreKey );
-			}
-			if (familyMatches) {
-				familyMatches->setObject( props );
-			}
-		} while (false);
-
-		OSSafeReleaseNULL(client);
-		OSSafeReleaseNULL(nextMatch);
-		OSSafeReleaseNULL(props);
-	}
-	OSSafeReleaseNULL(matches);
-	OSSafeReleaseNULL(rematchCountProp);
-
-	if (familyMatches) {
-		while (!needReloc
-		    && (props = (OSDictionary *) familyMatches->getFirstObject())) {
-			props->retain();
-			familyMatches->removeObject( props );
-
-			inst = NULL;
-			newInst = NULL;
+                // If reloc hasn't been loaded, exit;
+                // reprobing will occur after reloc has been loaded.
+                continue;
+	    }
+
+            // reorder on family matchPropertyTable score.
+            if( 0 == familyMatches)
+                familyMatches = OSOrderedSet::withCapacity( 1,
+                        IOServiceOrdering, (void *) gIOProbeScoreKey );
+            if( familyMatches)
+                familyMatches->setObject( props );
+
+        } while( false );
+
+        if (nextMatch) {
+            nextMatch->release();
+            nextMatch = 0;
+        }
+        if( props)
+            props->release();
+    }
+    matches->release();
+    matches = 0;
+
+    if( familyMatches) {
+
+        while( !needReloc
+             && (props = (OSDictionary *) familyMatches->getFirstObject())) {
+
+            props->retain();
+            familyMatches->removeObject( props );
+    
+            inst = 0;
+            newInst = 0;
 #if IOMATCHDEBUG
-			debugFlags = getDebugFlags( props );
+            debugFlags = getDebugFlags( props );
 #endif
-			do {
-				symbol = OSDynamicCast( OSSymbol,
-				    props->getObject( gIOClassKey));
-				if (!symbol) {
-					continue;
-				}
-
-				//IOLog("%s alloc (symbol %p props %p)\n", symbol->getCStringNoCopy(), IOSERVICE_OBFUSCATE(symbol), IOSERVICE_OBFUSCATE(props));
-
-				// alloc the driver instance
-				inst = (IOService *) OSMetaClass::allocClassWithName( symbol);
-
-				if (!inst || !OSDynamicCast(IOService, inst)) {
-					IOLog("Couldn't alloc class \"%s\"\n",
-					    symbol->getCStringNoCopy());
-					continue;
-				}
-
-				// init driver instance
-				if (!(inst->init( props ))) {
+            do {
+                symbol = OSDynamicCast( OSSymbol,
+                                props->getObject( gIOClassKey));
+                if( !symbol)
+                    continue;
+    
+                // alloc the driver instance
+                inst = (IOService *) OSMetaClass::allocClassWithName( symbol);
+    
+                if( !inst) {
+                    IOLog("Couldn't alloc class \"%s\"\n",
+                        symbol->getCStringNoCopy());
+                    continue;
+                }
+    
+                // init driver instance
+                if( !(inst->init( props ))) {
 #if IOMATCHDEBUG
-					if (debugFlags & kIOLogStart) {
-						IOLog("%s::init in provider %s[0x%qx] fails\n", symbol->getCStringNoCopy(), getName(), getRegistryEntryID());
-					}
+                    if( debugFlags & kIOLogStart)
+                        IOLog("%s::init fails\n", symbol->getCStringNoCopy());
 #endif
-					continue;
-				}
-				if (__state[1] & kIOServiceSynchronousState) {
-					inst->__state[1] |= kIOServiceSynchronousState;
-				}
-
-				// give the driver the default match category if not specified
-				category = OSDynamicCast( OSSymbol,
-				    props->getObject( gIOMatchCategoryKey ));
-				if (NULL == category) {
-					category = gIODefaultMatchCategoryKey;
-				}
-				inst->setProperty( gIOMatchCategoryKey, (OSObject *) category );
-				// attach driver instance
-				if (!(inst->attach( this ))) {
-					continue;
-				}
-
-				// pass in score from property table
-				score = familyMatches->orderObject( props );
-
-				// & probe the new driver instance
+                    continue;
+                }
+                if( __state[1] & kIOServiceSynchronousState)
+                    inst->__state[1] |= kIOServiceSynchronousState;
+    
+                // give the driver the default match category if not specified
+                category = OSDynamicCast( OSSymbol,
+                            props->getObject( gIOMatchCategoryKey ));
+                if( 0 == category)
+                    category = gIODefaultMatchCategoryKey;
+                inst->setProperty( gIOMatchCategoryKey, (OSObject *) category );
+    
+                // attach driver instance
+                if( !(inst->attach( this )))
+                        continue;
+    
+                // pass in score from property table
+                score = familyMatches->orderObject( props );
+    
+                // & probe the new driver instance
 #if IOMATCHDEBUG
-				if (debugFlags & kIOLogProbe) {
-					LOG("%s[0x%qx]::probe(%s)\n",
-					    inst->getMetaClass()->getClassName(), inst->getRegistryEntryID(), getName());
-				}
+                if( debugFlags & kIOLogProbe)
+                    LOG("%s::probe(%s)\n",
+                        inst->getMetaClass()->getClassName(), getName());
 #endif
-				newInst = inst->probe( this, &score );
-				inst->detach( this );
-				if (NULL == newInst) {
+    
+                newInst = inst->probe( this, &score );
+                inst->detach( this );
+                if( 0 == newInst) {
 #if IOMATCHDEBUG
-					if (debugFlags & kIOLogProbe) {
-						IOLog("%s[0x%qx]::probe fails\n", symbol->getCStringNoCopy(), inst->getRegistryEntryID());
-					}
+                    if( debugFlags & kIOLogProbe)
+                        IOLog("%s::probe fails\n", symbol->getCStringNoCopy());
 #endif
-					continue;
-				}
-
-				// save the score
-				newPri = OSNumber::withNumber( score, 32 );
-				if (newPri) {
-					newInst->setProperty( gIOProbeScoreKey, newPri );
-					newPri->release();
-				}
-
-				// add to start list for the match category
-				if (NULL == startDict) {
-					startDict = OSDictionary::withCapacity( 1 );
-				}
-				assert( startDict );
-				startList = (OSOrderedSet *)
-				    startDict->getObject( category );
-				if (NULL == startList) {
-					startList = OSOrderedSet::withCapacity( 1,
-					    IOServiceOrdering, (void *) gIOProbeScoreKey );
-					if (startDict && startList) {
-						startDict->setObject( category, startList );
-						startList->release();
-					}
-				}
-				assert( startList );
-				if (startList) {
-					startList->setObject( newInst );
-				}
-			} while (false);
-
-			props->release();
-			if (inst) {
-				inst->release();
-			}
-		}
-		familyMatches->release();
-		familyMatches = NULL;
-	}
-
-	if ((debugFlags & kIOLogMatch) && iokit_print_verbose_match_logs && startDict != NULL) {
-		IOLog("%s(0x%qx): %u categories\n", getName(), getRegistryEntryID(), startList->getCount());
-		startDict->iterateObjects(^(const OSSymbol *key, OSObject *value) {
-			OSOrderedSet *startList = OSDynamicCast(OSOrderedSet, value);
-			if (startList) {
-			        IOLog("%s(0x%qx): category %s, %u matches\n", getName(), getRegistryEntryID(), key->getCStringNoCopy(), startList->getCount());
-			        startList->iterateObjects(^(OSObject *obj) {
-					IOService *match = OSDynamicCast(IOService, obj);
-					OSNumber *probeScore = OSDynamicCast(OSNumber, match->getProperty(gIOProbeScoreKey));
-
-					if (match && probeScore) {
-					        IOLog("%s(0x%qx): category %s: matched %s, probe score %qd\n", getName(), getRegistryEntryID(), key->getCStringNoCopy(), match->getName(), probeScore->unsigned64BitValue());
-					}
-					return false;
-				});
-			}
-			return false;
-		});
-	}
-
-	// start the best (until success) of each category
-
-	iter = OSCollectionIterator::withCollection( startDict );
-	assert(startDict || !iter);
-	if (iter) {
-		while ((category = (const OSSymbol *) iter->getNextObject())) {
-			startList = (OSOrderedSet *) startDict->getObject( category );
-			assert( startList );
-			if (!startList) {
-				continue;
-			}
-			started = false;
-			while (true // (!started)
-			    && !matchDeferred
-			    && (inst = (IOService *)startList->getFirstObject())) {
-				inst->retain();
-				startList->removeObject(inst);
+                    continue;
+                }
+    
+                // save the score
+                newPri = OSNumber::withNumber( score, 32 );
+                if( newPri) {
+                    newInst->setProperty( gIOProbeScoreKey, newPri );
+                    newPri->release();
+                }
+    
+                // add to start list for the match category
+                if( 0 == startDict)
+                    startDict = OSDictionary::withCapacity( 1 );
+                assert( startDict );
+                startList = (OSOrderedSet *)
+                                startDict->getObject( category );
+                if( 0 == startList) {
+                    startList = OSOrderedSet::withCapacity( 1,
+                            IOServiceOrdering, (void *) gIOProbeScoreKey );
+                    if( startDict && startList) {
+                        startDict->setObject( category, startList );
+                        startList->release();
+                    }
+                }
+                assert( startList );
+                if( startList)
+                    startList->setObject( newInst );
+    
+            } while( false );
+
+            props->release();
+            if( inst)
+                inst->release();
+        }
+        familyMatches->release();
+        familyMatches = 0;
+    }
+
+    // start the best (until success) of each category
+
+    iter = OSCollectionIterator::withCollection( startDict );
+    if( iter) {
+	while( (category = (const OSSymbol *) iter->getNextObject())) {
+
+	    startList = (OSOrderedSet *) startDict->getObject( category );
+	    assert( startList );
+	    if( !startList)
+		continue;
+
+            started = false;
+            while( true // (!started)
+		   && (inst = (IOService *)startList->getFirstObject())) {
+
+		inst->retain();
+		startList->removeObject(inst);
+
 #if IOMATCHDEBUG
-				debugFlags = getDebugFlags( inst );
-
-				if (debugFlags & kIOLogStart) {
-					if (started) {
-						LOG( "match category exists, skipping " );
-					}
-					LOG( "%s[0x%qx]::start(%s) <%d>\n", inst->getName(), inst->getRegistryEntryID(),
-					    getName(), inst->getRetainCount());
-				}
+        	debugFlags = getDebugFlags( inst->getPropertyTable() );
+
+                if( debugFlags & kIOLogStart) {
+                    if( started)
+                        LOG( "match category exists, skipping " );
+                    LOG( "%s::start(%s) <%d>\n", inst->getName(),
+                         getName(), inst->getRetainCount());
+                }
 #endif
-				if (false == started) {
-#if !NO_KEXTD
-					IOLockLock(gJobsLock);
-					matchDeferred = (gIOMatchDeferList
-					    && kOSBooleanTrue == inst->getProperty(gIOMatchDeferKey));
-					if (matchDeferred && (-1U == gIOMatchDeferList->getNextIndexOfObject(this, 0))) {
-						gIOMatchDeferList->setObject(this);
-					}
-					if (matchDeferred) {
-						symbol = OSDynamicCast(OSSymbol, inst->getProperty(gIOClassKey));
-						IOLog("%s(0x%qx): matching deferred by %s%s\n",
-						    getName(), getRegistryEntryID(),
-						    symbol ? symbol->getCStringNoCopy() : "",
-						    IOService::getWillUserspaceReboot() ? " in userspace reboot" : "");
-						// rematching will occur after the IOKit daemon loads all plists
-					}
-					IOLockUnlock(gJobsLock);
+                if( false == started)
+                    started = startCandidate( inst );
+#if IOMATCHDEBUG
+                if( (debugFlags & kIOLogStart) && (false == started))
+                    LOG( "%s::start(%s) <%d> failed\n", inst->getName(), getName(),
+                         inst->getRetainCount());
 #endif
-					if (!matchDeferred) {
-						/* TODO
-						 * If a dext fails to start because an upgrade happened
-						 * concurrently, then the matching process has to restart
-						 */
-						started = startCandidate( inst );
-#if IOMATCHDEBUG
-						if ((debugFlags & kIOLogStart) && (false == started)) {
-							LOG( "%s[0x%qx]::start(%s[0x%qx]) <%d> failed\n", inst->getName(), inst->getRegistryEntryID(), getName(), getRegistryEntryID(),
-							    inst->getRetainCount());
-						}
-#endif
-						if (!started) {
-							if (inst->propertyExists(gIOServiceMatchDeferredKey)) {
-								matchDeferred = true;
-							} else if (inst->reserved->uvars && inst->reserved->uvars->userServer && !inst->reserved->uvars->instantiated &&
-							    (0 != (__state[1] & kIOServiceNeedConfigState))) {
-								// Start failed with no object instantiation
-								// Dext will be rematched as this nub got re-registered
-								// Do not start the next candidate, otherwise the rematched dext might not be able to replace it
-								OSString * bundleID = OSDynamicCast(OSString, inst->getProperty(gIOModuleIdentifierKey));
-								IOLog("%s(0x%qx): stop matching as %s will be relaunched\n",
-								    getName(), getRegistryEntryID(),
-								    bundleID ? bundleID->getCStringNoCopy() : "(null)");
-								matchDeferred = true;
-							}
-						}
-					}
-				}
-				inst->release();
-			}
-		}
-		iter->release();
-	}
-
-	OSSafeReleaseNULL(prop1);
-
-	if (dextCount) {
-		num = OSNumber::withNumber(dextCount, 32);
-		setProperty(gIODEXTMatchCountKey, num);
-		OSSafeReleaseNULL(num);
-	} else if (rematchPersonality) {
-		removeProperty(gIODEXTMatchCountKey);
-	}
-
-	// now that instances are created, drop the refs on any kexts allowing unload
-	if (kexts) {
-		OSKext::dropMatchingReferences(kexts);
-		OSSafeReleaseNULL(kexts);
-	}
-
-	// adjust the busy count by +1 if matching is stalled for a module,
-	// or -1 if a previously stalled matching is complete.
-	lockForArbitration();
-	SInt32 adjBusy = 0;
-	uint64_t regID = getRegistryEntryID();
-
-	if (needReloc) {
-		adjBusy = (__state[1] & kIOServiceModuleStallState) ? 0 : 1;
-		if (adjBusy) {
-			IOServiceTrace(
-				IOSERVICE_MODULESTALL,
-				(uintptr_t) regID,
-				(uintptr_t) (regID >> 32),
-				(uintptr_t) this,
-				0);
-
-			__state[1] |= kIOServiceModuleStallState;
-		}
-	} else if (__state[1] & kIOServiceModuleStallState) {
-		IOServiceTrace(
-			IOSERVICE_MODULEUNSTALL,
-			(uintptr_t) regID,
-			(uintptr_t) (regID >> 32),
-			(uintptr_t) this,
-			0);
-
-		__state[1] &= ~kIOServiceModuleStallState;
-		adjBusy = -1;
-	}
-	if (adjBusy) {
-		_adjustBusy( adjBusy );
-	}
-	unlockForArbitration();
-
-	if (startDict) {
-		startDict->release();
-	}
-}
-
-void
-IOService::willShutdown()
-{
-	gIOKitWillTerminate = true;
-#if !NO_KEXTD
-	IOUserServerCheckInToken::cancelAll();
-#endif
-	OSKext::willShutdown();
-}
-
-bool
-IOService::getWillUserspaceReboot()
-{
-	return os_atomic_load(&gInUserspaceReboot, relaxed);
-}
-
-void
-IOService::setWillUserspaceReboot()
-{
-	IOLockLock(gJobsLock);
-#if !NO_KEXTD
-	IOService  * provider;
-	IOService  * service;
-	OSIterator * iter;
-
-	// Recreate the defer list if it does not exist
-	if (!gIOMatchDeferList && OSKext::iokitDaemonAvailable()) {
-		gIOMatchDeferList = OSArray::withCapacity( 16 );
-	}
-
-	if (gIOMatchDeferList) {
-		iter = IORegistryIterator::iterateOver(gIOServicePlane, kIORegistryIterateRecursively);
-		if (iter) {
-			do {
-				iter->reset();
-				while ((service = (IOService *)iter->getNextObject())) {
-					/* Rematch providers of services that will be terminated on userspace reboot, after the userspace reboot
-					 * is complete. This normally happens automatically as the IOKit daemon sends personalities to the kernel
-					 * which triggers rematching. But if this doesn't happen (for example, if a feature flag is turned off),
-					 * then these services will never get rematched.
-					 */
-					if (service->propertyHasValue(gIOMatchDeferKey, kOSBooleanTrue) || service->hasUserServer()) {
-						provider = service->getProvider();
-						IOLog("deferring %s-%llx (provider of %s-%llx) matching after userspace reboot\n",
-						    provider->getName(), provider->getRegistryEntryID(), service->getName(), service->getRegistryEntryID());
-						gIOMatchDeferList->setObject(provider);
-					}
-				}
-			} while (!service && !iter->isValid());
-
-			OSSafeReleaseNULL(iter);
-		}
-	}
-#endif
-	os_atomic_store(&gInUserspaceReboot, true, relaxed);
-	IOLockUnlock(gJobsLock);
-}
-
-void
-IOService::userSpaceDidReboot()
-{
-	os_atomic_store(&gInUserspaceReboot, false, relaxed);
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-void
-IOServicePH::init(IOPMrootDomain * root)
-{
-	fUserServers     = OSArray::withCapacity(4);
-	fMatchingWork    = OSArray::withCapacity(4);
-
-	assert(fUserServers && fMatchingWork);
-
-	fRootNotifier = root->registerInterest(
-		gIOPriorityPowerStateInterest, &IOServicePH::systemPowerChange, NULL, NULL);
-
-	assert(fRootNotifier);
-
-	gIOUserResources->PMinit();
-	root->registerInterestedDriver(gIOUserResources);
-
-	fUserServerAckTimer = thread_call_allocate(&IOServicePH::userServerAckTimerExpired, (thread_call_param_t)NULL);
-}
-
-void
-IOServicePH::lock()
-{
-	IOLockLock(gJobsLock);
-}
-
-void
-IOServicePH::unlock()
-{
-	IOLockUnlock(gJobsLock);
-}
-
-void
-IOServicePH::serverAdd(IOUserServer * server)
-{
-	uint32_t idx;
-
-	lock();
-	idx = fUserServers->getNextIndexOfObject(server, 0);
-	if (idx == -1U) {
-		fUserServers->setObject(server);
-	}
-	unlock();
-}
-
-void
-IOServicePH::serverRemove(IOUserServer * server)
-{
-	uint32_t idx;
-
-	lock();
-	idx = fUserServers->getNextIndexOfObject(server, 0);
-	if (idx != -1U) {
-		fUserServers->removeObject(idx);
-	}
-
-	if (fWaitingUserServers) {
-		fWaitingUserServers = false;
-		IOLockWakeup(gJobsLock, &fWaitingUserServers, /* one-thread */ false);
-	}
-
-	unlock();
-}
-
-void
-IOServicePH::serverAck(IOUserServer * server)
-{
-	uint32_t    idx;
-	IOService * ackTo;
-	uint32_t    ackToRef;
-	OSArray *   notifyServers;
-
-	ackTo = NULL;
-	notifyServers = NULL;
-	lock();
-	if (server && fUserServersWait) {
-		idx = fUserServersWait->getNextIndexOfObject(server, 0);
-		if (idx != -1U) {
-			fUserServersWait->removeObject(idx);
-			if (0 == fUserServersWait->getCount()) {
-				OSSafeReleaseNULL(fUserServersWait);
-			}
-		}
-	}
-	if (!fUserServersWait && !fMatchingWork->getCount()) {
-		ackTo             = fSystemPowerAckTo;
-		ackToRef          = fSystemPowerAckRef;
-		fSystemPowerAckTo = NULL;
-		if (ackTo) {
-			if (ackTo == gIOUserResources) {
-				notifyServers = OSArray::withArray(fUserServers);
-			}
-			thread_call_cancel(fUserServerAckTimer);
-		}
-	}
-	if (fUserServersWait && fUserServersWait->getCount() > 0 && fMatchingWork && fMatchingWork->getCount() > 0) {
-		DKLOG("Waiting for %u user servers, %u matching work\n", fUserServersWait->getCount(), fMatchingWork->getCount());
-	}
-	unlock();
-
-	if (ackTo == gIOUserResources) {
-		// suspend DK processes all at once since they can talk amongst themselves
-		// after SetPowerState()
-		if (notifyServers) {
-			notifyServers->iterateObjects(^bool (OSObject * obj) {
-				IOUserServer * us;
-				us = (typeof(us))obj;
-				us->systemSuspend();
-				return false;
-			});
-			OSSafeReleaseNULL(notifyServers);
-		}
-		DKLOG("allowPowerChange(2)\n");
-		IOService::getPMRootDomain()->acknowledgePowerChange(gIOUserResources);
-	} else if (ackTo) {
-		DKLOG("allowPowerChange(1)\n");
-		ackTo->allowPowerChange((uintptr_t) ackToRef);
-	}
-}
-
-bool
-IOServicePH::matchingStart(IOService * service)
-{
-	uint32_t idx;
-	bool assertionActive = gIOPMRootDomain->acquireDriverKitMatchingAssertion() == kIOReturnSuccess;
-
-	lock();
-	bool matchNow = (kIOServiceSystemStateOn == fSystemState) && assertionActive;
-	if (matchNow) {
-		idx = fMatchingWork->getNextIndexOfObject(service, 0);
-		if (idx == -1U) {
-			fMatchingWork->setObject(service);
-		}
-	} else {
-		// Delay matching if system is transitioning to sleep
-		if (!fMatchingDelayed) {
-			fMatchingDelayed = OSArray::withObjects((const OSObject **) &service, 1, 1);
-		} else {
-			idx = fMatchingDelayed->getNextIndexOfObject(service, 0);
-			if (idx == -1U) {
-				fMatchingDelayed->setObject(service);
-			}
-		}
-	}
-	unlock();
-	if (!matchNow && assertionActive) {
-		gIOPMRootDomain->releaseDriverKitMatchingAssertion();
-	}
-
-	return matchNow;
-}
-
-void
-IOServicePH::matchingEnd(IOService * service)
-{
-	uint32_t idx;
-	OSArray   * notifyServers;
-	OSArray   * deferredMatches;
-
-	notifyServers   = NULL;
-	deferredMatches = NULL;
-
-	if (service) {
-		gIOPMRootDomain->releaseDriverKitMatchingAssertion();
-	}
-
-	lock();
-
-	if (service) {
-		idx = fMatchingWork->getNextIndexOfObject(service, 0);
-		if (idx != -1U) {
-			fMatchingWork->removeObject(idx);
-		}
-	}
-
-
-	if ((fUserServerSystemState != fSystemState) && fUserServers->getCount()) {
-		if (IsIOServiceSystemStateOff(fSystemState)) {
-			if (0 == fMatchingWork->getCount()) {
-				fUserServersWait = OSArray::withArray(fUserServers);
-				notifyServers = OSArray::withArray(fUserServers);
-				fUserServerSystemState = fSystemState;
-			}
-		} else {
-			notifyServers = OSArray::withArray(fUserServers);
-			fUserServerSystemState = fSystemState;
-		}
-	}
-
-	if ((kIOServiceSystemStateOn == fSystemState) && fMatchingDelayed) {
-		deferredMatches = fMatchingDelayed;
-		fMatchingDelayed = NULL;
-	}
-
-	unlock();
-
-	if (notifyServers) {
-		uint32_t sleepType = 0;
-		uint32_t standbyTimer = 0;
-		bool hibernate = false;
-		if (IsIOServiceSystemStateOff(fSystemState)
-		    && IOService::getPMRootDomain()->getSystemSleepType(&sleepType, &standbyTimer) == kIOReturnSuccess) {
-			hibernate = (sleepType == kIOPMSleepTypeHibernate);
-		}
-		notifyServers->iterateObjects(^bool (OSObject * obj) {
-			IOUserServer * us;
-			us = (typeof(us))obj;
-			us->systemPower(fSystemState, hibernate);
-			return false;
-		});
-		OSSafeReleaseNULL(notifyServers);
-	}
-
-	if (deferredMatches) {
-		DKLOG("sleep deferred rematching count %d\n", deferredMatches->getCount());
-		deferredMatches->iterateObjects(^bool (OSObject * obj)
-		{
-			((IOService *)obj)->startMatching(kIOServiceAsynchronous);
-			return false;
-		});
-		deferredMatches->release();
-	}
-
-	serverAck(NULL);
-}
-
-TUNABLE(uint32_t, dk_shutdown_timeout_ms, "dk_shutdown_timeout_ms", 30000);
-TUNABLE(bool, dk_panic_on_shutdown_hang, "dk_panic_on_shutdown_hang", false);
-#if DEVELOPMENT || DEBUG
-#define DK_SETPOWERSTATE_HANG true
-#else
-#define DK_SETPOWERSTATE_HANG false
-#endif
-TUNABLE(bool, dk_panic_on_setpowerstate_hang, "dk_panic_on_setpowerstate_hang", DK_SETPOWERSTATE_HANG);
-
-OSArray *
-IOServicePH::servicesWithPowerState(bool state)
-{
-	OSArray * userServersWait = NULL;
-	__block OSArray * services = NULL;
-	lock();
-	if (fUserServersWait) {
-		userServersWait = OSArray::withArray(fUserServersWait);
-	}
-	unlock();
-	if (!userServersWait) {
-		return NULL;
-	}
-	userServersWait->iterateObjects(^(OSObject * object) {
-		IOUserServer * us = OSDynamicCast(IOUserServer, object);
-		if (us) {
-		        OSArray * result = us->servicesWithPowerState(state);
-		        if (result) {
-		                if (!services) {
-		                        services = result;
-				} else {
-		                        services->merge(result);
-		                        OSSafeReleaseNULL(result);
-				}
-			}
-		}
-		return false;
-	});
-	OSSafeReleaseNULL(userServersWait);
-	return services;
-}
-
-void
-IOServicePH::userServerAckTimerExpired(void *, void *)
-{
-	OSArray * userServers = NULL;
-	lock();
-	if (fSystemPowerAckTo) {
-		DKLOG("ack timer expired\n");
-		if (dk_panic_on_setpowerstate_hang) {
-			// Enable emergency dext coredump as the kernel is panicking
-			fUserServersWait->iterateObjects(^(OSObject * object) {
-				IOUserServer * userServer = OSDynamicCast(IOUserServer, object);
-				if (userServer) {
-				        userServer->emergencyPanicCoreDumpEnable();
-				}
-				return false;
-			});
-
-			unlock();
-			char * servicesString = NULL;
-			__block size_t stringLength = 0, cursor = 0;
-			OSArray * services = NULL;
-			OSOrderedSet * sortedServices = NULL;
-
-			do {
-				sortedServices = OSOrderedSet::withCapacity(1,
-				    ^int32_t (const OSMetaClassBase * obj1, const OSMetaClassBase * obj2) {
-					IOService * service1 = OSDynamicCast(IOService, obj1);
-					IOService * service2 = OSDynamicCast(IOService, obj2);
-					if (service1 && service1->getName() && service2 && service2->getName()) {
-					        return -1 * strcmp(service1->getName(), service2->getName());
-					}
-					return 0;
-				});
-				if (!sortedServices) {
-					break;
-				}
-
-				services = servicesWithPowerState(true);
-				if (!services) {
-					break;
-				}
-
-				// These need to be sorted to keep the panic string consistent
-				services->iterateObjects(^(OSObject * object) {
-					sortedServices->setObject(object);
-					return false;
-				});
-
-				// Format a string with comma separated service names
-				sortedServices->iterateObjects(^(OSObject * object) {
-					IOService * service = (IOService *)object;
-					if (stringLength == 0) {
-					        stringLength = snprintf(NULL, 0, "\'%s\'", service->getName());
-					} else {
-					        stringLength += snprintf(NULL, 0, ",\'%s\'", service->getName());
-					}
-					return false;
-				});
-				if (stringLength == 0) {
-					break;
-				}
-
-				stringLength++;
-				servicesString = (char *)IOMallocData(stringLength);
-				if (!servicesString) {
-					break;
-				}
-
-				sortedServices->iterateObjects(^(OSObject * object) {
-					IOService * service = (IOService *)object;
-					if (cursor == 0) {
-					        cursor = snprintf(servicesString, stringLength, "\'%s\'", service->getName());
-					} else {
-					        cursor += snprintf(servicesString + cursor, stringLength - cursor, ",\'%s\'", service->getName());
-					}
-					return false;
-				});
-			} while (false);
-
-			panic("DK ack timer expired after %u ms: %s", dk_shutdown_timeout_ms, servicesString ? servicesString : "");
-		}
-		userServers = fUserServersWait;
-		fUserServersWait = NULL;
-	}
-	unlock();
-
-	if (userServers != NULL) {
-		userServers->iterateObjects(^bool (OSObject *obj) {
-			IOUserServer * us = OSDynamicCast(IOUserServer, obj);
-			if (us) {
-			        DKLOG(DKS " power state transition failed\n", DKN(us));
-			        us->kill("Power Management Failed");
-			}
-			return false;
-		});
-		OSSafeReleaseNULL(userServers);
-	}
-
-	serverAck(NULL);
-}
-
-void
-IOServicePH::systemHalt(int howto)
-{
-	OSArray * notifyServers;
-	uint64_t  deadline;
-
-	lock();
-	notifyServers = OSArray::withArray(fUserServers);
-	unlock();
-
-	if (notifyServers) {
-		notifyServers->iterateObjects(^bool (OSObject * obj) {
-			IOUserServer * us;
-			us = (typeof(us))obj;
-			us->systemHalt(howto);
-			return false;
-		});
-		OSSafeReleaseNULL(notifyServers);
-	}
-
-	lock();
-	clock_interval_to_deadline(dk_shutdown_timeout_ms, kMillisecondScale, &deadline);
-	while (0 < fUserServers->getCount()) {
-		fWaitingUserServers = true;
-		__assert_only int waitResult =
-		    IOLockSleepDeadline(gJobsLock, &fWaitingUserServers, deadline, THREAD_UNINT);
-		assert((THREAD_AWAKENED == waitResult) || (THREAD_TIMED_OUT == waitResult));
-		if (THREAD_TIMED_OUT == waitResult) {
-			IOUserServer::beginLeakingObjects();
-#if DEVELOPMENT || DEBUG
-			if (dk_panic_on_shutdown_hang) {
-				panic("Shutdown timed out waiting for DK drivers to stop");
-			}
-#endif /* DEVELOPMENT || DEBUG */
-			break;
-		}
-	}
-	unlock();
-}
-
-bool
-IOServicePH::serverSlept(void)
-{
-	bool ret;
-
-	lock();
-	ret = (kIOMessageSystemWillSleep == sSystemPower)
-	    || (kIOMessageSystemWillPowerOff == sSystemPower)
-	    || (kIOMessageSystemWillRestart == sSystemPower);
-	unlock();
-
-	return ret;
-}
-
-TUNABLE(uint32_t, dk_power_state_timeout_ms, "dk_power_state_timeout_ms", 30000);
-
-//
-// Handle system changes:
-//
-// kIOServiceSystemStateOn
-// kIOServiceSystemStateAOT
-// kIOServiceSystemStateOffPhase1 - non-DK user space suspension
-// kIOServiceSystemStateOffPhase2 - DK user space suspension
-//
-
-void
-IOServicePH::systemPowerChange(uint8_t newState,
-    IOService * ackTo,
-    uint32_t ackRef,
-    uint32_t * pMaxWaitForReply)
-{
-	AbsoluteTime deadline;
-
-	IOLog("IOServicePH::systemPowerChange to 0x%x\n", newState);
-
-	switch (newState) {
-	case kIOServiceSystemStateOffPhase1:
-	case kIOServiceSystemStateOffPhase2:
-
-		if (fSystemState == kIOServiceSystemStateAOT) {
-			IOPMNetworkStackWillSleepFromAOT();
-		}
-
-		lock();
-		DKLOG("arming ack timer, %u ms\n", dk_power_state_timeout_ms);
-		clock_interval_to_deadline(dk_power_state_timeout_ms, kMillisecondScale, &deadline);
-		fSystemState       = newState;
-		fSystemPowerAckRef = ackRef;
-		fSystemPowerAckTo  = ackTo;
-		thread_call_enter_delayed(fUserServerAckTimer, deadline);
-		unlock();
-		matchingEnd(NULL);
-
-		*pMaxWaitForReply = dk_power_state_timeout_ms * 2 * 1000;
-		break;
-
-	case kIOServiceSystemStateAOT:
-	case kIOServiceSystemStateOn:
-
-		lock();
-		fSystemState = newState;
-		unlock();
-		matchingEnd(NULL);
-		*pMaxWaitForReply = 0;
-		break;
-
-	default:
-		assert(false);
-		break;
-	}
-}
-
-IOReturn
-IOServicePH::systemPowerChange(
-	void * target,
-	void * refCon,
-	UInt32 messageType, IOService * service,
-	void * messageArgument, vm_size_t argSize)
-{
-	IOReturn                               ret;
-	IOPMSystemCapabilityChangeParameters * params;
-
-	switch (messageType) {
-	case kIOMessageSystemCapabilityChange:
-		params = (typeof params)messageArgument;
-
-		IOLog("IOServicePH::kIOMessageSystemCapabilityChange: %s%s 0x%x->0x%x\n",
-		    params->changeFlags & kIOPMSystemCapabilityWillChange ? "will" : "",
-		    params->changeFlags & kIOPMSystemCapabilityDidChange ? "did" : "",
-		    params->fromCapabilities,
-		    params->toCapabilities);
-
-		if ((params->changeFlags & kIOPMSystemCapabilityWillChange) &&
-		    (params->fromCapabilities & (kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityAOT)) &&
-		    ((params->toCapabilities & (kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityAOT)) == 0)) {
-			systemPowerChange(kIOServiceSystemStateOffPhase1, service, params->notifyRef, &params->maxWaitForReply);
-			ret = kIOReturnSuccess;
-		} else if ((params->changeFlags & kIOPMSystemCapabilityWillChange) &&
-		    (0 != ((params->fromCapabilities ^ params->toCapabilities)
-		    & (kIOPMSystemCapabilityCPU | kIOPMSystemCapabilityAOT)))) {
-			systemPowerChange((params->toCapabilities & kIOPMSystemCapabilityCPU) ? kIOServiceSystemStateOn : kIOServiceSystemStateAOT,
-			    service, params->notifyRef, &params->maxWaitForReply);
-			ret = kIOReturnSuccess;
-		} else {
-			params->maxWaitForReply = 0;
-			ret                 = kIOReturnSuccess;
-		}
-		break;
-
-	default:
-		ret = kIOReturnUnsupported;
-		break;
-	}
-
-	return ret;
-}
-
-IOReturn
-IOServicePH::rootWillChangeTo(IOPMPowerFlags flags, unsigned long state)
-{
-	IOReturn ret;
-	uint32_t maxWaitForReply = kIOPMAckImplied;
-
-	if (kIOPMSleepCapability & flags) {
-		systemPowerChange(kIOServiceSystemStateOffPhase2, gIOUserResources, 0, &maxWaitForReply);
-	} else if (kIOPMAOTCapability & flags) {
-		systemPowerChange(kIOServiceSystemStateAOT, NULL, 0, &maxWaitForReply);
-	} else if (kIOPMPowerOn & flags) {
-		systemPowerChange(kIOServiceSystemStateOn, NULL, 0, &maxWaitForReply);
-	}
-	ret = maxWaitForReply;
-	return ret;
-}
-
-bool
-IOSystemStateAOT(void)
-{
-	return kIOServiceSystemStateAOT == IOServicePH::fSystemState;
-}
-
-bool
-IOServicePH::checkPMReady(void)
-{
-	bool __block ready = true;
-
-	lock();
-	fUserServers->iterateObjects(^bool (OSObject *obj) {
-		IOUserServer * us = OSDynamicCast(IOUserServer, obj);
-		if (us) {
-		        if (!us->checkPMReady()) {
-		                ready = false;
-		                return true;
-			}
-		}
-		return false;
-	});
-	unlock();
-
-	return ready;
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-#if DEBUG || DEVELOPMENT
-void
-IOService::__patchProperties(void)
-{
-#if 0
-	if (!strcmp("AppleCentauriManager", getName())) {
-		setProperty(kIOPMAOTAllowKey, kIOPMDriverClassNetworkWifi | kIOPMDriverClassNetworkBluetooth, 64);
-	}
-	if (!strcmp("CentauriControl", getName())) {
-		setProperty(kIOPMAOTAllowKey, kIOPMDriverClassNetworkWifi | kIOPMDriverClassNetworkBluetooth, 64);
-	}
-	if (!strcmp("CentauriAlpha", getName())) {
-		setProperty(kIOPMAOTAllowKey, kIOPMDriverClassNetworkWifi, 64);
-	}
-	if (!strcmp("CentauriBeta", getName())) {
-		setProperty(kIOPMAOTAllowKey, kIOPMDriverClassNetworkBluetooth, 64);
-	}
-#endif
-}
-#endif /* DEBUG || DEVELOPMENT */
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+		inst->release();
+            }
+        }
+	iter->release();
+    }
+
+
+    // adjust the busy count by -1 if matching is stalled for a module,
+    // or +1 if a previously stalled matching is complete.
+    lockForArbitration();
+    SInt32 adjBusy = 0;
+    if( needReloc) {
+        adjBusy = (__state[1] & kIOServiceModuleStallState) ? 0 : 1;
+        if( adjBusy)
+            __state[1] |= kIOServiceModuleStallState;
+
+    } else if( __state[1] & kIOServiceModuleStallState) {
+        __state[1] &= ~kIOServiceModuleStallState;
+        adjBusy = -1;
+    }
+    if( adjBusy)
+        _adjustBusy( adjBusy );
+    unlockForArbitration();
+
+    if( startDict)
+	startDict->release();
+}
 
 /*
  * Start a previously attached & probed instance,
  * called on exporting object instance
  */
 
-bool
-IOService::startCandidate( IOService * service )
-{
-	bool                ok;
-	OSObject          * obj;
-	OSObject          * prop;
-	IOUserServer      * userServer;
-	bool                ph;
-
-	userServer = NULL;
-	obj = service->copyProperty(gIOUserServerNameKey);
-
-	if (obj && (this == gIOResources)) {
-		ok = false;
-	} else {
-		ok = service->attach( this );
+bool IOService::startCandidate( IOService * service )
+{
+    bool		ok;
+
+    ok = service->attach( this );
+
+    if( ok) {
+        // stall for any nub resources
+        checkResources();
+        // stall for any driver resources
+        service->checkResources();
+
+
+        ok = service->start( this );
+        if( !ok)
+            service->detach( this );
+    }
+    return( ok );
+}
+
+IOService * IOService::resources( void )
+{
+    return( gIOResources );
+}
+
+void IOService::publishResource( const char * key, OSObject * value = 0 )
+{
+    const OSSymbol *	sym;
+
+    if( (sym = OSSymbol::withCString( key))) {
+        publishResource( sym, value);
+	sym->release();
+    }
+}
+
+void IOService::publishResource( const OSSymbol * key, OSObject * value = 0 )
+{
+    if( 0 == value)
+	value = (OSObject *) gIOServiceKey;
+
+    gIOResources->setProperty( key, value);
+
+    gIOResourceGenerationCount++;
+    gIOResources->registerService();
+}
+
+bool IOService::addNeededResource( const char * key )
+{
+    OSObject *	resources;
+    OSSet *	set;
+    OSString *	newKey;
+    bool ret;
+
+    resources = getProperty( gIOResourceMatchKey );
+
+    newKey = OSString::withCString( key );
+    if( (0 == resources) || (0 == newKey))
+	return( false);
+
+    set = OSDynamicCast( OSSet, resources );
+    if( !set) {
+	set = OSSet::withCapacity( 1 );
+	if( set)
+            set->setObject( resources );
+    }
+    else
+        set->retain();
+
+    set->setObject( newKey );
+    newKey->release();
+    ret = setProperty( gIOResourceMatchKey, set );
+    set->release();
+
+    return( ret );
+}
+
+bool IOService::checkResource( OSObject * matching )
+{
+    OSString *		str;
+    OSDictionary *	table;
+
+    if( (str = OSDynamicCast( OSString, matching ))) {
+	if( gIOResources->getProperty( str ))
+	    return( true );
+    }
+
+    if( str)
+	table = resourceMatching( str );
+    else if( (table = OSDynamicCast( OSDictionary, matching )))
+	table->retain();
+    else {
+	IOLog("%s: Can't match using: %s\n", getName(),
+		matching->getMetaClass()->getClassName());
+	/* false would stall forever */
+	return( true );
+    }
+
+    if( gIOKitDebug & kIOLogConfig)
+        LOG("config(%x): stalling %s\n", (int) IOThreadSelf(), getName());
+
+    waitForService( table );
+
+    if( gIOKitDebug & kIOLogConfig)
+        LOG("config(%x): waking\n", (int) IOThreadSelf() );
+
+    return( true );
+}
+
+bool IOService::checkResources( void )
+{
+    OSObject * 		resources;
+    OSSet *		set;
+    OSIterator *	iter;
+    bool		ok;
+
+    resources = getProperty( gIOResourceMatchKey );
+    if( 0 == resources)
+        return( true );
+
+    if( (set = OSDynamicCast( OSSet, resources ))) {
+
+	iter = OSCollectionIterator::withCollection( set );
+	ok = (0 != iter);
+        while( ok && (resources = iter->getNextObject()) )
+            ok = checkResource( resources );
+	if( iter)
+	    iter->release();
+
+    } else
+	ok = checkResource( resources );
+
+    return( ok );
+}
+
+
+_IOConfigThread * _IOConfigThread::configThread( void )
+{
+    _IOConfigThread * 	inst;
+
+    do {
+	if( !(inst = new _IOConfigThread))
+	    continue;
+	if( !inst->init())
+	    continue;
+	if( !(inst->thread = IOCreateThread
+                ( (IOThreadFunc) &_IOConfigThread::main, inst )))
+	    continue;
+
+	return( inst );
+
+    } while( false);
+
+    if( inst)
+	inst->release();
+
+    return( 0 );
+}
+
+void _IOConfigThread::free( void )
+{
+    OSObject::free();
+}
+
+void IOService::doServiceMatch( IOOptionBits options )
+{
+    _IOServiceNotifier * notify;
+    OSIterator *	iter;
+    OSOrderedSet *	matches;
+    SInt32		catalogGeneration;
+    bool		keepGuessing = true;
+    bool		reRegistered = true;
+
+//    job->nub->deliverNotification( gIOPublishNotification,
+//  				kIOServiceRegisteredState, 0xffffffff );
+
+    while( keepGuessing ) {
+
+        matches = gIOCatalogue->findDrivers( this, &catalogGeneration );
+	// the matches list should always be created by findDrivers()
+        if( matches) {
+
+            lockForArbitration();
+            if( 0 == (__state[0] & kIOServiceFirstPublishState))
+                deliverNotification( gIOFirstPublishNotification,
+                                     kIOServiceFirstPublishState, 0xffffffff );
+	    LOCKREADNOTIFY();
+            __state[1] &= ~kIOServiceNeedConfigState;
+            __state[1] |= kIOServiceConfigState;
+            __state[0] |= kIOServiceRegisteredState;
+
+            if( reRegistered && (0 == (__state[0] & kIOServiceInactiveState))) {
+
+                iter = OSCollectionIterator::withCollection( (OSOrderedSet *)
+                        gNotifications->getObject( gIOPublishNotification ) );
+                if( iter) {
+                    while((notify = (_IOServiceNotifier *)
+                           iter->getNextObject())) {
+
+                        if( passiveMatch( notify->matching )
+                         && (kIOServiceNotifyEnable & notify->state))
+                            matches->setObject( notify );
+                    }
+                    iter->release();
+                }
+            }
+
+	    UNLOCKNOTIFY();
+            unlockForArbitration();
+
+            if( matches->getCount() && (kIOReturnSuccess == getResources()))
+                probeCandidates( matches );
+            else
+                matches->release();
+        }
+
+        lockForArbitration();
+	reRegistered = (0 != (__state[1] & kIOServiceNeedConfigState));
+	keepGuessing =
+		   (reRegistered || (catalogGeneration !=
+					gIOCatalogue->getGenerationCount()))
+                && (0 == (__state[0] & kIOServiceInactiveState));
+
+	if( keepGuessing)
+            unlockForArbitration();
+    }
+
+    if( (0 == (__state[0] & kIOServiceInactiveState))
+     && (0 == (__state[1] & kIOServiceModuleStallState)) ) {
+        deliverNotification( gIOMatchedNotification,
+		kIOServiceMatchedState, 0xffffffff );
+	if( 0 == (__state[0] & kIOServiceFirstMatchState))
+	    deliverNotification( gIOFirstMatchNotification,
+		kIOServiceFirstMatchState, 0xffffffff );
+    }
+
+    __state[1] &= ~kIOServiceConfigState;
+    if( __state[0] & kIOServiceInactiveState)
+        scheduleTerminatePhase2();
+
+    _adjustBusy( -1 );
+    unlockForArbitration();
+}
+
+UInt32 IOService::_adjustBusy( SInt32 delta )
+{
+    IOService * next;
+    UInt32	count;
+    UInt32	result;
+    bool	wasQuiet, nowQuiet, needWake;
+
+    next = this;
+    result = __state[1] & kIOServiceBusyStateMask;
+
+    if( delta) do {
+        if( next != this)
+            next->lockForArbitration();
+        count = next->__state[1] & kIOServiceBusyStateMask;
+        assert( count < kIOServiceBusyMax);
+        wasQuiet = (0 == count);
+        assert( (!wasQuiet) || (delta > 0));
+        next->__state[1] += delta;
+        nowQuiet = (0 == (next->__state[1] & kIOServiceBusyStateMask));
+	needWake = (0 != (kIOServiceBusyWaiterState & next->__state[1]));
+
+        if( needWake) {
+            next->__state[1] &= ~kIOServiceBusyWaiterState;
+            IOLockLock( gIOServiceBusyLock );
+	    thread_wakeup( (event_t) next);
+            IOLockUnlock( gIOServiceBusyLock );
+        }
+        if( next != this)
+            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();
+            }
+
+            if( nowQuiet && (next == gIOServiceRoot))
+                OSMetaClass::considerUnloads();
+        }
+
+        delta = nowQuiet ? -1 : +1;
+
+    } while( (wasQuiet || nowQuiet) && (next = next->getProvider()));
+
+    return( result );
+}
+
+void IOService::adjustBusy( SInt32 delta )
+{
+    lockForArbitration();
+    _adjustBusy( delta );
+    unlockForArbitration();
+}
+
+UInt32 IOService::getBusyState( void )
+{
+    return( __state[1] & kIOServiceBusyStateMask );
+}
+
+IOReturn IOService::waitForState( UInt32 mask, UInt32 value,
+				 mach_timespec_t * timeout = 0 )
+{
+    bool            wait;
+    int             waitResult = THREAD_AWAKENED;
+    bool            computeDeadline = true;
+    AbsoluteTime    abstime;
+
+    do {
+        lockForArbitration();
+        IOLockLock( gIOServiceBusyLock );
+        wait = (value != (__state[1] & mask));
+        if( wait) {
+            __state[1] |= kIOServiceBusyWaiterState;
+            unlockForArbitration();
+            assert_wait( (event_t) this, THREAD_UNINT );
+            if( timeout ) {
+                if( computeDeadline ) {
+                    AbsoluteTime  nsinterval;
+                    clock_interval_to_absolutetime_interval(
+                          timeout->tv_sec, kSecondScale, &abstime );
+                    clock_interval_to_absolutetime_interval(
+                          timeout->tv_nsec, kNanosecondScale, &nsinterval );
+                    ADD_ABSOLUTETIME( &abstime, &nsinterval );
+                    clock_absolutetime_interval_to_deadline(
+                          abstime, &abstime );
+                    computeDeadline = false;
+                }
+                thread_set_timer_deadline( abstime );
+            }
+        } else
+            unlockForArbitration();
+        IOLockUnlock( gIOServiceBusyLock );
+        if( wait) {
+            waitResult = thread_block((void (*)(void)) 0);
+            if( timeout && (waitResult != THREAD_TIMED_OUT))
+	    	thread_cancel_timer();
+        }
+
+    } while( wait && (waitResult != THREAD_TIMED_OUT));
+
+    if( waitResult == THREAD_TIMED_OUT)
+        return( kIOReturnTimeout );
+    else
+        return( kIOReturnSuccess );
+}
+
+IOReturn IOService::waitQuiet( mach_timespec_t * timeout = 0 )
+{
+    return( waitForState( kIOServiceBusyStateMask, 0, timeout ));
+}
+
+bool IOService::serializeProperties( OSSerialize * s ) const
+{
+#if 0
+    ((IOService *)this)->setProperty( ((IOService *)this)->__state,
+		sizeof( __state), "__state");
+#endif
+    return( super::serializeProperties(s) );
+}
+
+
+void _IOConfigThread::main( _IOConfigThread * self )
+{
+    _IOServiceJob *	job;
+    IOService 	*	nub;
+    bool		alive = true;
+
+    do {
+
+//	randomDelay();
+
+        semaphore_wait( gJobsSemaphore );
+
+	IOTakeLock( gJobsLock );
+	job = (_IOServiceJob *) gJobs->getFirstObject();
+        job->retain();
+        gJobs->removeObject(job);
+	if( job) {
+	    gOutstandingJobs--;
+//	    gNumConfigThreads--;	// we're out of service
+	    gNumWaitingThreads--;	// we're out of service
 	}
-	if (!ok) {
-		OSSafeReleaseNULL(obj);
-		return false;
+	IOUnlock( gJobsLock );
+
+	if( job) {
+
+	  nub = job->nub;
+
+          if( gIOKitDebug & kIOLogConfig)
+            LOG("config(%x): starting on %s, %d\n",
+                        (int) IOThreadSelf(), job->nub->getName(), job->type);
+
+	  switch( job->type) {
+
+	    case kMatchNubJob:
+		nub->doServiceMatch( job->options );
+		break;
+
+            default:
+                LOG("config(%x): strange type (%d)\n",
+			(int) IOThreadSelf(), job->type );
+		break;
+            }
+
+	    nub->release();
+            job->release();
+
+            IOTakeLock( gJobsLock );
+	    alive = (gOutstandingJobs > gNumWaitingThreads);
+	    if( alive)
+		gNumWaitingThreads++;	// back in service
+//		gNumConfigThreads++;
+	    else {
+                if( 0 == --gNumConfigThreads) {
+//                    IOLog("MATCH IDLE\n");
+                    thread_wakeup( (event_t) &gNumConfigThreads);
+                }
+            }
+            IOUnlock( gJobsLock );
 	}
 
-	if ((this != gIOResources) && (this != gIOUserResources)) {
-		// stall for any nub resources
-		checkResources();
-		// stall for any driver resources
-		service->checkResources();
+    } while( alive );
+
+    if( gIOKitDebug & kIOLogConfig)
+        LOG("config(%x): terminating\n", (int) IOThreadSelf() );
+
+    self->release();
+}
+
+IOReturn IOService::waitMatchIdle( UInt32 msToWait )
+{
+    bool            wait;
+    int             waitResult = THREAD_AWAKENED;
+    bool            computeDeadline = true;
+    AbsoluteTime    abstime;
+
+    do {
+        IOLockLock( gJobsLock );
+        wait = (0 != gNumConfigThreads);
+        if( wait) {
+            assert_wait( (event_t) &gNumConfigThreads, THREAD_UNINT );
+            if( msToWait) {
+                if( computeDeadline ) {
+                    clock_interval_to_absolutetime_interval(
+                          msToWait, kMillisecondScale, &abstime );
+                    clock_absolutetime_interval_to_deadline(
+                          abstime, &abstime );
+                    computeDeadline = false;
+                }
+                thread_set_timer_deadline( abstime );
+            }
+        }
+        IOUnlock( gJobsLock );
+        if( wait) {
+            waitResult = thread_block((void (*)(void)) 0);
+            if( msToWait && (waitResult != THREAD_TIMED_OUT))
+	    	thread_cancel_timer();
+        }
+
+    } while( wait && (waitResult != THREAD_TIMED_OUT));
+
+    if( waitResult == THREAD_TIMED_OUT)
+        return( kIOReturnTimeout );
+    else
+        return( kIOReturnSuccess );
+}
+
+void _IOServiceJob::pingConfig( _IOServiceJob * job )
+{
+    int		count;
+    bool	create;
+
+    assert( job );
+
+    IOTakeLock( gJobsLock );
+
+    gOutstandingJobs++;
+    gJobs->setLastObject( job );
+
+    count = gNumWaitingThreads;
+//    if( gNumConfigThreads) count++;// assume we're called from a config thread
+
+    create = (  (gOutstandingJobs > count)
+		&& (gNumConfigThreads < kMaxConfigThreads) );
+    if( create) {
+	gNumConfigThreads++;
+	gNumWaitingThreads++;
+    }
+
+    IOUnlock( gJobsLock );
+
+    job->release();
+
+    if( create) {
+        if( gIOKitDebug & kIOLogConfig)
+            LOG("config(%d): creating\n", gNumConfigThreads - 1);
+        _IOConfigThread::configThread();
+    }
+
+    semaphore_signal( gJobsSemaphore );
+}
+
+
+// internal - call with gNotificationLock
+OSObject * IOService::getExistingServices( OSDictionary * matching,
+		 IOOptionBits inState, IOOptionBits options = 0 )
+{
+    OSObject *		current = 0;
+    OSIterator *	iter;
+    IOService *		service;
+
+    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( current && (0 == (options & kIONotifyOnce))) {
+	iter = OSCollectionIterator::withCollection( (OSSet *)current );
+	current->release();
+	current = iter;
+    }
+
+    return( current );
+}
+
+// public version
+OSIterator * IOService::getMatchingServices( OSDictionary * matching )
+{
+    OSIterator *	iter;
+
+    // is a lock even needed?
+    LOCKWRITENOTIFY();
+
+    iter = (OSIterator *) getExistingServices( matching,
+						kIOServiceMatchedState );
+    
+    UNLOCKNOTIFY();
+
+    return( iter );
+}
+
+
+// internal - call with gNotificationLock
+IONotifier * IOService::setNotification(
+	    const OSSymbol * type, OSDictionary * matching,
+            IOServiceNotificationHandler handler, void * target, void * ref,
+            SInt32 priority = 0 )
+{
+    _IOServiceNotifier * notify = 0;
+    OSOrderedSet *	set;
+
+    if( !matching)
+	return( 0 );
+
+    notify = new _IOServiceNotifier;
+    if( notify && !notify->init()) {
+        notify->release();
+        notify = 0;
+    }
+
+    if( notify) {
+        notify->matching = matching;
+        notify->handler = handler;
+        notify->target = target;
+        notify->ref = ref;
+        notify->priority = priority;
+	notify->state = kIOServiceNotifyEnable;
+        queue_init( &notify->handlerInvocations );
+
+        ////// queue
+
+        if( 0 == (set = (OSOrderedSet *) gNotifications->getObject( type ))) {
+            set = OSOrderedSet::withCapacity( 1,
+			IONotifyOrdering, 0 );
+            if( set) {
+                gNotifications->setObject( type, set );
+                set->release();
+            }
+        }
+        notify->whence = set;
+        if( set)
+            set->setObject( notify );
+    }
+
+    return( notify );
+}
+
+// internal - call with gNotificationLock
+IONotifier * IOService::doInstallNotification(
+			const OSSymbol * type, OSDictionary * matching,
+			IOServiceNotificationHandler handler,
+			void * target, void * ref,
+			SInt32 priority, OSIterator ** existing )
+{
+    OSIterator *	exist;
+    IONotifier *	notify;
+    IOOptionBits	inState;
+
+    if( !matching)
+	return( 0 );
+
+    if( type == gIOPublishNotification)
+	inState = kIOServiceRegisteredState;
+
+    else if( type == gIOFirstPublishNotification)
+	inState = kIOServiceFirstPublishState;
+
+    else if( (type == gIOMatchedNotification)
+	  || (type == gIOFirstMatchNotification))
+	inState = kIOServiceMatchedState;
+    else if( type == gIOTerminatedNotification)
+	inState = 0;
+    else
+        return( 0 );
+
+    notify = setNotification( type, matching, handler, target, ref, priority );
+    
+    if( inState)
+        // get the current set
+        exist = (OSIterator *) getExistingServices( matching, inState );
+    else
+	exist = 0;
+
+    *existing = exist;    
+
+    return( notify );
+}
+
+
+IONotifier * IOService::installNotification(
+			const OSSymbol * type, OSDictionary * matching,
+			IOServiceNotificationHandler handler,
+			void * target, void * ref,
+			SInt32 priority, OSIterator ** existing )
+{
+    IONotifier *	notify;
+
+    LOCKWRITENOTIFY();
+
+    notify = doInstallNotification( type, matching, handler, target, ref,
+		priority, existing );
+
+    UNLOCKNOTIFY();
+
+    return( notify );
+}
+
+IONotifier * IOService::addNotification(
+			const OSSymbol * type, OSDictionary * matching,
+			IOServiceNotificationHandler handler,
+			void * target, void * ref = 0,
+			SInt32 priority = 0 )
+{
+    OSIterator *		existing;
+    _IOServiceNotifier *	notify;
+    IOService *			next;
+
+    notify = (_IOServiceNotifier *) installNotification( type, matching,
+		handler, target, ref, priority, &existing );
+
+    // send notifications for existing set
+    if( existing) {
+
+        notify->retain();		// in case handler remove()s
+        while( (next = (IOService *) existing->getNextObject())) {
+
+	    next->lockForArbitration();
+	    if( 0 == (next->__state[0] & kIOServiceInactiveState))
+                next->invokeNotifer( notify );
+	    next->unlockForArbitration();
 	}
-	ph = false;
-	{
-		OSString       * bundleID;
-		OSString       * serverName;
-		OSString       * str;
-		const OSSymbol * sym;
-		OSNumber       * serverTag;
-		uint64_t         entryID;
-		OSData         * serverDUI;
-
-		if ((serverName = OSDynamicCast(OSString, obj))) {
-			obj       = service->copyProperty(gIOModuleIdentifierKey);
-			bundleID  = OSDynamicCast(OSString, obj);
-			entryID   = service->getRegistryEntryID();
-			serverTag = OSNumber::withNumber(entryID, 64);
-
-			if (kIODKDisableDextLaunch & gIODKDebug) {
-				DKLOG(DKS " dext launches are disabled \n", DKN(service));
-				service->detach(this);
-				OSSafeReleaseNULL(serverName);
-				OSSafeReleaseNULL(obj);
-				OSSafeReleaseNULL(serverTag);
-				return false;
-			}
-
-			if (gIOKitWillTerminate) {
-				DKLOG("%s disabled in shutdown\n", serverName->getCStringNoCopy());
-				service->detach(this);
-				OSSafeReleaseNULL(serverName);
-				OSSafeReleaseNULL(obj);
-				OSSafeReleaseNULL(serverTag);
-				return false;
-			}
-
-			ph = IOServicePH::matchingStart(this);
-			if (!ph) {
-				DKLOG("%s deferred in sleep\n", serverName->getCStringNoCopy());
-				service->setProperty(gIOServiceMatchDeferredKey, kOSBooleanTrue);
-				service->detach(this);
-				OSSafeReleaseNULL(serverName);
-				OSSafeReleaseNULL(obj);
-				OSSafeReleaseNULL(serverTag);
-				return false;
-			}
-
-			prop = service->copyProperty(gIOUserClassKey);
-			str = OSDynamicCast(OSString, prop);
-			if (str) {
-				service->setName(str);
-			}
-			OSSafeReleaseNULL(prop);
-
-			sym = OSSymbol::withString(serverName);
-			bool reuse = service->propertyExists(gIOUserServerOneProcessKey);
-			serverDUI = OSDynamicCast(OSData, service->getProperty(kOSBundleDextUniqueIdentifierKey));
-			userServer = IOUserServer::launchUserServer(this, service, bundleID, sym, serverTag, reuse, serverDUI);
-			OSSafeReleaseNULL(sym);
-			OSSafeReleaseNULL(serverTag);
-			OSSafeReleaseNULL(serverName);
-			if (!userServer) {
-				DKLOG(DKS " failed to launch server\n", DKN(service));
-			}
-
-			if (!userServer) {
-				service->detach(this);
-				IOServicePH::matchingEnd(this);
-				OSSafeReleaseNULL(obj);
-				return false;
-			}
-
-			OSSafeReleaseNULL(obj);
-
-			if (!(kIODKDisableEntitlementChecking & gIODKDebug)) {
-				if (!userServer->checkEntitlements(this, service)) {
-					service->detach(this);
-					IOServicePH::matchingEnd(this);
-					userServer->exit("Entitlements check failed");
-					userServer->release();
-					return false;
-				}
-			}
-#if !XNU_TARGET_OS_OSX && !(DEVELOPMENT || DEBUG)
-			// Prevent third party drivers from matching IOUserResources/IOResources, except when signed for development
-			if (!userServer->isPlatformDriver() &&
-			    userServer->getCSValidationCategory() != CS_VALIDATION_CATEGORY_DEVELOPMENT
-			    && (this == gIOUserResources || this == gIOResources)) {
-				service->detach(this);
-				IOServicePH::matchingEnd(this);
-				userServer->exit("Third party driver may only match real hardware");
-				userServer->release();
-				return false;
-			}
-#endif /* !XNU_TARGET_OS_OSX && !(DEVELOPMENT || DEBUG) */
-
-			userServer->serviceAttach(service, this);
-		} else {
-			OSSafeReleaseNULL(obj);
-		}
-	}
-
-	AbsoluteTime startTime;
-	AbsoluteTime endTime;
-	UInt64       nano;
-	bool recordTime = (kIOLogStart & gIOKitDebug) != 0;
-
-	if (recordTime) {
-		clock_get_uptime(&startTime);
-	}
-
-#if DEBUG || DEVELOPMENT
-	service->__patchProperties();
-#endif /* DEBUG || DEVELOPMENT */
-
-	ok = service->start(this);
-
-	if (recordTime) {
-		clock_get_uptime(&endTime);
-
-		if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
-			SUB_ABSOLUTETIME(&endTime, &startTime);
-			absolutetime_to_nanoseconds(endTime, &nano);
-			if (nano > 500000000ULL) {
-				IOLog("%s[0x%qx]::start took %ld ms\n", service->getName(), service->getRegistryEntryID(), (long)(UInt32)(nano / 1000000ULL));
-			}
-		}
-	}
-	if (userServer) {
-		userServer->serviceStarted(service, this, ok);
-		userServer->release();
-	}
-
-	if (ok) {
-		IOInstallServiceSleepPlatformActions(service);
-#if 00
-		if (!strcmp("XHC1", getName())) {
-			service->setProperty(gIOPrimaryDriverTerminateOptionsKey, kOSBooleanTrue);
-		}
-#endif
-	}
-
-	if (!ok) {
-		service->detach( this );
-	}
-
-	if (ph) {
-		IOServicePH::matchingEnd(this);
-	}
-
-	return ok;
-}
-
-void
-IOService::publishResource( const char * key, OSObject * value )
-{
-	const OSSymbol *    sym;
-
-	if ((sym = OSSymbol::withCString( key))) {
-		publishResource( sym, value);
-		sym->release();
-	}
-}
-
-void
-IOService::publishResource( const OSSymbol * key, OSObject * value )
-{
-	if (NULL == value) {
-		value = (OSObject *) gIOServiceKey;
-	}
-
-	gIOResources->setProperty( key, value);
-
-	if (IORecursiveLockHaveLock( gNotificationLock)) {
-		return;
-	}
-
-	gIOResourceGenerationCount++;
-	gIOResources->registerService();
-}
-
-void
-IOService::publishUserResource( const OSSymbol * key, OSObject * value )
-{
-	if (NULL == value) {
-		value = (OSObject *) gIOServiceKey;
-	}
-
-	gIOUserResources->setProperty( key, value);
-
-	if (IORecursiveLockHaveLock( gNotificationLock)) {
-		return;
-	}
-
-	gIOResourceGenerationCount++;
-	gIOUserResources->registerService();
-}
-
-bool
-IOService::addNeededResource( const char * key )
-{
-	OSObject *  resourcesProp;
-	OSSet *     set;
-	OSString *  newKey;
-	bool ret;
-
-	resourcesProp = copyProperty( gIOResourceMatchKey );
-	if (!resourcesProp) {
-		return false;
-	}
-
-	newKey = OSString::withCString( key );
-	if (!newKey) {
-		resourcesProp->release();
-		return false;
-	}
-
-	set = OSDynamicCast( OSSet, resourcesProp );
-	if (!set) {
-		set = OSSet::withCapacity( 1 );
-		set->setObject( resourcesProp );
-	} else {
-		set->retain();
-	}
-
-	set->setObject( newKey );
-	newKey->release();
-	ret = setProperty( gIOResourceMatchKey, set );
-	set->release();
-	resourcesProp->release();
-
-	return ret;
-}
-
-bool
-IOService::checkResource( OSObject * matching )
-{
-	OSString *          str;
-	OSDictionary *      table;
-
-	if ((str = OSDynamicCast( OSString, matching ))) {
-		if (gIOResources->getProperty( str )) {
-			return true;
-		}
-	}
-
-	if (str) {
-		table = resourceMatching( str );
-	} else if ((table = OSDynamicCast( OSDictionary, matching ))) {
-		table->retain();
-	} else {
-		IOLog("%s: Can't match using: %s\n", getName(),
-		    matching->getMetaClass()->getClassName());
-		/* false would stall forever */
-		return true;
-	}
-
-	if (gIOKitDebug & kIOLogConfig) {
-		LOG("config(%p): stalling %s\n", IOSERVICE_OBFUSCATE(IOThreadSelf()), getName());
-	}
-
-	waitForService( table );
-
-	if (gIOKitDebug & kIOLogConfig) {
-		LOG("config(%p): waking\n", IOSERVICE_OBFUSCATE(IOThreadSelf()));
-	}
-
-	return true;
-}
-
-bool
-IOService::checkResources( void )
-{
-	OSObject *          resourcesProp;
-	OSSet *             set;
-	OSObject *          obj;
-	OSIterator *        iter;
-	bool                ok;
-
-	resourcesProp = copyProperty( gIOResourceMatchKey );
-	if (NULL == resourcesProp) {
-		return true;
-	}
-
-	if ((set = OSDynamicCast( OSSet, resourcesProp ))) {
-		iter = OSCollectionIterator::withCollection( set );
-		ok = (NULL != iter);
-		while (ok && (obj = iter->getNextObject())) {
-			ok = checkResource( obj );
-		}
-		if (iter) {
-			iter->release();
-		}
-	} else {
-		ok = checkResource( resourcesProp );
-	}
-
-	OSSafeReleaseNULL(resourcesProp);
-
-	return ok;
-}
-
-
-void
-_IOConfigThread::configThread( const char * name )
-{
-	_IOConfigThread *   inst;
-
-	do {
-		if (!(inst = new _IOConfigThread)) {
-			continue;
-		}
-		if (!inst->init()) {
-			continue;
-		}
-		thread_t thread;
-		if (KERN_SUCCESS != kernel_thread_start(&_IOConfigThread::main, inst, &thread)) {
-			continue;
-		}
-
-		char threadName[MAXTHREADNAMESIZE];
-		snprintf(threadName, sizeof(threadName), "IOConfigThread_'%s'", name);
-		thread_set_thread_name(thread, threadName);
-		thread_deallocate(thread);
-
-		return;
-	} while (false);
-
-	if (inst) {
-		inst->release();
-	}
-
-	return;
-}
-
-/*
- * To support driver replacement of boot matched drivers later in boot, drivers can
- * opt-in to be being terminated if a non-boot driver matches their provider, by
- * setting the gIOPrimaryDriverTerminateOptionsKey property. The driver providing the
- * root disk media may not be terminated.
- * IOMedia objects are hidden from user space until all drivers are available, but any
- * associated with the root disk must be published immediately.
- */
-
-struct FindRootMediaContext {
-	OSArray   * services;
-	IOService * parent;
+        notify->release();
+	existing->release();
+    }
+
+    return( notify );
+}
+
+struct SyncNotifyVars {
+    semaphore_port_t	waitHere;
+    IOService *		result;
 };
 
-bool
-IOService::hasParent(IOService * parent)
-{
-	IOService * service;
-
-	for (service = this;
-	    service && (service != parent);
-	    service = service->getProvider()) {
-	}
-
-	return service != NULL;
-}
-
-bool
-IOService::publishHiddenMediaApplier(const OSObject * entry, void * context)
-{
-	FindRootMediaContext * ctx     = (typeof(ctx))context;
-	IOService            * service = (typeof(service))entry;
-
-	do {
-		if (ctx->parent && !service->hasParent(ctx->parent)) {
-			break;
-		}
-		if (ctx->services) {
-			ctx->services->setObject(service);
-		} else {
-			ctx->services  = OSArray::withObjects((const OSObject **) &service, 1);
-			assert(ctx->services);
-		}
-	} while (false);
-
-	return false;
-}
-
-// publish to user space any hidden IOMedia under the 'parent' object, or all
-// if 'parent' is NULL
-
-void
-IOService::publishHiddenMedia(IOService * parent)
-{
-	const OSMetaClass * iomediaClass;
-	bool                wasHiding;
-
-	iomediaClass = OSMetaClass::getMetaClassWithName(gIOMediaKey);
-	assert(iomediaClass);
-
-	LOCKWRITENOTIFY();
-	wasHiding = gIOServiceHideIOMedia;
-	if (wasHiding && !parent) {
-		gIOServiceHideIOMedia = false;
-	}
-	UNLOCKNOTIFY();
-
-	FindRootMediaContext ctx = { .services = NULL, .parent = parent };
-
-	if (wasHiding) {
-		iomediaClass->applyToInstances(publishHiddenMediaApplier, &ctx);
-	}
-	if (ctx.services) {
-		unsigned int idx, notiIdx;
-		IOService * service;
-		OSArray   * notifiers[3] = {};
-
-		for (idx = 0; (service = (IOService *) ctx.services->getObject(idx)); idx++) {
-			service->lockForArbitration(true);
-			if (!(kIOServiceUserInvisibleMatchState & service->__state[0])) {
-				service->unlockForArbitration();
-				continue;
-			}
-			service->__state[0] &= ~kIOServiceUserInvisibleMatchState;
-			service->__state[1] |= kIOServiceUserUnhidden;
-			notifiers[0] = service->copyNotifiers(gIOFirstPublishNotification, 0, 0xffffffff);
-			if (kIOServiceMatchedState & service->__state[0]) {
-				notifiers[1] = service->copyNotifiers(gIOMatchedNotification, 0, 0xffffffff);
-			}
-			if (kIOServiceFirstMatchState & service->__state[0]) {
-				notifiers[2] = service->copyNotifiers(gIOFirstMatchNotification, 0, 0xffffffff);
-			}
-			service->unlockForArbitration();
-			for (notiIdx = 0; notiIdx < 3; notiIdx++) {
-				service->invokeNotifiers(&notifiers[notiIdx]);
-			}
-		}
-		OSSafeReleaseNULL(ctx.services);
-	}
-}
-
-// Find the block storage driver providing the root disk, or NULL if not booting from
-// a block device
-
-void
-IOService::setRootMedia(IOService * root)
-{
-	const OSMetaClass * ioblockstoragedriverClass;
-	bool unhide;
-
-	ioblockstoragedriverClass = OSMetaClass::getMetaClassWithName(gIOBlockStorageDriverKey);
-	assert(ioblockstoragedriverClass);
-
-	while (root) {
-		if (root->metaCast(ioblockstoragedriverClass)) {
-			break;
-		}
-		root = root->getProvider();
-	}
-
-	LOCKWRITENOTIFY();
-	unhide = (kIOServiceRootMediaParentInvalid == gIOServiceRootMediaParent);
-	if (unhide) {
-		gIOServiceRootMediaParent = root;
-	}
-	UNLOCKNOTIFY();
-
-	if (unhide) {
-		if (root) {
-			root->addPMDriverClass(kIOPMDriverClassStorage);
-		}
-		publishHiddenMedia(root);
-	}
-}
-
-// Check if the driver may be terminated when a later driver could be used instead
-
-bool
-IOService::canTerminateForReplacement(IOService * client)
-{
-	IOService * parent;
-
-	assert(kIOServiceRootMediaParentInvalid != gIOServiceRootMediaParent);
-
-	if (!gIOServiceHideIOMedia) {
-		return false;
-	}
-	if (!client->propertyExists(gIOPrimaryDriverTerminateOptionsKey)) {
-		return false;
-	}
-	if (!gIOServiceRootMediaParent) {
-		return false;
-	}
-	parent = gIOServiceRootMediaParent;
-	while (parent && (parent != client)) {
-		parent = parent->getProvider();
-	}
-	if (parent) {
-		IOLog("Can't replace primary matched driver on root media %s-0x%qx\n",
-		    client->getName(), client->getRegistryEntryID());
-		return false;
-	}
-	return true;
-}
-
-void
-IOService::doServiceMatch( IOOptionBits options )
-{
-	_IOServiceNotifier * notify;
-	OSIterator *        iter;
-	OSOrderedSet *      matches;
-	OSArray *           resourceKeys = NULL;
-	SInt32              catalogGeneration;
-	bool                keepGuessing = true;
-	bool                reRegistered = true;
-	bool                didRegister;
-	OSArray *           notifiers[2] = {NULL};
-
-//    job->nub->deliverNotification( gIOPublishNotification,
-//                              kIOServiceRegisteredState, 0xffffffff );
-
-	while (keepGuessing) {
-		matches = gIOCatalogue->findDrivers( this, &catalogGeneration );
-		// the matches list should always be created by findDrivers()
-		if (matches) {
-			lockForArbitration();
-			if (0 == (__state[0] & kIOServiceFirstPublishState)) {
-				getMetaClass()->addInstance(this);
-				notifiers[0] = copyNotifiers(gIOFirstPublishNotification,
-				    kIOServiceFirstPublishState, 0xffffffff );
-			}
-			LOCKREADNOTIFY();
-			__state[1] &= ~kIOServiceNeedConfigState;
-			__state[1] |= kIOServiceConfigState | kIOServiceConfigRunning;
-			didRegister = (0 == (kIOServiceRegisteredState & __state[0]));
-			__state[0] |= kIOServiceRegisteredState;
-
-			if (gIOServiceHideIOMedia
-			    && metaCast(gIOMediaKey)
-			    && !(kIOServiceUserUnhidden & __state[1])
-			    && gIOServiceRootMediaParent
-			    && !hasParent(gIOServiceRootMediaParent)
-			    && propertyExists(gIOPrimaryDriverTerminateOptionsKey, gIOServicePlane)) {
-				__state[0] |= kIOServiceUserInvisibleMatchState;
-			}
-
-			keepGuessing &= (0 == (__state[0] & kIOServiceInactiveState));
-			if (reRegistered && keepGuessing) {
-				iter = OSCollectionIterator::withCollection((OSOrderedSet *)
-				    gNotifications->getObject( gIOPublishNotification ));
-				if (iter) {
-					while ((notify = (_IOServiceNotifier *)
-					    iter->getNextObject())) {
-						if (matchPassive(notify->matching, 0)
-						    && (kIOServiceNotifyEnable & notify->state)) {
-							matches->setObject( notify );
-						}
-					}
-					iter->release();
-				}
-			}
-
-			UNLOCKNOTIFY();
-			unlockForArbitration();
-			invokeNotifiers(&notifiers[0]);
-			if (keepGuessing && matches->getCount() && (kIOReturnSuccess == getResources())) {
-				if ((this == gIOResources) || (this == gIOUserResources)) {
-					if (resourceKeys) {
-						resourceKeys->release();
-					}
-					resourceKeys = copyPropertyKeys();
-				}
-				probeCandidates( matches );
-			} else {
-				matches->release();
-			}
-		}
-
-		lockForArbitration();
-		reRegistered = (0 != (__state[1] & kIOServiceNeedConfigState));
-		keepGuessing =
-		    (reRegistered || (catalogGeneration !=
-		    gIOCatalogue->getGenerationCount()))
-		    && (0 == (__state[0] & kIOServiceInactiveState));
-
-		if (keepGuessing) {
-			unlockForArbitration();
-		}
-	}
-
-	if ((0 == (__state[0] & kIOServiceInactiveState))
-	    && (0 == (__state[1] & kIOServiceModuleStallState))) {
-		if (resourceKeys) {
-			setProperty(gIOResourceMatchedKey, resourceKeys);
-		}
-
-		notifiers[0] = copyNotifiers(gIOMatchedNotification,
-		    kIOServiceMatchedState, 0xffffffff);
-		if (0 == (__state[0] & kIOServiceFirstMatchState)) {
-			notifiers[1] = copyNotifiers(gIOFirstMatchNotification,
-			    kIOServiceFirstMatchState, 0xffffffff);
-		}
-	}
-
-	__state[1] &= ~kIOServiceConfigRunning;
-	unlockForArbitration();
-
-	if (resourceKeys) {
-		resourceKeys->release();
-	}
-
-	invokeNotifiers(&notifiers[0]);
-	invokeNotifiers(&notifiers[1]);
-
-	lockForArbitration();
-	__state[1] &= ~kIOServiceConfigState;
-	scheduleTerminatePhase2();
-
-	_adjustBusy(-1, /*unlock*/ true);
-	// does	unlockForArbitration();
-}
-
-UInt32
-IOService::_adjustBusy(SInt32 delta)
-{
-	return _adjustBusy(delta, false);
-}
-
-UInt32
-IOService::_adjustBusy(SInt32 delta, bool unlock)
-{
-	IOService * next;
-	IOService * nextProvider;
-	UInt32      count;
-	UInt32      result;
-	bool        wasQuiet, nowQuiet, needWake;
-
-	next = this;
-	result = __state[1] & kIOServiceBusyStateMask;
-
-	if (delta) {
-		do {
-			if (next != this) {
-				next->lockForArbitration();
-			}
-			count = next->__state[1] & kIOServiceBusyStateMask;
-			wasQuiet = (0 == count);
-			if (((delta < 0) && wasQuiet) || ((delta > 0) && (kIOServiceBusyMax == count))) {
-				OSReportWithBacktrace("%s: bad busy count (%d,%d)\n", next->getName(), (uint32_t)count, (int)delta);
-			} else {
-				count += delta;
-			}
-			next->__state[1] = (next->__state[1] & ~kIOServiceBusyStateMask) | count;
-			nowQuiet = (0 == count);
-			needWake = (0 != (kIOServiceBusyWaiterState & next->__state[1]));
-
-			if (needWake) {
-				next->__state[1] &= ~kIOServiceBusyWaiterState;
-				IOLockLock( gIOServiceBusyLock );
-				thread_wakeup((event_t) next);
-				IOLockUnlock( gIOServiceBusyLock );
-			}
-			if (wasQuiet || nowQuiet) {
-				nextProvider = next->getProvider();
-				if (nextProvider) {
-					nextProvider->retain();
-				}
-			}
-			if ((next != this) || unlock) {
-				next->unlockForArbitration();
-			}
-
-			if ((wasQuiet || nowQuiet)) {
-				uint64_t regID = next->getRegistryEntryID();
-				IOServiceTrace(
-					((wasQuiet /*nowBusy*/) ? IOSERVICE_BUSY : IOSERVICE_NONBUSY),
-					(uintptr_t) regID,
-					(uintptr_t) (regID >> 32),
-					(uintptr_t) next,
-					0);
-
-				if (wasQuiet) {
-					next->__timeBusy = mach_absolute_time();
-				} else {
-					next->__accumBusy += mach_absolute_time() - next->__timeBusy;
-					next->__timeBusy = 0;
-				}
-
-				MessageClientsContext context;
-
-				context.service  = next;
-				context.type     = kIOMessageServiceBusyStateChange;
-				context.argument = (void *) wasQuiet; /*nowBusy*/
-				context.argSize  = 0;
-
-				applyToInterestNotifiers( next, gIOBusyInterest,
-				    &messageClientsApplier, &context );
-
-#if !NO_KEXTD
-				if (nowQuiet && (next == gIOServiceRoot)) {
-					if (gIOServiceHideIOMedia) {
-						publishHiddenMedia(NULL);
-					}
-
-					OSKext::considerUnloads();
-					IOServiceTrace(IOSERVICE_REGISTRY_QUIET, 0, 0, 0, 0);
-				}
-#endif
-			}
-
-			delta = nowQuiet ? -1 : +1;
-			if (next != this) {
-				next->release();
-			}
-			next = nextProvider;
-			nextProvider = NULL;
-		} while ((wasQuiet || nowQuiet) && next);
-	}
-
-	return result;
-}
-
-void
-IOService::adjustBusy( SInt32 delta )
-{
-	lockForArbitration();
-	_adjustBusy( delta );
-	unlockForArbitration();
-}
-
-uint64_t
-IOService::getAccumulatedBusyTime( void )
-{
-	uint64_t accumBusy = __accumBusy;
-	uint64_t timeBusy = __timeBusy;
-	uint64_t nano;
-
-	do{
-		accumBusy = __accumBusy;
-		timeBusy  = __timeBusy;
-		if (timeBusy) {
-			accumBusy += mach_absolute_time() - timeBusy;
-		}
-	}while (timeBusy != __timeBusy);
-
-	absolutetime_to_nanoseconds(*(AbsoluteTime *)&accumBusy, &nano);
-
-	return nano;
-}
-
-UInt32
-IOService::getBusyState( void )
-{
-	return __state[1] & kIOServiceBusyStateMask;
-}
-
-IOReturn
-IOService::waitForState( UInt32 mask, UInt32 value,
-    mach_timespec_t * timeout )
-{
-	panic("waitForState");
-	return kIOReturnUnsupported;
-}
-
-IOReturn
-IOService::waitForState( UInt32 mask, UInt32 value,
-    uint64_t timeout )
-{
-	bool            wait, done;
-	int             waitResult = THREAD_AWAKENED;
-	bool            computeDeadline = true;
-	AbsoluteTime    abstime;
-
-	do {
-		lockForArbitration();
-		IOLockLock( gIOServiceBusyLock );
-		done = (value == (__state[1] & mask));
-		wait = (waitResult != THREAD_TIMED_OUT) && !done;
-		if (wait) {
-			__state[1] |= kIOServiceBusyWaiterState;
-			unlockForArbitration();
-			if (timeout != UINT64_MAX) {
-				if (computeDeadline) {
-					AbsoluteTime  nsinterval;
-					nanoseconds_to_absolutetime(timeout, &nsinterval );
-					clock_absolutetime_interval_to_deadline(nsinterval, &abstime);
-					computeDeadline = false;
-				}
-				assert_wait_deadline((event_t)this, THREAD_UNINT, __OSAbsoluteTime(abstime));
-			} else {
-				assert_wait((event_t)this, THREAD_UNINT );
-			}
-		} else {
-			unlockForArbitration();
-		}
-		IOLockUnlock( gIOServiceBusyLock );
-		if (wait) {
-			waitResult = thread_block(THREAD_CONTINUE_NULL);
-		}
-	} while (wait);
-
-	if (done) {
-		return kIOReturnSuccess;
-	} else {
-		return kIOReturnTimeout;
-	}
-}
-
-IOReturn
-IOService::waitQuietWithOptions( uint64_t timeout, IOOptionBits options )
-{
-	IOReturn ret;
-	uint32_t loops, timeoutExtensions;
-	char *   busyEntriesString = NULL;
-	char *   panicString = NULL;
-	size_t   busyEntriesStringLen;
-	size_t   panicStringLen;
-	uint64_t time;
-	uint64_t nano;
-	bool     pendingRequests;
-	bool     registryRootBusy;
-	bool     multipleEntries;
-	bool     dopanic = false;
-
-	enum { kIOServiceBusyTimeoutExtensionsMax = 8 };
-#if KASAN
-	/*
-	 * On kasan kernels, everything takes longer, so double the number of
-	 * timeout extensions. This should help with issues like 41259215
-	 * where WindowServer was timing out waiting for kextd to get all the
-	 * kasan kexts loaded and started.
-	 *
-	 * On legacy/x86 systems give a bit more time since we may be
-	 * booting from a HDD.
-	 */
-	enum { kTimeoutExtensions = 8 };
-#define WITH_IOWAITQUIET_EXTENSIONS 1
-#elif defined(__x86_64__)
-	enum { kTimeoutExtensions = 4 };
-#define WITH_IOWAITQUIET_EXTENSIONS 1
-#elif  defined(XNU_TARGET_OS_OSX)
-	enum { kTimeoutExtensions = 1 };
-#define WITH_IOWAITQUIET_EXTENSIONS 1
-#else
-	enum { kTimeoutExtensions = 1 };
-#define WITH_IOWAITQUIET_EXTENSIONS 0
-#endif
-
-	timeoutExtensions = kTimeoutExtensions;
-	time = mach_absolute_time();
-	pendingRequests = false;
-	for (loops = 0; loops < timeoutExtensions; loops++) {
-		ret = waitForState( kIOServiceBusyStateMask, 0, timeout );
-
-		if (loops && (kIOReturnSuccess == ret)) {
-			time = mach_absolute_time() - time;
-			absolutetime_to_nanoseconds(*(AbsoluteTime *)&time, &nano);
-			IOLog("busy extended ok[%d], (%llds, %llds)\n",
-			    loops, timeout / 1000000000ULL, nano / 1000000000ULL);
-			break;
-		} else if (kIOReturnTimeout != ret) {
-			break;
-		} else if (timeout < (41ull * NSEC_PER_SEC)) {
-			break;
-		}
-
-		{
-			IORegistryIterator * iter;
-			OSOrderedSet       * set;
-			OSOrderedSet       * leaves;
-			IOService          * next;
-			IOService          * nextParent;
-			char               * s;
-			size_t               l;
-			size_t               busyEntriesStringRemaining;
-
-			busyEntriesStringLen = 256;
-			panicStringLen = 256;
-			if (!busyEntriesString) {
-				busyEntriesString = IONewZeroData(char, busyEntriesStringLen);
-				assert(busyEntriesString != NULL);
-			}
-			if (!panicString) {
-				panicString = IONewZeroData(char, panicStringLen);
-				assert(panicString != NULL);
-			}
-
-			set = NULL;
-			pendingRequests = OSKext::pendingIOKitDaemonRequests();
-			iter = IORegistryIterator::iterateOver(this, gIOServicePlane, kIORegistryIterateRecursively);
-			leaves = OSOrderedSet::withCapacity(4);
-			if (iter) {
-				set = iter->iterateAll();
-			}
-			if (leaves && set) {
-				busyEntriesString[0] = panicString[0] = 0;
-				set->setObject(this);
-				while ((next = (IOService *) set->getLastObject())) {
-					if (next->getBusyState()) {
-						if (kIOServiceModuleStallState & next->__state[1]) {
-							pendingRequests = true;
-						}
-#if defined(XNU_TARGET_OS_OSX)
-						OSObject * prop;
-						if ((prop = next->copyProperty(kIOServiceBusyTimeoutExtensionsKey, gIOServicePlane))) {
-							OSNumber * num;
-							uint32_t   value;
-							if ((num = OSDynamicCast(OSNumber, prop))) {
-								value = num->unsigned32BitValue();
-								if (value
-								    && (value <= kIOServiceBusyTimeoutExtensionsMax)
-								    && (value > timeoutExtensions)) {
-									timeoutExtensions = value;
-								}
-							}
-							OSSafeReleaseNULL(prop);
-						}
-#endif /* defined(XNU_TARGET_OS_OSX) */
-						leaves->setObject(next);
-						nextParent = next;
-						while ((nextParent = nextParent->getProvider())) {
-							set->removeObject(nextParent);
-							leaves->removeObject(nextParent);
-						}
-					}
-					set->removeObject(next);
-				}
-				registryRootBusy = leaves->getCount() == 1 && leaves->getObject(0) == getServiceRoot();
-				multipleEntries = leaves->getCount() > 1;
-				s = busyEntriesString;
-				busyEntriesStringRemaining = busyEntriesStringLen;
-
-				if (registryRootBusy) {
-					snprintf(s, busyEntriesStringRemaining, "registry root held busy, " kIOKitDaemonName " %s checked in", OSKext::iokitDaemonActive() ? "has" : "has not");
-				} else {
-					while ((next = (IOService *) leaves->getLastObject())) {
-						l = snprintf(s, busyEntriesStringRemaining, "%s'%s' (%x,%x)", ((s == busyEntriesString) ? "" : ", "), next->getName(), (uint32_t)next->__state[0], (uint32_t)next->__state[1]);
-						if (l >= busyEntriesStringRemaining) {
-							break;
-						}
-						s += l;
-						busyEntriesStringRemaining -= l;
-						leaves->removeObject(next);
-					}
-				}
-			}
-			OSSafeReleaseNULL(leaves);
-			OSSafeReleaseNULL(set);
-			OSSafeReleaseNULL(iter);
-		}
-
-		dopanic = (kIOWaitQuietPanics & gIOKitDebug) && (options & kIOWaitQuietPanicOnFailure) && !gIOKitWillTerminate;
-#if WITH_IOWAITQUIET_EXTENSIONS
-		dopanic = (dopanic && (loops >= (timeoutExtensions - 1)));
-#endif
-		assert(panicString != NULL);
-		if (multipleEntries) {
-			snprintf(panicString, panicStringLen,
-			    "%s[%d], (%llds): multiple entries holding the registry busy, IOKit termination queue depth %u: %s",
-			    pendingRequests ? "IOKit Daemon (" kIOKitDaemonName ") stall" : "busy timeout",
-			    loops, timeout / 1000000000ULL,
-			    (uint32_t)gIOTerminateWork,
-			    busyEntriesString ? busyEntriesString : "");
-		} else {
-			snprintf(panicString, panicStringLen,
-			    "%s[%d], (%llds): %s",
-			    pendingRequests ? "IOKit Daemon (" kIOKitDaemonName ") stall" : "busy timeout",
-			    loops, timeout / 1000000000ULL,
-			    busyEntriesString ? busyEntriesString : "");
-		}
-
-		IOLog("%s\n", panicString);
-		if (dopanic) {
-			panic("%s", panicString);
-		} else if (!loops) {
-			getPMRootDomain()->startSpinDump(1);
-		}
-	}
-
-	if (busyEntriesString) {
-		IODeleteData(busyEntriesString, char, busyEntriesStringLen);
-	}
-	if (panicString) {
-		IODeleteData(panicString, char, panicStringLen);
-	}
-
-	return ret;
-}
-
-IOReturn
-IOService::waitQuiet( uint64_t timeout )
-{
-	return waitQuietWithOptions(timeout);
-}
-
-IOReturn
-IOService::waitQuiet( mach_timespec_t * timeout )
-{
-	uint64_t    timeoutNS;
-
-	if (timeout) {
-		timeoutNS = timeout->tv_sec;
-		timeoutNS *= kSecondScale;
-		timeoutNS += timeout->tv_nsec;
-	} else {
-		timeoutNS = UINT64_MAX;
-	}
-
-	return waitQuiet(timeoutNS);
-}
-
-bool
-IOService::serializeProperties( OSSerialize * s ) const
-{
-#if 0
-	((IOService *)this)->setProperty(((IOService *)this)->__state,
-	    sizeof(__state), "__state");
-#endif
-	return super::serializeProperties(s);
-}
-
-void
-IOService::resetRematchProperties()
-{
-	removeProperty(gIORematchCountKey);
-	removeProperty(gIORematchPersonalityKey);
-}
-
-
-void
-_IOConfigThread::main(void * arg, wait_result_t result)
-{
-	_IOConfigThread * self = (_IOConfigThread *) arg;
-	_IOServiceJob * job;
-	IOService   *   nub;
-	bool            alive = true;
-	kern_return_t   kr;
-	thread_precedence_policy_data_t precedence = { -1 };
-
-	kr = thread_policy_set(current_thread(),
-	    THREAD_PRECEDENCE_POLICY,
-	    (thread_policy_t) &precedence,
-	    THREAD_PRECEDENCE_POLICY_COUNT);
-	if (KERN_SUCCESS != kr) {
-		IOLog("thread_policy_set(%d)\n", kr);
-	}
-
-	do {
-//	randomDelay();
-
-		semaphore_wait( gJobsSemaphore );
-
-		IOTakeLock( gJobsLock );
-		job = (_IOServiceJob *) gJobs->getFirstObject();
-		job->retain();
-		gJobs->removeObject(job);
-		if (job) {
-			gOutstandingJobs--;
-//	    gNumConfigThreads--;	// we're out of service
-			gNumWaitingThreads--; // we're out of service
-		}
-		IOUnlock( gJobsLock );
-
-		if (job) {
-			nub = job->nub;
-
-			if (gIOKitDebug & kIOLogConfig) {
-				LOG("config(%p): starting on %s, %d\n",
-				    IOSERVICE_OBFUSCATE(IOThreadSelf()), job->nub->getName(), job->type);
-			}
-
-			switch (job->type) {
-			case kMatchNubJob:
-				nub->doServiceMatch( job->options );
-				break;
-
-			default:
-				LOG("config(%p): strange type (%d)\n",
-				    IOSERVICE_OBFUSCATE(IOThreadSelf()), job->type );
-				break;
-			}
-
-			if (job->options & kIOServiceDextRequirePowerForMatching) {
-				gIOPMRootDomain->releaseDriverKitMatchingAssertion();
-			}
-
-			OSSafeReleaseNULL(nub);
-			OSSafeReleaseNULL(job);
-
-			IOTakeLock( gJobsLock );
-			alive = (gOutstandingJobs > gNumWaitingThreads);
-			if (alive) {
-				gNumWaitingThreads++; // back in service
-			}
-//		gNumConfigThreads++;
-			else {
-				if (0 == --gNumConfigThreads) {
-//                    IOLog("MATCH IDLE\n");
-					IOLockWakeup( gJobsLock, (event_t) &gNumConfigThreads, /* one-thread */ false );
-				}
-			}
-			IOUnlock( gJobsLock );
-		}
-	} while (alive);
-
-	if (gIOKitDebug & kIOLogConfig) {
-		LOG("config(%p): terminating\n", IOSERVICE_OBFUSCATE(IOThreadSelf()));
-	}
-
-	self->release();
-}
-
-IOReturn
-IOService::waitMatchIdle( UInt32 msToWait )
-{
-	bool            wait;
-	int             waitResult = THREAD_AWAKENED;
-	bool            computeDeadline = true;
-	AbsoluteTime    deadline;
-
-	IOLockLock( gJobsLock );
-	do {
-		wait = (0 != gNumConfigThreads);
-		if (wait) {
-			if (msToWait) {
-				if (computeDeadline) {
-					clock_interval_to_deadline(
-						msToWait, kMillisecondScale, &deadline );
-					computeDeadline = false;
-				}
-				waitResult = IOLockSleepDeadline( gJobsLock, &gNumConfigThreads,
-				    deadline, THREAD_UNINT );
-			} else {
-				waitResult = IOLockSleep( gJobsLock, &gNumConfigThreads,
-				    THREAD_UNINT );
-			}
-		}
-	} while (wait && (waitResult != THREAD_TIMED_OUT));
-	IOLockUnlock( gJobsLock );
-
-	if (waitResult == THREAD_TIMED_OUT) {
-		return kIOReturnTimeout;
-	} else {
-		return kIOReturnSuccess;
-	}
-}
-
-void
-IOService::cpusRunning(void)
-{
-	gCPUsRunning = true;
-}
-
-void
-_IOServiceJob::pingConfig( _IOServiceJob * job )
-{
-	int         count;
-	bool        create;
-	IOService * nub;
-
-	assert( job );
-	nub = job->nub;
-
-	IOTakeLock( gJobsLock );
-
-	gOutstandingJobs++;
-	if (nub == gIOResources) {
-		gJobs->setFirstObject( job );
-	} else {
-		gJobs->setLastObject( job );
-	}
-
-	count = gNumWaitingThreads;
-//    if( gNumConfigThreads) count++;// assume we're called from a config thread
-
-	create = ((gOutstandingJobs > count)
-	    && ((gNumConfigThreads < gMaxConfigThreads)
-	    || (nub == gIOResources)
-	    || !gCPUsRunning));
-	if (create) {
-		gNumConfigThreads++;
-		gNumWaitingThreads++;
-		if (gNumConfigThreads > gHighNumConfigThreads) {
-			gHighNumConfigThreads = gNumConfigThreads;
-		}
-	}
-
-	IOUnlock( gJobsLock );
-
-	job->release();
-
-	if (create) {
-		if (gIOKitDebug & kIOLogConfig) {
-			LOG("config(%d): creating\n", gNumConfigThreads - 1);
-		}
-		_IOConfigThread::configThread(nub->getName());
-	}
-
-	semaphore_signal( gJobsSemaphore );
-}
-
-struct IOServiceMatchContext {
-	OSDictionary * table;
-	OSObject *     result;
-	uint32_t       options;
-	uint32_t       state;
-	uint32_t       count;
-	uint32_t       done;
-};
-
-bool
-IOService::instanceMatch(const OSObject * entry, void * context)
-{
-	IOServiceMatchContext * ctx = (typeof(ctx))context;
-	IOService *    service = (typeof(service))entry;
-	OSDictionary * table   = ctx->table;
-	uint32_t       options = ctx->options;
-	uint32_t       state   = ctx->state;
-	uint32_t       done;
-	bool           match;
-
-	done = 0;
-	do{
-		match = ((state == (state & service->__state[0]))
-		    && (0 == (service->__state[0] & kIOServiceInactiveState)));
-		if (!match) {
-			break;
-		}
-
-		match = service->matchInternal(table, options, &done);
-		if (match) {
-			ctx->count += table->getCount();
-			ctx->done += done;
-		}
-	}while (false);
-	if (!match) {
-		return false;
-	}
-
-	if ((kIONotifyOnce & options) && (ctx->done == ctx->count)) {
-		service->retain();
-		ctx->result = service;
-		return true;
-	} else if (!ctx->result) {
-		ctx->result = OSSet::withObjects((const OSObject **) &service, 1, 1);
-	} else {
-		((OSSet *)ctx->result)->setObject(service);
-	}
-	return false;
-}
-
-// internal - call with gNotificationLock
-OSObject *
-IOService::copyExistingServices( OSDictionary * matching,
-    IOOptionBits inState, IOOptionBits options )
-{
-	OSObject *   current = NULL;
-	OSIterator * iter;
-	IOService *  service;
-	OSObject *   obj;
-	OSString *   str;
-
-	if (!matching) {
-		return NULL;
-	}
-
-#if MATCH_DEBUG
-	OSSerialize * s = OSSerialize::withCapacity(128);
-	matching->serialize(s);
-#endif
-
-	if ((obj = matching->getObject(gIOProviderClassKey))
-	    && gIOResourcesKey
-	    && gIOResourcesKey->isEqualTo(obj)
-	    && (service = gIOResources)) {
-		if ((inState == (service->__state[0] & inState))
-		    && (0 == (service->__state[0] & kIOServiceInactiveState))
-		    && service->matchPassive(matching, options)) {
-			if (options & kIONotifyOnce) {
-				service->retain();
-				current = service;
-			} else {
-				current = OSSet::withObjects((const OSObject **) &service, 1, 1 );
-			}
-		}
-	} else {
-		IOServiceMatchContext ctx;
-
-		options    |= kIOServiceClassDone;
-		ctx.table   = matching;
-		ctx.state   = inState;
-		ctx.count   = 0;
-		ctx.done    = 0;
-		ctx.options = options;
-		ctx.result  = NULL;
-
-		if ((str = OSDynamicCast(OSString, obj))) {
-			const OSSymbol * sym = OSSymbol::withString(str);
-			OSMetaClass::applyToInstancesOfClassName(sym, instanceMatch, &ctx);
-			sym->release();
-		} else {
-			IOService::gMetaClass.applyToInstances(instanceMatch, &ctx);
-		}
-
-		if (((!(options & kIONotifyOnce) || !ctx.result))
-		    && matching->getObject(gIOCompatibilityMatchKey)) {
-			IOServiceCompatibility::gMetaClass.applyToInstances(instanceMatch, &ctx);
-		}
-
-		current = ctx.result;
-		options |= kIOServiceInternalDone;
-		if (current && (ctx.done != ctx.count)) {
-			OSSet * source = OSDynamicCast(OSSet, current);
-			current = NULL;
-			while ((service = (IOService *) source->getAnyObject())) {
-				if (service->matchPassive(matching, options)) {
-					if (options & kIONotifyOnce) {
-						service->retain();
-						current = service;
-						break;
-					}
-					if (current) {
-						((OSSet *)current)->setObject( service );
-					} else {
-						current = OSSet::withObjects(
-							(const OSObject **) &service, 1, 1 );
-					}
-				}
-				source->removeObject(service);
-			}
-			source->release();
-		}
-	}
-
-#if MATCH_DEBUG
-	{
-		OSObject * _current = 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->matchPassive(matching, 0)) {
-						if (options & kIONotifyOnce) {
-							service->retain();
-							_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) != (_current != 0))
-		    || (current && _current && !current->isEqualTo(_current))) {
-			OSSerialize * s1 = OSSerialize::withCapacity(128);
-			OSSerialize * s2 = OSSerialize::withCapacity(128);
-			current->serialize(s1);
-			_current->serialize(s2);
-			kprintf("**mismatch** %p %p\n%s\n%s\n%s\n", IOSERVICE_OBFUSCATE(current),
-			    IOSERVICE_OBFUSCATE(_current), s->text(), s1->text(), s2->text());
-			s1->release();
-			s2->release();
-		}
-
-		if (_current) {
-			_current->release();
-		}
-	}
-
-	s->release();
-#endif
-
-	if (current && (0 == (options & (kIONotifyOnce | kIOServiceExistingSet)))) {
-		iter = OSCollectionIterator::withCollection((OSSet *)current );
-		current->release();
-		current = iter;
-	}
-
-	return current;
-}
-
-// public version
-OSIterator *
-IOService::getMatchingServices( OSDictionary * matching )
-{
-	OSIterator *        iter;
-
-	// is a lock even needed?
-	LOCKWRITENOTIFY();
-
-	iter = (OSIterator *) copyExistingServices( matching,
-	    kIOServiceMatchedState );
-
-	UNLOCKNOTIFY();
-
-	return iter;
-}
-
-IOService *
-IOService::copyMatchingService( OSDictionary * matching )
-{
-	IOService * service;
-
-	// is a lock even needed?
-	LOCKWRITENOTIFY();
-
-	service = (IOService *) copyExistingServices( matching,
-	    kIOServiceMatchedState, kIONotifyOnce );
-
-	UNLOCKNOTIFY();
-
-	return service;
-}
-
-struct _IOServiceMatchingNotificationHandlerRef {
-	IOServiceNotificationHandler handler;
-	void * ref;
-};
-
-static bool
-_IOServiceMatchingNotificationHandler( void * target, void * refCon,
-    IOService * newService,
-    IONotifier * notifier )
-{
-	return (*((_IOServiceNotifier *) notifier)->compatHandler)(target, refCon, newService);
-}
-
-// internal - call with gNotificationLock
-IONotifier *
-IOService::setNotification(
-	const OSSymbol * type, OSDictionary * matching,
-	IOServiceMatchingNotificationHandler handler, void * target, void * ref,
-	SInt32 priority )
-{
-	_IOServiceNotifier * notify = NULL;
-	OSOrderedSet *      set;
-
-	if (!matching) {
-		return NULL;
-	}
-
-	notify = new _IOServiceNotifier;
-	if (notify && !notify->init()) {
-		notify->release();
-		notify = NULL;
-	}
-
-	if (notify) {
-		notify->handler = handler;
-		notify->target = target;
-		notify->type = type;
-		notify->matching = matching;
-		matching->retain();
-		if (handler == &_IOServiceMatchingNotificationHandler) {
-			notify->compatHandler = ((_IOServiceMatchingNotificationHandlerRef *)ref)->handler;
-			notify->ref = ((_IOServiceMatchingNotificationHandlerRef *)ref)->ref;
-		} else if (handler == &IOServiceMatchingNotificationHandlerToBlock) {
-			notify->ref = Block_copy(ref);
-		} else {
-			notify->ref = ref;
-		}
-		notify->priority = priority;
-		notify->state = kIOServiceNotifyEnable;
-		queue_init( &notify->handlerInvocations );
-
-		////// queue
-
-		if (NULL == (set = (OSOrderedSet *) gNotifications->getObject( type ))) {
-			set = OSOrderedSet::withCapacity( 1,
-			    IONotifyOrdering, NULL );
-			if (set) {
-				gNotifications->setObject( type, set );
-				set->release();
-			}
-		}
-		notify->whence = set;
-		if (set) {
-			set->setObject( notify );
-		}
-	}
-
-	return notify;
-}
-
-// internal - call with gNotificationLock
-IONotifier *
-IOService::doInstallNotification(
-	const OSSymbol * type, OSDictionary * matching,
-	IOServiceMatchingNotificationHandler handler,
-	void * target, void * ref,
-	SInt32 priority, OSIterator ** existing )
-{
-	OSIterator *        exist;
-	IONotifier *        notify;
-	IOOptionBits        inState;
-
-	if (!matching) {
-		return NULL;
-	}
-
-	if (type == gIOPublishNotification) {
-		inState = kIOServiceRegisteredState;
-	} else if (type == gIOFirstPublishNotification) {
-		inState = kIOServiceFirstPublishState;
-	} else if (type == gIOMatchedNotification) {
-		inState = kIOServiceMatchedState;
-	} else if (type == gIOFirstMatchNotification) {
-		inState = kIOServiceFirstMatchState;
-	} else if ((type == gIOTerminatedNotification) || (type == gIOWillTerminateNotification)) {
-		inState = 0;
-	} else {
-		return NULL;
-	}
-
-	notify = setNotification( type, matching, handler, target, ref, priority );
-
-	if (inState) {
-		// get the current set
-		exist = (OSIterator *) copyExistingServices( matching, inState );
-	} else {
-		exist = NULL;
-	}
-
-	*existing = exist;
-
-	return notify;
-}
-
-#if !defined(__LP64__)
-IONotifier *
-IOService::installNotification(const OSSymbol * type, OSDictionary * matching,
-    IOServiceNotificationHandler handler,
-    void * target, void * refCon,
-    SInt32 priority, OSIterator ** existing )
-{
-	IONotifier * result;
-	_IOServiceMatchingNotificationHandlerRef ref;
-	ref.handler = handler;
-	ref.ref     = refCon;
-
-	result = (_IOServiceNotifier *) installNotification( type, matching,
-	    &_IOServiceMatchingNotificationHandler,
-	    target, &ref, priority, existing );
-	if (result) {
-		matching->release();
-	}
-
-	return result;
-}
-
-#endif /* !defined(__LP64__) */
-
-
-IONotifier *
-IOService::installNotification(
-	const OSSymbol * type, OSDictionary * matching,
-	IOServiceMatchingNotificationHandler handler,
-	void * target, void * ref,
-	SInt32 priority, OSIterator ** existing )
-{
-	IONotifier * notify;
-
-	LOCKWRITENOTIFY();
-
-	notify = doInstallNotification( type, matching, handler, target, ref,
-	    priority, existing );
-
-	// in case handler remove()s
-	if (notify) {
-		notify->retain();
-	}
-
-	UNLOCKNOTIFY();
-
-	return notify;
-}
-
-IONotifier *
-IOService::addNotification(
-	const OSSymbol * type, OSDictionary * matching,
-	IOServiceNotificationHandler handler,
-	void * target, void * refCon,
-	SInt32 priority )
-{
-	IONotifier * result;
-	_IOServiceMatchingNotificationHandlerRef ref;
-
-	ref.handler = handler;
-	ref.ref     = refCon;
-
-	result = addMatchingNotification(type, matching, &_IOServiceMatchingNotificationHandler,
-	    target, &ref, priority);
-
-	if (result) {
-		matching->release();
-	}
-
-	return result;
-}
-
-IONotifier *
-IOService::addMatchingNotification(
-	const OSSymbol * type, OSDictionary * matching,
-	IOServiceMatchingNotificationHandler handler,
-	void * target, void * ref,
-	SInt32 priority )
-{
-	OSIterator *                existing = NULL;
-	IONotifier *                ret;
-	_IOServiceNotifier *        notify;
-	IOService *                 next;
-
-	ret = notify = (_IOServiceNotifier *) installNotification( type, matching,
-	    handler, target, ref, priority, &existing );
-	if (!ret) {
-		OSSafeReleaseNULL(existing);
-		return NULL;
-	}
-
-	// send notifications for existing set
-	if (existing) {
-		while ((next = (IOService *) existing->getNextObject())) {
-			if (0 == (next->__state[0] & kIOServiceInactiveState)) {
-				next->invokeNotifier( notify );
-			}
-		}
-		existing->release();
-	}
-
-	LOCKWRITENOTIFY();
-	bool removed = (NULL == notify->whence);
-	notify->release();
-	if (removed) {
-		ret = gIOServiceNullNotifier;
-	}
-	UNLOCKNOTIFY();
-
-	return ret;
-}
-
-static bool
-IOServiceMatchingNotificationHandlerToBlock( void * target __unused, void * refCon,
-    IOService * newService,
-    IONotifier * notifier )
-{
-	return ((IOServiceMatchingNotificationHandlerBlock) refCon)(newService, notifier);
-}
-
-IONotifier *
-IOService::addMatchingNotification(
-	const OSSymbol * type, OSDictionary * matching,
-	SInt32 priority,
-	IOServiceMatchingNotificationHandlerBlock handler)
-{
-	IONotifier * notify;
-
-	notify = addMatchingNotification(type, matching,
-	    &IOServiceMatchingNotificationHandlerToBlock, NULL, handler, priority);
-	return notify;
-}
-
-struct IOUserServerCancellationHandlerArgs {
-	IOService ** ref;
-	bool canceled;
-};
-
-void
-IOService::userServerCheckInTokenCancellationHandler(
-	__unused IOUserServerCheckInToken *token,
-	void *ref)
-{
-	IOUserServerCancellationHandlerArgs * args = (typeof(args))ref;
-	LOCKWRITENOTIFY();
-	WAKEUPNOTIFY(args->ref);
-	args->canceled = true;
-	UNLOCKNOTIFY();
-}
-
-bool
-IOService::syncNotificationHandler(
-	void * /* target */, void * ref,
-	IOService * newService,
-	IONotifier * notifier )
-{
-	LOCKWRITENOTIFY();
-	if (!*((IOService **) ref)) {
-		newService->retain();
-		(*(IOService **) ref) = newService;
-		WAKEUPNOTIFY(ref);
-	}
-	UNLOCKNOTIFY();
-
-	return false;
-}
-
-IOService *
-IOService::waitForMatchingServiceWithToken( OSDictionary * matching,
-    uint64_t timeout,
-    IOUserServerCheckInToken * checkInToken)
-{
-	IONotifier *        notify = NULL;
-	// priority doesn't help us much since we need a thread wakeup
-	SInt32              priority = 0;
-	IOService *         result;
-	IOUserServerCancellationHandlerArgs cancelArgs;
-	_IOUserServerCheckInCancellationHandler * cancellationHandler = NULL;
-
-	if (!matching) {
-		return NULL;
-	}
-
-	result = NULL;
-	cancelArgs.ref = &result;
-	cancelArgs.canceled = false;
-
-#if DEBUG || DEVELOPMENT
-	char                currentName[MAXTHREADNAMESIZE];
-	char                newName[MAXTHREADNAMESIZE];
-	OSObject          * obj;
-	OSString          * str;
-	OSDictionary      * dict;
-
-	currentName[0] = '\0';
-	if (thread_has_thread_name(current_thread())) {
-		dict = matching;
-		obj = matching->getObject(gIOPropertyMatchKey);
-		if ((dict = OSDynamicCast(OSDictionary, obj))) {
-			OSObject * result __block = NULL;
-			dict->iterateObjects(^bool (const OSSymbol * sym, OSObject * value) {
-				result = __DECONST(OSObject *, sym);
-				return true;
-			});
-			obj = result;
-		}
-		if (!obj) {
-			obj = matching->getObject(gIOResourceMatchKey);
-		}
-		if (!obj) {
-			obj = matching->getObject(gIONameMatchKey);
-		}
-		if (!obj) {
-			obj = matching->getObject(gIOProviderClassKey);
-		}
-		if ((str = OSDynamicCast(OSString, obj))) {
-			thread_get_thread_name(current_thread(), currentName);
-			snprintf(newName, sizeof(newName), "Waiting_'%s'", str->getCStringNoCopy());
-			thread_set_thread_name(current_thread(), newName);
-		}
-	}
-#endif /* DEBUG || DEVELOPMENT */
-
-	if (checkInToken) {
-		cancellationHandler = checkInToken->setCancellationHandler(&IOService::userServerCheckInTokenCancellationHandler,
-		    &cancelArgs);
-	}
-
-	LOCKWRITENOTIFY();
-	do{
-		result = (IOService *) copyExistingServices( matching,
-		    kIOServiceMatchedState, kIONotifyOnce );
-		if (result) {
-			break;
-		}
-		if (cancelArgs.canceled) {
-			// token was already canceled, no need to wait or find services
-			break;
-		}
-		notify = IOService::setNotification( gIOMatchedNotification, matching,
-		    &IOService::syncNotificationHandler, (void *) NULL,
-		    &result, priority );
-		if (!notify) {
-			break;
-		}
-		if (UINT64_MAX != timeout) {
-			AbsoluteTime deadline;
-			nanoseconds_to_absolutetime(timeout, &deadline);
-			clock_absolutetime_interval_to_deadline(deadline, &deadline);
-			SLEEPNOTIFYTO(&result, deadline);
-		} else {
-			SLEEPNOTIFY(&result);
-		}
-	}while (false);
-
-	UNLOCKNOTIFY();
-
-	if (checkInToken && cancellationHandler) {
-		checkInToken->removeCancellationHandler(cancellationHandler);
-	}
-
-#if DEBUG || DEVELOPMENT
-	if (currentName[0]) {
-		thread_set_thread_name(current_thread(), currentName);
-	}
-#endif /* DEBUG || DEVELOPMENT */
-
-	if (notify) {
-		notify->remove(); // dequeues
-	}
-
-	OSSafeReleaseNULL(cancellationHandler);
-
-	return result;
-}
-
-IOService *
-IOService::waitForMatchingService( OSDictionary * matching,
-    uint64_t timeout)
-{
-	return IOService::waitForMatchingServiceWithToken(matching, timeout, NULL);
-}
-
-IOService *
-IOService::waitForService( OSDictionary * matching,
-    mach_timespec_t * timeout )
-{
-	IOService * result;
-	uint64_t    timeoutNS;
-
-	if (timeout) {
-		timeoutNS = timeout->tv_sec;
-		timeoutNS *= kSecondScale;
-		timeoutNS += timeout->tv_nsec;
-	} else {
-		timeoutNS = UINT64_MAX;
-	}
-
-	result = waitForMatchingService(matching, timeoutNS);
-
-	matching->release();
-	if (result) {
-		result->release();
-	}
-
-	return result;
-}
-
-__dead2
-void
-IOService::deliverNotification( const OSSymbol * type,
-    IOOptionBits orNewState, IOOptionBits andNewState )
-{
-	panic("deliverNotification");
-}
-
-OSArray *
-IOService::copyNotifiers(const OSSymbol * type,
-    IOOptionBits orNewState, IOOptionBits andNewState )
-{
-	_IOServiceNotifier * notify;
-	OSIterator *         iter;
-	OSArray *            willSend = NULL;
-
-	lockForArbitration();
-
-	if ((0 == (__state[0] & kIOServiceInactiveState))
-	    || (type == gIOTerminatedNotification)
-	    || (type == gIOWillTerminateNotification)) {
-		LOCKREADNOTIFY();
-
-		iter = OSCollectionIterator::withCollection((OSOrderedSet *)
-		    gNotifications->getObject( type ));
-
-		if (iter) {
-			while ((notify = (_IOServiceNotifier *) iter->getNextObject())) {
-				if (matchPassive(notify->matching, 0)
-				    && (kIOServiceNotifyEnable & notify->state)) {
-					if (NULL == willSend) {
-						willSend = OSArray::withCapacity(8);
-					}
-					if (willSend) {
-						willSend->setObject( notify );
-					}
-				}
-			}
-			iter->release();
-		}
-		__state[0] = (__state[0] | orNewState) & andNewState;
-		UNLOCKNOTIFY();
-	}
-
-	unlockForArbitration();
-
-	return willSend;
-}
-
-IOOptionBits
-IOService::getState( void ) const
-{
-	return __state[0];
+bool IOService::syncNotificationHandler(
+			void * /* target */, void * ref,
+			IOService * newService )
+{
+
+    // result may get written more than once before the
+    // notification is removed!
+    ((SyncNotifyVars *) ref)->result = newService;
+    semaphore_signal( ((SyncNotifyVars *) ref)->waitHere );
+
+    return( false );
+}
+
+IOService * IOService::waitForService( OSDictionary * matching,
+				mach_timespec_t * timeout = 0 )
+{
+    IONotifier *	notify = 0;
+    // priority doesn't help us much since we need a thread wakeup
+    SInt32		priority = 0;
+    SyncNotifyVars	state;
+    kern_return_t	err = kIOReturnBadArgument;
+
+    if( !matching)
+        return( 0 );
+
+    state.waitHere = 0;
+    state.result = 0;
+
+    LOCKWRITENOTIFY();
+
+    do {
+
+        state.result = (IOService *) getExistingServices( matching,
+                            kIOServiceMatchedState, kIONotifyOnce );
+	if( state.result)
+	    continue;
+
+        err = semaphore_create( kernel_task, &state.waitHere,
+                                    SYNC_POLICY_FIFO, 0 );
+        if( KERN_SUCCESS != err)
+            continue;
+
+        notify = IOService::setNotification( gIOMatchedNotification, matching,
+                    &IOService::syncNotificationHandler, (void *) 0,
+                    (void *) &state, priority );
+
+    } while( false );
+
+    UNLOCKNOTIFY();
+
+     if( notify) {
+        if( timeout)
+            err = semaphore_timedwait( state.waitHere, *timeout );
+        else
+            err = semaphore_wait( state.waitHere );
+    }
+
+    if( notify)
+        notify->remove();	// dequeues
+    else
+        matching->release();
+    if( state.waitHere)
+        semaphore_destroy( kernel_task, state.waitHere );
+
+    return( state.result );
+}
+
+void IOService::deliverNotification( const OSSymbol * type,
+                            IOOptionBits orNewState, IOOptionBits andNewState )
+{
+    _IOServiceNotifier * notify;
+    OSIterator *	 iter;
+    OSArray *		 willSend = 0;
+
+    lockForArbitration();
+
+    if( (0 == (__state[0] & kIOServiceInactiveState))
+     ||	(type == gIOTerminatedNotification)) {
+
+	LOCKREADNOTIFY();
+
+        iter = OSCollectionIterator::withCollection( (OSOrderedSet *)
+                    gNotifications->getObject( type ) );
+
+        if( iter) {
+            while( (notify = (_IOServiceNotifier *) iter->getNextObject())) {
+
+                if( passiveMatch( notify->matching)
+                  && (kIOServiceNotifyEnable & notify->state)) {
+                    if( 0 == willSend)
+                        willSend = OSArray::withCapacity(8);
+                    if( willSend)
+                        willSend->setObject( notify );
+                }
+            }
+            iter->release();
+        }
+
+        __state[0] = (__state[0] | orNewState) & andNewState;
+
+        UNLOCKNOTIFY();
+    }
+
+    if( willSend) {
+        for( unsigned int idx = 0;
+             (notify = (_IOServiceNotifier *) willSend->getObject(idx));
+             idx++) {
+            invokeNotifer( notify );
+        }
+        willSend->release();
+    }
+    unlockForArbitration();
+}
+
+IOOptionBits IOService::getState( void ) const
+{
+    return( __state[0] );
 }
 
 /*
  * Helpers to make matching objects for simple cases
  */
 
-OSDictionary *
-IOService::serviceMatching( const OSString * name,
-    OSDictionary * table )
-{
-	const OSString *    str;
-
-	str = OSSymbol::withString(name);
-	if (!str) {
-		return NULL;
-	}
-
-	if (!table) {
-		table = OSDictionary::withCapacity( 2 );
-	}
-	if (table) {
-		table->setObject(gIOProviderClassKey, (OSObject *)str );
-	}
-	str->release();
-
-	return table;
-}
-
-
-OSSharedPtr<OSDictionary>
-IOService::serviceMatching( const OSString * name,
-    OSSharedPtr<OSDictionary> table)
-{
-	OSDictionary * result = serviceMatching(name, table.get());
-	if (table) {
-		return OSSharedPtr<OSDictionary>(result, OSRetain);
-	} else {
-		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
-	}
-}
-
-
-OSDictionary *
-IOService::serviceMatching( const char * name,
-    OSDictionary * table )
-{
-	const OSString *    str;
-
-	str = OSSymbol::withCString( name );
-	if (!str) {
-		return NULL;
-	}
-
-	table = serviceMatching( str, table );
-	str->release();
-	return table;
-}
-
-
-OSSharedPtr<OSDictionary>
-IOService::serviceMatching( const char * className,
-    OSSharedPtr<OSDictionary> table)
-{
-	OSDictionary * result = serviceMatching(className, table.get());
-	if (table) {
-		return OSSharedPtr<OSDictionary>(result, OSRetain);
-	} else {
-		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
-	}
-}
-
-
-OSDictionary *
-IOService::nameMatching( const OSString * name,
-    OSDictionary * table )
-{
-	if (!table) {
-		table = OSDictionary::withCapacity( 2 );
-	}
-	if (table) {
-		table->setObject( gIONameMatchKey, (OSObject *)name );
-	}
-
-	return table;
-}
-
-
-OSSharedPtr<OSDictionary>
-IOService::nameMatching( const OSString * name,
-    OSSharedPtr<OSDictionary> table)
-{
-	OSDictionary * result = nameMatching(name, table.get());
-	if (table) {
-		return OSSharedPtr<OSDictionary>(result, OSRetain);
-	} else {
-		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
-	}
-}
-
-
-OSDictionary *
-IOService::nameMatching( const char * name,
-    OSDictionary * table )
-{
-	const OSString *    str;
-
-	str = OSSymbol::withCString( name );
-	if (!str) {
-		return NULL;
-	}
-
-	table = nameMatching( str, table );
-	str->release();
-	return table;
-}
-
-
-OSSharedPtr<OSDictionary>
-IOService::nameMatching( const char * name,
-    OSSharedPtr<OSDictionary> table)
-{
-	OSDictionary * result = nameMatching(name, table.get());
-	if (table) {
-		return OSSharedPtr<OSDictionary>(result, OSRetain);
-	} else {
-		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
-	}
-}
-
-
-OSDictionary *
-IOService::resourceMatching( const OSString * str,
-    OSDictionary * table )
-{
-	table = serviceMatching( gIOResourcesKey, table );
-	if (table) {
-		table->setObject( gIOResourceMatchKey, (OSObject *) str );
-	}
-
-	return table;
-}
-
-
-OSSharedPtr<OSDictionary>
-IOService::resourceMatching( const OSString * str,
-    OSSharedPtr<OSDictionary> table)
-{
-	OSDictionary * result = resourceMatching(str, table.get());
-	if (table) {
-		return OSSharedPtr<OSDictionary>(result, OSRetain);
-	} else {
-		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
-	}
-}
-
-
-OSDictionary *
-IOService::resourceMatching( const char * name,
-    OSDictionary * table )
-{
-	const OSSymbol *    str;
-
-	str = OSSymbol::withCString( name );
-	if (!str) {
-		return NULL;
-	}
-
-	table = resourceMatching( str, table );
-	str->release();
-
-	return table;
-}
-
-
-OSSharedPtr<OSDictionary>
-IOService::resourceMatching( const char * name,
-    OSSharedPtr<OSDictionary> table)
-{
-	OSDictionary * result = resourceMatching(name, table.get());
-	if (table) {
-		return OSSharedPtr<OSDictionary>(result, OSRetain);
-	} else {
-		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
-	}
-}
-
-
-OSDictionary *
-IOService::propertyMatching( const OSSymbol * key, const OSObject * value,
-    OSDictionary * table )
-{
-	OSDictionary * properties;
-
-	properties = OSDictionary::withCapacity( 2 );
-	if (!properties) {
-		return NULL;
-	}
-	properties->setObject( key, value );
-
-	if (!table) {
-		table = OSDictionary::withCapacity( 2 );
-	}
-	if (table) {
-		table->setObject( gIOPropertyMatchKey, properties );
-	}
-
-	properties->release();
-
-	return table;
-}
-
-
-OSSharedPtr<OSDictionary>
-IOService::propertyMatching( const OSSymbol * key, const OSObject * value,
-    OSSharedPtr<OSDictionary> table)
-{
-	OSDictionary * result = propertyMatching(key, value, table.get());
-	if (table) {
-		return OSSharedPtr<OSDictionary>(result, OSRetain);
-	} else {
-		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
-	}
-}
-
-
-OSDictionary *
-IOService::registryEntryIDMatching( uint64_t entryID,
-    OSDictionary * table )
-{
-	OSNumber *     num;
-
-	num = OSNumber::withNumber( entryID, 64 );
-	if (!num) {
-		return NULL;
-	}
-
-	if (!table) {
-		table = OSDictionary::withCapacity( 2 );
-	}
-	if (table) {
-		table->setObject( gIORegistryEntryIDKey, num );
-	}
-
-	if (num) {
-		num->release();
-	}
-
-	return table;
-}
-
-
-OSSharedPtr<OSDictionary>
-IOService::registryEntryIDMatching( uint64_t entryID,
-    OSSharedPtr<OSDictionary> table)
-{
-	OSDictionary * result = registryEntryIDMatching(entryID, table.get());
-	if (table) {
-		return OSSharedPtr<OSDictionary>(result, OSRetain);
-	} else {
-		return OSSharedPtr<OSDictionary>(result, OSNoRetain);
-	}
-}
-
-
+OSDictionary * IOService::serviceMatching( const OSString * name,
+			OSDictionary * table = 0 )
+{
+    if( !table)
+	table = OSDictionary::withCapacity( 2 );
+    if( table)
+        table->setObject(gIOProviderClassKey, (OSObject *)name );
+
+    return( table );
+}
+
+OSDictionary * IOService::serviceMatching( const char * name,
+			OSDictionary * table = 0 )
+{
+    const OSString *	str;
+
+    str = OSSymbol::withCString( name );
+    if( !str)
+	return( 0 );
+
+    table = serviceMatching( str, table );
+    str->release();
+    return( table );
+}
+
+OSDictionary * IOService::nameMatching( const OSString * name,
+			OSDictionary * table = 0 )
+{
+    if( !table)
+	table = OSDictionary::withCapacity( 2 );
+    if( table)
+        table->setObject( gIONameMatchKey, (OSObject *)name );
+
+    return( table );
+}
+
+OSDictionary * IOService::nameMatching( const char * name,
+			OSDictionary * table = 0 )
+{
+    const OSString *	str;
+
+    str = OSSymbol::withCString( name );
+    if( !str)
+	return( 0 );
+
+    table = nameMatching( str, table );
+    str->release();
+    return( table );
+}
+
+OSDictionary * IOService::resourceMatching( const OSString * str,
+			OSDictionary * table = 0 )
+{
+    table = serviceMatching( gIOResourcesKey, table );
+    if( table)
+        table->setObject( gIOResourceMatchKey, (OSObject *) str );
+
+    return( table );
+}
+
+OSDictionary * IOService::resourceMatching( const char * name,
+			OSDictionary * table = 0 )
+{
+    const OSSymbol *	str;
+
+    str = OSSymbol::withCString( name );
+    if( !str)
+	return( 0 );
+
+    table = resourceMatching( str, table );
+    str->release();
+
+    return( table );
+}
 
 /*
  * _IOServiceNotifier
@@ -7171,491 +3452,137 @@
 // wait for all threads, other than the current one,
 //  to exit the handler
 
-void
-_IOServiceNotifier::wait()
-{
-	_IOServiceNotifierInvocation * next;
-	bool doWait;
-
-	do {
-		doWait = false;
-		queue_iterate( &handlerInvocations, next,
-		    _IOServiceNotifierInvocation *, link) {
-			if (next->thread != current_thread()) {
-				doWait = true;
-				break;
-			}
-		}
-		if (doWait) {
-			state |= kIOServiceNotifyWaiter;
-			SLEEPNOTIFY(this);
-		}
-	} while (doWait);
-}
-
-void
-_IOServiceNotifier::free()
-{
-	assert( queue_empty( &handlerInvocations ));
-
-	if (handler == &IOServiceMatchingNotificationHandlerToBlock) {
-		Block_release(ref);
-	}
-
-	OSObject::free();
-}
-
-void
-_IOServiceNotifier::remove()
-{
-	LOCKWRITENOTIFY();
-
-	if (whence) {
-		whence->removeObject((OSObject *) this );
-		whence = NULL;
-	}
-	if (matching) {
-		matching->release();
-		matching = NULL;
-	}
-
-	state &= ~kIOServiceNotifyEnable;
-
-	wait();
-
-	UNLOCKNOTIFY();
-
-	release();
-}
-
-bool
-_IOServiceNotifier::disable()
-{
-	bool        ret;
-
-	LOCKWRITENOTIFY();
-
-	ret = (0 != (kIOServiceNotifyEnable & state));
-	state &= ~kIOServiceNotifyEnable;
-	if (ret) {
-		wait();
-	}
-
-	UNLOCKNOTIFY();
-
-	return ret;
-}
-
-void
-_IOServiceNotifier::enable( bool was )
-{
-	LOCKWRITENOTIFY();
-	if (was) {
-		state |= kIOServiceNotifyEnable;
-	} else {
-		state &= ~kIOServiceNotifyEnable;
-	}
-	UNLOCKNOTIFY();
-}
-
-
-/*
- * _IOServiceNullNotifier
- */
-
-void
-_IOServiceNullNotifier::taggedRetain(const void *tag) const
-{
-}
-void
-_IOServiceNullNotifier::taggedRelease(const void *tag, const int when) const
-{
-}
-void
-_IOServiceNullNotifier::free()
-{
-}
-void
-_IOServiceNullNotifier::wait()
-{
-}
-void
-_IOServiceNullNotifier::remove()
-{
-}
-void
-_IOServiceNullNotifier::enable(bool was)
-{
-}
-bool
-_IOServiceNullNotifier::disable()
-{
-	return false;
+void _IOServiceNotifier::wait()
+{
+    _IOServiceNotifierInvocation * next;
+    bool doWait;
+
+    do {
+        doWait = false;
+        queue_iterate( &handlerInvocations, next,
+                        _IOServiceNotifierInvocation *, link) {
+            if( next->thread != current_thread() ) {
+                doWait = true;
+                break;
+            }
+        }
+        if( doWait) {
+            state |= kIOServiceNotifyWaiter;
+            assert_wait( this, THREAD_UNINT);
+            UNLOCKNOTIFY();
+            thread_block((void (*)(void)) 0);
+            LOCKWRITENOTIFY();
+        }
+
+    } while( doWait );
+}
+
+void _IOServiceNotifier::free()
+{
+    assert( queue_empty( &handlerInvocations ));
+    OSObject::free();
+}
+
+void _IOServiceNotifier::remove()
+{
+    LOCKWRITENOTIFY();
+
+    if( whence) {
+        whence->removeObject( (OSObject *) this );
+        whence = 0;
+    }
+    if( matching) {
+        matching->release();
+        matching = 0;
+    }
+
+    state &= ~kIOServiceNotifyEnable;
+
+    wait();
+
+    UNLOCKNOTIFY();
+    
+    release();
+}
+
+bool _IOServiceNotifier::disable()
+{
+    bool	ret;
+
+    LOCKWRITENOTIFY();
+
+    ret = (0 != (kIOServiceNotifyEnable & state));
+    state &= ~kIOServiceNotifyEnable;
+    if( ret)
+        wait();
+
+    UNLOCKNOTIFY();
+
+    return( ret );
+}
+
+void _IOServiceNotifier::enable( bool was )
+{
+    LOCKWRITENOTIFY();
+    if( was)
+        state |= kIOServiceNotifyEnable;
+    else
+        state &= ~kIOServiceNotifyEnable;
+    UNLOCKNOTIFY();
 }
 
 /*
  * IOResources
  */
 
-IOService *
-IOResources::resources( void )
-{
-	IOResources *       inst;
-
-	inst = new IOResources;
-	if (inst && !inst->init()) {
-		inst->release();
-		inst = NULL;
-	}
-
-	return inst;
-}
-
-bool
-IOResources::init( OSDictionary * dictionary )
-{
-	// Do super init first
-	if (!IOService::init()) {
-		return false;
-	}
-
-	// Allow PAL layer to publish a value
-	const char *property_name;
-	int property_value;
-
-	pal_get_resource_property( &property_name, &property_value );
-
-	if (property_name) {
-		OSNumber *num;
-		const OSSymbol *        sym;
-
-		if ((num = OSNumber::withNumber(property_value, 32)) != NULL) {
-			if ((sym = OSSymbol::withCString( property_name)) != NULL) {
-				this->setProperty( sym, num );
-				sym->release();
-			}
-			num->release();
-		}
-	}
-
-	return true;
-}
-
-IOReturn
-IOResources::newUserClient(task_t owningTask, void * securityID,
-    UInt32 type, OSDictionary * properties,
-    IOUserClient ** handler)
-{
-	return kIOReturnUnsupported;
-}
-
-IOWorkLoop *
-IOResources::getWorkLoop() const
-{
-	// If we are the resource root
-	// then use the platform's workloop
-	if (this == (IOResources *) gIOResources) {
-		return getPlatform()->getWorkLoop();
-	} else {
-		return IOService::getWorkLoop();
-	}
-}
-
-static bool
-IOResourcesMatchPropertyTable(IOService * resources, OSDictionary * table)
-{
-	OSObject *          prop;
-	bool __block        ok = true;
-
-	prop = table->getObject( gIOResourceMatchKey );
-	if (prop) {
-		prop->iterateObjects(^bool (OSObject * obj)
-		{
-			OSString *
-			str = OSDynamicCast(OSString, obj);
-			ok = (NULL != resources->getProperty(str));
-			return !ok;
-		});
-	} else if ((prop = table->getObject(gIOResourceMatchedKey))) {
-		OSObject * obj;
-		OSArray *  keys;
-
-		obj = resources->copyProperty(gIOResourceMatchedKey);
-		keys = OSDynamicCast(OSArray, obj);
-		ok = false;
-		if (keys) {
-			// assuming OSSymbol
-			ok = ((-1U) != keys->getNextIndexOfObject(prop, 0));
-		}
-		OSSafeReleaseNULL(obj);
-	}
-
-	return ok;
-}
-
-bool
-IOResources::matchPropertyTable( OSDictionary * table )
-{
-	return IOResourcesMatchPropertyTable(this, table);
-}
-
-/*
- * IOUserResources
- */
-
-IOService *
-IOUserResources::resources( void )
-{
-	IOUserResources *       inst;
-
-	inst = OSTypeAlloc(IOUserResources);
-	if (inst && !inst->init()) {
-		inst->release();
-		inst = NULL;
-	}
-
-	return inst;
-}
-
-bool
-IOUserResources::init( OSDictionary * dictionary )
-{
-	// Do super init first
-	if (!IOService::init()) {
-		return false;
-	}
-	return true;
-}
-
-IOReturn
-IOUserResources::newUserClient(task_t owningTask, void * securityID,
-    UInt32 type, OSDictionary * properties,
-    IOUserClient ** handler)
-{
-	return kIOReturnUnsupported;
-}
-
-IOWorkLoop *
-IOUserResources::getWorkLoop() const
-{
+IOService * IOResources::resources( void )
+{
+    IOResources *	inst;
+
+    inst = new IOResources;
+    if( inst && !inst->init()) {
+	inst->release();
+	inst = 0;
+    }
+
+    return( inst );
+}
+
+IOWorkLoop * IOResources::getWorkLoop() const
+{
+    // If we are the resource root then bringe over to the
+    // platform to get its workloop
+    if (this == (IOResources *) gIOResources)
 	return getPlatform()->getWorkLoop();
-}
-
-bool
-IOUserResources::matchPropertyTable( OSDictionary * table )
-{
-	return IOResourcesMatchPropertyTable(this, table);
-}
-
-IOReturn
-IOUserResources::powerStateWillChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service)
-{
-	assert(service == getPMRootDomain());
-	if (service != getPMRootDomain()) {
-		return kIOReturnSuccess;
-	}
-	return IOServicePH::rootWillChangeTo(flags, state);
-}
-
-// --
-
-void
-IOService::consoleLockTimer(thread_call_param_t p0, thread_call_param_t p1)
-{
-	IOService::updateConsoleUsers(NULL, 0);
-}
-
-void
-IOService::updateConsoleUsers(OSArray * consoleUsers, IOMessage systemMessage, bool afterUserspaceReboot)
-{
-	IORegistryEntry * regEntry;
-	OSObject *        locked = kOSBooleanFalse;
-	uint32_t          idx;
-	bool              publish;
-	OSDictionary *    user;
-	clock_sec_t       now = 0;
-	clock_usec_t      microsecs;
-
-	regEntry = IORegistryEntry::getRegistryRoot();
-
-	if (!gIOChosenEntry) {
-		gIOChosenEntry = IORegistryEntry::fromPath("/chosen", gIODTPlane);
-	}
-
-	IOLockLock(gIOConsoleUsersLock);
-
-	if (systemMessage) {
-		sSystemPower = systemMessage;
-#if HIBERNATION
-		if (kIOMessageSystemHasPoweredOn == systemMessage) {
-			uint32_t lockState = IOHibernateWasScreenLocked();
-			switch (lockState) {
-			case 0:
-				break;
-			case kIOScreenLockLocked:
-			case kIOScreenLockFileVaultDialog:
-				gIOConsoleBooterLockState = kOSBooleanTrue;
-				break;
-			case kIOScreenLockNoLock:
-				gIOConsoleBooterLockState = NULL;
-				break;
-			case kIOScreenLockUnlocked:
-			default:
-				gIOConsoleBooterLockState = kOSBooleanFalse;
-				break;
-			}
-		}
-#endif /* HIBERNATION */
-	}
-
-	if (consoleUsers) {
-		OSNumber * num = NULL;
-		bool       loginLocked = true;
-
-		gIOConsoleLoggedIn = false;
-		for (idx = 0;
-		    (user = OSDynamicCast(OSDictionary, consoleUsers->getObject(idx)));
-		    idx++) {
-			gIOConsoleLoggedIn |= ((kOSBooleanTrue == user->getObject(gIOConsoleSessionOnConsoleKey))
-			    && (kOSBooleanTrue == user->getObject(gIOConsoleSessionLoginDoneKey)));
-
-			loginLocked &= (kOSBooleanTrue == user->getObject(gIOConsoleSessionScreenIsLockedKey));
-			if (!num) {
-				num = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionScreenLockedTimeKey));
-			}
-		}
-#if HIBERNATION
-		if (!loginLocked || afterUserspaceReboot) {
-			gIOConsoleBooterLockState = NULL;
-		}
-		IOLog("IOConsoleUsers: time(%d) %ld->%d, lin %d, llk %d, \n",
-		    (num != NULL), gIOConsoleLockTime, (num ? num->unsigned32BitValue() : 0),
-		    gIOConsoleLoggedIn, loginLocked);
-#endif /* HIBERNATION */
-		gIOConsoleLockTime = num ? num->unsigned32BitValue() : 0;
-	}
-
-	if (!gIOConsoleLoggedIn
-	    || (kIOMessageSystemWillSleep == sSystemPower)
-	    || (kIOMessageSystemPagingOff == sSystemPower)) {
-		if (afterUserspaceReboot) {
-			// set "locked" to false after a user space reboot
-			// because the reboot happens directly after a user
-			// logs into the machine via fvunlock mode.
-			locked = kOSBooleanFalse;
-		} else {
-			locked = kOSBooleanTrue;
-		}
-	}
-#if HIBERNATION
-	else if (gIOConsoleBooterLockState) {
-		locked = gIOConsoleBooterLockState;
-	}
-#endif /* HIBERNATION */
-	else if (gIOConsoleLockTime) {
-		clock_get_calendar_microtime(&now, &microsecs);
-		if (gIOConsoleLockTime > now) {
-			AbsoluteTime deadline;
-			clock_sec_t interval;
-			uint32_t interval32;
-
-			interval = (gIOConsoleLockTime - now);
-			interval32 = (uint32_t) interval;
-			if (interval32 != interval) {
-				interval32 = UINT_MAX;
-			}
-			clock_interval_to_deadline(interval32, kSecondScale, &deadline);
-			thread_call_enter_delayed(gIOConsoleLockCallout, deadline);
-		} else {
-			locked = kOSBooleanTrue;
-		}
-	}
-
-	publish = (consoleUsers || (locked != regEntry->getProperty(gIOConsoleLockedKey)));
-	if (publish) {
-		regEntry->setProperty(gIOConsoleLockedKey, locked);
-		if (consoleUsers) {
-			regEntry->setProperty(gIOConsoleUsersKey, consoleUsers);
-		}
-		OSIncrementAtomic( &gIOConsoleUsersSeed );
-	}
-
-#if HIBERNATION
-	if (gIOChosenEntry) {
-		if (locked == kOSBooleanTrue) {
-			gIOScreenLockState = kIOScreenLockLocked;
-		} else if (gIOConsoleLockTime) {
-			gIOScreenLockState = kIOScreenLockUnlocked;
-		} else {
-			gIOScreenLockState = kIOScreenLockNoLock;
-		}
-		gIOChosenEntry->setProperty(kIOScreenLockStateKey, &gIOScreenLockState, sizeof(gIOScreenLockState));
-
-		IOLog("IOConsoleUsers: gIOScreenLockState %d, hs %d, bs %d, now %ld, sm 0x%x\n",
-		    gIOScreenLockState, gIOHibernateState, (gIOConsoleBooterLockState != NULL), now, systemMessage);
-	}
-#endif /* HIBERNATION */
-
-	IOLockUnlock(gIOConsoleUsersLock);
-
-	if (publish) {
-		publishResource( gIOConsoleUsersSeedKey, gIOConsoleUsersSeedValue );
-
-		MessageClientsContext context;
-
-		context.service  = getServiceRoot();
-		context.type     = kIOMessageConsoleSecurityChange;
-		context.argument = (void *) regEntry;
-		context.argSize  = 0;
-
-		applyToInterestNotifiers(getServiceRoot(), gIOConsoleSecurityInterest,
-		    &messageClientsApplier, &context );
-	}
-}
-
-IOReturn
-IOResources::setProperties( OSObject * properties )
-{
-	IOReturn                    err;
-	const OSSymbol *            key;
-	OSDictionary *              dict;
-	OSCollectionIterator *      iter;
-
-	if (!IOCurrentTaskHasEntitlement(kIOResourcesSetPropertyKey)) {
-		err = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
-		if (kIOReturnSuccess != err) {
-			return err;
-		}
-	}
-
-	dict = OSDynamicCast(OSDictionary, properties);
-	if (NULL == dict) {
-		return kIOReturnBadArgument;
-	}
-
-	iter = OSCollectionIterator::withCollection( dict);
-	if (NULL == iter) {
-		return kIOReturnBadArgument;
-	}
-
-	while ((key = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
-		if (gIOConsoleUsersKey == key) {
-			do{
-				OSArray * consoleUsers;
-				consoleUsers = OSDynamicCast(OSArray, dict->getObject(key));
-				if (!consoleUsers) {
-					continue;
-				}
-				IOService::updateConsoleUsers(consoleUsers, 0);
-			}while (false);
-		}
-
-		publishResource( key, dict->getObject(key));
-	}
-
-	iter->release();
-
-	return kIOReturnSuccess;
+    else
+	return IOService::getWorkLoop();
+}
+
+bool IOResources::matchPropertyTable( OSDictionary * table )
+{
+    OSObject *		prop;
+    OSString *		str;
+    OSSet *		set;
+    OSIterator *	iter;
+    bool		ok = false;
+
+    prop = table->getObject( gIOResourceMatchKey );
+    str = OSDynamicCast( OSString, prop );
+    if( str)
+	ok = (0 != getProperty( str ));
+
+    else if( (set = OSDynamicCast( OSSet, prop))) {
+
+	iter = OSCollectionIterator::withCollection( set );
+	ok = (iter != 0);
+        while( ok && (str = OSDynamicCast( OSString, iter->getNextObject()) ))
+            ok = (0 != getProperty( str ));
+
+        if( iter)
+	    iter->release();
+    }
+
+    return( ok );
 }
 
 /*
@@ -7664,1698 +3591,718 @@
  * Keys may be a string or OSCollection of IOStrings
  */
 
-bool
-IOService::compareProperty( OSDictionary * matching,
-    const char *   key )
-{
-	OSObject *  value;
-	OSObject *  prop;
-	bool        ok;
-
-	value = matching->getObject( key );
-	if (value) {
-		prop = copyProperty(key);
-		ok = value->isEqualTo(prop);
-		if (prop) {
-			prop->release();
-		}
-	} else {
-		ok = true;
-	}
-
-	return ok;
-}
-
-
-bool
-IOService::compareProperty( OSDictionary *   matching,
-    const OSString * key )
-{
-	OSObject *  value;
-	OSObject *  prop;
-	bool        ok;
-
-	value = matching->getObject( key );
-	if (value) {
-		prop = copyProperty(key);
-		ok = value->isEqualTo(prop);
-		if (prop) {
-			prop->release();
-		}
-	} else {
-		ok = true;
-	}
-
-	return ok;
-}
-
-#ifndef __clang_analyzer__
-// Implementation of this function is hidden from the static analyzer.
-// The analyzer was worried about this function's confusing contract over
-// the 'keys' parameter. The contract is to either release it or not release it
-// depending on whether 'matching' is non-null. Such contracts are discouraged
-// but changing it now would break compatibility.
-bool
-IOService::compareProperties( OSDictionary * matching,
-    OSCollection * keys )
-{
-	OSCollectionIterator *      iter;
-	const OSString *            key;
-	bool                        ok = true;
-
-	if (!matching || !keys) {
-		return false;
-	}
-
-	iter = OSCollectionIterator::withCollection( keys );
-
-	if (iter) {
-		while (ok && (key = OSDynamicCast( OSString, iter->getNextObject()))) {
-			ok = compareProperty( matching, key );
-		}
-
-		iter->release();
-	}
-	keys->release(); // !! consume a ref !!
-
-	return ok;
-}
-#endif // __clang_analyzer__
+bool IOService::compareProperty( OSDictionary * matching,
+                                 const char * 	key )
+{
+    OSObject *	value;
+    bool	ok;
+
+    value = matching->getObject( key );
+    if( value)
+        ok = value->isEqualTo( getProperty( key ));
+    else
+	ok = true;
+
+    return( ok );
+}
+
+
+bool IOService::compareProperty( OSDictionary *   matching,
+                                 const OSString * key )
+{
+    OSObject *	value;
+    bool	ok;
+
+    value = matching->getObject( key );
+    if( value)
+        ok = value->isEqualTo( getProperty( key ));
+    else
+	ok = true;
+
+    return( ok );
+}
+
+bool IOService::compareProperties( OSDictionary * matching,
+                                   OSCollection * keys )
+{
+    OSCollectionIterator *	iter;
+    const OSString *		key;
+    bool			ok = true;
+
+    if( !matching || !keys)
+	return( false );
+
+    iter = OSCollectionIterator::withCollection( keys );
+
+    if( iter) {
+	while( ok && (key = OSDynamicCast( OSString, iter->getNextObject())))
+	    ok = compareProperty( matching, key );
+
+	iter->release();
+    }
+    keys->release();	// !! consume a ref !!
+
+    return( ok );
+}
 
 /* Helper to add a location matching dict to the table */
 
-OSDictionary *
-IOService::addLocation( OSDictionary * table )
-{
-	OSDictionary *      dict;
-
-	if (!table) {
-		return NULL;
-	}
-
-	dict = OSDictionary::withCapacity( 1 );
-	if (dict) {
-		bool ok = table->setObject( gIOLocationMatchKey, dict );
-		dict->release();
-		if (!ok) {
-			dict = NULL;
-		}
-	}
-
-	return dict;
+OSDictionary * IOService::addLocation( OSDictionary * table )
+{
+    OSDictionary * 	dict;
+
+    if( !table)
+	return( 0 );
+
+    dict = OSDictionary::withCapacity( 1 );
+    if( dict) {
+        table->setObject( gIOLocationMatchKey, dict );
+        dict->release(); 
+    }
+
+    return( dict );
 }
 
 /*
  * Go looking for a provider to match a location dict.
  */
 
-IOService *
-IOService::matchLocation( IOService * /* client */ )
-{
-	IOService * parent;
-
-	parent = getProvider();
-
-	if (parent) {
-		parent = parent->matchLocation( this );
+IOService * IOService::matchLocation( IOService * /* client */ )
+{
+    IOService *	parent;
+
+    parent = getProvider();
+
+    if( parent)
+        parent = parent->matchLocation( this );
+
+    return( parent );
+}
+
+bool IOService::passiveMatch( OSDictionary * table, bool changesOK )
+{
+    IOService *		where;
+    OSString *		matched;
+    OSObject *		obj;
+    OSString *		str;
+    IORegistryEntry *	entry;
+    OSNumber *		num;
+    SInt32		score;
+    OSNumber *		newPri;
+    bool		match = true;
+    UInt32		done;
+
+    assert( table );
+
+    where = this;
+
+    do {
+        done = 0;
+
+        str = OSDynamicCast( OSString, table->getObject( gIOProviderClassKey));
+        if( str) {
+            done++;
+            match = (0 != where->metaCast( str ));
+            if( !match)
+                break;
+        }
+
+        obj = table->getObject( gIONameMatchKey );
+        if( obj) {
+            done++;
+            match = compareNames( obj, changesOK ? &matched : 0 );
+            if( !match)
+                break;
+            if( changesOK && matched) {
+                // leave a hint as to which name matched
+                table->setObject( gIONameMatchedKey, matched );
+                matched->release();
+            }
+        }
+        obj = table->getObject( gIOPropertyMatchKey );
+        if( obj) {
+
+            OSDictionary * dict;
+            OSDictionary * nextDict;
+            OSIterator *   iter;
+
+            done++;
+            dict = where->dictionaryWithProperties();
+            if( dict) {
+                nextDict = OSDynamicCast( OSDictionary, obj);
+                if( nextDict)
+                    iter = 0;
+                else
+                    iter = OSCollectionIterator::withCollection(
+                                OSDynamicCast(OSCollection, obj));
+
+                while( nextDict
+                    || (iter && (0 != (nextDict = OSDynamicCast(OSDictionary,
+                                            iter->getNextObject()))))) {
+                    match = dict->isEqualTo( nextDict, nextDict);
+                    if( match)
+                        break;
+                    nextDict = 0;
+                }
+                dict->release();
+                if( iter)
+                    iter->release();
+                if( !match)
+                    break;
+            }
 	}
 
-	return parent;
-}
-
-OSDictionary *
-IOService::_copyPropertiesForMatching(void)
-{
-	OSDictionary * matchProps;
-
-	matchProps = dictionaryWithProperties();
-	if (matchProps) {
-		// merge will check the OSDynamicCast
-		matchProps->merge((const OSDictionary *)matchProps->getObject(gIOUserServicePropertiesKey));
+        str = OSDynamicCast( OSString, table->getObject( gIOPathMatchKey ));
+        if( str) {
+            done++;
+            entry = IORegistryEntry::fromPath( str->getCStringNoCopy() );
+	    match = (where == entry);
+	    if( entry)
+                entry->release();
+	    if( !match)
+                break;
 	}
-	return matchProps;
-}
-
-bool
-IOService::matchInternal(OSDictionary * table, uint32_t options, uint32_t * did)
-{
-	OSString *          matched;
-	OSObject *          obj;
-	OSString *          str;
-	OSDictionary *      matchProps;
-	IORegistryEntry *   entry;
-	OSNumber *          num;
-	bool                match = true;
-	bool                changesOK = (0 != (kIOServiceChangesOK & options));
-	uint32_t            count;
-	uint32_t            done;
-
-	do{
-		count = table->getCount();
-		done = 0;
-		matchProps = NULL;
-		bool isUser;
-
-		isUser = (NULL != table->getObject(gIOServiceNotificationUserKey));
-		if (isUser) {
-			done++;
-			match = (0 == (kIOServiceUserInvisibleMatchState & __state[0]));
-			if ((!match) || (done == count)) {
-				break;
-			}
-		}
-
-		if (propertyExists(gIOExclaveAssignedKey)) {
-			if (!table->getObject(gIOExclaveProxyKey) && !isUser) {
-				match = false;
-				break;
-			}
-		} else if (table->getObject(gIOExclaveProxyKey)) {
-			match = false;
-			break;
-		}
-
-		if (table->getObject(gIOCompatibilityMatchKey)) {
-			done++;
-			obj = copyProperty(gIOCompatibilityPropertiesKey);
-			matchProps = OSDynamicCast(OSDictionary, obj);
-			if (!matchProps) {
-				OSSafeReleaseNULL(obj);
-			}
-		}
-
-		str = OSDynamicCast(OSString, table->getObject(gIOProviderClassKey));
-		if (str) {
-			done++;
-			if (matchProps && (obj = matchProps->getObject(gIOClassKey))) {
-				match = str->isEqualTo(obj);
-			} else {
-				match = ((kIOServiceClassDone & options) || (NULL != metaCast(str)));
-			}
-
-#if MATCH_DEBUG
-			match = (0 != metaCast( str ));
-			if ((kIOServiceClassDone & options) && !match) {
-				panic("classDone");
-			}
+
+        num = OSDynamicCast( OSNumber, table->getObject( gIOMatchedServiceCountKey ));
+        if( num) {
+
+            OSIterator *	iter;
+            IOService *		service = 0;
+            UInt32		serviceCount = 0;
+
+            done++;
+            iter = getClientIterator();
+            if( iter) {
+                while( (service = (IOService *) iter->getNextObject())) {
+                    if( kIOServiceInactiveState & service->__state[0])
+                        continue;
+                    if( 0 == service->getProperty( gIOMatchCategoryKey ))
+                        continue;
+                    ++serviceCount;
+                }
+                iter->release();
+            }
+	    match = (serviceCount == num->unsigned32BitValue());
+	    if( !match)
+                break;
+	}
+
+	if( done == table->getCount())
+	    // don't call family if we've done all the entries in the table
+	    break;
+
+        // pass in score from property table
+        score = IOServiceObjectOrder( table, (void *) gIOProbeScoreKey);
+
+	// do family specific matching
+	match = where->matchPropertyTable( table, &score );
+
+	if( !match) {
+#if IOMATCHDEBUG
+	    if( kIOLogMatch & getDebugFlags( table ))
+		LOG("%s: family specific matching fails\n", where->getName());
 #endif
-			if ((!match) || (done == count)) {
-				break;
-			}
-		}
-
-		obj = table->getObject( gIONameMatchKey );
-		if (obj) {
-			done++;
-			match = compareNames( obj, changesOK ? &matched : NULL );
-			if (!match) {
-				break;
-			}
-			if (changesOK && matched) {
-				// leave a hint as to which name matched
-				table->setObject( gIONameMatchedKey, matched );
-				matched->release();
-			}
-			if (done == count) {
-				break;
-			}
-		}
-
-		str = OSDynamicCast( OSString, table->getObject( gIOLocationMatchKey ));
-		if (str) {
-			const OSSymbol * sym;
-			done++;
-			match = false;
-			sym = copyLocation();
-			if (sym) {
-				match = sym->isEqualTo( str );
-				sym->release();
-			}
-			if ((!match) || (done == count)) {
-				break;
-			}
-		}
-
-		obj = table->getObject( gIOPropertyMatchKey );
-		if (obj) {
-			OSDictionary * nextDict;
-			OSIterator *   iter;
-			done++;
-			match = false;
-			if (!matchProps) {
-				matchProps = _copyPropertiesForMatching();
-			}
-			if (matchProps) {
-				nextDict = OSDynamicCast( OSDictionary, obj);
-				if (nextDict) {
-					iter = NULL;
-				} else {
-					iter = OSCollectionIterator::withCollection(
-						OSDynamicCast(OSCollection, obj));
-				}
-
-				while (nextDict
-				    || (iter && (NULL != (nextDict = OSDynamicCast(OSDictionary,
-				    iter->getNextObject()))))) {
-					match = matchProps->isEqualTo( nextDict, nextDict);
-					if (match) {
-						break;
-					}
-					nextDict = NULL;
-				}
-				if (iter) {
-					iter->release();
-				}
-			}
-			if ((!match) || (done == count)) {
-				break;
-			}
-		}
-
-		obj = table->getObject( gIOPropertyExistsMatchKey );
-		if (obj) {
-			OSString     * nextKey;
-			OSIterator *   iter;
-			done++;
-			match = false;
-			if (!matchProps) {
-				matchProps = _copyPropertiesForMatching();
-			}
-			if (matchProps) {
-				nextKey = OSDynamicCast( OSString, obj);
-				if (nextKey) {
-					iter = NULL;
-				} else {
-					iter = OSCollectionIterator::withCollection(
-						OSDynamicCast(OSCollection, obj));
-				}
-
-				while (nextKey
-				    || (iter && (NULL != (nextKey = OSDynamicCast(OSString,
-				    iter->getNextObject()))))) {
-					match = (NULL != matchProps->getObject(nextKey));
-					if (match) {
-						break;
-					}
-					nextKey = NULL;
-				}
-				if (iter) {
-					iter->release();
-				}
-			}
-			if ((!match) || (done == count)) {
-				break;
-			}
-		}
-
-		str = OSDynamicCast( OSString, table->getObject( gIOPathMatchKey ));
-		if (str) {
-			done++;
-			entry = IORegistryEntry::fromPath( str->getCStringNoCopy());
-			match = (this == entry);
-			if (entry) {
-				entry->release();
-			}
-			if (!match && matchProps && (obj = matchProps->getObject(gIOPathKey))) {
-				match = str->isEqualTo(obj);
-			}
-			if ((!match) || (done == count)) {
-				break;
-			}
-		}
-
-		num = OSDynamicCast( OSNumber, table->getObject( gIORegistryEntryIDKey ));
-		if (num) {
-			done++;
-			match = (getRegistryEntryID() == num->unsigned64BitValue());
-			if ((!match) || (done == count)) {
-				break;
-			}
-		}
-
-		num = OSDynamicCast( OSNumber, table->getObject( gIOMatchedServiceCountKey ));
-		if (num) {
-			OSIterator *        iter;
-			IOService *         service = NULL;
-			UInt32              serviceCount = 0;
-
-			done++;
-			iter = getClientIterator();
-			if (iter) {
-				while ((service = (IOService *) iter->getNextObject())) {
-					if (kIOServiceInactiveState & service->__state[0]) {
-						continue;
-					}
-					if (NULL == service->getProperty( gIOMatchCategoryKey )) {
-						continue;
-					}
-					++serviceCount;
-				}
-				iter->release();
-			}
-			match = (serviceCount == num->unsigned32BitValue());
-			if ((!match) || (done == count)) {
-				break;
-			}
-		}
-
-#define propMatch(key)                                  \
-	obj = table->getObject(key);                    \
-	if (obj)                                        \
-	{                                               \
-	    OSObject * prop;                            \
-	    done++;                                     \
-	    prop = copyProperty(key);                   \
-	    match = obj->isEqualTo(prop);               \
-	    if (prop) prop->release();                  \
-	    if ((!match) || (done == count)) break;     \
+	    break;
 	}
-		propMatch(gIOBSDNameKey)
-		propMatch(gIOBSDMajorKey)
-		propMatch(gIOBSDMinorKey)
-		propMatch(gIOBSDUnitKey)
-#undef propMatch
-	}while (false);
-
-	OSSafeReleaseNULL(matchProps);
-
-	if (did) {
-		*did = done;
+
+        if( changesOK) {
+            // save the score
+            newPri = OSNumber::withNumber( score, 32 );
+            if( newPri) {
+                table->setObject( gIOProbeScoreKey, newPri );
+                newPri->release();
+            }
+        }
+
+        if( !(match = where->compareProperty( table, kIOBSDNameKey )))
+	    break;
+
+	table = OSDynamicCast( OSDictionary,
+		table->getObject( gIOLocationMatchKey ));
+	if( table) {
+	    match = false;
+	    where = where->getProvider();
+	    if( where)
+		where = where->matchLocation( where );
 	}
-	return match;
-}
-
-bool
-IOService::passiveMatch( OSDictionary * table, bool changesOK )
-{
-	return matchPassive(table, changesOK ? kIOServiceChangesOK : 0);
-}
-
-bool
-IOService::matchPassive(OSDictionary * table, uint32_t options)
-{
-	IOService *         where;
-	OSDictionary *      nextTable;
-	SInt32              score;
-	OSNumber *          newPri;
-	bool                match = true;
-	bool                matchParent = false;
-	uint32_t            count;
-	uint32_t            done;
-
-	assert( table );
-
-#if defined(XNU_TARGET_OS_OSX)
-	OSArray* aliasServiceRegIds = NULL;
-	IOService* foundAlternateService = NULL;
-#endif /* defined(XNU_TARGET_OS_OSX) */
-
-#if MATCH_DEBUG
-	OSDictionary * root = table;
-#endif
-
-	where = this;
-	do{
-		do{
-			count = table->getCount();
-			if (!(kIOServiceInternalDone & options)) {
-				match = where->matchInternal(table, options, &done);
-				// don't call family if we've done all the entries in the table
-				if ((!match) || (done == count)) {
-					break;
-				}
-			}
-
-			// pass in score from property table
-			score = IOServiceObjectOrder( table, (void *) gIOProbeScoreKey);
-
-			// do family specific matching
-			match = where->matchPropertyTable( table, &score );
-
-			if (!match) {
-#if IOMATCHDEBUG
-				if (kIOLogMatch & getDebugFlags( table )) {
-					LOG("%s: family specific matching fails\n", where->getName());
-				}
-#endif
-				break;
-			}
-
-			if (kIOServiceChangesOK & options) {
-				// save the score
-				newPri = OSNumber::withNumber( score, 32 );
-				if (newPri) {
-					table->setObject( gIOProbeScoreKey, newPri );
-					newPri->release();
-				}
-			}
-
-			options = 0;
-			matchParent = false;
-
-			nextTable = OSDynamicCast(OSDictionary,
-			    table->getObject( gIOParentMatchKey ));
-			if (nextTable) {
-				// look for a matching entry anywhere up to root
-				match = false;
-				matchParent = true;
-				table = nextTable;
-				break;
-			}
-
-			table = OSDynamicCast(OSDictionary,
-			    table->getObject( gIOLocationMatchKey ));
-			if (table) {
-				// look for a matching entry at matchLocation()
-				match = false;
-				where = where->getProvider();
-				if (where && (where = where->matchLocation(where))) {
-					continue;
-				}
-			}
-			break;
-		}while (true);
-
-		if (match == true) {
-			break;
-		}
-
-		if (matchParent == true) {
-#if defined(XNU_TARGET_OS_OSX)
-			// check if service has an alias to search its other "parents" if a parent match isn't found
-			OSObject * prop = where->copyProperty(gIOServiceLegacyMatchingRegistryIDKey);
-			OSNumber * alternateRegistryID = OSDynamicCast(OSNumber, prop);
-			if (alternateRegistryID != NULL) {
-				if (aliasServiceRegIds == NULL) {
-					aliasServiceRegIds = OSArray::withCapacity(sizeof(alternateRegistryID));
-				}
-				aliasServiceRegIds->setObject(alternateRegistryID);
-			}
-			OSSafeReleaseNULL(prop);
-#endif /* defined(XNU_TARGET_OS_OSX) */
-		} else {
-			break;
-		}
-
-		where = where->getProvider();
-#if defined(XNU_TARGET_OS_OSX)
-		if (where == NULL) {
-			// there were no matching parent services, check to see if there are aliased services that have a matching parent
-			if (aliasServiceRegIds != NULL) {
-				unsigned int numAliasedServices = aliasServiceRegIds->getCount();
-				if (numAliasedServices != 0) {
-					OSNumber* alternateRegistryID = OSDynamicCast(OSNumber, aliasServiceRegIds->getObject(numAliasedServices - 1));
-					if (alternateRegistryID != NULL) {
-						OSDictionary* alternateMatchingDict = IOService::registryEntryIDMatching(alternateRegistryID->unsigned64BitValue());
-						aliasServiceRegIds->removeObject(numAliasedServices - 1);
-						if (alternateMatchingDict != NULL) {
-							OSSafeReleaseNULL(foundAlternateService);
-							foundAlternateService = IOService::copyMatchingService(alternateMatchingDict);
-							alternateMatchingDict->release();
-							if (foundAlternateService != NULL) {
-								where = foundAlternateService;
-							}
-						}
-					}
-				}
-			}
-		}
-#endif /* defined(XNU_TARGET_OS_OSX) */
-	}while (where != NULL);
-
-#if defined(XNU_TARGET_OS_OSX)
-	OSSafeReleaseNULL(foundAlternateService);
-	OSSafeReleaseNULL(aliasServiceRegIds);
-#endif /* defined(XNU_TARGET_OS_OSX) */
-
-#if MATCH_DEBUG
-	if (where != this) {
-		OSSerialize * s = OSSerialize::withCapacity(128);
-		root->serialize(s);
-		kprintf("parent match 0x%llx, %d,\n%s\n", getRegistryEntryID(), match, s->text());
-		s->release();
+
+    } while( table && where );
+
+    if( kIOLogMatch & gIOKitDebug)
+        if( where != this)
+            LOG("match location @ %s = %d\n",
+                        where->getName(), match );
+
+    return( match );
+}
+
+
+IOReturn IOService::newUserClient( task_t owningTask, void * securityID,
+                                    UInt32 type,  OSDictionary * properties,
+                                    IOUserClient ** handler )
+{
+    const OSSymbol *userClientClass = 0;
+    IOUserClient *client;
+    OSObject *temp;
+
+    // First try my own properties for a user client class name
+    temp = getProperty(gIOUserClientClassKey);
+    if (temp) {
+	if (OSDynamicCast(OSSymbol, temp))
+	    userClientClass = (const OSSymbol *) temp;
+	else if (OSDynamicCast(OSString, temp)) {
+	    userClientClass = OSSymbol::withString((OSString *) temp);
+	    if (userClientClass)
+		setProperty(kIOUserClientClassKey,
+			    (OSObject *) userClientClass);
 	}
-#endif
-
-	return match;
-}
-
-
-IOReturn
-IOService::newUserClient( task_t owningTask, void * securityID,
-    UInt32 type, OSDictionary * properties,
-    IOUserClient ** handler )
-{
-	const OSSymbol *userClientClass = NULL;
-	IOUserClient *client;
-	OSObject *prop;
-	OSObject *temp;
-
-	if (reserved && reserved->uvars && reserved->uvars->userServer) {
-		return reserved->uvars->userServer->serviceNewUserClient(this, owningTask, securityID, type, properties, handler);
-	}
-
-	if (kIOReturnSuccess == newUserClient( owningTask, securityID, type, handler )) {
-		return kIOReturnSuccess;
-	}
-
-	// First try my own properties for a user client class name
-	prop = copyProperty(gIOUserClientClassKey);
-	if (prop) {
-		if (OSDynamicCast(OSSymbol, prop)) {
-			userClientClass = (const OSSymbol *) prop;
-			prop = NULL;
-		} else if (OSDynamicCast(OSString, prop)) {
-			userClientClass = OSSymbol::withString((OSString *) prop);
-			OSSafeReleaseNULL(prop);
-			if (userClientClass) {
-				setProperty(gIOUserClientClassKey,
-				    (OSObject *) userClientClass);
-			}
-		} else {
-			OSSafeReleaseNULL(prop);
-		}
-	}
-
-	// Didn't find one so lets just bomb out now without further ado.
-	if (!userClientClass) {
-		return kIOReturnUnsupported;
-	}
-
-	// This reference is consumed by the IOServiceOpen call
-	temp = OSMetaClass::allocClassWithName(userClientClass);
-	OSSafeReleaseNULL(userClientClass);
-	if (!temp) {
-		return kIOReturnNoMemory;
-	}
-
-	if (OSDynamicCast(IOUserClient, temp)) {
-		client = (IOUserClient *) temp;
-	} else {
-		temp->release();
-		return kIOReturnUnsupported;
-	}
-
-	if (!client->initWithTask(owningTask, securityID, type, properties)) {
-		client->release();
-		return kIOReturnBadArgument;
-	}
-
-	if (!client->attach(this)) {
-		client->release();
-		return kIOReturnUnsupported;
-	}
-
-	if (!client->start(this)) {
-		client->detach(this);
-		client->release();
-		return kIOReturnUnsupported;
-	}
-
-	*handler = client;
-	return kIOReturnSuccess;
-}
-
-IOReturn
-IOService::newUserClient( task_t owningTask, void * securityID,
-    UInt32 type, OSDictionary * properties,
-    OSSharedPtr<IOUserClient>& handler )
-{
-	IOUserClient* handlerRaw = NULL;
-	IOReturn result = newUserClient(owningTask, securityID, type, properties, &handlerRaw);
-	handler.reset(handlerRaw, OSNoRetain);
-	return result;
-}
-
-IOReturn
-IOService::newUserClient( task_t owningTask, void * securityID,
-    UInt32 type, IOUserClient ** handler )
-{
-	return kIOReturnUnsupported;
-}
-
-IOReturn
-IOService::newUserClient( task_t owningTask, void * securityID,
-    UInt32 type, OSSharedPtr<IOUserClient>& handler )
-{
-	IOUserClient* handlerRaw = nullptr;
-	IOReturn result = IOService::newUserClient(owningTask, securityID, type, &handlerRaw);
-	handler.reset(handlerRaw, OSNoRetain);
-	return result;
-}
-
-
-IOReturn
-IOService::requestProbe( IOOptionBits options )
-{
-	return kIOReturnUnsupported;
-}
-
-bool
-IOService::hasUserServer() const
-{
-	return reserved && reserved->uvars && reserved->uvars->userServer;
+    }
+
+    // Didn't find one so lets just bomb out now without further ado.
+    if (!userClientClass)
+        return kIOReturnUnsupported;
+
+    temp = OSMetaClass::allocClassWithName(userClientClass);
+    if (!temp)
+        return kIOReturnNoMemory;
+
+    if (OSDynamicCast(IOUserClient, temp))
+        client = (IOUserClient *) temp;
+    else {
+        temp->release();
+        return kIOReturnUnsupported;
+    }
+
+    if ( !client->initWithTask(owningTask, securityID, type, properties) ) {
+        client->release();
+        return kIOReturnBadArgument;
+    }
+
+    if ( !client->attach(this) ) {
+        client->release();
+        return kIOReturnUnsupported;
+    }
+
+    if ( !client->start(this) ) {
+        client->detach(this);
+        client->release();
+        return kIOReturnUnsupported;
+    }
+
+    *handler = client;
+    return kIOReturnSuccess;
+}
+
+IOReturn IOService::newUserClient( task_t owningTask, void * securityID,
+                                    UInt32 type, IOUserClient ** handler )
+{
+    return( newUserClient( owningTask, securityID, type, 0, handler ));
+}
+
+IOReturn IOService::requestProbe( IOOptionBits options )
+{
+    return( kIOReturnUnsupported);
 }
 
 /*
  * Convert an IOReturn to text. Subclasses which add additional
- * IOReturn's should override this method and call
+ * IOReturn's should override this method and call 
  * super::stringFromReturn if the desired value is not found.
  */
 
-const char *
-IOService::stringFromReturn( IOReturn rtn )
-{
-	static const IONamedValue IOReturn_values[] = {
-		{kIOReturnSuccess, "success"                           },
-		{kIOReturnError, "general error"                     },
-		{kIOReturnNoMemory, "memory allocation error"           },
-		{kIOReturnNoResources, "resource shortage"                 },
-		{kIOReturnIPCError, "Mach IPC failure"                  },
-		{kIOReturnNoDevice, "no such device"                    },
-		{kIOReturnNotPrivileged, "privilege violation"               },
-		{kIOReturnBadArgument, "invalid argument"                  },
-		{kIOReturnLockedRead, "device is read locked"             },
-		{kIOReturnLockedWrite, "device is write locked"            },
-		{kIOReturnExclusiveAccess, "device is exclusive access"        },
-		{kIOReturnBadMessageID, "bad IPC message ID"                },
-		{kIOReturnUnsupported, "unsupported function"              },
-		{kIOReturnVMError, "virtual memory error"              },
-		{kIOReturnInternalError, "internal driver error"             },
-		{kIOReturnIOError, "I/O error"                         },
-		{kIOReturnCannotLock, "cannot acquire lock"               },
-		{kIOReturnNotOpen, "device is not open"                },
-		{kIOReturnNotReadable, "device is not readable"            },
-		{kIOReturnNotWritable, "device is not writeable"           },
-		{kIOReturnNotAligned, "alignment error"                   },
-		{kIOReturnBadMedia, "media error"                       },
-		{kIOReturnStillOpen, "device is still open"              },
-		{kIOReturnRLDError, "rld failure"                       },
-		{kIOReturnDMAError, "DMA failure"                       },
-		{kIOReturnBusy, "device is busy"                    },
-		{kIOReturnTimeout, "I/O timeout"                       },
-		{kIOReturnOffline, "device is offline"                 },
-		{kIOReturnNotReady, "device is not ready"               },
-		{kIOReturnNotAttached, "device/channel is not attached"    },
-		{kIOReturnNoChannels, "no DMA channels available"         },
-		{kIOReturnNoSpace, "no space for data"                 },
-		{kIOReturnPortExists, "device port already exists"        },
-		{kIOReturnCannotWire, "cannot wire physical memory"       },
-		{kIOReturnNoInterrupt, "no interrupt attached"             },
-		{kIOReturnNoFrames, "no DMA frames enqueued"            },
-		{kIOReturnMessageTooLarge, "message is too large"              },
-		{kIOReturnNotPermitted, "operation is not permitted"        },
-		{kIOReturnNoPower, "device is without power"           },
-		{kIOReturnNoMedia, "media is not present"              },
-		{kIOReturnUnformattedMedia, "media is not formatted"            },
-		{kIOReturnUnsupportedMode, "unsupported mode"                  },
-		{kIOReturnUnderrun, "data underrun"                     },
-		{kIOReturnOverrun, "data overrun"                      },
-		{kIOReturnDeviceError, "device error"                      },
-		{kIOReturnNoCompletion, "no completion routine"             },
-		{kIOReturnAborted, "operation was aborted"             },
-		{kIOReturnNoBandwidth, "bus bandwidth would be exceeded"   },
-		{kIOReturnNotResponding, "device is not responding"          },
-		{kIOReturnInvalid, "unanticipated driver error"        },
-		{0, NULL                                }
-	};
-
-	return IOFindNameForValue(rtn, IOReturn_values);
+const char * IOService::stringFromReturn( IOReturn rtn )
+{
+    static const IONamedValue IOReturn_values[] = { 
+        {kIOReturnSuccess,          "success"                           },
+        {kIOReturnError,            "general error"                     },
+        {kIOReturnNoMemory,         "memory allocation error"           },
+        {kIOReturnNoResources,      "resource shortage"                 },
+        {kIOReturnIPCError,         "Mach IPC failure"                  },
+        {kIOReturnNoDevice,         "no such device"                    },
+        {kIOReturnNotPrivileged,    "privilege violation"               },
+        {kIOReturnBadArgument,      "invalid argument"                  },
+        {kIOReturnLockedRead,       "device is read locked"             },
+        {kIOReturnLockedWrite,      "device is write locked"            },
+        {kIOReturnExclusiveAccess,  "device is exclusive access"        },
+        {kIOReturnBadMessageID,     "bad IPC message ID"                },
+        {kIOReturnUnsupported,      "unsupported function"              },
+        {kIOReturnVMError,          "virtual memory error"              },
+        {kIOReturnInternalError,    "internal driver error"             },
+        {kIOReturnIOError,          "I/O error"                         },
+        {kIOReturnCannotLock,       "cannot acquire lock"               },
+        {kIOReturnNotOpen,          "device is not open"                },
+        {kIOReturnNotReadable,      "device is not readable"            },
+        {kIOReturnNotWritable,      "device is not writeable"           },
+        {kIOReturnNotAligned,       "alignment error"                   },
+        {kIOReturnBadMedia,         "media error"                       },
+        {kIOReturnStillOpen,        "device is still open"              },
+        {kIOReturnRLDError,         "rld failure"                       },
+        {kIOReturnDMAError,         "DMA failure"                       },
+        {kIOReturnBusy,             "device is busy"                    },
+        {kIOReturnTimeout,          "I/O timeout"                       },
+        {kIOReturnOffline,          "device is offline"                 },
+        {kIOReturnNotReady,         "device is not ready"               },
+        {kIOReturnNotAttached,      "device/channel is not attached"    },
+        {kIOReturnNoChannels,       "no DMA channels available"         },
+        {kIOReturnNoSpace,          "no space for data"                 },
+        {kIOReturnPortExists,       "device port already exists"        },
+        {kIOReturnCannotWire,       "cannot wire physical memory"       },
+        {kIOReturnNoInterrupt,      "no interrupt attached"             },
+        {kIOReturnNoFrames,         "no DMA frames enqueued"            },
+        {kIOReturnMessageTooLarge,  "message is too large"              },
+        {kIOReturnNotPermitted,     "operation is not permitted"        },
+        {kIOReturnNoPower,          "device is without power"           },
+        {kIOReturnNoMedia,          "media is not present"              },
+        {kIOReturnUnformattedMedia, "media is not formatted"            },
+        {kIOReturnUnsupportedMode,  "unsupported mode"                  },
+        {kIOReturnUnderrun,         "data underrun"                     },
+        {kIOReturnOverrun,          "data overrun"                      },
+        {kIOReturnDeviceError,      "device error"                      },
+        {kIOReturnNoCompletion,     "no completion routine"             },
+        {kIOReturnAborted,          "operation was aborted"             },
+        {kIOReturnNoBandwidth,      "bus bandwidth would be exceeded"   },
+        {kIOReturnNotResponding,    "device is not responding"          },
+        {kIOReturnInvalid,          "unanticipated driver error"        },
+        {0,                         NULL                                }
+    };
+
+    return IOFindNameForValue(rtn, IOReturn_values);
 }
 
 /*
  * Convert an IOReturn to an errno.
  */
-int
-IOService::errnoFromReturn( IOReturn rtn )
-{
-	if (unix_err(err_get_code(rtn)) == rtn) {
-		return err_get_code(rtn);
-	}
-
-	switch (rtn) {
-	// (obvious match)
-	case kIOReturnSuccess:
-		return 0;
-	case kIOReturnNoMemory:
-		return ENOMEM;
-	case kIOReturnNoDevice:
-		return ENXIO;
-	case kIOReturnVMError:
-		return EFAULT;
-	case kIOReturnNotPermitted:
-		return EPERM;
-	case kIOReturnNotPrivileged:
-		return EACCES;
-	case kIOReturnIOError:
-		return EIO;
-	case kIOReturnNotWritable:
-		return EROFS;
-	case kIOReturnBadArgument:
-		return EINVAL;
-	case kIOReturnUnsupported:
-		return ENOTSUP;
-	case kIOReturnBusy:
-		return EBUSY;
-	case kIOReturnNoPower:
-		return EPWROFF;
-	case kIOReturnDeviceError:
-		return EDEVERR;
-	case kIOReturnTimeout:
-		return ETIMEDOUT;
-	case kIOReturnMessageTooLarge:
-		return EMSGSIZE;
-	case kIOReturnNoSpace:
-		return ENOSPC;
-	case kIOReturnCannotLock:
-		return ENOLCK;
-
-	// (best match)
-	case kIOReturnBadMessageID:
-	case kIOReturnNoCompletion:
-	case kIOReturnNotAligned:
-		return EINVAL;
-	case kIOReturnNotReady:
-		return EBUSY;
-	case kIOReturnRLDError:
-		return EBADMACHO;
-	case kIOReturnPortExists:
-	case kIOReturnStillOpen:
-		return EEXIST;
-	case kIOReturnExclusiveAccess:
-	case kIOReturnLockedRead:
-	case kIOReturnLockedWrite:
-	case kIOReturnNotOpen:
-	case kIOReturnNotReadable:
-		return EACCES;
-	case kIOReturnCannotWire:
-	case kIOReturnNoResources:
-		return ENOMEM;
-	case kIOReturnAborted:
-	case kIOReturnOffline:
-	case kIOReturnNotResponding:
-		return EBUSY;
-	case kIOReturnBadMedia:
-	case kIOReturnNoMedia:
-	case kIOReturnNotAttached:
-	case kIOReturnUnformattedMedia:
-		return ENXIO; // (media error)
-	case kIOReturnDMAError:
-	case kIOReturnOverrun:
-	case kIOReturnUnderrun:
-		return EIO; // (transfer error)
-	case kIOReturnNoBandwidth:
-	case kIOReturnNoChannels:
-	case kIOReturnNoFrames:
-	case kIOReturnNoInterrupt:
-		return EIO; // (hardware error)
-	case kIOReturnError:
-	case kIOReturnInternalError:
-	case kIOReturnInvalid:
-		return EIO; // (generic error)
-	case kIOReturnIPCError:
-		return EIO; // (ipc error)
-	default:
-		return EIO; // (all other errors)
-	}
-}
-
-IOReturn
-IOService::message( UInt32 type, IOService * provider,
-    void * argument )
-{
-	/*
-	 * Generic entry point for calls from the provider.  A return value of
-	 * kIOReturnSuccess indicates that the message was received, and where
-	 * applicable, that it was successful.
-	 */
-
-	return kIOReturnUnsupported;
+int IOService::errnoFromReturn( IOReturn rtn )
+{
+    switch(rtn) {
+        // (obvious match)
+        case kIOReturnSuccess:
+            return(0);
+        case kIOReturnNoMemory:
+            return(ENOMEM);
+        case kIOReturnNoDevice:
+            return(ENXIO);
+        case kIOReturnVMError:
+            return(EFAULT);
+        case kIOReturnNotPermitted:
+            return(EPERM);
+        case kIOReturnNotPrivileged:
+            return(EACCES);
+        case kIOReturnIOError:
+            return(EIO);
+        case kIOReturnNotWritable:
+            return(EROFS);
+        case kIOReturnBadArgument:
+            return(EINVAL);
+        case kIOReturnUnsupported:
+            return(EOPNOTSUPP);
+        case kIOReturnBusy:
+            return(EBUSY);
+        case kIOReturnNoPower:
+            return(EPWROFF);
+        case kIOReturnDeviceError:
+            return(EDEVERR);
+        case kIOReturnTimeout: 
+            return(ETIMEDOUT);
+        case kIOReturnMessageTooLarge:
+            return(EMSGSIZE);
+        case kIOReturnNoSpace:
+            return(ENOSPC);
+        case kIOReturnCannotLock:
+            return(ENOLCK);
+
+        // (best match)
+        case kIOReturnBadMessageID:
+        case kIOReturnNoCompletion:
+        case kIOReturnNotAligned:
+            return(EINVAL);
+        case kIOReturnNotReady:
+            return(EBUSY);
+        case kIOReturnRLDError:
+            return(EBADMACHO);
+        case kIOReturnPortExists:
+        case kIOReturnStillOpen:
+            return(EEXIST);
+        case kIOReturnExclusiveAccess:
+        case kIOReturnLockedRead:
+        case kIOReturnLockedWrite:
+        case kIOReturnNotAttached:
+        case kIOReturnNotOpen:
+        case kIOReturnNotReadable:
+            return(EACCES);
+        case kIOReturnCannotWire:
+        case kIOReturnNoResources:
+            return(ENOMEM);
+        case kIOReturnAborted:
+        case kIOReturnOffline:
+        case kIOReturnNotResponding:
+            return(EBUSY);
+        case kIOReturnBadMedia:
+        case kIOReturnNoMedia:
+        case kIOReturnUnformattedMedia:
+            return(EIO); // (media error)
+        case kIOReturnDMAError:
+        case kIOReturnOverrun:
+        case kIOReturnUnderrun:
+            return(EIO); // (transfer error)
+        case kIOReturnNoBandwidth:
+        case kIOReturnNoChannels:
+        case kIOReturnNoFrames:
+        case kIOReturnNoInterrupt:
+            return(EIO); // (hardware error)
+        case kIOReturnError:
+        case kIOReturnInternalError:
+        case kIOReturnInvalid:
+            return(EIO); // (generic error)
+        case kIOReturnIPCError:
+            return(EIO); // (ipc error)
+        default:
+            return(EIO); // (all other errors)
+    }
+}
+
+IOReturn IOService::message( UInt32 type, IOService * provider,
+				void * argument )
+{
+    /*
+     * Generic entry point for calls from the provider.  A return value of
+     * kIOReturnSuccess indicates that the message was received, and where
+     * applicable, that it was successful.
+     */
+
+    return kIOReturnUnsupported;
 }
 
 /*
  * Device memory
  */
 
-IOItemCount
-IOService::getDeviceMemoryCount( void )
-{
-	OSArray *           array;
-	IOItemCount         count;
-
-	array = OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
-	if (array) {
-		count = array->getCount();
-	} else {
-		count = 0;
-	}
-
-	return count;
-}
-
-IODeviceMemory *
-IOService::getDeviceMemoryWithIndex( unsigned int index )
-{
-	OSArray *           array;
-	IODeviceMemory *    range;
-
-	array = OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
-	if (array) {
-		range = (IODeviceMemory *) array->getObject( index );
-	} else {
-		range = NULL;
-	}
-
-	return range;
-}
-
-IOMemoryMap *
-IOService::mapDeviceMemoryWithIndex( unsigned int index,
-    IOOptionBits options )
-{
-	IODeviceMemory *    range;
-	IOMemoryMap *       map;
-
-	range = getDeviceMemoryWithIndex( index );
-	if (range) {
-		map = range->map( options );
-	} else {
-		map = NULL;
-	}
-
-	return map;
-}
-
-OSArray *
-IOService::getDeviceMemory( void )
-{
-	return OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
-}
-
-
-void
-IOService::setDeviceMemory( OSArray * array )
-{
-	setProperty( gIODeviceMemoryKey, array);
-}
-
-static void
-requireMaxCpuDelay(IOService * service, UInt32 ns, UInt32 delayType)
-{
-	static const UInt kNoReplace = -1U; // Must be an illegal index
-	UInt replace = kNoReplace;
-	bool setCpuDelay = false;
-
-	IORecursiveLockLock(sCpuDelayLock);
-
-	UInt count = sCpuDelayData->getLength() / sizeof(CpuDelayEntry);
-	__typed_allocators_ignore_push
-	CpuDelayEntry *entries = (CpuDelayEntry *) sCpuDelayData->getBytesNoCopy();
-	__typed_allocators_ignore_pop
-	IOService * holder = NULL;
-
-	if (ns) {
-		const CpuDelayEntry ne = {service, ns, delayType};
-		holder = service;
-		// Set maximum delay.
-		for (UInt i = 0; i < count; i++) {
-			IOService *thisService = entries[i].fService;
-			bool sameType = (delayType == entries[i].fDelayType);
-			if ((service == thisService) && sameType) {
-				replace = i;
-			} else if (!thisService) {
-				if (kNoReplace == replace) {
-					replace = i;
-				}
-			} else if (sameType) {
-				const UInt32 thisMax = entries[i].fMaxDelay;
-				if (thisMax < ns) {
-					ns = thisMax;
-					holder = thisService;
-				}
-			}
-		}
-
-		setCpuDelay = true;
-		if (kNoReplace == replace) {
-			__typed_allocators_ignore_push
-			sCpuDelayData->appendBytes(&ne, sizeof(ne));
-			__typed_allocators_ignore_pop
-		} else {
-			entries[replace] = ne;
-		}
-	} else {
-		ns = -1U; // Set to max unsigned, i.e. no restriction
-
-		for (UInt i = 0; i < count; i++) {
-			// Clear a maximum delay.
-			IOService *thisService = entries[i].fService;
-			if (thisService && (delayType == entries[i].fDelayType)) {
-				UInt32 thisMax = entries[i].fMaxDelay;
-				if (service == thisService) {
-					replace = i;
-				} else if (thisMax < ns) {
-					ns = thisMax;
-					holder = thisService;
-				}
-			}
-		}
-
-		// Check if entry found
-		if (kNoReplace != replace) {
-			entries[replace].fService = NULL; // Null the entry
-			setCpuDelay = true;
-		}
-	}
-
-	if (setCpuDelay) {
-		if (holder && debug_boot_arg) {
-			strlcpy(sCPULatencyHolderName[delayType], holder->getName(), sizeof(sCPULatencyHolderName[delayType]));
-		}
-
-		// Must be safe to call from locked context
-		if (delayType == kCpuDelayBusStall) {
-#if defined(__x86_64__)
-			ml_set_maxbusdelay(ns);
-#endif /* defined(__x86_64__) */
-		}
-#if defined(__x86_64__)
-		else if (delayType == kCpuDelayInterrupt) {
-			ml_set_maxintdelay(ns);
-		}
-#endif /* defined(__x86_64__) */
-		sCPULatencyHolder[delayType]->setValue(holder ? holder->getRegistryEntryID() : 0);
-		sCPULatencySet[delayType]->setValue(ns);
-
-		OSArray * handlers = sCpuLatencyHandlers[delayType];
-		IOService * target;
-		if (handlers) {
-			for (unsigned int idx = 0;
-			    (target = (IOService *) handlers->getObject(idx));
-			    idx++) {
-				target->callPlatformFunction(sCPULatencyFunctionName[delayType], false,
-				    (void *) (uintptr_t) ns, holder,
-				    NULL, NULL);
-			}
-		}
-	}
-
-	IORecursiveLockUnlock(sCpuDelayLock);
-}
-
-static IOReturn
-setLatencyHandler(UInt32 delayType, IOService * target, bool enable)
-{
-	IOReturn result = kIOReturnNotFound;
-	OSArray * array;
-	unsigned int idx;
-
-	IORecursiveLockLock(sCpuDelayLock);
-
-	do{
-		if (enable && !sCpuLatencyHandlers[delayType]) {
-			sCpuLatencyHandlers[delayType] = OSArray::withCapacity(4);
-		}
-		array = sCpuLatencyHandlers[delayType];
-		if (!array) {
-			break;
-		}
-		idx = array->getNextIndexOfObject(target, 0);
-		if (!enable) {
-			if (-1U != idx) {
-				array->removeObject(idx);
-				result = kIOReturnSuccess;
-			}
-		} else {
-			if (-1U != idx) {
-				result = kIOReturnExclusiveAccess;
-				break;
-			}
-			array->setObject(target);
-
-			UInt count = sCpuDelayData->getLength() / sizeof(CpuDelayEntry);
-			__typed_allocators_ignore_push
-			CpuDelayEntry *entries = (CpuDelayEntry *) sCpuDelayData->getBytesNoCopy();
-			__typed_allocators_ignore_pop
-			UInt32 ns = -1U; // Set to max unsigned, i.e. no restriction
-			IOService * holder = NULL;
-
-			for (UInt i = 0; i < count; i++) {
-				if (entries[i].fService
-				    && (delayType == entries[i].fDelayType)
-				    && (entries[i].fMaxDelay < ns)) {
-					ns = entries[i].fMaxDelay;
-					holder = entries[i].fService;
-				}
-			}
-			target->callPlatformFunction(sCPULatencyFunctionName[delayType], false,
-			    (void *) (uintptr_t) ns, holder,
-			    NULL, NULL);
-			result = kIOReturnSuccess;
-		}
-	}while (false);
-
-	IORecursiveLockUnlock(sCpuDelayLock);
-
-	return result;
-}
-
-IOReturn
-IOService::requireMaxBusStall(UInt32 ns)
-{
-#if !defined(__x86_64__)
-	switch (ns) {
-	case kIOMaxBusStall40usec:
-	case kIOMaxBusStall30usec:
-	case kIOMaxBusStall25usec:
-	case kIOMaxBusStall20usec:
-	case kIOMaxBusStall10usec:
-	case kIOMaxBusStall5usec:
-	case kIOMaxBusStallNone:
-		break;
-	default:
-		return kIOReturnBadArgument;
-	}
-#endif /* !defined(__x86_64__) */
-	requireMaxCpuDelay(this, ns, kCpuDelayBusStall);
-	return kIOReturnSuccess;
-}
-
-IOReturn
-IOService::requireMaxInterruptDelay(uint32_t ns)
-{
-#if defined(__x86_64__)
-	requireMaxCpuDelay(this, ns, kCpuDelayInterrupt);
-	return kIOReturnSuccess;
-#else /* defined(__x86_64__) */
-	return kIOReturnUnsupported;
-#endif /* defined(__x86_64__) */
+IOItemCount IOService::getDeviceMemoryCount( void )
+{
+    OSArray *		array;
+    IOItemCount		count;
+
+    array = OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
+    if( array)
+	count = array->getCount();
+    else
+	count = 0;
+
+    return( count);
+}
+
+IODeviceMemory * IOService::getDeviceMemoryWithIndex( unsigned int index )
+{
+    OSArray *		array;
+    IODeviceMemory *	range;
+
+    array = OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
+    if( array)
+	range = (IODeviceMemory *) array->getObject( index );
+    else
+	range = 0;
+
+    return( range);
+}
+
+IOMemoryMap * IOService::mapDeviceMemoryWithIndex( unsigned int index,
+						IOOptionBits options = 0 )
+{
+    IODeviceMemory *	range;
+    IOMemoryMap *	map;
+
+    range = getDeviceMemoryWithIndex( index );
+    if( range)
+	map = range->map( options );
+    else
+	map = 0;
+
+    return( map );
+}
+
+OSArray * IOService::getDeviceMemory( void )
+{
+    return( OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey)));
+}
+
+
+void IOService::setDeviceMemory( OSArray * array )
+{
+    setProperty( gIODeviceMemoryKey, array);
 }
 
 /*
  * Device interrupts
  */
 
-IOReturn
-IOService::resolveInterrupt(IOService *nub, int source)
-{
-	IOInterruptController *interruptController;
-	OSArray               *array;
-	OSData                *data;
-	OSSymbol              *interruptControllerName;
-	unsigned int           numSources;
-	IOInterruptSource     *interruptSources;
-	IOInterruptSourcePrivate *interruptSourcesPrivate;
-
-	// Get the parents list from the nub.
-	array = OSDynamicCast(OSArray, nub->getProperty(gIOInterruptControllersKey));
-	if (array == NULL) {
-		return kIOReturnNoResources;
-	}
-
-	// Allocate space for the IOInterruptSources if needed... then return early.
-	if (nub->_interruptSources == NULL) {
-		numSources = array->getCount();
-		interruptSources = IONewZero(IOInterruptSource, numSources);
-		interruptSourcesPrivate = IONewZero(IOInterruptSourcePrivate, numSources);
-
-		if (interruptSources == NULL || interruptSourcesPrivate == NULL) {
-			IODelete(interruptSources, IOInterruptSource, numSources);
-			IODelete(interruptSourcesPrivate, IOInterruptSourcePrivate, numSources);
-			return kIOReturnNoMemory;
-		}
-
-		nub->_numInterruptSources = numSources;
-		nub->_interruptSources = interruptSources;
-		nub->reserved->interruptSourcesPrivate = interruptSourcesPrivate;
-		return kIOReturnSuccess;
-	}
-
-	interruptControllerName = OSDynamicCast(OSSymbol, array->getObject(source));
-	if (interruptControllerName == NULL) {
-		return kIOReturnNoResources;
-	}
-
-	interruptController = getPlatform()->lookUpInterruptController(interruptControllerName);
-	if (interruptController == NULL) {
-		return kIOReturnNoResources;
-	}
-
-	// Get the interrupt numbers from the nub.
-	array = OSDynamicCast(OSArray, nub->getProperty(gIOInterruptSpecifiersKey));
-	if (array == NULL) {
-		return kIOReturnNoResources;
-	}
-	data = OSDynamicCast(OSData, array->getObject(source));
-	if (data == NULL) {
-		return kIOReturnNoResources;
-	}
-
-	// Set the interruptController and interruptSource in the nub's table.
-	interruptSources = nub->_interruptSources;
-	interruptSources[source].interruptController = interruptController;
-	interruptSources[source].vectorData = data;
-
-	return kIOReturnSuccess;
-}
-
-IOReturn
-IOService::lookupInterrupt(int source, bool resolve, IOInterruptController **interruptController)
-{
-	IOReturn ret;
-
-	/* Make sure the _interruptSources are set */
-	if (_interruptSources == NULL) {
-		ret = resolveInterrupt(this, source);
-		if (ret != kIOReturnSuccess) {
-			return ret;
-		}
-	}
-
-	/* Make sure the local source number is valid */
-	if ((source < 0) || (source >= _numInterruptSources)) {
-		return kIOReturnNoInterrupt;
-	}
-
-	/* Look up the contoller for the local source */
-	*interruptController = _interruptSources[source].interruptController;
-
-	if (*interruptController == NULL) {
-		if (!resolve) {
-			return kIOReturnNoInterrupt;
-		}
-
-		/* Try to resolve the interrupt */
-		ret = resolveInterrupt(this, source);
-		if (ret != kIOReturnSuccess) {
-			return ret;
-		}
-
-		*interruptController = _interruptSources[source].interruptController;
-	}
-
-	return kIOReturnSuccess;
-}
-
-IOReturn
-IOService::registerInterrupt(int source, OSObject *target,
-    IOInterruptAction handler,
-    void *refCon)
-{
-	IOInterruptController *interruptController;
-	IOReturn              ret;
-
-	ret = lookupInterrupt(source, true, &interruptController);
-	if (ret != kIOReturnSuccess) {
-		return ret;
-	}
-
-	/* Register the source */
-	return interruptController->registerInterrupt(this, source, target,
-	           (IOInterruptHandler)handler,
-	           refCon);
-}
-
-static void
-IOServiceInterruptActionToBlock( OSObject * target, void * refCon,
-    IOService * nub, int source )
-{
-	((IOInterruptActionBlock)(refCon))(nub, source);
-}
-
-IOReturn
-IOService::registerInterruptBlock(int source, OSObject *target,
-    IOInterruptActionBlock handler)
-{
-	IOReturn ret;
-	void   * block;
-
-	block = Block_copy(handler);
-	if (!block) {
-		return kIOReturnNoMemory;
-	}
-
-	ret = registerInterrupt(source, target, &IOServiceInterruptActionToBlock, block);
-	if (kIOReturnSuccess != ret) {
-		Block_release(block);
-		return ret;
-	}
-
-	reserved->interruptSourcesPrivate[source].vectorBlock = block;
-
-	return ret;
-}
-
-IOReturn
-IOService::unregisterInterrupt(int source)
-{
-	IOReturn              ret;
-	IOInterruptController *interruptController;
-	IOInterruptSourcePrivate *priv;
-	void                  *block;
-
-	ret = lookupInterrupt(source, false, &interruptController);
-	if (ret != kIOReturnSuccess) {
-		return ret;
-	}
-
-	/* Unregister the source */
-	priv = &reserved->interruptSourcesPrivate[source];
-	block = priv->vectorBlock;
-	ret = interruptController->unregisterInterrupt(this, source);
-	if ((kIOReturnSuccess == ret) && (block = priv->vectorBlock)) {
-		priv->vectorBlock = NULL;
-		Block_release(block);
-	}
-
-	return ret;
-}
-
-void
-IOService::unregisterAllInterrupts(void)
-{
-	for (int source = 0; source < _numInterruptSources; source++) {
-		(void) unregisterInterrupt(source);
-	}
-}
-
-IOReturn
-IOService::addInterruptStatistics(IOInterruptAccountingData * statistics, int source)
-{
-	IOReportLegend * legend = NULL;
-	IOInterruptAccountingData * oldValue = NULL;
-	IOInterruptAccountingReporter * newArray = NULL;
-	char subgroupName[64];
-	int newArraySize = 0;
-	int i = 0;
-
-	if (source < 0) {
-		return kIOReturnBadArgument;
-	}
-
-	/*
-	 * We support statistics on a maximum of 256 interrupts per nub; if a nub
-	 * has more than 256 interrupt specifiers associated with it, and tries
-	 * to register a high interrupt index with interrupt accounting, panic.
-	 * Having more than 256 interrupts associated with a single nub is
-	 * probably a sign that something fishy is going on.
-	 */
-	if (source > IA_INDEX_MAX) {
-		panic("addInterruptStatistics called for an excessively large index (%d)", source);
-	}
-
-	/*
-	 * TODO: This is ugly (wrapping a lock around an allocation).  I'm only
-	 * leaving it as is because the likelihood of contention where we are
-	 * actually growing the array is minimal (we would realistically need
-	 * to be starting a driver for the first time, with an IOReporting
-	 * client already in place).  Nonetheless, cleanup that can be done
-	 * to adhere to best practices; it'll make the code more complicated,
-	 * unfortunately.
-	 */
-	IOLockLock(&reserved->interruptStatisticsLock);
-
-	/*
-	 * Lazily allocate the statistics array.
-	 */
-	if (!reserved->interruptStatisticsArray) {
-		reserved->interruptStatisticsArray = IONew(IOInterruptAccountingReporter, 1);
-		assert(reserved->interruptStatisticsArray);
-		reserved->interruptStatisticsArrayCount = 1;
-		bzero(reserved->interruptStatisticsArray, sizeof(*reserved->interruptStatisticsArray));
-	}
-
-	if (source >= reserved->interruptStatisticsArrayCount) {
-		/*
-		 * We're still within the range of supported indices, but we are out
-		 * of space in the current array.  Do a nasty realloc (because
-		 * IORealloc isn't a thing) here.  We'll double the size with each
-		 * reallocation.
-		 *
-		 * Yes, the "next power of 2" could be more efficient; but this will
-		 * be invoked incredibly rarely.  Who cares.
-		 */
-		newArraySize = (reserved->interruptStatisticsArrayCount << 1);
-
-		while (newArraySize <= source) {
-			newArraySize = (newArraySize << 1);
-		}
-		newArray = IONew(IOInterruptAccountingReporter, newArraySize);
-
-		assert(newArray);
-
-		/*
-		 * TODO: This even zeroes the memory it is about to overwrite.
-		 * Shameful; fix it.  Not particularly high impact, however.
-		 */
-		bzero(newArray, newArraySize * sizeof(*newArray));
-		memcpy(newArray, reserved->interruptStatisticsArray, reserved->interruptStatisticsArrayCount * sizeof(*newArray));
-		IODelete(reserved->interruptStatisticsArray, IOInterruptAccountingReporter, reserved->interruptStatisticsArrayCount);
-		reserved->interruptStatisticsArray = newArray;
-		reserved->interruptStatisticsArrayCount = newArraySize;
-	}
-
-	if (!reserved->interruptStatisticsArray[source].reporter) {
-		/*
-		 * We don't have a reporter associated with this index yet, so we
-		 * need to create one.
-		 */
-		/*
-		 * TODO: Some statistics do in fact have common units (time); should this be
-		 * split into separate reporters to communicate this?
-		 */
-		reserved->interruptStatisticsArray[source].reporter = IOSimpleReporter::with(this, kIOReportCategoryPower, kIOReportUnitNone);
-
-		/*
-		 * Each statistic is given an identifier based on the interrupt index (which
-		 * should be unique relative to any single nub) and the statistic involved.
-		 * We should now have a sane (small and positive) index, so start
-		 * constructing the channels for statistics.
-		 */
-		for (i = 0; i < IA_NUM_INTERRUPT_ACCOUNTING_STATISTICS; i++) {
-			/*
-			 * TODO: Currently, this does not add channels for disabled statistics.
-			 * Will this be confusing for clients?  If so, we should just add the
-			 * channels; we can avoid updating the channels even if they exist.
-			 */
-			if (IA_GET_STATISTIC_ENABLED(i)) {
-				reserved->interruptStatisticsArray[source].reporter->addChannel(IA_GET_CHANNEL_ID(source, i), kInterruptAccountingStatisticNameArray[i]);
-			}
-		}
-
-		/*
-		 * We now need to add the legend for this reporter to the registry.
-		 */
-		OSObject * prop = copyProperty(kIOReportLegendKey);
-		legend = IOReportLegend::with(OSDynamicCast(OSArray, prop));
-		OSSafeReleaseNULL(prop);
-
-		/*
-		 * Note that while we compose the subgroup name, we do not need to
-		 * manage its lifecycle (the reporter will handle this).
-		 */
-		snprintf(subgroupName, sizeof(subgroupName), "%s %d", getName(), source);
-		subgroupName[sizeof(subgroupName) - 1] = 0;
-		legend->addReporterLegend(reserved->interruptStatisticsArray[source].reporter, kInterruptAccountingGroupName, subgroupName);
-		setProperty(kIOReportLegendKey, legend->getLegend());
-		legend->release();
-
-		/*
-		 * TODO: Is this a good idea?  Probably not; my assumption is it opts
-		 * all entities who register interrupts into public disclosure of all
-		 * IOReporting channels.  Unfortunately, this appears to be as fine
-		 * grain as it gets.
-		 */
-		setProperty(kIOReportLegendPublicKey, true);
-	}
-
-	/*
-	 * Don't stomp existing entries.  If we are about to, panic; this
-	 * probably means we failed to tear down our old interrupt source
-	 * correctly.
-	 */
-	oldValue = reserved->interruptStatisticsArray[source].statistics;
-
-	if (oldValue) {
-		panic("addInterruptStatistics call for index %d would have clobbered existing statistics", source);
-	}
-
-	reserved->interruptStatisticsArray[source].statistics = statistics;
-
-	/*
-	 * Inherit the reporter values for each statistic.  The target may
-	 * be torn down as part of the runtime of the service (especially
-	 * for sleep/wake), so we inherit in order to avoid having values
-	 * reset for no apparent reason.  Our statistics are ultimately
-	 * tied to the index and the sevice, not to an individual target,
-	 * so we should maintain them accordingly.
-	 */
-	interruptAccountingDataInheritChannels(reserved->interruptStatisticsArray[source].statistics, reserved->interruptStatisticsArray[source].reporter);
-
-	IOLockUnlock(&reserved->interruptStatisticsLock);
-
-	return kIOReturnSuccess;
-}
-
-IOReturn
-IOService::removeInterruptStatistics(int source)
-{
-	IOInterruptAccountingData * value = NULL;
-
-	if (source < 0) {
-		return kIOReturnBadArgument;
-	}
-
-	IOLockLock(&reserved->interruptStatisticsLock);
-
-	/*
-	 * We dynamically grow the statistics array, so an excessively
-	 * large index value has NEVER been registered.  This either
-	 * means our cap on the array size is too small (unlikely), or
-	 * that we have been passed a corrupt index (this must be passed
-	 * the plain index into the interrupt specifier list).
-	 */
-	if (source >= reserved->interruptStatisticsArrayCount) {
-		panic("removeInterruptStatistics called for index %d, which was never registered", source);
-	}
-
-	assert(reserved->interruptStatisticsArray);
-
-	/*
-	 * If there is no existing entry, we are most likely trying to
-	 * free an interrupt owner twice, or we have corrupted the
-	 * index value.
-	 */
-	value = reserved->interruptStatisticsArray[source].statistics;
-
-	if (!value) {
-		panic("removeInterruptStatistics called for empty index %d", source);
-	}
-
-	/*
-	 * We update the statistics, so that any delta with the reporter
-	 * state is not lost.
-	 */
-	interruptAccountingDataUpdateChannels(reserved->interruptStatisticsArray[source].statistics, reserved->interruptStatisticsArray[source].reporter);
-	reserved->interruptStatisticsArray[source].statistics = NULL;
-	IOLockUnlock(&reserved->interruptStatisticsLock);
-
-	return kIOReturnSuccess;
-}
-
-IOReturn
-IOService::getInterruptType(int source, int *interruptType)
-{
-	IOInterruptController *interruptController;
-	IOReturn              ret;
-
-	ret = lookupInterrupt(source, true, &interruptController);
-	if (ret != kIOReturnSuccess) {
-		return ret;
-	}
-
-	/* Return the type */
-	return interruptController->getInterruptType(this, source, interruptType);
-}
-
-IOReturn
-IOService::enableInterrupt(int source)
-{
-	IOInterruptController *interruptController;
-	IOReturn              ret;
-
-	ret = lookupInterrupt(source, false, &interruptController);
-	if (ret != kIOReturnSuccess) {
-		return ret;
-	}
-
-	/* Enable the source */
-	return interruptController->enableInterrupt(this, source);
-}
-
-IOReturn
-IOService::disableInterrupt(int source)
-{
-	IOInterruptController *interruptController;
-	IOReturn              ret;
-
-	ret = lookupInterrupt(source, false, &interruptController);
-	if (ret != kIOReturnSuccess) {
-		return ret;
-	}
-
-	/* Disable the source */
-	return interruptController->disableInterrupt(this, source);
-}
-
-IOReturn
-IOService::causeInterrupt(int source)
-{
-	IOInterruptController *interruptController;
-	IOReturn              ret;
-
-	ret = lookupInterrupt(source, false, &interruptController);
-	if (ret != kIOReturnSuccess) {
-		return ret;
-	}
-
-	/* Cause an interrupt for the source */
-	return interruptController->causeInterrupt(this, source);
-}
-
-IOReturn
-IOService::configureReport(IOReportChannelList    *channelList,
-    IOReportConfigureAction action,
-    void                   *result,
-    void                   *destination)
-{
-	unsigned cnt;
-
-	for (cnt = 0; cnt < channelList->nchannels; cnt++) {
-		if (channelList->channels[cnt].channel_id == kPMPowerStatesChID) {
-			if (pwrMgt) {
-				configurePowerStatesReport(action, result);
-			} else {
-				return kIOReturnUnsupported;
-			}
-		} else if (channelList->channels[cnt].channel_id == kPMCurrStateChID) {
-			if (pwrMgt) {
-				configureSimplePowerReport(action, result);
-			} else {
-				return kIOReturnUnsupported;
-			}
-		}
-	}
-
-	IOLockLock(&reserved->interruptStatisticsLock);
-
-	/* The array count is signed (because the interrupt indices are signed), hence the cast */
-	for (cnt = 0; cnt < (unsigned) reserved->interruptStatisticsArrayCount; cnt++) {
-		if (reserved->interruptStatisticsArray[cnt].reporter) {
-			/*
-			 * If the reporter is currently associated with the statistics
-			 * for an event source, we may need to update the reporter.
-			 */
-			if (reserved->interruptStatisticsArray[cnt].statistics) {
-				interruptAccountingDataUpdateChannels(reserved->interruptStatisticsArray[cnt].statistics, reserved->interruptStatisticsArray[cnt].reporter);
-			}
-
-			reserved->interruptStatisticsArray[cnt].reporter->configureReport(channelList, action, result, destination);
-		}
-	}
-
-	IOLockUnlock(&reserved->interruptStatisticsLock);
-
-	if (hasUserServer()) {
-		return _ConfigureReport(channelList, action, result, destination);
-	} else {
-		return kIOReturnSuccess;
-	}
-}
-
-IOReturn
-IOService::updateReport(IOReportChannelList      *channelList,
-    IOReportUpdateAction      action,
-    void                     *result,
-    void                     *destination)
-{
-	unsigned cnt;
-
-	for (cnt = 0; cnt < channelList->nchannels; cnt++) {
-		if (channelList->channels[cnt].channel_id == kPMPowerStatesChID) {
-			if (pwrMgt) {
-				updatePowerStatesReport(action, result, destination);
-			} else {
-				return kIOReturnUnsupported;
-			}
-		} else if (channelList->channels[cnt].channel_id == kPMCurrStateChID) {
-			if (pwrMgt) {
-				updateSimplePowerReport(action, result, destination);
-			} else {
-				return kIOReturnUnsupported;
-			}
-		}
-	}
-
-	IOLockLock(&reserved->interruptStatisticsLock);
-
-	/* The array count is signed (because the interrupt indices are signed), hence the cast */
-	for (cnt = 0; cnt < (unsigned) reserved->interruptStatisticsArrayCount; cnt++) {
-		if (reserved->interruptStatisticsArray[cnt].reporter) {
-			/*
-			 * If the reporter is currently associated with the statistics
-			 * for an event source, we need to update the reporter.
-			 */
-			if (reserved->interruptStatisticsArray[cnt].statistics) {
-				interruptAccountingDataUpdateChannels(reserved->interruptStatisticsArray[cnt].statistics, reserved->interruptStatisticsArray[cnt].reporter);
-			}
-
-			reserved->interruptStatisticsArray[cnt].reporter->updateReport(channelList, action, result, destination);
-		}
-	}
-
-	IOLockUnlock(&reserved->interruptStatisticsLock);
-
-
-	if (hasUserServer()) {
-		return _UpdateReport(channelList, action, result, destination);
-	} else {
-		return kIOReturnSuccess;
-	}
-}
-
-uint64_t
-IOService::getAuthorizationID( void )
-{
-	return reserved->authorizationID;
-}
-
-IOReturn
-IOService::setAuthorizationID( uint64_t authorizationID )
-{
-	OSObject * entitlement;
-	IOReturn status;
-
-	entitlement = IOUserClient::copyClientEntitlement( current_task(), "com.apple.private.iokit.IOServiceSetAuthorizationID" );
-
-	if (entitlement) {
-		if (entitlement == kOSBooleanTrue) {
-			reserved->authorizationID = authorizationID;
-
-			status = kIOReturnSuccess;
-		} else {
-			status = kIOReturnNotPrivileged;
-		}
-
-		entitlement->release();
-	} else {
-		status = kIOReturnNotPrivileged;
-	}
-
-	return status;
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-#if __LP64__
-OSMetaClassDefineReservedUsedX86(IOService, 0);
-OSMetaClassDefineReservedUsedX86(IOService, 1);
-OSMetaClassDefineReservedUnused(IOService, 2);
+IOReturn IOService::resolveInterrupt(IOService *nub, int source)
+{
+  IOInterruptController *interruptController;
+  OSDictionary          *propTable;
+  OSArray               *array;
+  OSData                *data;
+  OSSymbol              *interruptControllerName;
+  long                  numSources;
+  IOInterruptSource     *interruptSources;
+  
+  // Get the property table from the nub.
+  propTable = nub->getPropertyTable();
+  if (propTable == 0) return kIOReturnNoResources;
+
+  // Get the parents list from the property table.
+  array = OSDynamicCast(OSArray,
+			propTable->getObject(gIOInterruptControllersKey));
+  if (array == 0) return kIOReturnNoResources;
+  
+  // Allocate space for the IOInterruptSources if needed... then return early.
+  if (nub->_interruptSources == 0) {
+    numSources = array->getCount();
+    interruptSources = (IOInterruptSource *)IOMalloc(numSources * sizeof(IOInterruptSource));
+    if (interruptSources == 0) return kIOReturnNoMemory;
+    
+    bzero(interruptSources, numSources * sizeof(IOInterruptSource));
+    
+    nub->_numInterruptSources = numSources;
+    nub->_interruptSources = interruptSources;
+    return kIOReturnSuccess;
+  }
+  
+  interruptControllerName = OSDynamicCast(OSSymbol,array->getObject(source));
+  if (interruptControllerName == 0) return kIOReturnNoResources;
+  
+  interruptController = getPlatform()->lookUpInterruptController(interruptControllerName);
+  if (interruptController == 0) return kIOReturnNoResources;
+  
+  // Get the interrupt numbers from the property table.
+  array = OSDynamicCast(OSArray,
+			propTable->getObject(gIOInterruptSpecifiersKey));
+  if (array == 0) return kIOReturnNoResources;
+  data = OSDynamicCast(OSData, array->getObject(source));
+  if (data == 0) return kIOReturnNoResources;
+  
+  // Set the interruptController and interruptSource in the nub's table.
+  interruptSources = nub->_interruptSources;
+  interruptSources[source].interruptController = interruptController;
+  interruptSources[source].vectorData = data;
+  
+  return kIOReturnSuccess;
+}
+
+IOReturn IOService::lookupInterrupt(int source, bool resolve, IOInterruptController **interruptController)
+{
+  IOReturn ret;
+  
+  /* Make sure the _interruptSources are set */
+  if (_interruptSources == 0) {
+    ret = resolveInterrupt(this, source);
+    if (ret != kIOReturnSuccess) return ret;
+  }
+  
+  /* Make sure the local source number is valid */
+  if ((source < 0) || (source >= _numInterruptSources))
+    return kIOReturnNoInterrupt;
+  
+  /* Look up the contoller for the local source */
+  *interruptController = _interruptSources[source].interruptController;
+  
+  if (*interruptController == NULL) {
+    if (!resolve) return kIOReturnNoInterrupt;
+    
+    /* Try to reslove the interrupt */
+    ret = resolveInterrupt(this, source);
+    if (ret != kIOReturnSuccess) return ret;    
+    
+    *interruptController = _interruptSources[source].interruptController;
+  }
+  
+  return kIOReturnSuccess;
+}
+
+IOReturn IOService::registerInterrupt(int source, OSObject *target,
+				      IOInterruptAction handler,
+				      void *refCon)
+{
+  IOInterruptController *interruptController;
+  IOReturn              ret;
+  
+  ret = lookupInterrupt(source, true, &interruptController);
+  if (ret != kIOReturnSuccess) return ret;
+  
+  /* Register the source */
+  return interruptController->registerInterrupt(this, source, target,
+						(IOInterruptHandler)handler,
+						refCon);
+}
+
+IOReturn IOService::unregisterInterrupt(int source)
+{
+  IOInterruptController *interruptController;
+  IOReturn              ret;
+  
+  ret = lookupInterrupt(source, false, &interruptController);
+  if (ret != kIOReturnSuccess) return ret;
+  
+  /* Unregister the source */
+  return interruptController->unregisterInterrupt(this, source);
+}
+
+IOReturn IOService::getInterruptType(int source, int *interruptType)
+{
+  IOInterruptController *interruptController;
+  IOReturn              ret;
+  
+  ret = lookupInterrupt(source, true, &interruptController);
+  if (ret != kIOReturnSuccess) return ret;
+    
+  /* Return the type */
+  return interruptController->getInterruptType(this, source, interruptType);
+}
+
+IOReturn IOService::enableInterrupt(int source)
+{
+  IOInterruptController *interruptController;
+  IOReturn              ret;
+  
+  ret = lookupInterrupt(source, false, &interruptController);
+  if (ret != kIOReturnSuccess) return ret;
+  
+  /* Enable the source */
+  return interruptController->enableInterrupt(this, source);
+}
+
+IOReturn IOService::disableInterrupt(int source)
+{
+  IOInterruptController *interruptController;
+  IOReturn              ret;
+  
+  ret = lookupInterrupt(source, false, &interruptController);
+  if (ret != kIOReturnSuccess) return ret;
+  
+  /* Disable the source */
+  return interruptController->disableInterrupt(this, source);
+}
+
+IOReturn IOService::causeInterrupt(int source)
+{
+  IOInterruptController *interruptController;
+  IOReturn              ret;
+  
+  ret = lookupInterrupt(source, false, &interruptController);
+  if (ret != kIOReturnSuccess) return ret;
+  
+  /* Cause an interrupt for the source */
+  return interruptController->causeInterrupt(this, source);
+}
+
+OSMetaClassDefineReservedUsed(IOService, 0);
+OSMetaClassDefineReservedUsed(IOService, 1);
+OSMetaClassDefineReservedUsed(IOService, 2);
+
 OSMetaClassDefineReservedUnused(IOService, 3);
 OSMetaClassDefineReservedUnused(IOService, 4);
 OSMetaClassDefineReservedUnused(IOService, 5);
 OSMetaClassDefineReservedUnused(IOService, 6);
 OSMetaClassDefineReservedUnused(IOService, 7);
-#else
-OSMetaClassDefineReservedUsedX86(IOService, 0);
-OSMetaClassDefineReservedUsedX86(IOService, 1);
-OSMetaClassDefineReservedUsedX86(IOService, 2);
-OSMetaClassDefineReservedUsedX86(IOService, 3);
-OSMetaClassDefineReservedUsedX86(IOService, 4);
-OSMetaClassDefineReservedUsedX86(IOService, 5);
-OSMetaClassDefineReservedUsedX86(IOService, 6);
-OSMetaClassDefineReservedUsedX86(IOService, 7);
-#endif
 OSMetaClassDefineReservedUnused(IOService, 8);
 OSMetaClassDefineReservedUnused(IOService, 9);
 OSMetaClassDefineReservedUnused(IOService, 10);
@@ -9396,3 +4343,19 @@
 OSMetaClassDefineReservedUnused(IOService, 45);
 OSMetaClassDefineReservedUnused(IOService, 46);
 OSMetaClassDefineReservedUnused(IOService, 47);
+OSMetaClassDefineReservedUnused(IOService, 48);
+OSMetaClassDefineReservedUnused(IOService, 49);
+OSMetaClassDefineReservedUnused(IOService, 50);
+OSMetaClassDefineReservedUnused(IOService, 51);
+OSMetaClassDefineReservedUnused(IOService, 52);
+OSMetaClassDefineReservedUnused(IOService, 53);
+OSMetaClassDefineReservedUnused(IOService, 54);
+OSMetaClassDefineReservedUnused(IOService, 55);
+OSMetaClassDefineReservedUnused(IOService, 56);
+OSMetaClassDefineReservedUnused(IOService, 57);
+OSMetaClassDefineReservedUnused(IOService, 58);
+OSMetaClassDefineReservedUnused(IOService, 59);
+OSMetaClassDefineReservedUnused(IOService, 60);
+OSMetaClassDefineReservedUnused(IOService, 61);
+OSMetaClassDefineReservedUnused(IOService, 62);
+OSMetaClassDefineReservedUnused(IOService, 63);