]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOService.cpp
xnu-6153.121.1.tar.gz
[apple/xnu.git] / iokit / Kernel / IOService.cpp
1 /*
2 * Copyright (c) 1998-2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <IOKit/system.h>
30 #include <IOKit/IOService.h>
31 #include <libkern/OSDebug.h>
32 #include <libkern/c++/OSContainers.h>
33 #include <libkern/c++/OSKext.h>
34 #include <libkern/c++/OSUnserialize.h>
35 #include <libkern/c++/OSKext.h>
36 #include <libkern/Block.h>
37 #include <IOKit/IOCatalogue.h>
38 #include <IOKit/IOCommand.h>
39 #include <IOKit/IODeviceTreeSupport.h>
40 #include <IOKit/IODeviceMemory.h>
41 #include <IOKit/IOInterrupts.h>
42 #include <IOKit/IOInterruptController.h>
43 #include <IOKit/IOPlatformExpert.h>
44 #include <IOKit/IOMessage.h>
45 #include <IOKit/IOLib.h>
46 #include <IOKit/IOKitKeysPrivate.h>
47 #include <IOKit/IOBSD.h>
48 #include <IOKit/IOUserClient.h>
49 #include <IOKit/IOUserServer.h>
50 #include <IOKit/IOWorkLoop.h>
51 #include <IOKit/IOTimeStamp.h>
52 #include <IOKit/IOHibernatePrivate.h>
53 #include <IOKit/IOInterruptAccountingPrivate.h>
54 #include <IOKit/IOKernelReporters.h>
55 #include <IOKit/AppleKeyStoreInterface.h>
56 #include <IOKit/pwr_mgt/RootDomain.h>
57 #include <IOKit/IOCPU.h>
58 #include <mach/sync_policy.h>
59 #include <mach/thread_info.h>
60 #include <IOKit/assert.h>
61 #include <sys/errno.h>
62 #include <sys/kdebug.h>
63 #include <string.h>
64
65 #include <machine/pal_routines.h>
66
67 #define LOG kprintf
68 //#define LOG IOLog
69 #define MATCH_DEBUG 0
70 #define IOSERVICE_OBFUSCATE(x) ((void *)(VM_KERNEL_ADDRPERM(x)))
71
72 // disabled since lockForArbitration() can be held externally
73 #define DEBUG_NOTIFIER_LOCKED 0
74
75 enum{
76 kIOUserServerCheckInTimeoutSecs = 120ULL
77 };
78
79 #include "IOServicePrivate.h"
80 #include "IOKitKernelInternal.h"
81
82 // take lockForArbitration before LOCKNOTIFY
83
84 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
85
86 #define super IORegistryEntry
87
88 OSDefineMetaClassAndStructors(IOService, IORegistryEntry)
89
90 OSDefineMetaClassAndStructors(_IOServiceNotifier, IONotifier)
91 OSDefineMetaClassAndStructors(_IOServiceNullNotifier, IONotifier)
92
93 OSDefineMetaClassAndStructors(_IOServiceInterestNotifier, IONotifier)
94
95 OSDefineMetaClassAndStructors(_IOConfigThread, OSObject)
96
97 OSDefineMetaClassAndStructors(_IOServiceJob, OSObject)
98
99 OSDefineMetaClassAndStructors(IOResources, IOService)
100 OSDefineMetaClassAndStructors(IOUserResources, IOService)
101
102 OSDefineMetaClassAndStructors(_IOOpenServiceIterator, OSIterator)
103
104 OSDefineMetaClassAndAbstractStructors(IONotifier, OSObject)
105
106 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
107
108 static IOPlatformExpert * gIOPlatform;
109 static class IOPMrootDomain * gIOPMRootDomain;
110 const IORegistryPlane * gIOServicePlane;
111 const IORegistryPlane * gIOPowerPlane;
112 const OSSymbol * gIODeviceMemoryKey;
113 const OSSymbol * gIOInterruptControllersKey;
114 const OSSymbol * gIOInterruptSpecifiersKey;
115
116 const OSSymbol * gIOResourcesKey;
117 const OSSymbol * gIOUserResourcesKey;
118 const OSSymbol * gIOResourceMatchKey;
119 const OSSymbol * gIOResourceMatchedKey;
120 const OSSymbol * gIOResourceIOKitKey;
121
122 const OSSymbol * gIOProviderClassKey;
123 const OSSymbol * gIONameMatchKey;
124 const OSSymbol * gIONameMatchedKey;
125 const OSSymbol * gIOPropertyMatchKey;
126 const OSSymbol * gIOPropertyExistsMatchKey;
127 const OSSymbol * gIOLocationMatchKey;
128 const OSSymbol * gIOParentMatchKey;
129 const OSSymbol * gIOPathMatchKey;
130 const OSSymbol * gIOMatchCategoryKey;
131 const OSSymbol * gIODefaultMatchCategoryKey;
132 const OSSymbol * gIOMatchedServiceCountKey;
133 const OSSymbol * gIOMatchedPersonalityKey;
134 const OSSymbol * gIORematchPersonalityKey;
135 const OSSymbol * gIORematchCountKey;
136 const OSSymbol * gIODEXTMatchCountKey;
137 const OSSymbol * gIOSupportedPropertiesKey;
138 const OSSymbol * gIOUserServicePropertiesKey;
139 #if !CONFIG_EMBEDDED
140 const OSSymbol * gIOServiceLegacyMatchingRegistryIDKey;
141 #endif
142
143 const OSSymbol * gIOMapperIDKey;
144 const OSSymbol * gIOUserClientClassKey;
145
146 const OSSymbol * gIOUserClassKey;
147 const OSSymbol * gIOUserServerClassKey;
148 const OSSymbol * gIOUserServerNameKey;
149 const OSSymbol * gIOUserServerTagKey;
150 const OSSymbol * gIOUserServerCDHashKey;
151 const OSSymbol * gIOUserUserClientKey;
152
153 const OSSymbol * gIOKitDebugKey;
154
155 const OSSymbol * gIOCommandPoolSizeKey;
156
157 const OSSymbol * gIOConsoleLockedKey;
158 const OSSymbol * gIOConsoleUsersKey;
159 const OSSymbol * gIOConsoleSessionUIDKey;
160 const OSSymbol * gIOConsoleSessionAuditIDKey;
161 const OSSymbol * gIOConsoleUsersSeedKey;
162 const OSSymbol * gIOConsoleSessionOnConsoleKey;
163 const OSSymbol * gIOConsoleSessionLoginDoneKey;
164 const OSSymbol * gIOConsoleSessionSecureInputPIDKey;
165 const OSSymbol * gIOConsoleSessionScreenLockedTimeKey;
166 const OSSymbol * gIOConsoleSessionScreenIsLockedKey;
167 clock_sec_t gIOConsoleLockTime;
168 static bool gIOConsoleLoggedIn;
169 #if HIBERNATION
170 static OSBoolean * gIOConsoleBooterLockState;
171 static uint32_t gIOScreenLockState;
172 #endif
173 static IORegistryEntry * gIOChosenEntry;
174
175 static int gIOResourceGenerationCount;
176
177 const OSSymbol * gIOServiceKey;
178 const OSSymbol * gIOPublishNotification;
179 const OSSymbol * gIOFirstPublishNotification;
180 const OSSymbol * gIOMatchedNotification;
181 const OSSymbol * gIOFirstMatchNotification;
182 const OSSymbol * gIOTerminatedNotification;
183 const OSSymbol * gIOWillTerminateNotification;
184
185 const OSSymbol * gIOServiceDEXTEntitlementsKey;
186 const OSSymbol * gIODriverKitEntitlementKey;
187 const OSSymbol * gIODriverKitUserClientEntitlementsKey;
188 const OSSymbol * gIOMatchDeferKey;
189
190 const OSSymbol * gIOGeneralInterest;
191 const OSSymbol * gIOBusyInterest;
192 const OSSymbol * gIOAppPowerStateInterest;
193 const OSSymbol * gIOPriorityPowerStateInterest;
194 const OSSymbol * gIOConsoleSecurityInterest;
195
196 const OSSymbol * gIOBSDKey;
197 const OSSymbol * gIOBSDNameKey;
198 const OSSymbol * gIOBSDMajorKey;
199 const OSSymbol * gIOBSDMinorKey;
200 const OSSymbol * gIOBSDUnitKey;
201
202 const OSSymbol * gAKSGetKey;
203 #if defined(__i386__) || defined(__x86_64__)
204 const OSSymbol * gIOCreateEFIDevicePathSymbol;
205 #endif
206
207 static OSDictionary * gNotifications;
208 static IORecursiveLock * gNotificationLock;
209
210 static IOService * gIOResources;
211 static IOService * gIOUserResources;
212 static IOService * gIOServiceRoot;
213
214 static OSOrderedSet * gJobs;
215 static semaphore_port_t gJobsSemaphore;
216 static IOLock * gJobsLock;
217 static int gOutstandingJobs;
218 static int gNumConfigThreads;
219 static int gNumWaitingThreads;
220 static IOLock * gIOServiceBusyLock;
221 bool gCPUsRunning;
222 bool gKextdWillTerminate;
223
224 static thread_t gIOTerminateThread;
225 static thread_t gIOTerminateWorkerThread;
226 static UInt32 gIOTerminateWork;
227 static OSArray * gIOTerminatePhase2List;
228 static OSArray * gIOStopList;
229 static OSArray * gIOStopProviderList;
230 static OSArray * gIOFinalizeList;
231
232 #if !NO_KEXTD
233 static OSArray * gIOMatchDeferList;
234 #endif
235
236 static SInt32 gIOConsoleUsersSeed;
237 static OSData * gIOConsoleUsersSeedValue;
238
239 extern const OSSymbol * gIODTPHandleKey;
240
241 const OSSymbol * gIOPlatformFunctionHandlerSet;
242
243
244 static IOLock * gIOConsoleUsersLock;
245 static thread_call_t gIOConsoleLockCallout;
246 static IONotifier * gIOServiceNullNotifier;
247
248 static uint32_t gIODextRelaunchMax = 1000;
249
250 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
251
252 #define LOCKREADNOTIFY() \
253 IORecursiveLockLock( gNotificationLock )
254 #define LOCKWRITENOTIFY() \
255 IORecursiveLockLock( gNotificationLock )
256 #define LOCKWRITE2READNOTIFY()
257 #define UNLOCKNOTIFY() \
258 IORecursiveLockUnlock( gNotificationLock )
259 #define SLEEPNOTIFY(event) \
260 IORecursiveLockSleep( gNotificationLock, (void *)(event), THREAD_UNINT )
261 #define SLEEPNOTIFYTO(event, deadline) \
262 IORecursiveLockSleepDeadline( gNotificationLock, (void *)(event), deadline, THREAD_UNINT )
263 #define WAKEUPNOTIFY(event) \
264 IORecursiveLockWakeup( gNotificationLock, (void *)(event), /* wake one */ false )
265
266 #define randomDelay() \
267 int del = read_processor_clock(); \
268 del = (((int)IOThreadSelf()) ^ del ^ (del >> 10)) & 0x3ff; \
269 IOSleep( del );
270
271 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
272
273 #define queue_element(entry, element, type, field) do { \
274 vm_address_t __ele = (vm_address_t) (entry); \
275 __ele -= -4 + ((size_t)(&((type) 4)->field)); \
276 (element) = (type) __ele; \
277 } while(0)
278
279 #define iterqueue(que, elt) \
280 for (queue_entry_t elt = queue_first(que); \
281 !queue_end(que, elt); \
282 elt = queue_next(elt))
283
284 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
285
286 struct IOInterruptAccountingReporter {
287 IOSimpleReporter * reporter; /* Reporter responsible for communicating the statistics */
288 IOInterruptAccountingData * statistics; /* The live statistics values, if any */
289 };
290
291 struct ArbitrationLockQueueElement {
292 queue_chain_t link;
293 IOThread thread;
294 IOService * service;
295 unsigned count;
296 bool required;
297 bool aborted;
298 };
299
300 static queue_head_t gArbitrationLockQueueActive;
301 static queue_head_t gArbitrationLockQueueWaiting;
302 static queue_head_t gArbitrationLockQueueFree;
303 static IOLock * gArbitrationLockQueueLock;
304
305 bool
306 IOService::isInactive( void ) const
307 {
308 return 0 != (kIOServiceInactiveState & getState());
309 }
310
311 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
312
313 #if defined(__i386__) || defined(__x86_64__)
314
315 // Only used by the intel implementation of
316 // IOService::requireMaxBusStall(UInt32 ns)
317 // IOService::requireMaxInterruptDelay(uint32_t ns)
318 struct CpuDelayEntry {
319 IOService * fService;
320 UInt32 fMaxDelay;
321 UInt32 fDelayType;
322 };
323
324 enum {
325 kCpuDelayBusStall, kCpuDelayInterrupt,
326 kCpuNumDelayTypes
327 };
328
329 static OSData *sCpuDelayData = OSData::withCapacity(8 * sizeof(CpuDelayEntry));
330 static IORecursiveLock *sCpuDelayLock = IORecursiveLockAlloc();
331 static OSArray *sCpuLatencyHandlers[kCpuNumDelayTypes];
332 const OSSymbol *sCPULatencyFunctionName[kCpuNumDelayTypes];
333 static OSNumber * sCPULatencyHolder[kCpuNumDelayTypes];
334 static char sCPULatencyHolderName[kCpuNumDelayTypes][128];
335 static OSNumber * sCPULatencySet[kCpuNumDelayTypes];
336
337 static void
338 requireMaxCpuDelay(IOService * service, UInt32 ns, UInt32 delayType);
339 static IOReturn
340 setLatencyHandler(UInt32 delayType, IOService * target, bool enable);
341
342 #endif /* defined(__i386__) || defined(__x86_64__) */
343
344 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
345
346 namespace IOServicePH
347 {
348 IONotifier * fRootNotifier;
349 OSArray * fUserServers;
350 OSArray * fUserServersWait;
351 OSArray * fMatchingWork;
352 OSArray * fMatchingDelayed;
353 IOService * fSystemPowerAckTo;
354 uint32_t fSystemPowerAckRef;
355 uint8_t fSystemOff;
356 uint8_t fUserServerOff;
357
358 void lock();
359 void unlock();
360
361 void init(IOPMrootDomain * root);
362
363 IOReturn systemPowerChange(
364 void * target,
365 void * refCon,
366 UInt32 messageType, IOService * service,
367 void * messageArgument, vm_size_t argSize);
368
369 bool matchingStart(IOService * service);
370 void matchingEnd(IOService * service);
371 };
372
373 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
374
375 void
376 IOService::initialize( void )
377 {
378 kern_return_t err;
379
380 gIOServicePlane = IORegistryEntry::makePlane( kIOServicePlane );
381 gIOPowerPlane = IORegistryEntry::makePlane( kIOPowerPlane );
382
383 gIOProviderClassKey = OSSymbol::withCStringNoCopy( kIOProviderClassKey );
384 gIONameMatchKey = OSSymbol::withCStringNoCopy( kIONameMatchKey );
385 gIONameMatchedKey = OSSymbol::withCStringNoCopy( kIONameMatchedKey );
386 gIOPropertyMatchKey = OSSymbol::withCStringNoCopy( kIOPropertyMatchKey );
387 gIOPropertyExistsMatchKey = OSSymbol::withCStringNoCopy( kIOPropertyExistsMatchKey );
388 gIOPathMatchKey = OSSymbol::withCStringNoCopy( kIOPathMatchKey );
389 gIOLocationMatchKey = OSSymbol::withCStringNoCopy( kIOLocationMatchKey );
390 gIOParentMatchKey = OSSymbol::withCStringNoCopy( kIOParentMatchKey );
391
392 gIOMatchCategoryKey = OSSymbol::withCStringNoCopy( kIOMatchCategoryKey );
393 gIODefaultMatchCategoryKey = OSSymbol::withCStringNoCopy(
394 kIODefaultMatchCategoryKey );
395 gIOMatchedServiceCountKey = OSSymbol::withCStringNoCopy(
396 kIOMatchedServiceCountKey );
397 gIOMatchedPersonalityKey = OSSymbol::withCStringNoCopy(
398 kIOMatchedPersonalityKey );
399 gIORematchPersonalityKey = OSSymbol::withCStringNoCopy(
400 kIORematchPersonalityKey );
401 gIORematchCountKey = OSSymbol::withCStringNoCopy(
402 kIORematchCountKey );
403 gIODEXTMatchCountKey = OSSymbol::withCStringNoCopy(
404 kIODEXTMatchCountKey );
405
406 #if !CONFIG_EMBEDDED
407 gIOServiceLegacyMatchingRegistryIDKey = OSSymbol::withCStringNoCopy(
408 kIOServiceLegacyMatchingRegistryIDKey );
409 #endif
410
411 PE_parse_boot_argn("dextrelaunch", &gIODextRelaunchMax, sizeof(gIODextRelaunchMax));
412
413 gIOUserClientClassKey = OSSymbol::withCStringNoCopy( kIOUserClientClassKey );
414
415 gIOUserClassKey = OSSymbol::withCStringNoCopy(kIOUserClassKey);
416
417 gIOUserServerClassKey = OSSymbol::withCStringNoCopy(kIOUserServerClassKey);
418 gIOUserServerNameKey = OSSymbol::withCStringNoCopy(kIOUserServerNameKey);
419 gIOUserServerTagKey = OSSymbol::withCStringNoCopy(kIOUserServerTagKey);
420 gIOUserServerCDHashKey = OSSymbol::withCStringNoCopy(kIOUserServerCDHashKey);
421 gIOUserUserClientKey = OSSymbol::withCStringNoCopy(kIOUserUserClientKey);
422
423 gIOResourcesKey = OSSymbol::withCStringNoCopy( kIOResourcesClass );
424 gIOResourceMatchKey = OSSymbol::withCStringNoCopy( kIOResourceMatchKey );
425 gIOResourceMatchedKey = OSSymbol::withCStringNoCopy( kIOResourceMatchedKey );
426 gIOResourceIOKitKey = OSSymbol::withCStringNoCopy("IOKit");
427
428 gIODeviceMemoryKey = OSSymbol::withCStringNoCopy( "IODeviceMemory" );
429 gIOInterruptControllersKey
430 = OSSymbol::withCStringNoCopy("IOInterruptControllers");
431 gIOInterruptSpecifiersKey
432 = OSSymbol::withCStringNoCopy("IOInterruptSpecifiers");
433
434 gIOSupportedPropertiesKey = OSSymbol::withCStringNoCopy(kIOSupportedPropertiesKey);
435 gIOUserServicePropertiesKey = OSSymbol::withCStringNoCopy(kIOUserServicePropertiesKey);
436
437 gIOMapperIDKey = OSSymbol::withCStringNoCopy(kIOMapperIDKey);
438
439 gIOKitDebugKey = OSSymbol::withCStringNoCopy( kIOKitDebugKey );
440
441 gIOCommandPoolSizeKey = OSSymbol::withCStringNoCopy( kIOCommandPoolSizeKey );
442
443 gIOGeneralInterest = OSSymbol::withCStringNoCopy( kIOGeneralInterest );
444 gIOBusyInterest = OSSymbol::withCStringNoCopy( kIOBusyInterest );
445 gIOAppPowerStateInterest = OSSymbol::withCStringNoCopy( kIOAppPowerStateInterest );
446 gIOPriorityPowerStateInterest = OSSymbol::withCStringNoCopy( kIOPriorityPowerStateInterest );
447 gIOConsoleSecurityInterest = OSSymbol::withCStringNoCopy( kIOConsoleSecurityInterest );
448
449 gIOBSDKey = OSSymbol::withCStringNoCopy(kIOBSDKey);
450 gIOBSDNameKey = OSSymbol::withCStringNoCopy(kIOBSDNameKey);
451 gIOBSDMajorKey = OSSymbol::withCStringNoCopy(kIOBSDMajorKey);
452 gIOBSDMinorKey = OSSymbol::withCStringNoCopy(kIOBSDMinorKey);
453 gIOBSDUnitKey = OSSymbol::withCStringNoCopy(kIOBSDUnitKey);
454
455 gNotifications = OSDictionary::withCapacity( 1 );
456 gIOPublishNotification = OSSymbol::withCStringNoCopy(
457 kIOPublishNotification );
458 gIOFirstPublishNotification = OSSymbol::withCStringNoCopy(
459 kIOFirstPublishNotification );
460 gIOMatchedNotification = OSSymbol::withCStringNoCopy(
461 kIOMatchedNotification );
462 gIOFirstMatchNotification = OSSymbol::withCStringNoCopy(
463 kIOFirstMatchNotification );
464 gIOTerminatedNotification = OSSymbol::withCStringNoCopy(
465 kIOTerminatedNotification );
466 gIOWillTerminateNotification = OSSymbol::withCStringNoCopy(
467 kIOWillTerminateNotification );
468 gIOServiceKey = OSSymbol::withCStringNoCopy( kIOServiceClass);
469
470
471 gIOConsoleLockedKey = OSSymbol::withCStringNoCopy( kIOConsoleLockedKey);
472 gIOConsoleUsersKey = OSSymbol::withCStringNoCopy( kIOConsoleUsersKey);
473 gIOConsoleSessionUIDKey = OSSymbol::withCStringNoCopy( kIOConsoleSessionUIDKey);
474 gIOConsoleSessionAuditIDKey = OSSymbol::withCStringNoCopy( kIOConsoleSessionAuditIDKey);
475
476 gIOConsoleUsersSeedKey = OSSymbol::withCStringNoCopy(kIOConsoleUsersSeedKey);
477 gIOConsoleSessionOnConsoleKey = OSSymbol::withCStringNoCopy(kIOConsoleSessionOnConsoleKey);
478 gIOConsoleSessionLoginDoneKey = OSSymbol::withCStringNoCopy(kIOConsoleSessionLoginDoneKey);
479 gIOConsoleSessionSecureInputPIDKey = OSSymbol::withCStringNoCopy(kIOConsoleSessionSecureInputPIDKey);
480 gIOConsoleSessionScreenLockedTimeKey = OSSymbol::withCStringNoCopy(kIOConsoleSessionScreenLockedTimeKey);
481 gIOConsoleSessionScreenIsLockedKey = OSSymbol::withCStringNoCopy(kIOConsoleSessionScreenIsLockedKey);
482
483 gIOConsoleUsersSeedValue = OSData::withBytesNoCopy(&gIOConsoleUsersSeed, sizeof(gIOConsoleUsersSeed));
484
485 gIOServiceDEXTEntitlementsKey = OSSymbol::withCStringNoCopy( kIOServiceDEXTEntitlementsKey );
486 gIODriverKitEntitlementKey = OSSymbol::withCStringNoCopy( kIODriverKitEntitlementKey );
487 gIODriverKitUserClientEntitlementsKey = OSSymbol::withCStringNoCopy( kIODriverKitUserClientEntitlementsKey );
488 gIOMatchDeferKey = OSSymbol::withCStringNoCopy( kIOMatchDeferKey );
489
490 gIOPlatformFunctionHandlerSet = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerSet);
491 #if defined(__i386__) || defined(__x86_64__)
492 sCPULatencyFunctionName[kCpuDelayBusStall] = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerMaxBusDelay);
493 sCPULatencyFunctionName[kCpuDelayInterrupt] = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerMaxInterruptDelay);
494 uint32_t idx;
495 for (idx = 0; idx < kCpuNumDelayTypes; idx++) {
496 sCPULatencySet[idx] = OSNumber::withNumber(-1U, 32);
497 sCPULatencyHolder[idx] = OSNumber::withNumber(0ULL, 64);
498 assert(sCPULatencySet[idx] && sCPULatencyHolder[idx]);
499 }
500 gIOCreateEFIDevicePathSymbol = OSSymbol::withCString("CreateEFIDevicePath");
501 #endif
502 gNotificationLock = IORecursiveLockAlloc();
503
504 gAKSGetKey = OSSymbol::withCStringNoCopy(AKS_PLATFORM_FUNCTION_GETKEY);
505
506 assert( gIOServicePlane && gIODeviceMemoryKey
507 && gIOInterruptControllersKey && gIOInterruptSpecifiersKey
508 && gIOResourcesKey && gNotifications && gNotificationLock
509 && gIOProviderClassKey && gIONameMatchKey && gIONameMatchedKey
510 && gIOMatchCategoryKey && gIODefaultMatchCategoryKey
511 && gIOPublishNotification && gIOMatchedNotification
512 && gIOTerminatedNotification && gIOServiceKey
513 && gIOConsoleUsersKey && gIOConsoleSessionUIDKey
514 && gIOConsoleSessionOnConsoleKey && gIOConsoleSessionSecureInputPIDKey
515 && gIOConsoleUsersSeedKey && gIOConsoleUsersSeedValue);
516
517 gJobsLock = IOLockAlloc();
518 gJobs = OSOrderedSet::withCapacity( 10 );
519
520 gIOServiceBusyLock = IOLockAlloc();
521
522 gIOConsoleUsersLock = IOLockAlloc();
523
524 err = semaphore_create(kernel_task, &gJobsSemaphore, SYNC_POLICY_FIFO, 0);
525
526 gIOConsoleLockCallout = thread_call_allocate(&IOService::consoleLockTimer, NULL);
527
528 IORegistryEntry::getRegistryRoot()->setProperty(gIOConsoleLockedKey, kOSBooleanTrue);
529
530 assert( gIOServiceBusyLock && gJobs && gJobsLock && gIOConsoleUsersLock
531 && gIOConsoleLockCallout && (err == KERN_SUCCESS));
532
533 gIOResources = IOResources::resources();
534 gIOUserResources = IOUserResources::resources();
535 assert( gIOResources && gIOUserResources );
536
537 gIOServiceNullNotifier = OSTypeAlloc(_IOServiceNullNotifier);
538 assert(gIOServiceNullNotifier);
539
540 gArbitrationLockQueueLock = IOLockAlloc();
541 queue_init(&gArbitrationLockQueueActive);
542 queue_init(&gArbitrationLockQueueWaiting);
543 queue_init(&gArbitrationLockQueueFree);
544
545 assert( gArbitrationLockQueueLock );
546
547 gIOTerminatePhase2List = OSArray::withCapacity( 2 );
548 gIOStopList = OSArray::withCapacity( 16 );
549 gIOStopProviderList = OSArray::withCapacity( 16 );
550 gIOFinalizeList = OSArray::withCapacity( 16 );
551 #if !NO_KEXTD
552 gIOMatchDeferList = OSArray::withCapacity( 16 );
553 #endif
554 assert( gIOTerminatePhase2List && gIOStopList && gIOStopProviderList && gIOFinalizeList );
555
556 // worker thread that is responsible for terminating / cleaning up threads
557 kernel_thread_start(&terminateThread, NULL, &gIOTerminateWorkerThread);
558 assert(gIOTerminateWorkerThread);
559 thread_set_thread_name(gIOTerminateWorkerThread, "IOServiceTerminateThread");
560 }
561
562 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
563
564 #if defined(__i386__) || defined(__x86_64__)
565 extern "C" {
566 const char *getCpuDelayBusStallHolderName(void);
567 const char *
568 getCpuDelayBusStallHolderName(void)
569 {
570 return sCPULatencyHolderName[kCpuDelayBusStall];
571 }
572
573 const char *getCpuInterruptDelayHolderName(void);
574 const char *
575 getCpuInterruptDelayHolderName(void)
576 {
577 return sCPULatencyHolderName[kCpuDelayInterrupt];
578 }
579 }
580 #endif
581
582 #if IOMATCHDEBUG
583 static UInt64
584 getDebugFlags( OSDictionary * props )
585 {
586 OSNumber * debugProp;
587 UInt64 debugFlags;
588
589 debugProp = OSDynamicCast( OSNumber,
590 props->getObject( gIOKitDebugKey ));
591 if (debugProp) {
592 debugFlags = debugProp->unsigned64BitValue();
593 } else {
594 debugFlags = gIOKitDebug;
595 }
596
597 return debugFlags;
598 }
599
600 static UInt64
601 getDebugFlags( IOService * inst )
602 {
603 OSObject * prop;
604 OSNumber * debugProp;
605 UInt64 debugFlags;
606
607 prop = inst->copyProperty(gIOKitDebugKey);
608 debugProp = OSDynamicCast(OSNumber, prop);
609 if (debugProp) {
610 debugFlags = debugProp->unsigned64BitValue();
611 } else {
612 debugFlags = gIOKitDebug;
613 }
614
615 OSSafeReleaseNULL(prop);
616
617 return debugFlags;
618 }
619 #endif
620
621 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
622
623 // Probe a matched service and return an instance to be started.
624 // The default score is from the property table, & may be altered
625 // during probe to change the start order.
626
627 IOService *
628 IOService::probe( IOService * provider,
629 SInt32 * score )
630 {
631 return this;
632 }
633
634 bool
635 IOService::start( IOService * provider )
636 {
637 return true;
638 }
639
640 void
641 IOService::stop( IOService * provider )
642 {
643 if (reserved->uvars && reserved->uvars->started && reserved->uvars->userServer) {
644 reserved->uvars->userServer->serviceStop(this, provider);
645 }
646 }
647
648 bool
649 IOService::init( OSDictionary * dictionary )
650 {
651 bool ret;
652
653 ret = super::init(dictionary);
654 if (!ret) {
655 return false;
656 }
657 if (reserved) {
658 return true;
659 }
660
661 reserved = IONew(ExpansionData, 1);
662 if (!reserved) {
663 return false;
664 }
665 bzero(reserved, sizeof(*reserved));
666
667 /*
668 * TODO: Improve on this. Previous efforts to more lazily allocate this
669 * lock based on the presence of specifiers ran into issues as some
670 * platforms set up the specifiers after IOService initialization.
671 *
672 * We may be able to get away with a global lock, as this should only be
673 * contended by IOReporting clients and driver start/stop (unless a
674 * driver wants to remove/add handlers in the course of normal operation,
675 * which should be unlikely).
676 */
677 reserved->interruptStatisticsLock = IOLockAlloc();
678 if (!reserved->interruptStatisticsLock) {
679 return false;
680 }
681
682 return true;
683 }
684
685 bool
686 IOService::init( IORegistryEntry * from,
687 const IORegistryPlane * inPlane )
688 {
689 bool ret;
690
691 ret = super::init(from, inPlane);
692 if (!ret) {
693 return false;
694 }
695 if (reserved) {
696 return true;
697 }
698
699 reserved = IONew(ExpansionData, 1);
700 if (!reserved) {
701 return false;
702 }
703 bzero(reserved, sizeof(*reserved));
704
705 /*
706 * TODO: Improve on this. Previous efforts to more lazily allocate this
707 * lock based on the presence of specifiers ran into issues as some
708 * platforms set up the specifiers after IOService initialization.
709 *
710 * We may be able to get away with a global lock, as this should only be
711 * contended by IOReporting clients and driver start/stop (unless a
712 * driver wants to remove/add handlers in the course of normal operation,
713 * which should be unlikely).
714 */
715 reserved->interruptStatisticsLock = IOLockAlloc();
716 if (!reserved->interruptStatisticsLock) {
717 return false;
718 }
719
720 return true;
721 }
722
723 void
724 IOService::free( void )
725 {
726 int i = 0;
727 requireMaxBusStall(0);
728 requireMaxInterruptDelay(0);
729 if (getPropertyTable()) {
730 unregisterAllInterest();
731 }
732 PMfree();
733
734 if (reserved) {
735 if (reserved->interruptStatisticsArray) {
736 for (i = 0; i < reserved->interruptStatisticsArrayCount; i++) {
737 if (reserved->interruptStatisticsArray[i].reporter) {
738 reserved->interruptStatisticsArray[i].reporter->release();
739 }
740 }
741
742 IODelete(reserved->interruptStatisticsArray, IOInterruptAccountingReporter, reserved->interruptStatisticsArrayCount);
743 }
744
745 if (reserved->interruptStatisticsLock) {
746 IOLockFree(reserved->interruptStatisticsLock);
747 }
748 if (reserved->uvars && reserved->uvars->userServer) {
749 reserved->uvars->userServer->serviceFree(this);
750 }
751 IODelete(reserved, ExpansionData, 1);
752 }
753
754 if (_numInterruptSources && _interruptSources) {
755 for (i = 0; i < _numInterruptSources; i++) {
756 void * block = _interruptSourcesPrivate(this)[i].vectorBlock;
757 if (block) {
758 Block_release(block);
759 }
760 }
761 IOFree(_interruptSources,
762 _numInterruptSources * sizeofAllIOInterruptSource);
763 _interruptSources = NULL;
764 }
765
766 super::free();
767 }
768
769 /*
770 * Attach in service plane
771 */
772 bool
773 IOService::attach( IOService * provider )
774 {
775 bool ok;
776 uint32_t count;
777 AbsoluteTime deadline;
778 int waitResult = THREAD_AWAKENED;
779 bool wait, computeDeadline = true;
780
781 if (provider) {
782 if (gIOKitDebug & kIOLogAttach) {
783 LOG( "%s::attach(%s)\n", getName(),
784 provider->getName());
785 }
786
787 ok = false;
788 do{
789 wait = false;
790 provider->lockForArbitration();
791 if (provider->__state[0] & kIOServiceInactiveState) {
792 ok = false;
793 } else {
794 count = provider->getChildCount(gIOServicePlane);
795 wait = (count > (kIOServiceBusyMax - 4));
796 if (!wait) {
797 ok = attachToParent(provider, gIOServicePlane);
798 } else {
799 IOLog("stalling for detach from %s\n", provider->getName());
800 IOLockLock( gIOServiceBusyLock );
801 provider->__state[1] |= kIOServiceWaitDetachState;
802 }
803 }
804 provider->unlockForArbitration();
805 if (wait) {
806 if (computeDeadline) {
807 clock_interval_to_deadline(15, kSecondScale, &deadline);
808 computeDeadline = false;
809 }
810 assert_wait_deadline((event_t)&provider->__provider, THREAD_UNINT, deadline);
811 IOLockUnlock( gIOServiceBusyLock );
812 waitResult = thread_block(THREAD_CONTINUE_NULL);
813 wait = (waitResult != THREAD_TIMED_OUT);
814 }
815 }while (wait);
816 } else {
817 gIOServiceRoot = this;
818 ok = attachToParent( getRegistryRoot(), gIOServicePlane);
819 }
820
821 if (ok && !__provider) {
822 (void) getProvider();
823 }
824
825 return ok;
826 }
827
828 IOService *
829 IOService::getServiceRoot( void )
830 {
831 return gIOServiceRoot;
832 }
833
834 void
835 IOService::detach( IOService * provider )
836 {
837 IOService * newProvider = NULL;
838 SInt32 busy;
839 bool adjParent;
840
841 if (gIOKitDebug & kIOLogAttach) {
842 LOG("%s::detach(%s)\n", getName(), provider->getName());
843 }
844
845 #if !NO_KEXTD
846 IOLockLock(gJobsLock);
847 if (gIOMatchDeferList) {
848 auto idx = gIOMatchDeferList->getNextIndexOfObject(this, 0);
849 if (-1U != idx) {
850 gIOMatchDeferList->removeObject(idx);
851 }
852 }
853 if (IOServicePH::fMatchingDelayed) {
854 auto idx = IOServicePH::fMatchingDelayed->getNextIndexOfObject(this, 0);
855 if (-1U != idx) {
856 IOServicePH::fMatchingDelayed->removeObject(idx);
857 }
858 }
859 IOLockUnlock(gJobsLock);
860 #endif /* NO_KEXTD */
861
862 lockForArbitration();
863
864 uint64_t regID1 = provider->getRegistryEntryID();
865 uint64_t regID2 = getRegistryEntryID();
866 IOServiceTrace(
867 IOSERVICE_DETACH,
868 (uintptr_t) regID1,
869 (uintptr_t) (regID1 >> 32),
870 (uintptr_t) regID2,
871 (uintptr_t) (regID2 >> 32));
872
873 adjParent = ((busy = (__state[1] & kIOServiceBusyStateMask))
874 && (provider == getProvider()));
875
876 detachFromParent( provider, gIOServicePlane );
877
878 if (busy) {
879 newProvider = getProvider();
880 if (busy && (__state[1] & kIOServiceTermPhase3State) && (NULL == newProvider)) {
881 _adjustBusy( -busy );
882 }
883 }
884
885 if (kIOServiceInactiveState & __state[0]) {
886 getMetaClass()->removeInstance(this);
887 IORemoveServicePlatformActions(this);
888 }
889
890 unlockForArbitration();
891
892 if (newProvider && adjParent) {
893 newProvider->lockForArbitration();
894 newProvider->_adjustBusy(1);
895 newProvider->unlockForArbitration();
896 }
897
898 // check for last client detach from a terminated service
899 if (provider->lockForArbitration( true )) {
900 if (kIOServiceStartState & __state[1]) {
901 provider->scheduleTerminatePhase2();
902 }
903 if (adjParent) {
904 provider->_adjustBusy( -1 );
905 }
906 if ((provider->__state[1] & kIOServiceTermPhase3State)
907 && (NULL == provider->getClient())) {
908 provider->scheduleFinalize(false);
909 }
910
911 IOLockLock( gIOServiceBusyLock );
912 if (kIOServiceWaitDetachState & provider->__state[1]) {
913 provider->__state[1] &= ~kIOServiceWaitDetachState;
914 thread_wakeup(&provider->__provider);
915 }
916 IOLockUnlock( gIOServiceBusyLock );
917
918 provider->unlockForArbitration();
919 }
920 }
921
922 /*
923 * Register instance - publish it for matching
924 */
925
926 void
927 IOService::registerService( IOOptionBits options )
928 {
929 char * pathBuf;
930 const char * path;
931 char * skip;
932 int len;
933 enum { kMaxPathLen = 256 };
934 enum { kMaxChars = 63 };
935
936 IORegistryEntry * parent = this;
937 IORegistryEntry * root = getRegistryRoot();
938 while (parent && (parent != root)) {
939 parent = parent->getParentEntry( gIOServicePlane);
940 }
941
942 if (parent != root) {
943 IOLog("%s: not registry member at registerService()\n", getName());
944 return;
945 }
946
947 // Allow the Platform Expert to adjust this node.
948 if (gIOPlatform && (!gIOPlatform->platformAdjustService(this))) {
949 return;
950 }
951
952 IOInstallServicePlatformActions(this);
953
954 if ((this != gIOResources)
955 && (kIOLogRegister & gIOKitDebug)) {
956 pathBuf = (char *) IOMalloc( kMaxPathLen );
957
958 IOLog( "Registering: " );
959
960 len = kMaxPathLen;
961 if (pathBuf && getPath( pathBuf, &len, gIOServicePlane)) {
962 path = pathBuf;
963 if (len > kMaxChars) {
964 IOLog("..");
965 len -= kMaxChars;
966 path += len;
967 if ((skip = strchr( path, '/'))) {
968 path = skip;
969 }
970 }
971 } else {
972 path = getName();
973 }
974
975 IOLog( "%s\n", path );
976
977 if (pathBuf) {
978 IOFree( pathBuf, kMaxPathLen );
979 }
980 }
981
982 startMatching( options );
983 }
984
985 void
986 IOService::startMatching( IOOptionBits options )
987 {
988 IOService * provider;
989 UInt32 prevBusy = 0;
990 bool needConfig;
991 bool needWake = false;
992 bool ok;
993 bool sync;
994 bool waitAgain;
995
996 lockForArbitration();
997
998 sync = (options & kIOServiceSynchronous)
999 || ((provider = getProvider())
1000 && (provider->__state[1] & kIOServiceSynchronousState));
1001
1002 if (options & kIOServiceAsynchronous) {
1003 sync = false;
1004 }
1005
1006 needConfig = (0 == (__state[1] & (kIOServiceNeedConfigState | kIOServiceConfigRunning)))
1007 && (0 == (__state[0] & kIOServiceInactiveState));
1008
1009 __state[1] |= kIOServiceNeedConfigState;
1010
1011 // __state[0] &= ~kIOServiceInactiveState;
1012
1013 // if( sync) LOG("OSKernelStackRemaining = %08x @ %s\n",
1014 // OSKernelStackRemaining(), getName());
1015
1016 if (needConfig) {
1017 needWake = (0 != (kIOServiceSyncPubState & __state[1]));
1018 }
1019
1020 if (sync) {
1021 __state[1] |= kIOServiceSynchronousState;
1022 } else {
1023 __state[1] &= ~kIOServiceSynchronousState;
1024 }
1025
1026 if (needConfig) {
1027 prevBusy = _adjustBusy( 1 );
1028 }
1029
1030 unlockForArbitration();
1031
1032 if (needConfig) {
1033 if (needWake) {
1034 IOLockLock( gIOServiceBusyLock );
1035 thread_wakeup((event_t) this /*&__state[1]*/ );
1036 IOLockUnlock( gIOServiceBusyLock );
1037 } else if (!sync || (kIOServiceAsynchronous & options)) {
1038 ok = (NULL != _IOServiceJob::startJob( this, kMatchNubJob, options ));
1039 } else {
1040 do {
1041 if ((__state[1] & kIOServiceNeedConfigState)) {
1042 doServiceMatch( options );
1043 }
1044
1045 lockForArbitration();
1046 IOLockLock( gIOServiceBusyLock );
1047
1048 waitAgain = ((prevBusy < (__state[1] & kIOServiceBusyStateMask))
1049 && (0 == (__state[0] & kIOServiceInactiveState)));
1050
1051 if (waitAgain) {
1052 __state[1] |= kIOServiceSyncPubState | kIOServiceBusyWaiterState;
1053 } else {
1054 __state[1] &= ~kIOServiceSyncPubState;
1055 }
1056
1057 unlockForArbitration();
1058
1059 if (waitAgain) {
1060 assert_wait((event_t) this /*&__state[1]*/, THREAD_UNINT);
1061 }
1062
1063 IOLockUnlock( gIOServiceBusyLock );
1064 if (waitAgain) {
1065 thread_block(THREAD_CONTINUE_NULL);
1066 }
1067 } while (waitAgain);
1068 }
1069 }
1070 }
1071
1072
1073 void
1074 IOService::startDeferredMatches(void)
1075 {
1076 #if !NO_KEXTD
1077 OSArray * array;
1078
1079 IOLockLock(gJobsLock);
1080 array = gIOMatchDeferList;
1081 gIOMatchDeferList = NULL;
1082 IOLockUnlock(gJobsLock);
1083
1084 if (array) {
1085 IOLog("deferred rematching count %d\n", array->getCount());
1086 array->iterateObjects(^bool (OSObject * obj)
1087 {
1088 ((IOService *)obj)->startMatching(kIOServiceAsynchronous);
1089 return false;
1090 });
1091 array->release();
1092 }
1093 #endif /* !NO_KEXTD */
1094 }
1095
1096 void
1097 IOService::kextdLaunched(void)
1098 {
1099 #if !NO_KEXTD
1100 IOServiceTrace(IOSERVICE_KEXTD_READY, 0, 0, 0, 0);
1101 startDeferredMatches();
1102 getServiceRoot()->adjustBusy(-1);
1103 IOService::publishUserResource(gIOResourceIOKitKey);
1104 #endif /* !NO_KEXTD */
1105 }
1106
1107 IOReturn
1108 IOService::catalogNewDrivers( OSOrderedSet * newTables )
1109 {
1110 OSDictionary * table;
1111 OSSet * set;
1112 OSSet * allSet = NULL;
1113 IOService * service;
1114 #if IOMATCHDEBUG
1115 SInt32 count = 0;
1116 #endif
1117
1118 newTables->retain();
1119
1120 while ((table = (OSDictionary *) newTables->getFirstObject())) {
1121 LOCKWRITENOTIFY();
1122 set = (OSSet *) copyExistingServices( table,
1123 kIOServiceRegisteredState,
1124 kIOServiceExistingSet);
1125 UNLOCKNOTIFY();
1126 if (set) {
1127 #if IOMATCHDEBUG
1128 count += set->getCount();
1129 #endif
1130 if (allSet) {
1131 allSet->merge((const OSSet *) set);
1132 set->release();
1133 } else {
1134 allSet = set;
1135 }
1136 }
1137
1138 #if IOMATCHDEBUG
1139 if (getDebugFlags( table ) & kIOLogMatch) {
1140 LOG("Matching service count = %ld\n", (long)count);
1141 }
1142 #endif
1143 newTables->removeObject(table);
1144 }
1145
1146 if (allSet) {
1147 while ((service = (IOService *) allSet->getAnyObject())) {
1148 service->startMatching(kIOServiceAsynchronous);
1149 allSet->removeObject(service);
1150 }
1151 allSet->release();
1152 }
1153
1154 newTables->release();
1155
1156 return kIOReturnSuccess;
1157 }
1158
1159 _IOServiceJob *
1160 _IOServiceJob::startJob( IOService * nub, int type,
1161 IOOptionBits options )
1162 {
1163 _IOServiceJob * job;
1164
1165 job = new _IOServiceJob;
1166 if (job && !job->init()) {
1167 job->release();
1168 job = NULL;
1169 }
1170
1171 if (job) {
1172 job->type = type;
1173 job->nub = nub;
1174 job->options = options;
1175 nub->retain(); // thread will release()
1176 pingConfig( job );
1177 }
1178
1179 return job;
1180 }
1181
1182 /*
1183 * Called on a registered service to see if it matches
1184 * a property table.
1185 */
1186
1187 bool
1188 IOService::matchPropertyTable( OSDictionary * table, SInt32 * score )
1189 {
1190 return matchPropertyTable(table);
1191 }
1192
1193 bool
1194 IOService::matchPropertyTable( OSDictionary * table )
1195 {
1196 return true;
1197 }
1198
1199 /*
1200 * Called on a matched service to allocate resources
1201 * before first driver is attached.
1202 */
1203
1204 IOReturn
1205 IOService::getResources( void )
1206 {
1207 return kIOReturnSuccess;
1208 }
1209
1210 /*
1211 * Client/provider accessors
1212 */
1213
1214 IOService *
1215 IOService::getProvider( void ) const
1216 {
1217 IOService * self = (IOService *) this;
1218 IOService * parent;
1219 SInt32 generation;
1220
1221 generation = getRegistryEntryGenerationCount();
1222 if (__providerGeneration == generation) {
1223 return __provider;
1224 }
1225
1226 parent = (IOService *) getParentEntry( gIOServicePlane);
1227 if (parent == IORegistryEntry::getRegistryRoot()) {
1228 /* root is not an IOService */
1229 parent = NULL;
1230 }
1231
1232 self->__provider = parent;
1233 OSMemoryBarrier();
1234 // save the count from before call to getParentEntry()
1235 self->__providerGeneration = generation;
1236
1237 return parent;
1238 }
1239
1240 IOWorkLoop *
1241 IOService::getWorkLoop() const
1242 {
1243 IOService *provider = getProvider();
1244
1245 if (provider) {
1246 return provider->getWorkLoop();
1247 } else {
1248 return NULL;
1249 }
1250 }
1251
1252 OSIterator *
1253 IOService::getProviderIterator( void ) const
1254 {
1255 return getParentIterator( gIOServicePlane);
1256 }
1257
1258 IOService *
1259 IOService::getClient( void ) const
1260 {
1261 return (IOService *) getChildEntry( gIOServicePlane);
1262 }
1263
1264 OSIterator *
1265 IOService::getClientIterator( void ) const
1266 {
1267 return getChildIterator( gIOServicePlane);
1268 }
1269
1270 OSIterator *
1271 _IOOpenServiceIterator::iterator( OSIterator * _iter,
1272 const IOService * client,
1273 const IOService * provider )
1274 {
1275 _IOOpenServiceIterator * inst;
1276
1277 if (!_iter) {
1278 return NULL;
1279 }
1280
1281 inst = new _IOOpenServiceIterator;
1282
1283 if (inst && !inst->init()) {
1284 inst->release();
1285 inst = NULL;
1286 }
1287 if (inst) {
1288 inst->iter = _iter;
1289 inst->client = client;
1290 inst->provider = provider;
1291 }
1292
1293 return inst;
1294 }
1295
1296 void
1297 _IOOpenServiceIterator::free()
1298 {
1299 iter->release();
1300 if (last) {
1301 last->unlockForArbitration();
1302 }
1303 OSIterator::free();
1304 }
1305
1306 OSObject *
1307 _IOOpenServiceIterator::getNextObject()
1308 {
1309 IOService * next;
1310
1311 if (last) {
1312 last->unlockForArbitration();
1313 }
1314
1315 while ((next = (IOService *) iter->getNextObject())) {
1316 next->lockForArbitration();
1317 if ((client && (next->isOpen( client )))
1318 || (provider && (provider->isOpen( next )))) {
1319 break;
1320 }
1321 next->unlockForArbitration();
1322 }
1323
1324 last = next;
1325
1326 return next;
1327 }
1328
1329 bool
1330 _IOOpenServiceIterator::isValid()
1331 {
1332 return iter->isValid();
1333 }
1334
1335 void
1336 _IOOpenServiceIterator::reset()
1337 {
1338 if (last) {
1339 last->unlockForArbitration();
1340 last = NULL;
1341 }
1342 iter->reset();
1343 }
1344
1345 OSIterator *
1346 IOService::getOpenProviderIterator( void ) const
1347 {
1348 return _IOOpenServiceIterator::iterator( getProviderIterator(), this, NULL );
1349 }
1350
1351 OSIterator *
1352 IOService::getOpenClientIterator( void ) const
1353 {
1354 return _IOOpenServiceIterator::iterator( getClientIterator(), NULL, this );
1355 }
1356
1357
1358 IOReturn
1359 IOService::callPlatformFunction( const OSSymbol * functionName,
1360 bool waitForFunction,
1361 void *param1, void *param2,
1362 void *param3, void *param4 )
1363 {
1364 IOReturn result = kIOReturnUnsupported;
1365 IOService *provider;
1366
1367 if (functionName == gIOPlatformQuiesceActionKey ||
1368 functionName == gIOPlatformActiveActionKey) {
1369 /*
1370 * Services which register for IOPlatformQuiesceAction / IOPlatformActiveAction
1371 * must consume that event themselves, without passing it up to super/IOService.
1372 */
1373 if (gEnforceQuiesceSafety) {
1374 panic("Class %s passed the quiesce/active action to IOService",
1375 getMetaClass()->getClassName());
1376 }
1377 }
1378
1379 if (gIOPlatformFunctionHandlerSet == functionName) {
1380 #if defined(__i386__) || defined(__x86_64__)
1381 const OSSymbol * functionHandlerName = (const OSSymbol *) param1;
1382 IOService * target = (IOService *) param2;
1383 bool enable = (param3 != NULL);
1384
1385 if (sCPULatencyFunctionName[kCpuDelayBusStall] == functionHandlerName) {
1386 result = setLatencyHandler(kCpuDelayBusStall, target, enable);
1387 } else if (sCPULatencyFunctionName[kCpuDelayInterrupt] == param1) {
1388 result = setLatencyHandler(kCpuDelayInterrupt, target, enable);
1389 }
1390 #endif /* defined(__i386__) || defined(__x86_64__) */
1391 }
1392
1393 if ((kIOReturnUnsupported == result) && (provider = getProvider())) {
1394 result = provider->callPlatformFunction(functionName, waitForFunction,
1395 param1, param2, param3, param4);
1396 }
1397
1398 return result;
1399 }
1400
1401 IOReturn
1402 IOService::callPlatformFunction( const char * functionName,
1403 bool waitForFunction,
1404 void *param1, void *param2,
1405 void *param3, void *param4 )
1406 {
1407 IOReturn result = kIOReturnNoMemory;
1408 const OSSymbol *functionSymbol = OSSymbol::withCString(functionName);
1409
1410 if (functionSymbol != NULL) {
1411 result = callPlatformFunction(functionSymbol, waitForFunction,
1412 param1, param2, param3, param4);
1413 functionSymbol->release();
1414 }
1415
1416 return result;
1417 }
1418
1419
1420 /*
1421 * Accessors for global services
1422 */
1423
1424 IOPlatformExpert *
1425 IOService::getPlatform( void )
1426 {
1427 return gIOPlatform;
1428 }
1429
1430 class IOPMrootDomain *
1431 IOService::getPMRootDomain( void )
1432 {
1433 return gIOPMRootDomain;
1434 }
1435
1436 IOService *
1437 IOService::getResourceService( void )
1438 {
1439 return gIOResources;
1440 }
1441
1442 void
1443 IOService::setPlatform( IOPlatformExpert * platform)
1444 {
1445 gIOPlatform = platform;
1446 gIOResources->attachToParent( gIOServiceRoot, gIOServicePlane );
1447 gIOUserResources->attachToParent( gIOServiceRoot, gIOServicePlane );
1448
1449 #if defined(__i386__) || defined(__x86_64__)
1450
1451 static const char * keys[kCpuNumDelayTypes] = {
1452 kIOPlatformMaxBusDelay, kIOPlatformMaxInterruptDelay };
1453 const OSObject * objs[2];
1454 OSArray * array;
1455 uint32_t idx;
1456
1457 for (idx = 0; idx < kCpuNumDelayTypes; idx++) {
1458 objs[0] = sCPULatencySet[idx];
1459 objs[1] = sCPULatencyHolder[idx];
1460 array = OSArray::withObjects(objs, 2);
1461 if (!array) {
1462 break;
1463 }
1464 platform->setProperty(keys[idx], array);
1465 array->release();
1466 }
1467 #endif /* defined(__i386__) || defined(__x86_64__) */
1468 }
1469
1470 void
1471 IOService::setPMRootDomain( class IOPMrootDomain * rootDomain)
1472 {
1473 gIOPMRootDomain = rootDomain;
1474 publishResource(gIOResourceIOKitKey);
1475 IOServicePH::init(rootDomain);
1476 }
1477
1478 /*
1479 * Stacking change
1480 */
1481
1482 bool
1483 IOService::lockForArbitration( bool isSuccessRequired )
1484 {
1485 bool found;
1486 bool success;
1487 ArbitrationLockQueueElement * element;
1488 ArbitrationLockQueueElement * active;
1489 ArbitrationLockQueueElement * waiting;
1490
1491 enum { kPutOnFreeQueue, kPutOnActiveQueue, kPutOnWaitingQueue } action;
1492
1493 // lock global access
1494 IOTakeLock( gArbitrationLockQueueLock );
1495
1496 // obtain an unused queue element
1497 if (!queue_empty( &gArbitrationLockQueueFree )) {
1498 queue_remove_first( &gArbitrationLockQueueFree,
1499 element,
1500 ArbitrationLockQueueElement *,
1501 link );
1502 } else {
1503 element = IONew( ArbitrationLockQueueElement, 1 );
1504 assert( element );
1505 }
1506
1507 // prepare the queue element
1508 element->thread = IOThreadSelf();
1509 element->service = this;
1510 element->count = 1;
1511 element->required = isSuccessRequired;
1512 element->aborted = false;
1513
1514 // determine whether this object is already locked (ie. on active queue)
1515 found = false;
1516 queue_iterate( &gArbitrationLockQueueActive,
1517 active,
1518 ArbitrationLockQueueElement *,
1519 link )
1520 {
1521 if (active->service == element->service) {
1522 found = true;
1523 break;
1524 }
1525 }
1526
1527 if (found) { // this object is already locked
1528 // determine whether it is the same or a different thread trying to lock
1529 if (active->thread != element->thread) { // it is a different thread
1530 ArbitrationLockQueueElement * victim = NULL;
1531
1532 // before placing this new thread on the waiting queue, we look for
1533 // a deadlock cycle...
1534
1535 while (1) {
1536 // determine whether the active thread holding the object we
1537 // want is waiting for another object to be unlocked
1538 found = false;
1539 queue_iterate( &gArbitrationLockQueueWaiting,
1540 waiting,
1541 ArbitrationLockQueueElement *,
1542 link )
1543 {
1544 if (waiting->thread == active->thread) {
1545 assert( false == waiting->aborted );
1546 found = true;
1547 break;
1548 }
1549 }
1550
1551 if (found) { // yes, active thread waiting for another object
1552 // this may be a candidate for rejection if the required
1553 // flag is not set, should we detect a deadlock later on
1554 if (false == waiting->required) {
1555 victim = waiting;
1556 }
1557
1558 // find the thread that is holding this other object, that
1559 // is blocking the active thread from proceeding (fun :-)
1560 found = false;
1561 queue_iterate( &gArbitrationLockQueueActive,
1562 active, // (reuse active queue element)
1563 ArbitrationLockQueueElement *,
1564 link )
1565 {
1566 if (active->service == waiting->service) {
1567 found = true;
1568 break;
1569 }
1570 }
1571
1572 // someone must be holding it or it wouldn't be waiting
1573 assert( found );
1574
1575 if (active->thread == element->thread) {
1576 // doh, it's waiting for the thread that originated
1577 // this whole lock (ie. current thread) -> deadlock
1578 if (false == element->required) { // willing to fail?
1579 // the originating thread doesn't have the required
1580 // flag, so it can fail
1581 success = false; // (fail originating lock request)
1582 break; // (out of while)
1583 } else { // originating thread is not willing to fail
1584 // see if we came across a waiting thread that did
1585 // not have the 'required' flag set: we'll fail it
1586 if (victim) {
1587 // we do have a willing victim, fail it's lock
1588 victim->aborted = true;
1589
1590 // take the victim off the waiting queue
1591 queue_remove( &gArbitrationLockQueueWaiting,
1592 victim,
1593 ArbitrationLockQueueElement *,
1594 link );
1595
1596 // wake the victim
1597 IOLockWakeup( gArbitrationLockQueueLock,
1598 victim,
1599 /* one thread */ true );
1600
1601 // allow this thread to proceed (ie. wait)
1602 success = true; // (put request on wait queue)
1603 break; // (out of while)
1604 } else {
1605 // all the waiting threads we came across in
1606 // finding this loop had the 'required' flag
1607 // set, so we've got a deadlock we can't avoid
1608 panic("I/O Kit: Unrecoverable deadlock.");
1609 }
1610 }
1611 } else {
1612 // repeat while loop, redefining active thread to be the
1613 // thread holding "this other object" (see above), and
1614 // looking for threads waiting on it; note the active
1615 // variable points to "this other object" already... so
1616 // there nothing to do in this else clause.
1617 }
1618 } else { // no, active thread is not waiting for another object
1619 success = true; // (put request on wait queue)
1620 break; // (out of while)
1621 }
1622 } // while forever
1623
1624 if (success) { // put the request on the waiting queue?
1625 kern_return_t wait_result;
1626
1627 // place this thread on the waiting queue and put it to sleep;
1628 // we place it at the tail of the queue...
1629 queue_enter( &gArbitrationLockQueueWaiting,
1630 element,
1631 ArbitrationLockQueueElement *,
1632 link );
1633
1634 // declare that this thread will wait for a given event
1635 restart_sleep: wait_result = assert_wait( element,
1636 element->required ? THREAD_UNINT
1637 : THREAD_INTERRUPTIBLE );
1638
1639 // unlock global access
1640 IOUnlock( gArbitrationLockQueueLock );
1641
1642 // put thread to sleep, waiting for our event to fire...
1643 if (wait_result == THREAD_WAITING) {
1644 wait_result = thread_block(THREAD_CONTINUE_NULL);
1645 }
1646
1647
1648 // ...and we've been woken up; we might be in one of two states:
1649 // (a) we've been aborted and our queue element is not on
1650 // any of the three queues, but is floating around
1651 // (b) we're allowed to proceed with the lock and we have
1652 // already been moved from the waiting queue to the
1653 // active queue.
1654 // ...plus a 3rd state, should the thread have been interrupted:
1655 // (c) we're still on the waiting queue
1656
1657 // determine whether we were interrupted out of our sleep
1658 if (THREAD_INTERRUPTED == wait_result) {
1659 // re-lock global access
1660 IOTakeLock( gArbitrationLockQueueLock );
1661
1662 // determine whether we're still on the waiting queue
1663 found = false;
1664 queue_iterate( &gArbitrationLockQueueWaiting,
1665 waiting, // (reuse waiting queue element)
1666 ArbitrationLockQueueElement *,
1667 link )
1668 {
1669 if (waiting == element) {
1670 found = true;
1671 break;
1672 }
1673 }
1674
1675 if (found) { // yes, we're still on the waiting queue
1676 // determine whether we're willing to fail
1677 if (false == element->required) {
1678 // mark us as aborted
1679 element->aborted = true;
1680
1681 // take us off the waiting queue
1682 queue_remove( &gArbitrationLockQueueWaiting,
1683 element,
1684 ArbitrationLockQueueElement *,
1685 link );
1686 } else { // we are not willing to fail
1687 // ignore interruption, go back to sleep
1688 goto restart_sleep;
1689 }
1690 }
1691
1692 // unlock global access
1693 IOUnlock( gArbitrationLockQueueLock );
1694
1695 // proceed as though this were a normal wake up
1696 wait_result = THREAD_AWAKENED;
1697 }
1698
1699 assert( THREAD_AWAKENED == wait_result );
1700
1701 // determine whether we've been aborted while we were asleep
1702 if (element->aborted) {
1703 assert( false == element->required );
1704
1705 // re-lock global access
1706 IOTakeLock( gArbitrationLockQueueLock );
1707
1708 action = kPutOnFreeQueue;
1709 success = false;
1710 } else { // we weren't aborted, so we must be ready to go :-)
1711 // we've already been moved from waiting to active queue
1712 return true;
1713 }
1714 } else { // the lock request is to be failed
1715 // return unused queue element to queue
1716 action = kPutOnFreeQueue;
1717 }
1718 } else { // it is the same thread, recursive access is allowed
1719 // add one level of recursion
1720 active->count++;
1721
1722 // return unused queue element to queue
1723 action = kPutOnFreeQueue;
1724 success = true;
1725 }
1726 } else { // this object is not already locked, so let this thread through
1727 action = kPutOnActiveQueue;
1728 success = true;
1729 }
1730
1731 // put the new element on a queue
1732 if (kPutOnActiveQueue == action) {
1733 queue_enter( &gArbitrationLockQueueActive,
1734 element,
1735 ArbitrationLockQueueElement *,
1736 link );
1737 } else if (kPutOnFreeQueue == action) {
1738 queue_enter( &gArbitrationLockQueueFree,
1739 element,
1740 ArbitrationLockQueueElement *,
1741 link );
1742 } else {
1743 assert( 0 ); // kPutOnWaitingQueue never occurs, handled specially above
1744 }
1745
1746 // unlock global access
1747 IOUnlock( gArbitrationLockQueueLock );
1748
1749 return success;
1750 }
1751
1752 void
1753 IOService::unlockForArbitration( void )
1754 {
1755 bool found;
1756 ArbitrationLockQueueElement * element;
1757
1758 // lock global access
1759 IOTakeLock( gArbitrationLockQueueLock );
1760
1761 // find the lock element for this object (ie. on active queue)
1762 found = false;
1763 queue_iterate( &gArbitrationLockQueueActive,
1764 element,
1765 ArbitrationLockQueueElement *,
1766 link )
1767 {
1768 if (element->service == this) {
1769 found = true;
1770 break;
1771 }
1772 }
1773
1774 assert( found );
1775
1776 // determine whether the lock has been taken recursively
1777 if (element->count > 1) {
1778 // undo one level of recursion
1779 element->count--;
1780 } else {
1781 // remove it from the active queue
1782 queue_remove( &gArbitrationLockQueueActive,
1783 element,
1784 ArbitrationLockQueueElement *,
1785 link );
1786
1787 // put it on the free queue
1788 queue_enter( &gArbitrationLockQueueFree,
1789 element,
1790 ArbitrationLockQueueElement *,
1791 link );
1792
1793 // determine whether a thread is waiting for object (head to tail scan)
1794 found = false;
1795 queue_iterate( &gArbitrationLockQueueWaiting,
1796 element,
1797 ArbitrationLockQueueElement *,
1798 link )
1799 {
1800 if (element->service == this) {
1801 found = true;
1802 break;
1803 }
1804 }
1805
1806 if (found) { // we found an interested thread on waiting queue
1807 // remove it from the waiting queue
1808 queue_remove( &gArbitrationLockQueueWaiting,
1809 element,
1810 ArbitrationLockQueueElement *,
1811 link );
1812
1813 // put it on the active queue
1814 queue_enter( &gArbitrationLockQueueActive,
1815 element,
1816 ArbitrationLockQueueElement *,
1817 link );
1818
1819 // wake the waiting thread
1820 IOLockWakeup( gArbitrationLockQueueLock,
1821 element,
1822 /* one thread */ true );
1823 }
1824 }
1825
1826 // unlock global access
1827 IOUnlock( gArbitrationLockQueueLock );
1828 }
1829
1830 uint32_t
1831 IOService::isLockedForArbitration(IOService * service)
1832 {
1833 #if DEBUG_NOTIFIER_LOCKED
1834 uint32_t count;
1835 ArbitrationLockQueueElement * active;
1836
1837 // lock global access
1838 IOLockLock(gArbitrationLockQueueLock);
1839
1840 // determine whether this object is already locked (ie. on active queue)
1841 count = 0;
1842 queue_iterate(&gArbitrationLockQueueActive,
1843 active,
1844 ArbitrationLockQueueElement *,
1845 link)
1846 {
1847 if ((active->thread == IOThreadSelf())
1848 && (!service || (active->service == service))) {
1849 count += 0x10000;
1850 count += active->count;
1851 }
1852 }
1853
1854 IOLockUnlock(gArbitrationLockQueueLock);
1855
1856 return count;
1857
1858 #else /* DEBUG_NOTIFIER_LOCKED */
1859
1860 return 0;
1861
1862 #endif /* DEBUG_NOTIFIER_LOCKED */
1863 }
1864
1865 void
1866 IOService::applyToProviders( IOServiceApplierFunction applier,
1867 void * context )
1868 {
1869 applyToParents((IORegistryEntryApplierFunction) applier,
1870 context, gIOServicePlane );
1871 }
1872
1873 void
1874 IOService::applyToClients( IOServiceApplierFunction applier,
1875 void * context )
1876 {
1877 applyToChildren((IORegistryEntryApplierFunction) applier,
1878 context, gIOServicePlane );
1879 }
1880
1881
1882 /*
1883 * Client messages
1884 */
1885
1886
1887 // send a message to a client or interested party of this service
1888 IOReturn
1889 IOService::messageClient( UInt32 type, OSObject * client,
1890 void * argument, vm_size_t argSize )
1891 {
1892 IOReturn ret;
1893 IOService * service;
1894 _IOServiceInterestNotifier * notify;
1895
1896 if ((service = OSDynamicCast( IOService, client))) {
1897 ret = service->message( type, this, argument );
1898 } else if ((notify = OSDynamicCast( _IOServiceInterestNotifier, client))) {
1899 _IOServiceNotifierInvocation invocation;
1900 bool willNotify;
1901
1902 invocation.thread = current_thread();
1903
1904 LOCKWRITENOTIFY();
1905 willNotify = (0 != (kIOServiceNotifyEnable & notify->state));
1906
1907 if (willNotify) {
1908 queue_enter( &notify->handlerInvocations, &invocation,
1909 _IOServiceNotifierInvocation *, link );
1910 }
1911 UNLOCKNOTIFY();
1912
1913 if (willNotify) {
1914 ret = (*notify->handler)( notify->target, notify->ref,
1915 type, this, argument, argSize );
1916
1917 LOCKWRITENOTIFY();
1918 queue_remove( &notify->handlerInvocations, &invocation,
1919 _IOServiceNotifierInvocation *, link );
1920 if (kIOServiceNotifyWaiter & notify->state) {
1921 notify->state &= ~kIOServiceNotifyWaiter;
1922 WAKEUPNOTIFY( notify );
1923 }
1924 UNLOCKNOTIFY();
1925 } else {
1926 ret = kIOReturnSuccess;
1927 }
1928 } else {
1929 ret = kIOReturnBadArgument;
1930 }
1931
1932 return ret;
1933 }
1934
1935 static void
1936 applyToInterestNotifiers(const IORegistryEntry *target,
1937 const OSSymbol * typeOfInterest,
1938 OSObjectApplierFunction applier,
1939 void * context )
1940 {
1941 OSArray * copyArray = NULL;
1942 OSObject * prop;
1943
1944 LOCKREADNOTIFY();
1945
1946 prop = target->copyProperty(typeOfInterest);
1947 IOCommand *notifyList = OSDynamicCast(IOCommand, prop);
1948
1949 if (notifyList) {
1950 copyArray = OSArray::withCapacity(1);
1951
1952 // iterate over queue, entry is set to each element in the list
1953 iterqueue(&notifyList->fCommandChain, entry) {
1954 _IOServiceInterestNotifier * notify;
1955
1956 queue_element(entry, notify, _IOServiceInterestNotifier *, chain);
1957 copyArray->setObject(notify);
1958 }
1959 }
1960 UNLOCKNOTIFY();
1961
1962 if (copyArray) {
1963 unsigned int index;
1964 OSObject * next;
1965
1966 for (index = 0; (next = copyArray->getObject( index )); index++) {
1967 (*applier)(next, context);
1968 }
1969 copyArray->release();
1970 }
1971
1972 OSSafeReleaseNULL(prop);
1973 }
1974
1975 void
1976 IOService::applyToInterested( const OSSymbol * typeOfInterest,
1977 OSObjectApplierFunction applier,
1978 void * context )
1979 {
1980 if (gIOGeneralInterest == typeOfInterest) {
1981 applyToClients((IOServiceApplierFunction) applier, context );
1982 }
1983 applyToInterestNotifiers(this, typeOfInterest, applier, context);
1984 }
1985
1986 struct MessageClientsContext {
1987 IOService * service;
1988 UInt32 type;
1989 void * argument;
1990 vm_size_t argSize;
1991 IOReturn ret;
1992 };
1993
1994 static void
1995 messageClientsApplier( OSObject * object, void * ctx )
1996 {
1997 IOReturn ret;
1998 MessageClientsContext * context = (MessageClientsContext *) ctx;
1999
2000 ret = context->service->messageClient( context->type,
2001 object, context->argument, context->argSize );
2002 if (kIOReturnSuccess != ret) {
2003 context->ret = ret;
2004 }
2005 }
2006
2007 // send a message to all clients
2008 IOReturn
2009 IOService::messageClients( UInt32 type,
2010 void * argument, vm_size_t argSize )
2011 {
2012 MessageClientsContext context;
2013
2014 context.service = this;
2015 context.type = type;
2016 context.argument = argument;
2017 context.argSize = argSize;
2018 context.ret = kIOReturnSuccess;
2019
2020 applyToInterested( gIOGeneralInterest,
2021 &messageClientsApplier, &context );
2022
2023 return context.ret;
2024 }
2025
2026 IOReturn
2027 IOService::acknowledgeNotification( IONotificationRef notification,
2028 IOOptionBits response )
2029 {
2030 return kIOReturnUnsupported;
2031 }
2032
2033 IONotifier *
2034 IOService::registerInterest( const OSSymbol * typeOfInterest,
2035 IOServiceInterestHandler handler, void * target, void * ref )
2036 {
2037 _IOServiceInterestNotifier * notify = NULL;
2038 IOReturn rc = kIOReturnError;
2039
2040 notify = new _IOServiceInterestNotifier;
2041 if (!notify) {
2042 return NULL;
2043 }
2044
2045 if (notify->init()) {
2046 rc = registerInterestForNotifier(notify, typeOfInterest,
2047 handler, target, ref);
2048 }
2049
2050 if (rc != kIOReturnSuccess) {
2051 notify->release();
2052 notify = NULL;
2053 }
2054
2055 return notify;
2056 }
2057
2058
2059
2060 static IOReturn
2061 IOServiceInterestHandlerToBlock( void * target __unused, void * refCon,
2062 UInt32 messageType, IOService * provider,
2063 void * messageArgument, vm_size_t argSize )
2064 {
2065 return ((IOServiceInterestHandlerBlock) refCon)(messageType, provider, messageArgument, argSize);
2066 }
2067
2068 IONotifier *
2069 IOService::registerInterest(const OSSymbol * typeOfInterest,
2070 IOServiceInterestHandlerBlock handler)
2071 {
2072 IONotifier * notify;
2073 void * block;
2074
2075 block = Block_copy(handler);
2076 if (!block) {
2077 return NULL;
2078 }
2079
2080 notify = registerInterest(typeOfInterest, &IOServiceInterestHandlerToBlock, NULL, block);
2081
2082 if (!notify) {
2083 Block_release(block);
2084 }
2085
2086 return notify;
2087 }
2088
2089 IOReturn
2090 IOService::registerInterestForNotifier( IONotifier *svcNotify, const OSSymbol * typeOfInterest,
2091 IOServiceInterestHandler handler, void * target, void * ref )
2092 {
2093 IOReturn rc = kIOReturnSuccess;
2094 _IOServiceInterestNotifier *notify = NULL;
2095
2096 if (!svcNotify || !(notify = OSDynamicCast(_IOServiceInterestNotifier, svcNotify))) {
2097 return kIOReturnBadArgument;
2098 }
2099
2100 notify->handler = handler;
2101 notify->target = target;
2102 notify->ref = ref;
2103
2104 if ((typeOfInterest != gIOGeneralInterest)
2105 && (typeOfInterest != gIOBusyInterest)
2106 && (typeOfInterest != gIOAppPowerStateInterest)
2107 && (typeOfInterest != gIOConsoleSecurityInterest)
2108 && (typeOfInterest != gIOPriorityPowerStateInterest)) {
2109 return kIOReturnBadArgument;
2110 }
2111
2112 lockForArbitration();
2113 if (0 == (__state[0] & kIOServiceInactiveState)) {
2114 notify->state = kIOServiceNotifyEnable;
2115
2116 ////// queue
2117
2118 LOCKWRITENOTIFY();
2119
2120 // Get the head of the notifier linked list
2121 IOCommand * notifyList;
2122 OSObject * obj = copyProperty( typeOfInterest );
2123 if (!(notifyList = OSDynamicCast(IOCommand, obj))) {
2124 notifyList = OSTypeAlloc(IOCommand);
2125 if (notifyList) {
2126 notifyList->init();
2127 bool ok = setProperty( typeOfInterest, notifyList);
2128 notifyList->release();
2129 if (!ok) {
2130 notifyList = NULL;
2131 }
2132 }
2133 }
2134 if (obj) {
2135 obj->release();
2136 }
2137
2138 if (notifyList) {
2139 enqueue(&notifyList->fCommandChain, &notify->chain);
2140 notify->retain(); // ref'ed while in list
2141 }
2142
2143 UNLOCKNOTIFY();
2144 } else {
2145 rc = kIOReturnNotReady;
2146 }
2147 unlockForArbitration();
2148
2149 return rc;
2150 }
2151
2152 static void
2153 cleanInterestList( OSObject * head )
2154 {
2155 IOCommand *notifyHead = OSDynamicCast(IOCommand, head);
2156 if (!notifyHead) {
2157 return;
2158 }
2159
2160 LOCKWRITENOTIFY();
2161 while (queue_entry_t entry = dequeue(&notifyHead->fCommandChain)) {
2162 queue_next(entry) = queue_prev(entry) = NULL;
2163
2164 _IOServiceInterestNotifier * notify;
2165
2166 queue_element(entry, notify, _IOServiceInterestNotifier *, chain);
2167 notify->release();
2168 }
2169 UNLOCKNOTIFY();
2170 }
2171
2172 void
2173 IOService::unregisterAllInterest( void )
2174 {
2175 OSObject * prop;
2176
2177 prop = copyProperty(gIOGeneralInterest);
2178 cleanInterestList(prop);
2179 OSSafeReleaseNULL(prop);
2180
2181 prop = copyProperty(gIOBusyInterest);
2182 cleanInterestList(prop);
2183 OSSafeReleaseNULL(prop);
2184
2185 prop = copyProperty(gIOAppPowerStateInterest);
2186 cleanInterestList(prop);
2187 OSSafeReleaseNULL(prop);
2188
2189 prop = copyProperty(gIOPriorityPowerStateInterest);
2190 cleanInterestList(prop);
2191 OSSafeReleaseNULL(prop);
2192
2193 prop = copyProperty(gIOConsoleSecurityInterest);
2194 cleanInterestList(prop);
2195 OSSafeReleaseNULL(prop);
2196 }
2197
2198 /*
2199 * _IOServiceInterestNotifier
2200 */
2201
2202 // wait for all threads, other than the current one,
2203 // to exit the handler
2204
2205 void
2206 _IOServiceInterestNotifier::wait()
2207 {
2208 _IOServiceNotifierInvocation * next;
2209 bool doWait;
2210
2211 do {
2212 doWait = false;
2213 queue_iterate( &handlerInvocations, next,
2214 _IOServiceNotifierInvocation *, link) {
2215 if (next->thread != current_thread()) {
2216 doWait = true;
2217 break;
2218 }
2219 }
2220 if (doWait) {
2221 state |= kIOServiceNotifyWaiter;
2222 SLEEPNOTIFY(this);
2223 }
2224 } while (doWait);
2225 }
2226
2227 void
2228 _IOServiceInterestNotifier::free()
2229 {
2230 assert( queue_empty( &handlerInvocations ));
2231
2232 if (handler == &IOServiceInterestHandlerToBlock) {
2233 Block_release(ref);
2234 }
2235
2236 OSObject::free();
2237 }
2238
2239 void
2240 _IOServiceInterestNotifier::remove()
2241 {
2242 LOCKWRITENOTIFY();
2243
2244 if (queue_next( &chain )) {
2245 remqueue(&chain);
2246 queue_next( &chain) = queue_prev( &chain) = NULL;
2247 release();
2248 }
2249
2250 state &= ~kIOServiceNotifyEnable;
2251
2252 wait();
2253
2254 UNLOCKNOTIFY();
2255
2256 release();
2257 }
2258
2259 bool
2260 _IOServiceInterestNotifier::disable()
2261 {
2262 bool ret;
2263
2264 LOCKWRITENOTIFY();
2265
2266 ret = (0 != (kIOServiceNotifyEnable & state));
2267 state &= ~kIOServiceNotifyEnable;
2268 if (ret) {
2269 wait();
2270 }
2271
2272 UNLOCKNOTIFY();
2273
2274 return ret;
2275 }
2276
2277 void
2278 _IOServiceInterestNotifier::enable( bool was )
2279 {
2280 LOCKWRITENOTIFY();
2281 if (was) {
2282 state |= kIOServiceNotifyEnable;
2283 } else {
2284 state &= ~kIOServiceNotifyEnable;
2285 }
2286 UNLOCKNOTIFY();
2287 }
2288
2289 bool
2290 _IOServiceInterestNotifier::init()
2291 {
2292 queue_init( &handlerInvocations );
2293 return OSObject::init();
2294 }
2295 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2296
2297 /*
2298 * Termination
2299 */
2300
2301 #define tailQ(o) setObject(o)
2302 #define headQ(o) setObject(0, o)
2303 #define TLOG(fmt, args...) { if(kIOLogYield & gIOKitDebug) { IOLog("[%llx] ", thread_tid(current_thread())); IOLog(fmt, ## args); }}
2304
2305 static void
2306 _workLoopAction( IOWorkLoop::Action action,
2307 IOService * service,
2308 void * p0 = NULL, void * p1 = NULL,
2309 void * p2 = NULL, void * p3 = NULL )
2310 {
2311 IOWorkLoop * wl;
2312
2313 if ((wl = service->getWorkLoop())) {
2314 wl->retain();
2315 wl->runAction( action, service, p0, p1, p2, p3 );
2316 wl->release();
2317 } else {
2318 (*action)( service, p0, p1, p2, p3 );
2319 }
2320 }
2321
2322 bool
2323 IOService::requestTerminate( IOService * provider, IOOptionBits options )
2324 {
2325 bool ok;
2326
2327 // if its our only provider
2328 ok = isParent( provider, gIOServicePlane, true);
2329
2330 // -- compat
2331 if (ok) {
2332 provider->terminateClient( this, options | kIOServiceRecursing );
2333 ok = (0 != (kIOServiceInactiveState & __state[0]));
2334 }
2335 // --
2336
2337 return ok;
2338 }
2339
2340 bool
2341 IOService::terminatePhase1( IOOptionBits options )
2342 {
2343 IOService * victim;
2344 IOService * client;
2345 IOService * rematchProvider;
2346 OSIterator * iter;
2347 OSArray * makeInactive;
2348 OSArray * waitingInactive;
2349 IOOptionBits callerOptions;
2350 int waitResult = THREAD_AWAKENED;
2351 bool wait;
2352 bool ok;
2353 bool didInactive;
2354 bool startPhase2 = false;
2355
2356 TLOG("%s[0x%qx]::terminatePhase1(%08llx)\n", getName(), getRegistryEntryID(), (long long)options);
2357
2358 callerOptions = options;
2359 rematchProvider = NULL;
2360 uint64_t regID = getRegistryEntryID();
2361 IOServiceTrace(
2362 IOSERVICE_TERMINATE_PHASE1,
2363 (uintptr_t) regID,
2364 (uintptr_t) (regID >> 32),
2365 (uintptr_t) this,
2366 (uintptr_t) options);
2367
2368 // -- compat
2369 if (options & kIOServiceRecursing) {
2370 lockForArbitration();
2371 if (0 == (kIOServiceInactiveState & __state[0])) {
2372 __state[0] |= kIOServiceInactiveState;
2373 __state[1] |= kIOServiceRecursing | kIOServiceTermPhase1State;
2374 }
2375 unlockForArbitration();
2376
2377 return true;
2378 }
2379 // --
2380
2381 makeInactive = OSArray::withCapacity( 16 );
2382 waitingInactive = OSArray::withCapacity( 16 );
2383 if (!makeInactive || !waitingInactive) {
2384 return false;
2385 }
2386
2387 victim = this;
2388 victim->retain();
2389
2390 while (victim) {
2391 didInactive = victim->lockForArbitration( true );
2392 if (didInactive) {
2393 uint64_t regID1 = victim->getRegistryEntryID();
2394 IOServiceTrace(IOSERVICE_TERM_SET_INACTIVE,
2395 (uintptr_t) regID1,
2396 (uintptr_t) (regID1 >> 32),
2397 (uintptr_t) victim->__state[1],
2398 (uintptr_t) 0);
2399
2400 enum { kRP1 = kIOServiceRecursing | kIOServiceTermPhase1State };
2401 didInactive = (kRP1 == (victim->__state[1] & kRP1))
2402 || (0 == (victim->__state[0] & kIOServiceInactiveState));
2403
2404 if (!didInactive) {
2405 // a multiply attached IOService can be visited twice
2406 if (-1U == waitingInactive->getNextIndexOfObject(victim, 0)) {
2407 do{
2408 IOLockLock(gIOServiceBusyLock);
2409 wait = (victim->__state[1] & kIOServiceTermPhase1State);
2410 if (wait) {
2411 TLOG("%s[0x%qx]::waitPhase1(%s[0x%qx])\n",
2412 getName(), getRegistryEntryID(), victim->getName(), victim->getRegistryEntryID());
2413 victim->__state[1] |= kIOServiceTerm1WaiterState;
2414 victim->unlockForArbitration();
2415 assert_wait((event_t)&victim->__state[1], THREAD_UNINT);
2416 }
2417 IOLockUnlock(gIOServiceBusyLock);
2418 if (wait) {
2419 waitResult = thread_block(THREAD_CONTINUE_NULL);
2420 TLOG("%s[0x%qx]::did waitPhase1(%s[0x%qx])\n",
2421 getName(), getRegistryEntryID(), victim->getName(), victim->getRegistryEntryID());
2422 victim->lockForArbitration();
2423 }
2424 }while (wait && (waitResult != THREAD_TIMED_OUT));
2425 }
2426 } else {
2427 victim->__state[0] |= kIOServiceInactiveState;
2428 victim->__state[0] &= ~(kIOServiceRegisteredState | kIOServiceMatchedState
2429 | kIOServiceFirstPublishState | kIOServiceFirstMatchState);
2430 victim->__state[1] &= ~kIOServiceRecursing;
2431 victim->__state[1] |= kIOServiceTermPhase1State;
2432 waitingInactive->headQ(victim);
2433 if (victim == this) {
2434 if (kIOServiceTerminateNeedWillTerminate & options) {
2435 victim->__state[1] |= kIOServiceNeedWillTerminate;
2436 }
2437 }
2438 victim->_adjustBusy( 1 );
2439
2440 if ((options & kIOServiceTerminateWithRematch) && (victim == this)) {
2441 OSObject * obj;
2442 OSObject * rematchProps;
2443 OSNumber * num;
2444 uint32_t count;
2445
2446 rematchProvider = getProvider();
2447 if (rematchProvider) {
2448 obj = rematchProvider->copyProperty(gIORematchCountKey);
2449 num = OSDynamicCast(OSNumber, obj);
2450 count = 0;
2451 if (num) {
2452 count = num->unsigned32BitValue();
2453 count++;
2454 }
2455 num = OSNumber::withNumber(count, 32);
2456 rematchProvider->setProperty(gIORematchCountKey, num);
2457 rematchProps = copyProperty(gIOMatchedPersonalityKey);
2458 rematchProvider->setProperty(gIORematchPersonalityKey, rematchProps);
2459 OSSafeReleaseNULL(num);
2460 OSSafeReleaseNULL(rematchProps);
2461 OSSafeReleaseNULL(obj);
2462 }
2463 }
2464 }
2465 victim->unlockForArbitration();
2466 }
2467 if (victim == this) {
2468 options &= ~kIOServiceTerminateWithRematch;
2469 startPhase2 = didInactive;
2470 }
2471 if (didInactive) {
2472 OSArray * notifiers;
2473 notifiers = victim->copyNotifiers(gIOTerminatedNotification, 0, 0xffffffff);
2474 victim->invokeNotifiers(&notifiers);
2475
2476 IOUserClient::destroyUserReferences( victim );
2477
2478 iter = victim->getClientIterator();
2479 if (iter) {
2480 while ((client = (IOService *) iter->getNextObject())) {
2481 TLOG("%s[0x%qx]::requestTerminate(%s[0x%qx], %08llx)\n",
2482 client->getName(), client->getRegistryEntryID(),
2483 victim->getName(), victim->getRegistryEntryID(), (long long)options);
2484 ok = client->requestTerminate( victim, options );
2485 TLOG("%s[0x%qx]::requestTerminate(%s[0x%qx], ok = %d)\n",
2486 client->getName(), client->getRegistryEntryID(),
2487 victim->getName(), victim->getRegistryEntryID(), ok);
2488
2489 uint64_t regID1 = client->getRegistryEntryID();
2490 uint64_t regID2 = victim->getRegistryEntryID();
2491 IOServiceTrace(
2492 (ok ? IOSERVICE_TERMINATE_REQUEST_OK
2493 : IOSERVICE_TERMINATE_REQUEST_FAIL),
2494 (uintptr_t) regID1,
2495 (uintptr_t) (regID1 >> 32),
2496 (uintptr_t) regID2,
2497 (uintptr_t) (regID2 >> 32));
2498
2499 if (ok) {
2500 makeInactive->setObject( client );
2501 }
2502 }
2503 iter->release();
2504 }
2505 }
2506 victim->release();
2507 victim = (IOService *) makeInactive->getObject(0);
2508 if (victim) {
2509 victim->retain();
2510 makeInactive->removeObject(0);
2511 }
2512 }
2513 makeInactive->release();
2514
2515 while ((victim = (IOService *) waitingInactive->getObject(0))) {
2516 victim->retain();
2517 waitingInactive->removeObject(0);
2518
2519 victim->lockForArbitration();
2520 victim->__state[1] &= ~kIOServiceTermPhase1State;
2521 if (kIOServiceTerm1WaiterState & victim->__state[1]) {
2522 victim->__state[1] &= ~kIOServiceTerm1WaiterState;
2523 TLOG("%s[0x%qx]::wakePhase1\n", victim->getName(), victim->getRegistryEntryID());
2524 IOLockLock( gIOServiceBusyLock );
2525 thread_wakeup((event_t) &victim->__state[1]);
2526 IOLockUnlock( gIOServiceBusyLock );
2527 }
2528 victim->unlockForArbitration();
2529 victim->release();
2530 }
2531 waitingInactive->release();
2532
2533 if (startPhase2) {
2534 retain();
2535 lockForArbitration();
2536 scheduleTerminatePhase2(options);
2537 unlockForArbitration();
2538 release();
2539 }
2540
2541 if (rematchProvider) {
2542 DKLOG(DKS " rematching after dext crash\n", DKN(rematchProvider));
2543 rematchProvider->registerService();
2544 }
2545
2546 return true;
2547 }
2548
2549 void
2550 IOService::setTerminateDefer(IOService * provider, bool defer)
2551 {
2552 lockForArbitration();
2553 if (defer) {
2554 __state[1] |= kIOServiceStartState;
2555 } else {
2556 __state[1] &= ~kIOServiceStartState;
2557 }
2558 unlockForArbitration();
2559
2560 if (provider && !defer) {
2561 provider->lockForArbitration();
2562 provider->scheduleTerminatePhase2();
2563 provider->unlockForArbitration();
2564 }
2565 }
2566
2567 // Must call this while holding gJobsLock
2568 void
2569 IOService::waitToBecomeTerminateThread(void)
2570 {
2571 IOLockAssert(gJobsLock, kIOLockAssertOwned);
2572 bool wait;
2573 do {
2574 wait = (gIOTerminateThread != THREAD_NULL);
2575 if (wait) {
2576 IOLockSleep(gJobsLock, &gIOTerminateThread, THREAD_UNINT);
2577 }
2578 } while (wait);
2579 gIOTerminateThread = current_thread();
2580 }
2581
2582 // call with lockForArbitration
2583 void
2584 IOService::scheduleTerminatePhase2( IOOptionBits options )
2585 {
2586 AbsoluteTime deadline;
2587 uint64_t regID1;
2588 int waitResult = THREAD_AWAKENED;
2589 bool wait = false, haveDeadline = false;
2590
2591 if (!(__state[0] & kIOServiceInactiveState)) {
2592 return;
2593 }
2594
2595 regID1 = getRegistryEntryID();
2596 IOServiceTrace(
2597 IOSERVICE_TERM_SCHED_PHASE2,
2598 (uintptr_t) regID1,
2599 (uintptr_t) (regID1 >> 32),
2600 (uintptr_t) __state[1],
2601 (uintptr_t) options);
2602
2603 if (__state[1] & kIOServiceTermPhase1State) {
2604 return;
2605 }
2606
2607 retain();
2608 unlockForArbitration();
2609 options |= kIOServiceRequired;
2610 IOLockLock( gJobsLock );
2611
2612 if ((options & kIOServiceSynchronous)
2613 && (current_thread() != gIOTerminateThread)) {
2614 waitToBecomeTerminateThread();
2615 gIOTerminatePhase2List->setObject( this );
2616 gIOTerminateWork++;
2617
2618 do {
2619 while (gIOTerminateWork) {
2620 terminateWorker( options );
2621 }
2622 wait = (0 != (__state[1] & kIOServiceBusyStateMask));
2623 if (wait) {
2624 /* wait for the victim to go non-busy */
2625 if (!haveDeadline) {
2626 clock_interval_to_deadline( 15, kSecondScale, &deadline );
2627 haveDeadline = true;
2628 }
2629 /* let others do work while we wait */
2630 gIOTerminateThread = NULL;
2631 IOLockWakeup( gJobsLock, (event_t) &gIOTerminateThread, /* one-thread */ false);
2632 waitResult = IOLockSleepDeadline( gJobsLock, &gIOTerminateWork,
2633 deadline, THREAD_UNINT );
2634 if (__improbable(waitResult == THREAD_TIMED_OUT)) {
2635 IOLog("%s[0x%qx]::terminate(kIOServiceSynchronous): THREAD_TIMED_OUT. "
2636 "Attempting to auto-resolve your deadlock. PLEASE FIX!\n", getName(), getRegistryEntryID());
2637 }
2638 waitToBecomeTerminateThread();
2639 }
2640 } while (gIOTerminateWork || (wait && (waitResult != THREAD_TIMED_OUT)));
2641
2642 gIOTerminateThread = NULL;
2643 IOLockWakeup( gJobsLock, (event_t) &gIOTerminateThread, /* one-thread */ false);
2644 } else {
2645 // ! kIOServiceSynchronous
2646
2647 gIOTerminatePhase2List->setObject( this );
2648 if (0 == gIOTerminateWork++) {
2649 assert(gIOTerminateWorkerThread);
2650 IOLockWakeup(gJobsLock, (event_t)&gIOTerminateWork, /* one-thread */ false );
2651 }
2652 }
2653
2654 IOLockUnlock( gJobsLock );
2655 lockForArbitration();
2656 release();
2657 }
2658
2659 __attribute__((__noreturn__))
2660 void
2661 IOService::terminateThread( void * arg, wait_result_t waitResult )
2662 {
2663 // IOLockSleep re-acquires the lock on wakeup, so we only need to do this once
2664 IOLockLock(gJobsLock);
2665 while (true) {
2666 if (gIOTerminateThread != gIOTerminateWorkerThread) {
2667 waitToBecomeTerminateThread();
2668 }
2669
2670 while (gIOTerminateWork) {
2671 terminateWorker((uintptr_t)arg );
2672 }
2673
2674 gIOTerminateThread = NULL;
2675 IOLockWakeup( gJobsLock, (event_t) &gIOTerminateThread, /* one-thread */ false);
2676 IOLockSleep(gJobsLock, &gIOTerminateWork, THREAD_UNINT);
2677 }
2678 }
2679
2680 void
2681 IOService::scheduleStop( IOService * provider )
2682 {
2683 uint64_t regID1 = getRegistryEntryID();
2684 uint64_t regID2 = provider->getRegistryEntryID();
2685
2686 TLOG("%s[0x%qx]::scheduleStop(%s[0x%qx])\n", getName(), regID1, provider->getName(), regID2);
2687 IOServiceTrace(
2688 IOSERVICE_TERMINATE_SCHEDULE_STOP,
2689 (uintptr_t) regID1,
2690 (uintptr_t) (regID1 >> 32),
2691 (uintptr_t) regID2,
2692 (uintptr_t) (regID2 >> 32));
2693
2694 IOLockLock( gJobsLock );
2695 gIOStopList->tailQ( this );
2696 gIOStopProviderList->tailQ( provider );
2697
2698 if (0 == gIOTerminateWork++) {
2699 assert(gIOTerminateWorkerThread);
2700 IOLockWakeup(gJobsLock, (event_t)&gIOTerminateWork, /* one-thread */ false );
2701 }
2702
2703 IOLockUnlock( gJobsLock );
2704 }
2705
2706 void
2707 IOService::scheduleFinalize(bool now)
2708 {
2709 uint64_t regID1 = getRegistryEntryID();
2710
2711 TLOG("%s[0x%qx]::scheduleFinalize\n", getName(), regID1);
2712 IOServiceTrace(
2713 IOSERVICE_TERMINATE_SCHEDULE_FINALIZE,
2714 (uintptr_t) regID1,
2715 (uintptr_t) (regID1 >> 32),
2716 0, 0);
2717
2718 if (now || IOUserClient::finalizeUserReferences(this)) {
2719 IOLockLock( gJobsLock );
2720 gIOFinalizeList->tailQ(this);
2721 if (0 == gIOTerminateWork++) {
2722 assert(gIOTerminateWorkerThread);
2723 IOLockWakeup(gJobsLock, (event_t)&gIOTerminateWork, /* one-thread */ false );
2724 }
2725 IOLockUnlock( gJobsLock );
2726 }
2727 }
2728
2729 bool
2730 IOService::willTerminate( IOService * provider, IOOptionBits options )
2731 {
2732 if (reserved->uvars) {
2733 IOUserServer::serviceWillTerminate(this, provider, options);
2734 }
2735 return true;
2736 }
2737
2738 bool
2739 IOService::didTerminate( IOService * provider, IOOptionBits options, bool * defer )
2740 {
2741 if (reserved->uvars) {
2742 IOUserServer::serviceDidTerminate(this, provider, options, defer);
2743 }
2744
2745 if (false == *defer) {
2746 if (lockForArbitration( true )) {
2747 if (false == provider->handleIsOpen( this )) {
2748 scheduleStop( provider );
2749 }
2750 // -- compat
2751 else {
2752 message( kIOMessageServiceIsRequestingClose, provider, (void *)(uintptr_t) options );
2753 if (false == provider->handleIsOpen( this )) {
2754 scheduleStop( provider );
2755 }
2756 }
2757 // --
2758 unlockForArbitration();
2759 }
2760 }
2761
2762 return true;
2763 }
2764
2765 void
2766 IOService::actionWillTerminate( IOService * victim, IOOptionBits options,
2767 OSArray * doPhase2List,
2768 bool user,
2769 void *unused3 __unused)
2770 {
2771 OSIterator * iter;
2772 IOService * client;
2773 bool ok;
2774 uint64_t regID1, regID2 = victim->getRegistryEntryID();
2775
2776 iter = victim->getClientIterator();
2777 if (iter) {
2778 while ((client = (IOService *) iter->getNextObject())) {
2779 if (user != (NULL != client->reserved->uvars)) {
2780 continue;
2781 }
2782 regID1 = client->getRegistryEntryID();
2783 TLOG("%s[0x%qx]::willTerminate(%s[0x%qx], %08llx)\n",
2784 client->getName(), regID1,
2785 victim->getName(), regID2, (long long)options);
2786 IOServiceTrace(
2787 IOSERVICE_TERMINATE_WILL,
2788 (uintptr_t) regID1,
2789 (uintptr_t) (regID1 >> 32),
2790 (uintptr_t) regID2,
2791 (uintptr_t) (regID2 >> 32));
2792
2793 ok = client->willTerminate( victim, options );
2794 doPhase2List->tailQ( client );
2795 }
2796 iter->release();
2797 }
2798 }
2799
2800 void
2801 IOService::actionDidTerminate( IOService * victim, IOOptionBits options,
2802 void *unused1 __unused, void *unused2 __unused,
2803 void *unused3 __unused )
2804 {
2805 OSIterator * iter;
2806 IOService * client;
2807 bool defer;
2808 uint64_t regID1, regID2 = victim->getRegistryEntryID();
2809
2810 victim->messageClients( kIOMessageServiceIsTerminated, (void *)(uintptr_t) options );
2811
2812 iter = victim->getClientIterator();
2813 if (iter) {
2814 while ((client = (IOService *) iter->getNextObject())) {
2815 regID1 = client->getRegistryEntryID();
2816 TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], %08llx)\n",
2817 client->getName(), regID1,
2818 victim->getName(), regID2, (long long)options);
2819 defer = false;
2820 client->didTerminate( victim, options, &defer );
2821
2822 IOServiceTrace(
2823 (defer ? IOSERVICE_TERMINATE_DID_DEFER
2824 : IOSERVICE_TERMINATE_DID),
2825 (uintptr_t) regID1,
2826 (uintptr_t) (regID1 >> 32),
2827 (uintptr_t) regID2,
2828 (uintptr_t) (regID2 >> 32));
2829
2830 TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], defer %d)\n",
2831 client->getName(), regID1,
2832 victim->getName(), regID2, defer);
2833 }
2834 iter->release();
2835 }
2836 }
2837
2838
2839 void
2840 IOService::actionWillStop( IOService * victim, IOOptionBits options,
2841 void *unused1 __unused, void *unused2 __unused,
2842 void *unused3 __unused )
2843 {
2844 OSIterator * iter;
2845 IOService * provider;
2846 bool ok;
2847 uint64_t regID1, regID2 = victim->getRegistryEntryID();
2848
2849 iter = victim->getProviderIterator();
2850 if (iter) {
2851 while ((provider = (IOService *) iter->getNextObject())) {
2852 regID1 = provider->getRegistryEntryID();
2853 TLOG("%s[0x%qx]::willTerminate(%s[0x%qx], %08llx)\n",
2854 victim->getName(), regID2,
2855 provider->getName(), regID1, (long long)options);
2856 IOServiceTrace(
2857 IOSERVICE_TERMINATE_WILL,
2858 (uintptr_t) regID2,
2859 (uintptr_t) (regID2 >> 32),
2860 (uintptr_t) regID1,
2861 (uintptr_t) (regID1 >> 32));
2862
2863 ok = victim->willTerminate( provider, options );
2864 }
2865 iter->release();
2866 }
2867 }
2868
2869 void
2870 IOService::actionDidStop( IOService * victim, IOOptionBits options,
2871 void *unused1 __unused, void *unused2 __unused,
2872 void *unused3 __unused )
2873 {
2874 OSIterator * iter;
2875 IOService * provider;
2876 bool defer = false;
2877 uint64_t regID1, regID2 = victim->getRegistryEntryID();
2878
2879 iter = victim->getProviderIterator();
2880 if (iter) {
2881 while ((provider = (IOService *) iter->getNextObject())) {
2882 regID1 = provider->getRegistryEntryID();
2883 TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], %08llx)\n",
2884 victim->getName(), regID2,
2885 provider->getName(), regID1, (long long)options);
2886 victim->didTerminate( provider, options, &defer );
2887
2888 IOServiceTrace(
2889 (defer ? IOSERVICE_TERMINATE_DID_DEFER
2890 : IOSERVICE_TERMINATE_DID),
2891 (uintptr_t) regID2,
2892 (uintptr_t) (regID2 >> 32),
2893 (uintptr_t) regID1,
2894 (uintptr_t) (regID1 >> 32));
2895
2896 TLOG("%s[0x%qx]::didTerminate(%s[0x%qx], defer %d)\n",
2897 victim->getName(), regID2,
2898 provider->getName(), regID1, defer);
2899 }
2900 iter->release();
2901 }
2902 }
2903
2904
2905 void
2906 IOService::actionFinalize( IOService * victim, IOOptionBits options,
2907 void *unused1 __unused, void *unused2 __unused,
2908 void *unused3 __unused )
2909 {
2910 uint64_t regID1 = victim->getRegistryEntryID();
2911 TLOG("%s[0x%qx]::finalize(%08llx)\n", victim->getName(), regID1, (long long)options);
2912 IOServiceTrace(
2913 IOSERVICE_TERMINATE_FINALIZE,
2914 (uintptr_t) regID1,
2915 (uintptr_t) (regID1 >> 32),
2916 0, 0);
2917
2918 victim->finalize( options );
2919 }
2920
2921 void
2922 IOService::actionStop( IOService * provider, IOService * client,
2923 void *unused1 __unused, void *unused2 __unused,
2924 void *unused3 __unused )
2925 {
2926 uint64_t regID1 = provider->getRegistryEntryID();
2927 uint64_t regID2 = client->getRegistryEntryID();
2928
2929 TLOG("%s[0x%qx]::stop(%s[0x%qx])\n", client->getName(), regID2, provider->getName(), regID1);
2930 IOServiceTrace(
2931 IOSERVICE_TERMINATE_STOP,
2932 (uintptr_t) regID1,
2933 (uintptr_t) (regID1 >> 32),
2934 (uintptr_t) regID2,
2935 (uintptr_t) (regID2 >> 32));
2936
2937 client->stop( provider );
2938 if (provider->isOpen( client )) {
2939 provider->close( client );
2940 }
2941
2942 TLOG("%s[0x%qx]::detach(%s[0x%qx])\n", client->getName(), regID2, provider->getName(), regID1);
2943 client->detach( provider );
2944 }
2945
2946 void
2947 IOService::terminateWorker( IOOptionBits options )
2948 {
2949 OSArray * doPhase2List;
2950 OSArray * didPhase2List;
2951 OSSet * freeList;
2952 OSIterator * iter;
2953 UInt32 workDone;
2954 IOService * victim;
2955 IOService * client;
2956 IOService * provider;
2957 unsigned int idx;
2958 bool moreToDo;
2959 bool doPhase2;
2960 bool doPhase3;
2961
2962 options |= kIOServiceRequired;
2963
2964 doPhase2List = OSArray::withCapacity( 16 );
2965 didPhase2List = OSArray::withCapacity( 16 );
2966 freeList = OSSet::withCapacity( 16 );
2967 if ((NULL == doPhase2List) || (NULL == didPhase2List) || (NULL == freeList)) {
2968 return;
2969 }
2970
2971 do {
2972 workDone = gIOTerminateWork;
2973
2974 while ((victim = (IOService *) gIOTerminatePhase2List->getObject(0))) {
2975 victim->retain();
2976 gIOTerminatePhase2List->removeObject(0);
2977 IOLockUnlock( gJobsLock );
2978
2979 uint64_t regID1 = victim->getRegistryEntryID();
2980 IOServiceTrace(
2981 IOSERVICE_TERM_START_PHASE2,
2982 (uintptr_t) regID1,
2983 (uintptr_t) (regID1 >> 32),
2984 (uintptr_t) 0,
2985 (uintptr_t) 0);
2986
2987 while (victim) {
2988 doPhase2 = victim->lockForArbitration( true );
2989 if (doPhase2) {
2990 doPhase2 = (0 != (kIOServiceInactiveState & victim->__state[0]));
2991 if (doPhase2) {
2992 uint64_t regID1 = victim->getRegistryEntryID();
2993 IOServiceTrace(
2994 IOSERVICE_TERM_TRY_PHASE2,
2995 (uintptr_t) regID1,
2996 (uintptr_t) (regID1 >> 32),
2997 (uintptr_t) victim->__state[1],
2998 (uintptr_t) 0);
2999
3000 doPhase2 = (0 == (victim->__state[1] &
3001 (kIOServiceTermPhase1State
3002 | kIOServiceTermPhase2State
3003 | kIOServiceConfigState)));
3004
3005 if (doPhase2 && (iter = victim->getClientIterator())) {
3006 while (doPhase2 && (client = (IOService *) iter->getNextObject())) {
3007 doPhase2 = (0 == (client->__state[1] & kIOServiceStartState));
3008 if (!doPhase2) {
3009 uint64_t regID1 = client->getRegistryEntryID();
3010 IOServiceTrace(
3011 IOSERVICE_TERM_UC_DEFER,
3012 (uintptr_t) regID1,
3013 (uintptr_t) (regID1 >> 32),
3014 (uintptr_t) client->__state[1],
3015 (uintptr_t) 0);
3016 TLOG("%s[0x%qx]::defer phase2(%s[0x%qx])\n",
3017 victim->getName(), victim->getRegistryEntryID(),
3018 client->getName(), client->getRegistryEntryID());
3019 }
3020 }
3021 iter->release();
3022 }
3023 if (doPhase2) {
3024 victim->__state[1] |= kIOServiceTermPhase2State;
3025 }
3026 }
3027 victim->unlockForArbitration();
3028 }
3029 if (doPhase2) {
3030 if (kIOServiceNeedWillTerminate & victim->__state[1]) {
3031 if (NULL == victim->reserved->uvars) {
3032 _workLoopAction((IOWorkLoop::Action) &actionWillStop,
3033 victim, (void *)(uintptr_t) options);
3034 } else {
3035 actionWillStop(victim, options, NULL, NULL, NULL);
3036 }
3037 }
3038
3039 OSArray * notifiers;
3040 notifiers = victim->copyNotifiers(gIOWillTerminateNotification, 0, 0xffffffff);
3041 victim->invokeNotifiers(&notifiers);
3042
3043 _workLoopAction((IOWorkLoop::Action) &actionWillTerminate,
3044 victim,
3045 (void *)(uintptr_t) options,
3046 (void *)(uintptr_t) doPhase2List,
3047 (void *)(uintptr_t) false);
3048
3049 actionWillTerminate(
3050 victim, options, doPhase2List, true, NULL);
3051
3052 didPhase2List->headQ( victim );
3053 }
3054 victim->release();
3055 victim = (IOService *) doPhase2List->getObject(0);
3056 if (victim) {
3057 victim->retain();
3058 doPhase2List->removeObject(0);
3059 }
3060 }
3061
3062 while ((victim = (IOService *) didPhase2List->getObject(0))) {
3063 bool scheduleFinalize = false;
3064 if (victim->lockForArbitration( true )) {
3065 victim->__state[1] |= kIOServiceTermPhase3State;
3066 scheduleFinalize = (NULL == victim->getClient());
3067 victim->unlockForArbitration();
3068 }
3069 _workLoopAction((IOWorkLoop::Action) &actionDidTerminate,
3070 victim, (void *)(uintptr_t) options );
3071 if (kIOServiceNeedWillTerminate & victim->__state[1]) {
3072 _workLoopAction((IOWorkLoop::Action) &actionDidStop,
3073 victim, (void *)(uintptr_t) options, NULL );
3074 }
3075 // no clients - will go to finalize
3076 if (scheduleFinalize) {
3077 victim->scheduleFinalize(false);
3078 }
3079 didPhase2List->removeObject(0);
3080 }
3081 IOLockLock( gJobsLock );
3082 }
3083
3084 // phase 3
3085 do {
3086 doPhase3 = false;
3087 // finalize leaves
3088 while ((victim = (IOService *) gIOFinalizeList->getObject(0))) {
3089 bool sendFinal = false;
3090 IOLockUnlock( gJobsLock );
3091 if (victim->lockForArbitration(true)) {
3092 sendFinal = (0 == (victim->__state[1] & kIOServiceFinalized));
3093 if (sendFinal) {
3094 victim->__state[1] |= kIOServiceFinalized;
3095 }
3096 victim->unlockForArbitration();
3097 }
3098 if (sendFinal) {
3099 _workLoopAction((IOWorkLoop::Action) &actionFinalize,
3100 victim, (void *)(uintptr_t) options );
3101 }
3102 IOLockLock( gJobsLock );
3103 // hold off free
3104 freeList->setObject( victim );
3105 // safe if finalize list is append only
3106 gIOFinalizeList->removeObject(0);
3107 }
3108
3109 for (idx = 0;
3110 (!doPhase3) && (client = (IOService *) gIOStopList->getObject(idx));) {
3111 provider = (IOService *) gIOStopProviderList->getObject(idx);
3112 assert( provider );
3113
3114 uint64_t regID1 = provider->getRegistryEntryID();
3115 uint64_t regID2 = client->getRegistryEntryID();
3116
3117 if (!provider->isChild( client, gIOServicePlane )) {
3118 // may be multiply queued - nop it
3119 TLOG("%s[0x%qx]::nop stop(%s[0x%qx])\n", client->getName(), regID2, provider->getName(), regID1);
3120 IOServiceTrace(
3121 IOSERVICE_TERMINATE_STOP_NOP,
3122 (uintptr_t) regID1,
3123 (uintptr_t) (regID1 >> 32),
3124 (uintptr_t) regID2,
3125 (uintptr_t) (regID2 >> 32));
3126 } else {
3127 // a terminated client is not ready for stop if it has clients, skip it
3128 bool deferStop = (0 != (kIOServiceInactiveState & client->__state[0]));
3129 IOLockUnlock( gJobsLock );
3130 if (deferStop && client->lockForArbitration(true)) {
3131 deferStop = (0 == (client->__state[1] & kIOServiceFinalized));
3132 //deferStop = (!deferStop && (0 != client->getClient()));
3133 //deferStop = (0 != client->getClient());
3134 client->unlockForArbitration();
3135 if (deferStop) {
3136 TLOG("%s[0x%qx]::defer stop()\n", client->getName(), regID2);
3137 IOServiceTrace(IOSERVICE_TERMINATE_STOP_DEFER,
3138 (uintptr_t) regID1,
3139 (uintptr_t) (regID1 >> 32),
3140 (uintptr_t) regID2,
3141 (uintptr_t) (regID2 >> 32));
3142
3143 idx++;
3144 IOLockLock( gJobsLock );
3145 continue;
3146 }
3147 }
3148 _workLoopAction((IOWorkLoop::Action) &actionStop,
3149 provider, (void *) client );
3150 IOLockLock( gJobsLock );
3151 // check the finalize list now
3152 doPhase3 = true;
3153 }
3154 // hold off free
3155 freeList->setObject( client );
3156 freeList->setObject( provider );
3157
3158 // safe if stop list is append only
3159 gIOStopList->removeObject( idx );
3160 gIOStopProviderList->removeObject( idx );
3161 idx = 0;
3162 }
3163 } while (doPhase3);
3164
3165 gIOTerminateWork -= workDone;
3166 moreToDo = (gIOTerminateWork != 0);
3167
3168 if (!moreToDo) {
3169 TLOG("iokit terminate done, %d stops remain\n", gIOStopList->getCount());
3170 IOServiceTrace(
3171 IOSERVICE_TERMINATE_DONE,
3172 (uintptr_t) gIOStopList->getCount(), 0, 0, 0);
3173 }
3174 } while (moreToDo);
3175
3176 IOLockUnlock( gJobsLock );
3177
3178 freeList->release();
3179 doPhase2List->release();
3180 didPhase2List->release();
3181
3182 IOLockLock( gJobsLock );
3183 }
3184
3185 bool
3186 IOService::finalize( IOOptionBits options )
3187 {
3188 OSIterator * iter;
3189 IOService * provider;
3190 uint64_t regID1, regID2 = getRegistryEntryID();
3191
3192 iter = getProviderIterator();
3193 assert( iter );
3194
3195 if (iter) {
3196 while ((provider = (IOService *) iter->getNextObject())) {
3197 // -- compat
3198 if (0 == (__state[1] & kIOServiceTermPhase3State)) {
3199 /* we come down here on programmatic terminate */
3200
3201 regID1 = provider->getRegistryEntryID();
3202 TLOG("%s[0x%qx]::stop1(%s[0x%qx])\n", getName(), regID2, provider->getName(), regID1);
3203 IOServiceTrace(
3204 IOSERVICE_TERMINATE_STOP,
3205 (uintptr_t) regID1,
3206 (uintptr_t) (regID1 >> 32),
3207 (uintptr_t) regID2,
3208 (uintptr_t) (regID2 >> 32));
3209
3210 stop( provider );
3211 if (provider->isOpen( this )) {
3212 provider->close( this );
3213 }
3214 detach( provider );
3215 } else {
3216 //--
3217 if (provider->lockForArbitration( true )) {
3218 if (0 == (provider->__state[1] & kIOServiceTermPhase3State)) {
3219 scheduleStop( provider );
3220 }
3221 provider->unlockForArbitration();
3222 }
3223 }
3224 }
3225 iter->release();
3226 }
3227
3228 return true;
3229 }
3230
3231 #undef tailQ
3232 #undef headQ
3233
3234 /*
3235 * Terminate
3236 */
3237
3238 void
3239 IOService::doServiceTerminate( IOOptionBits options )
3240 {
3241 }
3242
3243 // a method in case someone needs to override it
3244 bool
3245 IOService::terminateClient( IOService * client, IOOptionBits options )
3246 {
3247 bool ok;
3248
3249 if (client->isParent( this, gIOServicePlane, true)) {
3250 // we are the clients only provider
3251 ok = client->terminate( options );
3252 } else {
3253 ok = true;
3254 }
3255
3256 return ok;
3257 }
3258
3259 bool
3260 IOService::terminate( IOOptionBits options )
3261 {
3262 options |= kIOServiceTerminate;
3263
3264 return terminatePhase1( options );
3265 }
3266
3267 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3268
3269 /*
3270 * Open & close
3271 */
3272
3273 struct ServiceOpenMessageContext {
3274 IOService * service;
3275 UInt32 type;
3276 IOService * excludeClient;
3277 IOOptionBits options;
3278 };
3279
3280 static void
3281 serviceOpenMessageApplier( OSObject * object, void * ctx )
3282 {
3283 ServiceOpenMessageContext * context = (ServiceOpenMessageContext *) ctx;
3284
3285 if (object != context->excludeClient) {
3286 context->service->messageClient( context->type, object, (void *)(uintptr_t) context->options );
3287 }
3288 }
3289
3290 bool
3291 IOService::open( IOService * forClient,
3292 IOOptionBits options,
3293 void * arg )
3294 {
3295 bool ok;
3296 ServiceOpenMessageContext context;
3297
3298 context.service = this;
3299 context.type = kIOMessageServiceIsAttemptingOpen;
3300 context.excludeClient = forClient;
3301 context.options = options;
3302
3303 applyToInterested( gIOGeneralInterest,
3304 &serviceOpenMessageApplier, &context );
3305
3306 if (false == lockForArbitration(false)) {
3307 return false;
3308 }
3309
3310 ok = (0 == (__state[0] & kIOServiceInactiveState));
3311 if (ok) {
3312 ok = handleOpen( forClient, options, arg );
3313 }
3314
3315 if (ok && forClient && forClient->reserved->uvars && forClient->reserved->uvars->userServer) {
3316 forClient->reserved->uvars->userServer->serviceOpen(this, forClient);
3317 }
3318
3319 unlockForArbitration();
3320
3321 return ok;
3322 }
3323
3324 void
3325 IOService::close( IOService * forClient,
3326 IOOptionBits options )
3327 {
3328 bool wasClosed;
3329 bool last = false;
3330
3331 lockForArbitration();
3332
3333 wasClosed = handleIsOpen( forClient );
3334 if (wasClosed) {
3335 handleClose( forClient, options );
3336 last = (__state[1] & kIOServiceTermPhase3State);
3337
3338 if (forClient && forClient->reserved->uvars && forClient->reserved->uvars->userServer) {
3339 forClient->reserved->uvars->userServer->serviceClose(this, forClient);
3340 }
3341 }
3342
3343 unlockForArbitration();
3344
3345 if (last) {
3346 forClient->scheduleStop( this );
3347 } else if (wasClosed) {
3348 ServiceOpenMessageContext context;
3349
3350 context.service = this;
3351 context.type = kIOMessageServiceWasClosed;
3352 context.excludeClient = forClient;
3353 context.options = options;
3354
3355 applyToInterested( gIOGeneralInterest,
3356 &serviceOpenMessageApplier, &context );
3357 }
3358 }
3359
3360 bool
3361 IOService::isOpen( const IOService * forClient ) const
3362 {
3363 IOService * self = (IOService *) this;
3364 bool ok;
3365
3366 self->lockForArbitration();
3367
3368 ok = handleIsOpen( forClient );
3369
3370 self->unlockForArbitration();
3371
3372 return ok;
3373 }
3374
3375 bool
3376 IOService::handleOpen( IOService * forClient,
3377 IOOptionBits options,
3378 void * arg )
3379 {
3380 bool ok;
3381
3382 ok = (NULL == __owner);
3383 if (ok) {
3384 __owner = forClient;
3385 } else if (options & kIOServiceSeize) {
3386 ok = (kIOReturnSuccess == messageClient( kIOMessageServiceIsRequestingClose,
3387 __owner, (void *)(uintptr_t) options ));
3388 if (ok && (NULL == __owner)) {
3389 __owner = forClient;
3390 } else {
3391 ok = false;
3392 }
3393 }
3394 return ok;
3395 }
3396
3397 void
3398 IOService::handleClose( IOService * forClient,
3399 IOOptionBits options )
3400 {
3401 if (__owner == forClient) {
3402 __owner = NULL;
3403 }
3404 }
3405
3406 bool
3407 IOService::handleIsOpen( const IOService * forClient ) const
3408 {
3409 if (forClient) {
3410 return __owner == forClient;
3411 } else {
3412 return __owner != forClient;
3413 }
3414 }
3415
3416 /*
3417 * Probing & starting
3418 */
3419 static SInt32
3420 IONotifyOrdering( const OSMetaClassBase * inObj1, const OSMetaClassBase * inObj2, void * ref )
3421 {
3422 const _IOServiceNotifier * obj1 = (const _IOServiceNotifier *) inObj1;
3423 const _IOServiceNotifier * obj2 = (const _IOServiceNotifier *) inObj2;
3424 SInt32 val1;
3425 SInt32 val2;
3426
3427 val1 = 0;
3428 val2 = 0;
3429
3430 if (obj1) {
3431 val1 = obj1->priority;
3432 }
3433
3434 if (obj2) {
3435 val2 = obj2->priority;
3436 }
3437
3438 return val1 - val2;
3439 }
3440
3441 static SInt32
3442 IOServiceObjectOrder( const OSObject * entry, void * ref)
3443 {
3444 OSDictionary * dict;
3445 IOService * service;
3446 _IOServiceNotifier * notify;
3447 OSSymbol * key = (OSSymbol *) ref;
3448 OSNumber * offset;
3449 OSObject * prop;
3450 SInt32 result;
3451
3452 prop = NULL;
3453 result = kIODefaultProbeScore;
3454 if ((dict = OSDynamicCast( OSDictionary, entry))) {
3455 offset = OSDynamicCast(OSNumber, dict->getObject( key ));
3456 } else if ((notify = OSDynamicCast( _IOServiceNotifier, entry))) {
3457 return notify->priority;
3458 } else if ((service = OSDynamicCast( IOService, entry))) {
3459 prop = service->copyProperty(key);
3460 offset = OSDynamicCast(OSNumber, prop);
3461 } else {
3462 assert( false );
3463 offset = NULL;
3464 }
3465
3466 if (offset) {
3467 result = offset->unsigned32BitValue();
3468 }
3469
3470 OSSafeReleaseNULL(prop);
3471
3472 return result;
3473 }
3474
3475 SInt32
3476 IOServiceOrdering( const OSMetaClassBase * inObj1, const OSMetaClassBase * inObj2, void * ref )
3477 {
3478 const OSObject * obj1 = (const OSObject *) inObj1;
3479 const OSObject * obj2 = (const OSObject *) inObj2;
3480 SInt32 val1;
3481 SInt32 val2;
3482
3483 val1 = 0;
3484 val2 = 0;
3485
3486 if (obj1) {
3487 val1 = IOServiceObjectOrder( obj1, ref );
3488 }
3489
3490 if (obj2) {
3491 val2 = IOServiceObjectOrder( obj2, ref );
3492 }
3493
3494 return val1 - val2;
3495 }
3496
3497 IOService *
3498 IOService::copyClientWithCategory( const OSSymbol * category )
3499 {
3500 IOService * service = NULL;
3501 OSIterator * iter;
3502 const OSSymbol * nextCat;
3503
3504 iter = getClientIterator();
3505 if (iter) {
3506 while ((service = (IOService *) iter->getNextObject())) {
3507 if (kIOServiceInactiveState & service->__state[0]) {
3508 continue;
3509 }
3510 nextCat = (const OSSymbol *) OSDynamicCast( OSSymbol,
3511 service->getProperty( gIOMatchCategoryKey ));
3512 if (category == nextCat) {
3513 service->retain();
3514 break;
3515 }
3516 }
3517 iter->release();
3518 }
3519 return service;
3520 }
3521
3522 IOService *
3523 IOService::getClientWithCategory( const OSSymbol * category )
3524 {
3525 IOService *
3526 service = copyClientWithCategory(category);
3527 if (service) {
3528 service->release();
3529 }
3530 return service;
3531 }
3532
3533 bool
3534 IOService::invokeNotifier( _IOServiceNotifier * notify )
3535 {
3536 _IOServiceNotifierInvocation invocation;
3537 bool willNotify;
3538 bool ret = true;
3539 invocation.thread = current_thread();
3540
3541 #if DEBUG_NOTIFIER_LOCKED
3542 uint32_t count;
3543 if ((count = isLockedForArbitration(0))) {
3544 IOLog("[%s, 0x%x]\n", notify->type->getCStringNoCopy(), count);
3545 panic("[%s, 0x%x]\n", notify->type->getCStringNoCopy(), count);
3546 }
3547 #endif /* DEBUG_NOTIFIER_LOCKED */
3548
3549 LOCKWRITENOTIFY();
3550 willNotify = (0 != (kIOServiceNotifyEnable & notify->state));
3551
3552 if (willNotify) {
3553 queue_enter( &notify->handlerInvocations, &invocation,
3554 _IOServiceNotifierInvocation *, link );
3555 }
3556 UNLOCKNOTIFY();
3557
3558 if (willNotify) {
3559 ret = (*notify->handler)(notify->target, notify->ref, this, notify);
3560
3561 LOCKWRITENOTIFY();
3562 queue_remove( &notify->handlerInvocations, &invocation,
3563 _IOServiceNotifierInvocation *, link );
3564 if (kIOServiceNotifyWaiter & notify->state) {
3565 notify->state &= ~kIOServiceNotifyWaiter;
3566 WAKEUPNOTIFY( notify );
3567 }
3568 UNLOCKNOTIFY();
3569 }
3570
3571 return ret;
3572 }
3573
3574 bool
3575 IOService::invokeNotifiers(OSArray * willSend[])
3576 {
3577 OSArray * array;
3578 _IOServiceNotifier * notify;
3579 bool ret = true;
3580
3581 array = *willSend;
3582 if (!array) {
3583 return true;
3584 }
3585 *willSend = NULL;
3586
3587 for (unsigned int idx = 0;
3588 (notify = (_IOServiceNotifier *) array->getObject(idx));
3589 idx++) {
3590 ret &= invokeNotifier(notify);
3591 }
3592 array->release();
3593
3594 return ret;
3595 }
3596
3597
3598 /*
3599 * Alloc and probe matching classes,
3600 * called on the provider instance
3601 */
3602
3603 void
3604 IOService::probeCandidates( OSOrderedSet * matches )
3605 {
3606 OSDictionary * match = NULL;
3607 OSSymbol * symbol;
3608 IOService * inst;
3609 IOService * newInst;
3610 OSDictionary * props;
3611 SInt32 score;
3612 OSNumber * newPri;
3613 OSOrderedSet * familyMatches = NULL;
3614 OSOrderedSet * startList;
3615 OSSet * kexts = NULL;
3616 OSObject * kextRef;
3617
3618 OSDictionary * startDict = NULL;
3619 const OSSymbol * category;
3620 OSIterator * iter;
3621 _IOServiceNotifier * notify;
3622 OSObject * nextMatch = NULL;
3623 bool started;
3624 bool needReloc = false;
3625 bool matchDeferred = false;
3626 #if IOMATCHDEBUG
3627 SInt64 debugFlags;
3628 #endif
3629 IOService * client = NULL;
3630 OSObject * prop1;
3631 OSObject * prop2;
3632 OSDictionary * rematchPersonality;
3633 OSNumber * num;
3634 uint32_t count;
3635 uint32_t dextCount;
3636 bool isDext;
3637 bool categoryConsumed;
3638
3639 prop2 = NULL;
3640 count = 0;
3641 prop1 = copyProperty(gIORematchPersonalityKey);
3642 rematchPersonality = OSDynamicCast(OSDictionary, prop1);
3643 if (rematchPersonality) {
3644 prop2 = copyProperty(gIORematchCountKey);
3645 num = OSDynamicCast(OSNumber, prop2);
3646 if (num) {
3647 count = num->unsigned32BitValue();
3648 }
3649 OSSafeReleaseNULL(prop2);
3650 }
3651 dextCount = 0;
3652
3653 assert( matches );
3654 while (!needReloc
3655 && (nextMatch = matches->getFirstObject())) {
3656 nextMatch->retain();
3657 matches->removeObject(nextMatch);
3658
3659 if ((notify = OSDynamicCast( _IOServiceNotifier, nextMatch ))) {
3660 if (0 == (__state[0] & kIOServiceInactiveState)) {
3661 invokeNotifier( notify );
3662 }
3663 nextMatch->release();
3664 nextMatch = NULL;
3665 continue;
3666 } else if (!(match = OSDynamicCast( OSDictionary, nextMatch ))) {
3667 nextMatch->release();
3668 nextMatch = NULL;
3669 continue;
3670 }
3671
3672 props = NULL;
3673 #if IOMATCHDEBUG
3674 debugFlags = getDebugFlags( match );
3675 #endif
3676
3677 do {
3678 isDext = (NULL != match->getObject(gIOUserServerNameKey));
3679 if (isDext && !(kIODKEnable & gIODKDebug)) {
3680 continue;
3681 }
3682
3683 category = OSDynamicCast( OSSymbol,
3684 match->getObject( gIOMatchCategoryKey ));
3685 if (NULL == category) {
3686 category = gIODefaultMatchCategoryKey;
3687 }
3688 client = copyClientWithCategory(category);
3689
3690 categoryConsumed = (client != NULL);
3691 if (categoryConsumed) {
3692 #if IOMATCHDEBUG
3693 if ((debugFlags & kIOLogMatch) && (this != gIOResources)) {
3694 LOG("%s: match category %s exists\n", getName(),
3695 category->getCStringNoCopy());
3696 }
3697 #endif
3698 OSSafeReleaseNULL(client);
3699 if (!isDext) {
3700 break;
3701 }
3702 }
3703
3704 // create a copy now in case its modified during matching
3705 props = OSDictionary::withDictionary(match, match->getCount());
3706 if (NULL == props) {
3707 break;
3708 }
3709 props->setCapacityIncrement(1);
3710
3711 // check the nub matches
3712 if (false == matchPassive(props, kIOServiceChangesOK | kIOServiceClassDone)) {
3713 break;
3714 }
3715 if (isDext) {
3716 dextCount++;
3717 if (categoryConsumed) {
3718 break;
3719 }
3720 }
3721
3722 if (rematchPersonality) {
3723 bool personalityMatch = match->isEqualTo(rematchPersonality);
3724 if (count > gIODextRelaunchMax) {
3725 personalityMatch = !personalityMatch;
3726 }
3727 if (!personalityMatch) {
3728 break;
3729 }
3730 }
3731
3732 // Check to see if driver reloc has been loaded.
3733 needReloc = (false == gIOCatalogue->isModuleLoaded( match, &kextRef ));
3734 if (needReloc) {
3735 #if IOMATCHDEBUG
3736 if (debugFlags & kIOLogCatalogue) {
3737 LOG("%s: stalling for module\n", getName());
3738 }
3739 #endif
3740 // If reloc hasn't been loaded, exit;
3741 // reprobing will occur after reloc has been loaded.
3742 break;
3743 }
3744 if (kextRef) {
3745 if (NULL == kexts) {
3746 kexts = OSSet::withCapacity(1);
3747 }
3748 if (kexts) {
3749 kexts->setObject(kextRef);
3750 kextRef->release();
3751 }
3752 }
3753 if (isDext) {
3754 // copy saved for rematchng
3755 props->setObject(gIOMatchedPersonalityKey, match);
3756 }
3757 // reorder on family matchPropertyTable score.
3758 if (NULL == familyMatches) {
3759 familyMatches = OSOrderedSet::withCapacity( 1,
3760 IOServiceOrdering, (void *) gIOProbeScoreKey );
3761 }
3762 if (familyMatches) {
3763 familyMatches->setObject( props );
3764 }
3765 } while (false);
3766
3767 OSSafeReleaseNULL(nextMatch);
3768 OSSafeReleaseNULL(props);
3769 }
3770 matches->release();
3771 matches = NULL;
3772
3773 if (familyMatches) {
3774 while (!needReloc
3775 && (props = (OSDictionary *) familyMatches->getFirstObject())) {
3776 props->retain();
3777 familyMatches->removeObject( props );
3778
3779 inst = NULL;
3780 newInst = NULL;
3781 #if IOMATCHDEBUG
3782 debugFlags = getDebugFlags( props );
3783 #endif
3784 do {
3785 symbol = OSDynamicCast( OSSymbol,
3786 props->getObject( gIOClassKey));
3787 if (!symbol) {
3788 continue;
3789 }
3790
3791 //IOLog("%s alloc (symbol %p props %p)\n", symbol->getCStringNoCopy(), IOSERVICE_OBFUSCATE(symbol), IOSERVICE_OBFUSCATE(props));
3792
3793 // alloc the driver instance
3794 inst = (IOService *) OSMetaClass::allocClassWithName( symbol);
3795
3796 if (!inst || !OSDynamicCast(IOService, inst)) {
3797 IOLog("Couldn't alloc class \"%s\"\n",
3798 symbol->getCStringNoCopy());
3799 continue;
3800 }
3801
3802 // init driver instance
3803 if (!(inst->init( props ))) {
3804 #if IOMATCHDEBUG
3805 if (debugFlags & kIOLogStart) {
3806 IOLog("%s::init fails\n", symbol->getCStringNoCopy());
3807 }
3808 #endif
3809 continue;
3810 }
3811 if (__state[1] & kIOServiceSynchronousState) {
3812 inst->__state[1] |= kIOServiceSynchronousState;
3813 }
3814
3815 // give the driver the default match category if not specified
3816 category = OSDynamicCast( OSSymbol,
3817 props->getObject( gIOMatchCategoryKey ));
3818 if (NULL == category) {
3819 category = gIODefaultMatchCategoryKey;
3820 }
3821 inst->setProperty( gIOMatchCategoryKey, (OSObject *) category );
3822 // attach driver instance
3823 if (!(inst->attach( this ))) {
3824 continue;
3825 }
3826
3827 // pass in score from property table
3828 score = familyMatches->orderObject( props );
3829
3830 // & probe the new driver instance
3831 #if IOMATCHDEBUG
3832 if (debugFlags & kIOLogProbe) {
3833 LOG("%s::probe(%s)\n",
3834 inst->getMetaClass()->getClassName(), getName());
3835 }
3836 #endif
3837
3838 newInst = inst->probe( this, &score );
3839 inst->detach( this );
3840 if (NULL == newInst) {
3841 #if IOMATCHDEBUG
3842 if (debugFlags & kIOLogProbe) {
3843 IOLog("%s::probe fails\n", symbol->getCStringNoCopy());
3844 }
3845 #endif
3846 continue;
3847 }
3848
3849 // save the score
3850 newPri = OSNumber::withNumber( score, 32 );
3851 if (newPri) {
3852 newInst->setProperty( gIOProbeScoreKey, newPri );
3853 newPri->release();
3854 }
3855
3856 // add to start list for the match category
3857 if (NULL == startDict) {
3858 startDict = OSDictionary::withCapacity( 1 );
3859 }
3860 assert( startDict );
3861 startList = (OSOrderedSet *)
3862 startDict->getObject( category );
3863 if (NULL == startList) {
3864 startList = OSOrderedSet::withCapacity( 1,
3865 IOServiceOrdering, (void *) gIOProbeScoreKey );
3866 if (startDict && startList) {
3867 startDict->setObject( category, startList );
3868 startList->release();
3869 }
3870 }
3871 assert( startList );
3872 if (startList) {
3873 startList->setObject( newInst );
3874 }
3875 } while (false);
3876
3877 props->release();
3878 if (inst) {
3879 inst->release();
3880 }
3881 }
3882 familyMatches->release();
3883 familyMatches = NULL;
3884 }
3885
3886 // start the best (until success) of each category
3887
3888 iter = OSCollectionIterator::withCollection( startDict );
3889 if (iter) {
3890 while ((category = (const OSSymbol *) iter->getNextObject())) {
3891 startList = (OSOrderedSet *) startDict->getObject( category );
3892 assert( startList );
3893 if (!startList) {
3894 continue;
3895 }
3896
3897 started = false;
3898 while (true // (!started)
3899 && !matchDeferred
3900 && (inst = (IOService *)startList->getFirstObject())) {
3901 inst->retain();
3902 startList->removeObject(inst);
3903
3904 #if IOMATCHDEBUG
3905 debugFlags = getDebugFlags( inst );
3906
3907 if (debugFlags & kIOLogStart) {
3908 if (started) {
3909 LOG( "match category exists, skipping " );
3910 }
3911 LOG( "%s::start(%s) <%d>\n", inst->getName(),
3912 getName(), inst->getRetainCount());
3913 }
3914 #endif
3915 if (false == started) {
3916 #if !NO_KEXTD
3917 IOLockLock(gJobsLock);
3918 matchDeferred = (gIOMatchDeferList
3919 && (kOSBooleanTrue == inst->getProperty(gIOMatchDeferKey)));
3920 if (matchDeferred && (-1U == gIOMatchDeferList->getNextIndexOfObject(this, 0))) {
3921 gIOMatchDeferList->setObject(this);
3922 }
3923 IOLockUnlock(gJobsLock);
3924 if (matchDeferred) {
3925 symbol = OSDynamicCast(OSSymbol, inst->getProperty(gIOClassKey));
3926 IOLog("%s(0x%qx): matching deferred by %s\n",
3927 getName(), getRegistryEntryID(),
3928 symbol ? symbol->getCStringNoCopy() : "");
3929 // rematching will occur after kextd loads all plists
3930 }
3931 #endif
3932 if (!matchDeferred) {
3933 started = startCandidate( inst );
3934 #if IOMATCHDEBUG
3935 if ((debugFlags & kIOLogStart) && (false == started)) {
3936 LOG( "%s::start(%s) <%d> failed\n", inst->getName(), getName(),
3937 inst->getRetainCount());
3938 }
3939 #endif
3940 }
3941 }
3942 inst->release();
3943 }
3944 }
3945 iter->release();
3946 }
3947
3948 OSSafeReleaseNULL(prop1);
3949
3950 if (dextCount) {
3951 num = OSNumber::withNumber(dextCount, 32);
3952 setProperty(gIODEXTMatchCountKey, num);
3953 OSSafeReleaseNULL(num);
3954 } else if (rematchPersonality) {
3955 removeProperty(gIODEXTMatchCountKey);
3956 }
3957
3958 // now that instances are created, drop the refs on any kexts allowing unload
3959 if (kexts) {
3960 OSKext::dropMatchingReferences(kexts);
3961 OSSafeReleaseNULL(kexts);
3962 }
3963
3964 // adjust the busy count by +1 if matching is stalled for a module,
3965 // or -1 if a previously stalled matching is complete.
3966 lockForArbitration();
3967 SInt32 adjBusy = 0;
3968 uint64_t regID = getRegistryEntryID();
3969
3970 if (needReloc) {
3971 adjBusy = (__state[1] & kIOServiceModuleStallState) ? 0 : 1;
3972 if (adjBusy) {
3973 IOServiceTrace(
3974 IOSERVICE_MODULESTALL,
3975 (uintptr_t) regID,
3976 (uintptr_t) (regID >> 32),
3977 (uintptr_t) this,
3978 0);
3979
3980 __state[1] |= kIOServiceModuleStallState;
3981 }
3982 } else if (__state[1] & kIOServiceModuleStallState) {
3983 IOServiceTrace(
3984 IOSERVICE_MODULEUNSTALL,
3985 (uintptr_t) regID,
3986 (uintptr_t) (regID >> 32),
3987 (uintptr_t) this,
3988 0);
3989
3990 __state[1] &= ~kIOServiceModuleStallState;
3991 adjBusy = -1;
3992 }
3993 if (adjBusy) {
3994 _adjustBusy( adjBusy );
3995 }
3996 unlockForArbitration();
3997
3998 if (startDict) {
3999 startDict->release();
4000 }
4001 }
4002
4003 /*
4004 * Wait for a IOUserServer to check in
4005 */
4006
4007 static
4008 __attribute__((noinline, not_tail_called))
4009 IOService *
4010 __WAITING_FOR_USER_SERVER__(OSDictionary * matching)
4011 {
4012 IOService * server;
4013 server = IOService::waitForMatchingService(matching, kIOUserServerCheckInTimeoutSecs * NSEC_PER_SEC);
4014 return server;
4015 }
4016
4017 void
4018 IOService::willShutdown()
4019 {
4020 gKextdWillTerminate = true;
4021 #if !NO_KEXTD
4022 getPlatform()->waitQuiet(30 * NSEC_PER_SEC);
4023 #endif
4024 OSKext::willShutdown();
4025 }
4026
4027 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4028
4029 void
4030 IOServicePH::init(IOPMrootDomain * root)
4031 {
4032 fUserServers = OSArray::withCapacity(4);
4033 fMatchingWork = OSArray::withCapacity(4);
4034
4035 assert(fUserServers && fMatchingWork);
4036
4037 fRootNotifier = root->registerInterest(
4038 gIOPriorityPowerStateInterest, &IOServicePH::systemPowerChange, NULL, NULL);
4039
4040 assert(fRootNotifier);
4041 }
4042
4043 void
4044 IOServicePH::lock()
4045 {
4046 IOLockLock(gJobsLock);
4047 }
4048
4049 void
4050 IOServicePH::unlock()
4051 {
4052 IOLockUnlock(gJobsLock);
4053 }
4054
4055 void
4056 IOServicePH::serverAdd(IOUserServer * server)
4057 {
4058 uint32_t idx;
4059
4060 lock();
4061 idx = fUserServers->getNextIndexOfObject(server, 0);
4062 if (idx == -1U) {
4063 fUserServers->setObject(server);
4064 }
4065 unlock();
4066 }
4067
4068 void
4069 IOServicePH::serverRemove(IOUserServer * server)
4070 {
4071 uint32_t idx;
4072
4073 lock();
4074 idx = fUserServers->getNextIndexOfObject(server, 0);
4075 if (idx != -1U) {
4076 fUserServers->removeObject(idx);
4077 }
4078 unlock();
4079 }
4080
4081 void
4082 IOServicePH::serverAck(IOUserServer * server)
4083 {
4084 uint32_t idx;
4085 IOService * ackTo;
4086 uint32_t ackToRef;
4087
4088 ackTo = NULL;
4089 lock();
4090 if (server && fUserServersWait) {
4091 idx = fUserServersWait->getNextIndexOfObject(server, 0);
4092 if (idx != -1U) {
4093 fUserServersWait->removeObject(idx);
4094 if (0 == fUserServersWait->getCount()) {
4095 OSSafeReleaseNULL(fUserServersWait);
4096 }
4097 }
4098 }
4099 if (!fUserServersWait && !fMatchingWork->getCount()) {
4100 ackTo = fSystemPowerAckTo;
4101 ackToRef = fSystemPowerAckRef;
4102 fSystemPowerAckTo = NULL;
4103 }
4104 unlock();
4105
4106 if (ackTo) {
4107 DKLOG("allowPowerChange\n");
4108 ackTo->allowPowerChange((uintptr_t) ackToRef);
4109 }
4110 }
4111
4112 bool
4113 IOServicePH::matchingStart(IOService * service)
4114 {
4115 uint32_t idx;
4116 bool ok;
4117
4118 lock();
4119 ok = !fSystemOff;
4120 if (ok) {
4121 idx = fMatchingWork->getNextIndexOfObject(service, 0);
4122 if (idx == -1U) {
4123 fMatchingWork->setObject(service);
4124 }
4125 } else {
4126 if (!fMatchingDelayed) {
4127 fMatchingDelayed = OSArray::withObjects((const OSObject **) &service, 1, 1);
4128 } else {
4129 idx = fMatchingDelayed->getNextIndexOfObject(service, 0);
4130 if (idx == -1U) {
4131 fMatchingDelayed->setObject(service);
4132 }
4133 }
4134 }
4135 unlock();
4136
4137 return ok;
4138 }
4139
4140 void
4141 IOServicePH::matchingEnd(IOService * service)
4142 {
4143 uint32_t idx;
4144 OSArray * notifyServers;
4145 OSArray * deferredMatches;
4146
4147 notifyServers = NULL;
4148 deferredMatches = NULL;
4149
4150 lock();
4151
4152 if (service) {
4153 idx = fMatchingWork->getNextIndexOfObject(service, 0);
4154 if (idx != -1U) {
4155 fMatchingWork->removeObject(idx);
4156 }
4157 }
4158
4159
4160 if ((fUserServerOff != fSystemOff) && fUserServers->getCount()) {
4161 if (fSystemOff) {
4162 if (0 == fMatchingWork->getCount()) {
4163 fUserServersWait = OSArray::withArray(fUserServers);
4164 notifyServers = OSArray::withArray(fUserServers);
4165 fUserServerOff = fSystemOff;
4166 }
4167 } else {
4168 notifyServers = OSArray::withArray(fUserServers);
4169 fUserServerOff = fSystemOff;
4170 }
4171 }
4172
4173 if (!fSystemOff && fMatchingDelayed) {
4174 deferredMatches = fMatchingDelayed;
4175 fMatchingDelayed = NULL;
4176 }
4177
4178 unlock();
4179
4180 if (notifyServers) {
4181 notifyServers->iterateObjects(^bool (OSObject * obj) {
4182 IOUserServer * us;
4183 us = (typeof(us))obj;
4184 us->systemPower(fSystemOff);
4185 return false;
4186 });
4187 OSSafeReleaseNULL(notifyServers);
4188 }
4189
4190 if (deferredMatches) {
4191 DKLOG("sleep deferred rematching count %d\n", deferredMatches->getCount());
4192 deferredMatches->iterateObjects(^bool (OSObject * obj)
4193 {
4194 ((IOService *)obj)->startMatching(kIOServiceAsynchronous);
4195 return false;
4196 });
4197 deferredMatches->release();
4198 }
4199
4200 serverAck(NULL);
4201 }
4202
4203 IOReturn
4204 IOServicePH::systemPowerChange(
4205 void * target,
4206 void * refCon,
4207 UInt32 messageType, IOService * service,
4208 void * messageArgument, vm_size_t argSize)
4209 {
4210 IOReturn ret;
4211 IOUserServer * us;
4212 IOPMSystemCapabilityChangeParameters * params;
4213
4214 us = NULL;
4215
4216 switch (messageType) {
4217 case kIOMessageSystemCapabilityChange:
4218
4219 params = (typeof params)messageArgument;
4220
4221 if (kIODKLogPM & gIODKDebug) {
4222 IOLog("IOServicePH::kIOMessageSystemCapabilityChange: %s%s 0x%x->0x%x\n",
4223 params->changeFlags & kIOPMSystemCapabilityWillChange ? "will" : "",
4224 params->changeFlags & kIOPMSystemCapabilityDidChange ? "did" : "",
4225 params->fromCapabilities,
4226 params->toCapabilities);
4227 }
4228
4229 if ((params->changeFlags & kIOPMSystemCapabilityWillChange) &&
4230 (params->fromCapabilities & kIOPMSystemCapabilityCPU) &&
4231 ((params->toCapabilities & kIOPMSystemCapabilityCPU) == 0)) {
4232 lock();
4233 fSystemOff = true;
4234 fSystemPowerAckRef = params->notifyRef;
4235 fSystemPowerAckTo = service;
4236 unlock();
4237
4238 matchingEnd(NULL);
4239
4240 params->maxWaitForReply = 60 * 1000 * 1000;
4241 ret = kIOReturnSuccess;
4242 } else if ((params->changeFlags & kIOPMSystemCapabilityWillChange) &&
4243 ((params->fromCapabilities & kIOPMSystemCapabilityCPU) == 0) &&
4244 (params->toCapabilities & kIOPMSystemCapabilityCPU)) {
4245 lock();
4246 fSystemOff = false;
4247 unlock();
4248
4249 matchingEnd(NULL);
4250
4251 params->maxWaitForReply = 0;
4252 ret = kIOReturnSuccess;
4253 } else {
4254 params->maxWaitForReply = 0;
4255 ret = kIOReturnSuccess;
4256 }
4257 break;
4258
4259 default:
4260 ret = kIOReturnUnsupported;
4261 break;
4262 }
4263
4264 return ret;
4265 }
4266
4267 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4268
4269 /*
4270 * Start a previously attached & probed instance,
4271 * called on exporting object instance
4272 */
4273
4274 bool
4275 IOService::startCandidate( IOService * service )
4276 {
4277 bool ok;
4278 OSObject * obj;
4279 OSObject * prop;
4280 IOUserServer * userServer;
4281 bool ph;
4282
4283 userServer = NULL;
4284 obj = service->copyProperty(gIOUserServerNameKey);
4285
4286 if (obj && (this == gIOResources)) {
4287 ok = false;
4288 } else {
4289 ok = service->attach( this );
4290 }
4291 if (!ok) {
4292 return false;
4293 }
4294
4295 if ((this != gIOResources) && (this != gIOUserResources)) {
4296 // stall for any nub resources
4297 checkResources();
4298 // stall for any driver resources
4299 service->checkResources();
4300 }
4301 ph = false;
4302 {
4303 OSString * bundleID;
4304 OSString * serverName;
4305 OSString * str;
4306 const OSSymbol * sym;
4307 OSDictionary * matching;
4308 IOService * server;
4309 OSNumber * serverTag;
4310 uint64_t entryID;
4311
4312 if ((serverName = OSDynamicCast(OSString, obj))) {
4313 obj = service->copyProperty(gIOModuleIdentifierKey);
4314 bundleID = OSDynamicCast(OSString, obj);
4315 entryID = service->getRegistryEntryID();
4316 serverTag = OSNumber::withNumber(entryID, 64);
4317
4318 if (gKextdWillTerminate) {
4319 DKLOG("%s disabled in shutdown\n", serverName->getCStringNoCopy());
4320 service->detach(this);
4321 OSSafeReleaseNULL(obj);
4322 return false;
4323 }
4324
4325 ph = IOServicePH::matchingStart(this);
4326 if (!ph) {
4327 DKLOG("%s deferred in sleep\n", serverName->getCStringNoCopy());
4328 service->detach(this);
4329 OSSafeReleaseNULL(obj);
4330 return false;
4331 }
4332
4333 prop = service->copyProperty(gIOUserClassKey);
4334 str = OSDynamicCast(OSString, prop);
4335 if (str) {
4336 service->setName(str);
4337 }
4338 OSSafeReleaseNULL(prop);
4339
4340 if (!(kIODKDisableDextLaunch & gIODKDebug)) {
4341 OSKext::requestDaemonLaunch(bundleID, serverName, serverTag);
4342 }
4343 sym = OSSymbol::withString(serverName);
4344 matching = serviceMatching(gIOUserServerClassKey);
4345 propertyMatching(gIOUserServerNameKey, sym, matching);
4346 if (!(kIODKDisableDextTag & gIODKDebug)) {
4347 propertyMatching(gIOUserServerTagKey, serverTag, matching);
4348 }
4349
4350 server = __WAITING_FOR_USER_SERVER__(matching);
4351 matching->release();
4352 OSSafeReleaseNULL(serverTag);
4353 OSSafeReleaseNULL(serverName);
4354
4355 userServer = OSDynamicCast(IOUserServer, server);
4356 if (!userServer) {
4357 service->detach(this);
4358 IOServicePH::matchingEnd(this);
4359 DKLOG(DKS " user server timeout\n", DKN(service));
4360 return false;
4361 }
4362
4363 if (!(kIODKDisableCDHashChecking & gIODKDebug)) {
4364 if (!userServer->serviceMatchesCDHash(service)) {
4365 service->detach(this);
4366 IOServicePH::matchingEnd(this);
4367 userServer->exit("CDHash check failed");
4368 userServer->release();
4369 return false;
4370 }
4371 }
4372 OSKext *kext = OSKext::lookupKextWithIdentifier(bundleID);
4373 if (!kext) {
4374 const char *name = bundleID->getCStringNoCopy();
4375 IOLog("%s Could not find OSKext for %s\n", __func__, name);
4376 goto skip_log;
4377 }
4378
4379 /*
4380 * Used for logging
4381 */
4382 userServer->setTaskLoadTag(kext);
4383 userServer->setDriverKitUUID(kext);
4384 OSKext::OSKextLogDriverKitInfoLoad(kext);
4385 skip_log:
4386 OSSafeReleaseNULL(bundleID);
4387 OSSafeReleaseNULL(kext);
4388
4389 if (!(kIODKDisableEntitlementChecking & gIODKDebug)) {
4390 if (!userServer->checkEntitlements(this, service)) {
4391 service->detach(this);
4392 IOServicePH::matchingEnd(this);
4393 userServer->exit("Entitlements check failed");
4394 userServer->release();
4395 return false;
4396 }
4397 }
4398
4399 userServer->serviceAttach(service, this);
4400 }
4401 }
4402
4403 AbsoluteTime startTime;
4404 AbsoluteTime endTime;
4405 UInt64 nano;
4406
4407 if (kIOLogStart & gIOKitDebug) {
4408 clock_get_uptime(&startTime);
4409 }
4410
4411 ok = service->start(this);
4412
4413 if (kIOLogStart & gIOKitDebug) {
4414 clock_get_uptime(&endTime);
4415
4416 if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0) {
4417 SUB_ABSOLUTETIME(&endTime, &startTime);
4418 absolutetime_to_nanoseconds(endTime, &nano);
4419 if (nano > 500000000ULL) {
4420 IOLog("%s::start took %ld ms\n", service->getName(), (long)(UInt32)(nano / 1000000ULL));
4421 }
4422 }
4423 }
4424 if (userServer) {
4425 userServer->serviceStarted(service, this, ok);
4426 userServer->release();
4427 }
4428 if (!ok) {
4429 service->detach( this );
4430 }
4431
4432 if (ph) {
4433 IOServicePH::matchingEnd(this);
4434 }
4435
4436 return ok;
4437 }
4438
4439 void
4440 IOService::publishResource( const char * key, OSObject * value )
4441 {
4442 const OSSymbol * sym;
4443
4444 if ((sym = OSSymbol::withCString( key))) {
4445 publishResource( sym, value);
4446 sym->release();
4447 }
4448 }
4449
4450 void
4451 IOService::publishResource( const OSSymbol * key, OSObject * value )
4452 {
4453 if (NULL == value) {
4454 value = (OSObject *) gIOServiceKey;
4455 }
4456
4457 gIOResources->setProperty( key, value);
4458
4459 if (IORecursiveLockHaveLock( gNotificationLock)) {
4460 return;
4461 }
4462
4463 gIOResourceGenerationCount++;
4464 gIOResources->registerService();
4465 }
4466
4467 void
4468 IOService::publishUserResource( const OSSymbol * key, OSObject * value )
4469 {
4470 if (NULL == value) {
4471 value = (OSObject *) gIOServiceKey;
4472 }
4473
4474 gIOUserResources->setProperty( key, value);
4475
4476 if (IORecursiveLockHaveLock( gNotificationLock)) {
4477 return;
4478 }
4479
4480 gIOResourceGenerationCount++;
4481 gIOUserResources->registerService();
4482 }
4483
4484 bool
4485 IOService::addNeededResource( const char * key )
4486 {
4487 OSObject * resourcesProp;
4488 OSSet * set;
4489 OSString * newKey;
4490 bool ret;
4491
4492 resourcesProp = copyProperty( gIOResourceMatchKey );
4493 if (!resourcesProp) {
4494 return false;
4495 }
4496
4497 newKey = OSString::withCString( key );
4498 if (!newKey) {
4499 resourcesProp->release();
4500 return false;
4501 }
4502
4503 set = OSDynamicCast( OSSet, resourcesProp );
4504 if (!set) {
4505 set = OSSet::withCapacity( 1 );
4506 if (set) {
4507 set->setObject( resourcesProp );
4508 }
4509 } else {
4510 set->retain();
4511 }
4512
4513 set->setObject( newKey );
4514 newKey->release();
4515 ret = setProperty( gIOResourceMatchKey, set );
4516 set->release();
4517 resourcesProp->release();
4518
4519 return ret;
4520 }
4521
4522 bool
4523 IOService::checkResource( OSObject * matching )
4524 {
4525 OSString * str;
4526 OSDictionary * table;
4527
4528 if ((str = OSDynamicCast( OSString, matching ))) {
4529 if (gIOResources->getProperty( str )) {
4530 return true;
4531 }
4532 }
4533
4534 if (str) {
4535 table = resourceMatching( str );
4536 } else if ((table = OSDynamicCast( OSDictionary, matching ))) {
4537 table->retain();
4538 } else {
4539 IOLog("%s: Can't match using: %s\n", getName(),
4540 matching->getMetaClass()->getClassName());
4541 /* false would stall forever */
4542 return true;
4543 }
4544
4545 if (gIOKitDebug & kIOLogConfig) {
4546 LOG("config(%p): stalling %s\n", IOSERVICE_OBFUSCATE(IOThreadSelf()), getName());
4547 }
4548
4549 waitForService( table );
4550
4551 if (gIOKitDebug & kIOLogConfig) {
4552 LOG("config(%p): waking\n", IOSERVICE_OBFUSCATE(IOThreadSelf()));
4553 }
4554
4555 return true;
4556 }
4557
4558 bool
4559 IOService::checkResources( void )
4560 {
4561 OSObject * resourcesProp;
4562 OSSet * set;
4563 OSIterator * iter;
4564 bool ok;
4565
4566 resourcesProp = copyProperty( gIOResourceMatchKey );
4567 if (NULL == resourcesProp) {
4568 return true;
4569 }
4570
4571 if ((set = OSDynamicCast( OSSet, resourcesProp ))) {
4572 iter = OSCollectionIterator::withCollection( set );
4573 ok = (NULL != iter);
4574 while (ok && (resourcesProp = iter->getNextObject())) {
4575 ok = checkResource( resourcesProp );
4576 }
4577 if (iter) {
4578 iter->release();
4579 }
4580 } else {
4581 ok = checkResource( resourcesProp );
4582 }
4583
4584 OSSafeReleaseNULL(resourcesProp);
4585
4586 return ok;
4587 }
4588
4589
4590 void
4591 _IOConfigThread::configThread( int configThreadId )
4592 {
4593 _IOConfigThread * inst;
4594
4595 do {
4596 if (!(inst = new _IOConfigThread)) {
4597 continue;
4598 }
4599 if (!inst->init()) {
4600 continue;
4601 }
4602 thread_t thread;
4603 if (KERN_SUCCESS != kernel_thread_start(&_IOConfigThread::main, inst, &thread)) {
4604 continue;
4605 }
4606
4607 char threadName[MAXTHREADNAMESIZE];
4608 snprintf(threadName, sizeof(threadName), "IOConfigThread_%d", configThreadId);
4609 thread_set_thread_name(thread, threadName);
4610 thread_deallocate(thread);
4611
4612 return;
4613 } while (false);
4614
4615 if (inst) {
4616 inst->release();
4617 }
4618
4619 return;
4620 }
4621
4622 void
4623 IOService::doServiceMatch( IOOptionBits options )
4624 {
4625 _IOServiceNotifier * notify;
4626 OSIterator * iter;
4627 OSOrderedSet * matches;
4628 OSArray * resourceKeys = NULL;
4629 SInt32 catalogGeneration;
4630 bool keepGuessing = true;
4631 bool reRegistered = true;
4632 bool didRegister;
4633 OSArray * notifiers[2] = {NULL};
4634
4635 // job->nub->deliverNotification( gIOPublishNotification,
4636 // kIOServiceRegisteredState, 0xffffffff );
4637
4638 while (keepGuessing) {
4639 matches = gIOCatalogue->findDrivers( this, &catalogGeneration );
4640 // the matches list should always be created by findDrivers()
4641 if (matches) {
4642 lockForArbitration();
4643 if (0 == (__state[0] & kIOServiceFirstPublishState)) {
4644 getMetaClass()->addInstance(this);
4645 notifiers[0] = copyNotifiers(gIOFirstPublishNotification,
4646 kIOServiceFirstPublishState, 0xffffffff );
4647 }
4648 LOCKREADNOTIFY();
4649 __state[1] &= ~kIOServiceNeedConfigState;
4650 __state[1] |= kIOServiceConfigState | kIOServiceConfigRunning;
4651 didRegister = (0 == (kIOServiceRegisteredState & __state[0]));
4652 __state[0] |= kIOServiceRegisteredState;
4653
4654 keepGuessing &= (0 == (__state[0] & kIOServiceInactiveState));
4655 if (reRegistered && keepGuessing) {
4656 iter = OSCollectionIterator::withCollection((OSOrderedSet *)
4657 gNotifications->getObject( gIOPublishNotification ));
4658 if (iter) {
4659 while ((notify = (_IOServiceNotifier *)
4660 iter->getNextObject())) {
4661 if (matchPassive(notify->matching, 0)
4662 && (kIOServiceNotifyEnable & notify->state)) {
4663 matches->setObject( notify );
4664 }
4665 }
4666 iter->release();
4667 }
4668 }
4669
4670 UNLOCKNOTIFY();
4671 unlockForArbitration();
4672 invokeNotifiers(&notifiers[0]);
4673
4674 if (keepGuessing && matches->getCount() && (kIOReturnSuccess == getResources())) {
4675 if ((this == gIOResources) || (this == gIOUserResources)) {
4676 if (resourceKeys) {
4677 resourceKeys->release();
4678 }
4679 resourceKeys = copyPropertyKeys();
4680 }
4681 probeCandidates( matches );
4682 } else {
4683 matches->release();
4684 }
4685 }
4686
4687 lockForArbitration();
4688 reRegistered = (0 != (__state[1] & kIOServiceNeedConfigState));
4689 keepGuessing =
4690 (reRegistered || (catalogGeneration !=
4691 gIOCatalogue->getGenerationCount()))
4692 && (0 == (__state[0] & kIOServiceInactiveState));
4693
4694 if (keepGuessing) {
4695 unlockForArbitration();
4696 }
4697 }
4698
4699 if ((0 == (__state[0] & kIOServiceInactiveState))
4700 && (0 == (__state[1] & kIOServiceModuleStallState))) {
4701 if (resourceKeys) {
4702 setProperty(gIOResourceMatchedKey, resourceKeys);
4703 }
4704
4705 notifiers[0] = copyNotifiers(gIOMatchedNotification,
4706 kIOServiceMatchedState, 0xffffffff);
4707 if (0 == (__state[0] & kIOServiceFirstMatchState)) {
4708 notifiers[1] = copyNotifiers(gIOFirstMatchNotification,
4709 kIOServiceFirstMatchState, 0xffffffff);
4710 }
4711 }
4712
4713 __state[1] &= ~kIOServiceConfigRunning;
4714 unlockForArbitration();
4715
4716 if (resourceKeys) {
4717 resourceKeys->release();
4718 }
4719
4720 invokeNotifiers(&notifiers[0]);
4721 invokeNotifiers(&notifiers[1]);
4722
4723 lockForArbitration();
4724 __state[1] &= ~kIOServiceConfigState;
4725 scheduleTerminatePhase2();
4726
4727 _adjustBusy( -1 );
4728 unlockForArbitration();
4729 }
4730
4731 UInt32
4732 IOService::_adjustBusy( SInt32 delta )
4733 {
4734 IOService * next;
4735 UInt32 count;
4736 UInt32 result;
4737 bool wasQuiet, nowQuiet, needWake;
4738
4739 next = this;
4740 result = __state[1] & kIOServiceBusyStateMask;
4741
4742 if (delta) {
4743 do {
4744 if (next != this) {
4745 next->lockForArbitration();
4746 }
4747 count = next->__state[1] & kIOServiceBusyStateMask;
4748 wasQuiet = (0 == count);
4749 if (((delta < 0) && wasQuiet) || ((delta > 0) && (kIOServiceBusyMax == count))) {
4750 OSReportWithBacktrace("%s: bad busy count (%d,%d)\n", next->getName(), count, delta);
4751 } else {
4752 count += delta;
4753 }
4754 next->__state[1] = (next->__state[1] & ~kIOServiceBusyStateMask) | count;
4755 nowQuiet = (0 == count);
4756 needWake = (0 != (kIOServiceBusyWaiterState & next->__state[1]));
4757
4758 if (needWake) {
4759 next->__state[1] &= ~kIOServiceBusyWaiterState;
4760 IOLockLock( gIOServiceBusyLock );
4761 thread_wakeup((event_t) next);
4762 IOLockUnlock( gIOServiceBusyLock );
4763 }
4764 if (next != this) {
4765 next->unlockForArbitration();
4766 }
4767
4768 if ((wasQuiet || nowQuiet)) {
4769 uint64_t regID = next->getRegistryEntryID();
4770 IOServiceTrace(
4771 ((wasQuiet /*nowBusy*/) ? IOSERVICE_BUSY : IOSERVICE_NONBUSY),
4772 (uintptr_t) regID,
4773 (uintptr_t) (regID >> 32),
4774 (uintptr_t) next,
4775 0);
4776
4777 if (wasQuiet) {
4778 next->__timeBusy = mach_absolute_time();
4779 } else {
4780 next->__accumBusy += mach_absolute_time() - next->__timeBusy;
4781 next->__timeBusy = 0;
4782 }
4783
4784 MessageClientsContext context;
4785
4786 context.service = next;
4787 context.type = kIOMessageServiceBusyStateChange;
4788 context.argument = (void *) wasQuiet; /*nowBusy*/
4789 context.argSize = 0;
4790
4791 applyToInterestNotifiers( next, gIOBusyInterest,
4792 &messageClientsApplier, &context );
4793
4794 #if !NO_KEXTD
4795 if (nowQuiet && (next == gIOServiceRoot)) {
4796 OSKext::considerUnloads();
4797 IOServiceTrace(IOSERVICE_REGISTRY_QUIET, 0, 0, 0, 0);
4798 }
4799 #endif
4800 }
4801
4802 delta = nowQuiet ? -1 : +1;
4803 } while ((wasQuiet || nowQuiet) && (next = next->getProvider()));
4804 }
4805
4806 return result;
4807 }
4808
4809 void
4810 IOService::adjustBusy( SInt32 delta )
4811 {
4812 lockForArbitration();
4813 _adjustBusy( delta );
4814 unlockForArbitration();
4815 }
4816
4817 uint64_t
4818 IOService::getAccumulatedBusyTime( void )
4819 {
4820 uint64_t accumBusy = __accumBusy;
4821 uint64_t timeBusy = __timeBusy;
4822 uint64_t nano;
4823
4824 do{
4825 accumBusy = __accumBusy;
4826 timeBusy = __timeBusy;
4827 if (timeBusy) {
4828 accumBusy += mach_absolute_time() - timeBusy;
4829 }
4830 }while (timeBusy != __timeBusy);
4831
4832 absolutetime_to_nanoseconds(*(AbsoluteTime *)&accumBusy, &nano);
4833
4834 return nano;
4835 }
4836
4837 UInt32
4838 IOService::getBusyState( void )
4839 {
4840 return __state[1] & kIOServiceBusyStateMask;
4841 }
4842
4843 IOReturn
4844 IOService::waitForState( UInt32 mask, UInt32 value,
4845 mach_timespec_t * timeout )
4846 {
4847 panic("waitForState");
4848 return kIOReturnUnsupported;
4849 }
4850
4851 IOReturn
4852 IOService::waitForState( UInt32 mask, UInt32 value,
4853 uint64_t timeout )
4854 {
4855 bool wait;
4856 int waitResult = THREAD_AWAKENED;
4857 bool computeDeadline = true;
4858 AbsoluteTime abstime;
4859
4860 do {
4861 lockForArbitration();
4862 IOLockLock( gIOServiceBusyLock );
4863 wait = (value != (__state[1] & mask));
4864 if (wait) {
4865 __state[1] |= kIOServiceBusyWaiterState;
4866 unlockForArbitration();
4867 if (timeout != UINT64_MAX) {
4868 if (computeDeadline) {
4869 AbsoluteTime nsinterval;
4870 nanoseconds_to_absolutetime(timeout, &nsinterval );
4871 clock_absolutetime_interval_to_deadline(nsinterval, &abstime);
4872 computeDeadline = false;
4873 }
4874 assert_wait_deadline((event_t)this, THREAD_UNINT, __OSAbsoluteTime(abstime));
4875 } else {
4876 assert_wait((event_t)this, THREAD_UNINT );
4877 }
4878 } else {
4879 unlockForArbitration();
4880 }
4881 IOLockUnlock( gIOServiceBusyLock );
4882 if (wait) {
4883 waitResult = thread_block(THREAD_CONTINUE_NULL);
4884 }
4885 } while (wait && (waitResult != THREAD_TIMED_OUT));
4886
4887 if (waitResult == THREAD_TIMED_OUT) {
4888 return kIOReturnTimeout;
4889 } else {
4890 return kIOReturnSuccess;
4891 }
4892 }
4893
4894 IOReturn
4895 IOService::waitQuiet( uint64_t timeout )
4896 {
4897 IOReturn ret;
4898 uint32_t loops;
4899 char * string = NULL;
4900 char * panicString = NULL;
4901 size_t len;
4902 size_t panicStringLen;
4903 uint64_t time;
4904 uint64_t nano;
4905 bool kextdWait;
4906 bool dopanic;
4907
4908 #if KASAN
4909 /*
4910 * On kasan kernels, everything takes longer, so double the number of
4911 * timeout extensions. This should help with issues like 41259215
4912 * where WindowServer was timing out waiting for kextd to get all the
4913 * kasan kexts loaded and started.
4914 */
4915 enum { kTimeoutExtensions = 8 };
4916 #else
4917 enum { kTimeoutExtensions = 4 };
4918 #endif
4919
4920 time = mach_absolute_time();
4921 kextdWait = false;
4922 for (loops = 0; loops < kTimeoutExtensions; loops++) {
4923 ret = waitForState( kIOServiceBusyStateMask, 0, timeout );
4924
4925 if (loops && (kIOReturnSuccess == ret)) {
4926 time = mach_absolute_time() - time;
4927 absolutetime_to_nanoseconds(*(AbsoluteTime *)&time, &nano);
4928 IOLog("busy extended ok[%d], (%llds, %llds)\n",
4929 loops, timeout / 1000000000ULL, nano / 1000000000ULL);
4930 break;
4931 } else if (kIOReturnTimeout != ret) {
4932 break;
4933 } else if (timeout < (4100ull * NSEC_PER_SEC)) {
4934 break;
4935 }
4936
4937 {
4938 IORegistryIterator * iter;
4939 OSOrderedSet * set;
4940 OSOrderedSet * leaves;
4941 IOService * next;
4942 IOService * nextParent;
4943 char * s;
4944 size_t l;
4945
4946 len = 256;
4947 panicStringLen = 256;
4948 if (!string) {
4949 string = IONew(char, len);
4950 }
4951 if (!panicString) {
4952 panicString = IONew(char, panicStringLen);
4953 }
4954 set = NULL;
4955 kextdWait = OSKext::isWaitingKextd();
4956 iter = IORegistryIterator::iterateOver(this, gIOServicePlane, kIORegistryIterateRecursively);
4957 leaves = OSOrderedSet::withCapacity(4);
4958 if (iter) {
4959 set = iter->iterateAll();
4960 }
4961 if (string && panicString && leaves && set) {
4962 string[0] = panicString[0] = 0;
4963 set->setObject(this);
4964 while ((next = (IOService *) set->getLastObject())) {
4965 if (next->getBusyState()) {
4966 if (kIOServiceModuleStallState & next->__state[1]) {
4967 kextdWait = true;
4968 }
4969 leaves->setObject(next);
4970 nextParent = next;
4971 while ((nextParent = nextParent->getProvider())) {
4972 set->removeObject(nextParent);
4973 leaves->removeObject(nextParent);
4974 }
4975 }
4976 set->removeObject(next);
4977 }
4978 s = string;
4979 while ((next = (IOService *) leaves->getLastObject())) {
4980 l = snprintf(s, len, "%s'%s'", ((s == string) ? "" : ", "), next->getName());
4981 if (l >= len) {
4982 break;
4983 }
4984 s += l;
4985 len -= l;
4986 leaves->removeObject(next);
4987 }
4988 }
4989 OSSafeReleaseNULL(leaves);
4990 OSSafeReleaseNULL(set);
4991 OSSafeReleaseNULL(iter);
4992 }
4993
4994 dopanic = ((loops >= (kTimeoutExtensions - 1)) && (kIOWaitQuietPanics & gIOKitDebug));
4995 snprintf(panicString, panicStringLen,
4996 "%s[%d], (%llds): %s",
4997 kextdWait ? "kextd stall" : "busy timeout",
4998 loops, timeout / 1000000000ULL,
4999 string ? string : "");
5000 IOLog("%s\n", panicString);
5001 if (dopanic) {
5002 panic("%s", panicString);
5003 } else if (!loops) {
5004 getPMRootDomain()->startSpinDump(1);
5005 }
5006 }
5007
5008 if (string) {
5009 IODelete(string, char, 256);
5010 }
5011 if (panicString) {
5012 IODelete(panicString, char, panicStringLen);
5013 }
5014
5015 return ret;
5016 }
5017
5018 IOReturn
5019 IOService::waitQuiet( mach_timespec_t * timeout )
5020 {
5021 uint64_t timeoutNS;
5022
5023 if (timeout) {
5024 timeoutNS = timeout->tv_sec;
5025 timeoutNS *= kSecondScale;
5026 timeoutNS += timeout->tv_nsec;
5027 } else {
5028 timeoutNS = UINT64_MAX;
5029 }
5030
5031 return waitQuiet(timeoutNS);
5032 }
5033
5034 bool
5035 IOService::serializeProperties( OSSerialize * s ) const
5036 {
5037 #if 0
5038 ((IOService *)this)->setProperty(((IOService *)this)->__state,
5039 sizeof(__state), "__state");
5040 #endif
5041 return super::serializeProperties(s);
5042 }
5043
5044
5045 void
5046 _IOConfigThread::main(void * arg, wait_result_t result)
5047 {
5048 _IOConfigThread * self = (_IOConfigThread *) arg;
5049 _IOServiceJob * job;
5050 IOService * nub;
5051 bool alive = true;
5052 kern_return_t kr;
5053 thread_precedence_policy_data_t precedence = { -1 };
5054
5055 kr = thread_policy_set(current_thread(),
5056 THREAD_PRECEDENCE_POLICY,
5057 (thread_policy_t) &precedence,
5058 THREAD_PRECEDENCE_POLICY_COUNT);
5059 if (KERN_SUCCESS != kr) {
5060 IOLog("thread_policy_set(%d)\n", kr);
5061 }
5062
5063 do {
5064 // randomDelay();
5065
5066 semaphore_wait( gJobsSemaphore );
5067
5068 IOTakeLock( gJobsLock );
5069 job = (_IOServiceJob *) gJobs->getFirstObject();
5070 job->retain();
5071 gJobs->removeObject(job);
5072 if (job) {
5073 gOutstandingJobs--;
5074 // gNumConfigThreads--; // we're out of service
5075 gNumWaitingThreads--; // we're out of service
5076 }
5077 IOUnlock( gJobsLock );
5078
5079 if (job) {
5080 nub = job->nub;
5081
5082 if (gIOKitDebug & kIOLogConfig) {
5083 LOG("config(%p): starting on %s, %d\n",
5084 IOSERVICE_OBFUSCATE(IOThreadSelf()), job->nub->getName(), job->type);
5085 }
5086
5087 switch (job->type) {
5088 case kMatchNubJob:
5089 nub->doServiceMatch( job->options );
5090 break;
5091
5092 default:
5093 LOG("config(%p): strange type (%d)\n",
5094 IOSERVICE_OBFUSCATE(IOThreadSelf()), job->type );
5095 break;
5096 }
5097
5098 nub->release();
5099 job->release();
5100
5101 IOTakeLock( gJobsLock );
5102 alive = (gOutstandingJobs > gNumWaitingThreads);
5103 if (alive) {
5104 gNumWaitingThreads++; // back in service
5105 }
5106 // gNumConfigThreads++;
5107 else {
5108 if (0 == --gNumConfigThreads) {
5109 // IOLog("MATCH IDLE\n");
5110 IOLockWakeup( gJobsLock, (event_t) &gNumConfigThreads, /* one-thread */ false );
5111 }
5112 }
5113 IOUnlock( gJobsLock );
5114 }
5115 } while (alive);
5116
5117 if (gIOKitDebug & kIOLogConfig) {
5118 LOG("config(%p): terminating\n", IOSERVICE_OBFUSCATE(IOThreadSelf()));
5119 }
5120
5121 self->release();
5122 }
5123
5124 IOReturn
5125 IOService::waitMatchIdle( UInt32 msToWait )
5126 {
5127 bool wait;
5128 int waitResult = THREAD_AWAKENED;
5129 bool computeDeadline = true;
5130 AbsoluteTime deadline;
5131
5132 IOLockLock( gJobsLock );
5133 do {
5134 wait = (0 != gNumConfigThreads);
5135 if (wait) {
5136 if (msToWait) {
5137 if (computeDeadline) {
5138 clock_interval_to_deadline(
5139 msToWait, kMillisecondScale, &deadline );
5140 computeDeadline = false;
5141 }
5142 waitResult = IOLockSleepDeadline( gJobsLock, &gNumConfigThreads,
5143 deadline, THREAD_UNINT );
5144 } else {
5145 waitResult = IOLockSleep( gJobsLock, &gNumConfigThreads,
5146 THREAD_UNINT );
5147 }
5148 }
5149 } while (wait && (waitResult != THREAD_TIMED_OUT));
5150 IOLockUnlock( gJobsLock );
5151
5152 if (waitResult == THREAD_TIMED_OUT) {
5153 return kIOReturnTimeout;
5154 } else {
5155 return kIOReturnSuccess;
5156 }
5157 }
5158
5159 void
5160 IOService::cpusRunning(void)
5161 {
5162 gCPUsRunning = true;
5163 }
5164
5165 void
5166 _IOServiceJob::pingConfig( _IOServiceJob * job )
5167 {
5168 int count;
5169 bool create;
5170
5171 assert( job );
5172
5173 IOTakeLock( gJobsLock );
5174
5175 gOutstandingJobs++;
5176 gJobs->setLastObject( job );
5177
5178 count = gNumWaitingThreads;
5179 // if( gNumConfigThreads) count++;// assume we're called from a config thread
5180
5181 create = ((gOutstandingJobs > count)
5182 && ((gNumConfigThreads < kMaxConfigThreads)
5183 || (job->nub == gIOResources)
5184 || !gCPUsRunning));
5185 if (create) {
5186 gNumConfigThreads++;
5187 gNumWaitingThreads++;
5188 }
5189
5190 IOUnlock( gJobsLock );
5191
5192 job->release();
5193
5194 if (create) {
5195 if (gIOKitDebug & kIOLogConfig) {
5196 LOG("config(%d): creating\n", gNumConfigThreads - 1);
5197 }
5198 _IOConfigThread::configThread(gNumConfigThreads - 1);
5199 }
5200
5201 semaphore_signal( gJobsSemaphore );
5202 }
5203
5204 struct IOServiceMatchContext {
5205 OSDictionary * table;
5206 OSObject * result;
5207 uint32_t options;
5208 uint32_t state;
5209 uint32_t count;
5210 uint32_t done;
5211 };
5212
5213 bool
5214 IOService::instanceMatch(const OSObject * entry, void * context)
5215 {
5216 IOServiceMatchContext * ctx = (typeof(ctx))context;
5217 IOService * service = (typeof(service))entry;
5218 OSDictionary * table = ctx->table;
5219 uint32_t options = ctx->options;
5220 uint32_t state = ctx->state;
5221 uint32_t done;
5222 bool match;
5223
5224 done = 0;
5225 do{
5226 match = ((state == (state & service->__state[0]))
5227 && (0 == (service->__state[0] & kIOServiceInactiveState)));
5228 if (!match) {
5229 break;
5230 }
5231 ctx->count += table->getCount();
5232 match = service->matchInternal(table, options, &done);
5233 ctx->done += done;
5234 }while (false);
5235 if (!match) {
5236 return false;
5237 }
5238
5239 if ((kIONotifyOnce & options) && (ctx->done == ctx->count)) {
5240 service->retain();
5241 ctx->result = service;
5242 return true;
5243 } else if (!ctx->result) {
5244 ctx->result = OSSet::withObjects((const OSObject **) &service, 1, 1);
5245 } else {
5246 ((OSSet *)ctx->result)->setObject(service);
5247 }
5248 return false;
5249 }
5250
5251 // internal - call with gNotificationLock
5252 OSObject *
5253 IOService::copyExistingServices( OSDictionary * matching,
5254 IOOptionBits inState, IOOptionBits options )
5255 {
5256 OSObject * current = NULL;
5257 OSIterator * iter;
5258 IOService * service;
5259 OSObject * obj;
5260 OSString * str;
5261
5262 if (!matching) {
5263 return NULL;
5264 }
5265
5266 #if MATCH_DEBUG
5267 OSSerialize * s = OSSerialize::withCapacity(128);
5268 matching->serialize(s);
5269 #endif
5270
5271 if ((obj = matching->getObject(gIOProviderClassKey))
5272 && gIOResourcesKey
5273 && gIOResourcesKey->isEqualTo(obj)
5274 && (service = gIOResources)) {
5275 if ((inState == (service->__state[0] & inState))
5276 && (0 == (service->__state[0] & kIOServiceInactiveState))
5277 && service->matchPassive(matching, options)) {
5278 if (options & kIONotifyOnce) {
5279 service->retain();
5280 current = service;
5281 } else {
5282 current = OSSet::withObjects((const OSObject **) &service, 1, 1 );
5283 }
5284 }
5285 } else {
5286 IOServiceMatchContext ctx;
5287 ctx.table = matching;
5288 ctx.state = inState;
5289 ctx.count = 0;
5290 ctx.done = 0;
5291 ctx.options = options;
5292 ctx.result = NULL;
5293
5294 if ((str = OSDynamicCast(OSString, obj))) {
5295 const OSSymbol * sym = OSSymbol::withString(str);
5296 OSMetaClass::applyToInstancesOfClassName(sym, instanceMatch, &ctx);
5297 sym->release();
5298 } else {
5299 IOService::gMetaClass.applyToInstances(instanceMatch, &ctx);
5300 }
5301
5302
5303 current = ctx.result;
5304
5305 options |= kIOServiceInternalDone | kIOServiceClassDone;
5306 if (current && (ctx.done != ctx.count)) {
5307 OSSet *
5308 source = OSDynamicCast(OSSet, current);
5309 current = NULL;
5310 while ((service = (IOService *) source->getAnyObject())) {
5311 if (service->matchPassive(matching, options)) {
5312 if (options & kIONotifyOnce) {
5313 service->retain();
5314 current = service;
5315 break;
5316 }
5317 if (current) {
5318 ((OSSet *)current)->setObject( service );
5319 } else {
5320 current = OSSet::withObjects(
5321 (const OSObject **) &service, 1, 1 );
5322 }
5323 }
5324 source->removeObject(service);
5325 }
5326 source->release();
5327 }
5328 }
5329
5330 #if MATCH_DEBUG
5331 {
5332 OSObject * _current = 0;
5333
5334 iter = IORegistryIterator::iterateOver( gIOServicePlane,
5335 kIORegistryIterateRecursively );
5336 if (iter) {
5337 do {
5338 iter->reset();
5339 while ((service = (IOService *) iter->getNextObject())) {
5340 if ((inState == (service->__state[0] & inState))
5341 && (0 == (service->__state[0] & kIOServiceInactiveState))
5342 && service->matchPassive(matching, 0)) {
5343 if (options & kIONotifyOnce) {
5344 service->retain();
5345 _current = service;
5346 break;
5347 }
5348 if (_current) {
5349 ((OSSet *)_current)->setObject( service );
5350 } else {
5351 _current = OSSet::withObjects(
5352 (const OSObject **) &service, 1, 1 );
5353 }
5354 }
5355 }
5356 } while (!service && !iter->isValid());
5357 iter->release();
5358 }
5359
5360 if (((current != 0) != (_current != 0))
5361 || (current && _current && !current->isEqualTo(_current))) {
5362 OSSerialize * s1 = OSSerialize::withCapacity(128);
5363 OSSerialize * s2 = OSSerialize::withCapacity(128);
5364 current->serialize(s1);
5365 _current->serialize(s2);
5366 kprintf("**mismatch** %p %p\n%s\n%s\n%s\n", IOSERVICE_OBFUSCATE(current),
5367 IOSERVICE_OBFUSCATE(_current), s->text(), s1->text(), s2->text());
5368 s1->release();
5369 s2->release();
5370 }
5371
5372 if (_current) {
5373 _current->release();
5374 }
5375 }
5376
5377 s->release();
5378 #endif
5379
5380 if (current && (0 == (options & (kIONotifyOnce | kIOServiceExistingSet)))) {
5381 iter = OSCollectionIterator::withCollection((OSSet *)current );
5382 current->release();
5383 current = iter;
5384 }
5385
5386 return current;
5387 }
5388
5389 // public version
5390 OSIterator *
5391 IOService::getMatchingServices( OSDictionary * matching )
5392 {
5393 OSIterator * iter;
5394
5395 // is a lock even needed?
5396 LOCKWRITENOTIFY();
5397
5398 iter = (OSIterator *) copyExistingServices( matching,
5399 kIOServiceMatchedState );
5400
5401 UNLOCKNOTIFY();
5402
5403 return iter;
5404 }
5405
5406 IOService *
5407 IOService::copyMatchingService( OSDictionary * matching )
5408 {
5409 IOService * service;
5410
5411 // is a lock even needed?
5412 LOCKWRITENOTIFY();
5413
5414 service = (IOService *) copyExistingServices( matching,
5415 kIOServiceMatchedState, kIONotifyOnce );
5416
5417 UNLOCKNOTIFY();
5418
5419 return service;
5420 }
5421
5422 struct _IOServiceMatchingNotificationHandlerRef {
5423 IOServiceNotificationHandler handler;
5424 void * ref;
5425 };
5426
5427 static bool
5428 _IOServiceMatchingNotificationHandler( void * target, void * refCon,
5429 IOService * newService,
5430 IONotifier * notifier )
5431 {
5432 return (*((_IOServiceNotifier *) notifier)->compatHandler)(target, refCon, newService);
5433 }
5434
5435 // internal - call with gNotificationLock
5436 IONotifier *
5437 IOService::setNotification(
5438 const OSSymbol * type, OSDictionary * matching,
5439 IOServiceMatchingNotificationHandler handler, void * target, void * ref,
5440 SInt32 priority )
5441 {
5442 _IOServiceNotifier * notify = NULL;
5443 OSOrderedSet * set;
5444
5445 if (!matching) {
5446 return NULL;
5447 }
5448
5449 notify = new _IOServiceNotifier;
5450 if (notify && !notify->init()) {
5451 notify->release();
5452 notify = NULL;
5453 }
5454
5455 if (notify) {
5456 notify->handler = handler;
5457 notify->target = target;
5458 notify->type = type;
5459 notify->matching = matching;
5460 matching->retain();
5461 if (handler == &_IOServiceMatchingNotificationHandler) {
5462 notify->compatHandler = ((_IOServiceMatchingNotificationHandlerRef *)ref)->handler;
5463 notify->ref = ((_IOServiceMatchingNotificationHandlerRef *)ref)->ref;
5464 } else {
5465 notify->ref = ref;
5466 }
5467 notify->priority = priority;
5468 notify->state = kIOServiceNotifyEnable;
5469 queue_init( &notify->handlerInvocations );
5470
5471 ////// queue
5472
5473 if (NULL == (set = (OSOrderedSet *) gNotifications->getObject( type ))) {
5474 set = OSOrderedSet::withCapacity( 1,
5475 IONotifyOrdering, NULL );
5476 if (set) {
5477 gNotifications->setObject( type, set );
5478 set->release();
5479 }
5480 }
5481 notify->whence = set;
5482 if (set) {
5483 set->setObject( notify );
5484 }
5485 }
5486
5487 return notify;
5488 }
5489
5490 // internal - call with gNotificationLock
5491 IONotifier *
5492 IOService::doInstallNotification(
5493 const OSSymbol * type, OSDictionary * matching,
5494 IOServiceMatchingNotificationHandler handler,
5495 void * target, void * ref,
5496 SInt32 priority, OSIterator ** existing )
5497 {
5498 OSIterator * exist;
5499 IONotifier * notify;
5500 IOOptionBits inState;
5501
5502 if (!matching) {
5503 return NULL;
5504 }
5505
5506 if (type == gIOPublishNotification) {
5507 inState = kIOServiceRegisteredState;
5508 } else if (type == gIOFirstPublishNotification) {
5509 inState = kIOServiceFirstPublishState;
5510 } else if (type == gIOMatchedNotification) {
5511 inState = kIOServiceMatchedState;
5512 } else if (type == gIOFirstMatchNotification) {
5513 inState = kIOServiceFirstMatchState;
5514 } else if ((type == gIOTerminatedNotification) || (type == gIOWillTerminateNotification)) {
5515 inState = 0;
5516 } else {
5517 return NULL;
5518 }
5519
5520 notify = setNotification( type, matching, handler, target, ref, priority );
5521
5522 if (inState) {
5523 // get the current set
5524 exist = (OSIterator *) copyExistingServices( matching, inState );
5525 } else {
5526 exist = NULL;
5527 }
5528
5529 *existing = exist;
5530
5531 return notify;
5532 }
5533
5534 #if !defined(__LP64__)
5535 IONotifier *
5536 IOService::installNotification(const OSSymbol * type, OSDictionary * matching,
5537 IOServiceNotificationHandler handler,
5538 void * target, void * refCon,
5539 SInt32 priority, OSIterator ** existing )
5540 {
5541 IONotifier * result;
5542 _IOServiceMatchingNotificationHandlerRef ref;
5543 ref.handler = handler;
5544 ref.ref = refCon;
5545
5546 result = (_IOServiceNotifier *) installNotification( type, matching,
5547 &_IOServiceMatchingNotificationHandler,
5548 target, &ref, priority, existing );
5549 if (result) {
5550 matching->release();
5551 }
5552
5553 return result;
5554 }
5555 #endif /* !defined(__LP64__) */
5556
5557
5558 IONotifier *
5559 IOService::installNotification(
5560 const OSSymbol * type, OSDictionary * matching,
5561 IOServiceMatchingNotificationHandler handler,
5562 void * target, void * ref,
5563 SInt32 priority, OSIterator ** existing )
5564 {
5565 IONotifier * notify;
5566
5567 LOCKWRITENOTIFY();
5568
5569 notify = doInstallNotification( type, matching, handler, target, ref,
5570 priority, existing );
5571
5572 // in case handler remove()s
5573 if (notify) {
5574 notify->retain();
5575 }
5576
5577 UNLOCKNOTIFY();
5578
5579 return notify;
5580 }
5581
5582 IONotifier *
5583 IOService::addNotification(
5584 const OSSymbol * type, OSDictionary * matching,
5585 IOServiceNotificationHandler handler,
5586 void * target, void * refCon,
5587 SInt32 priority )
5588 {
5589 IONotifier * result;
5590 _IOServiceMatchingNotificationHandlerRef ref;
5591
5592 ref.handler = handler;
5593 ref.ref = refCon;
5594
5595 result = addMatchingNotification(type, matching, &_IOServiceMatchingNotificationHandler,
5596 target, &ref, priority);
5597
5598 if (result) {
5599 matching->release();
5600 }
5601
5602 return result;
5603 }
5604
5605 IONotifier *
5606 IOService::addMatchingNotification(
5607 const OSSymbol * type, OSDictionary * matching,
5608 IOServiceMatchingNotificationHandler handler,
5609 void * target, void * ref,
5610 SInt32 priority )
5611 {
5612 OSIterator * existing = NULL;
5613 IONotifier * ret;
5614 _IOServiceNotifier * notify;
5615 IOService * next;
5616
5617 ret = notify = (_IOServiceNotifier *) installNotification( type, matching,
5618 handler, target, ref, priority, &existing );
5619 if (!ret) {
5620 return NULL;
5621 }
5622
5623 // send notifications for existing set
5624 if (existing) {
5625 while ((next = (IOService *) existing->getNextObject())) {
5626 if (0 == (next->__state[0] & kIOServiceInactiveState)) {
5627 next->invokeNotifier( notify );
5628 }
5629 }
5630 existing->release();
5631 }
5632
5633 LOCKWRITENOTIFY();
5634 bool removed = (NULL == notify->whence);
5635 notify->release();
5636 if (removed) {
5637 ret = gIOServiceNullNotifier;
5638 }
5639 UNLOCKNOTIFY();
5640
5641 return ret;
5642 }
5643
5644 static bool
5645 IOServiceMatchingNotificationHandlerToBlock( void * target __unused, void * refCon,
5646 IOService * newService,
5647 IONotifier * notifier )
5648 {
5649 return ((IOServiceMatchingNotificationHandlerBlock) refCon)(newService, notifier);
5650 }
5651
5652 IONotifier *
5653 IOService::addMatchingNotification(
5654 const OSSymbol * type, OSDictionary * matching,
5655 SInt32 priority,
5656 IOServiceMatchingNotificationHandlerBlock handler)
5657 {
5658 IONotifier * notify;
5659 void * block;
5660
5661 block = Block_copy(handler);
5662 if (!block) {
5663 return NULL;
5664 }
5665
5666 notify = addMatchingNotification(type, matching,
5667 &IOServiceMatchingNotificationHandlerToBlock, NULL, block, priority);
5668
5669 if (!notify) {
5670 Block_release(block);
5671 }
5672
5673 return notify;
5674 }
5675
5676
5677 bool
5678 IOService::syncNotificationHandler(
5679 void * /* target */, void * ref,
5680 IOService * newService,
5681 IONotifier * notifier )
5682 {
5683 LOCKWRITENOTIFY();
5684 if (!*((IOService **) ref)) {
5685 newService->retain();
5686 (*(IOService **) ref) = newService;
5687 WAKEUPNOTIFY(ref);
5688 }
5689 UNLOCKNOTIFY();
5690
5691 return false;
5692 }
5693
5694 IOService *
5695 IOService::waitForMatchingService( OSDictionary * matching,
5696 uint64_t timeout)
5697 {
5698 IONotifier * notify = NULL;
5699 // priority doesn't help us much since we need a thread wakeup
5700 SInt32 priority = 0;
5701 IOService * result;
5702
5703 if (!matching) {
5704 return NULL;
5705 }
5706
5707 result = NULL;
5708
5709 LOCKWRITENOTIFY();
5710 do{
5711 result = (IOService *) copyExistingServices( matching,
5712 kIOServiceMatchedState, kIONotifyOnce );
5713 if (result) {
5714 break;
5715 }
5716 notify = IOService::setNotification( gIOMatchedNotification, matching,
5717 &IOService::syncNotificationHandler, (void *) NULL,
5718 &result, priority );
5719 if (!notify) {
5720 break;
5721 }
5722 if (UINT64_MAX != timeout) {
5723 AbsoluteTime deadline;
5724 nanoseconds_to_absolutetime(timeout, &deadline);
5725 clock_absolutetime_interval_to_deadline(deadline, &deadline);
5726 SLEEPNOTIFYTO(&result, deadline);
5727 } else {
5728 SLEEPNOTIFY(&result);
5729 }
5730 }while (false);
5731
5732 UNLOCKNOTIFY();
5733
5734 if (notify) {
5735 notify->remove(); // dequeues
5736 }
5737 return result;
5738 }
5739
5740 IOService *
5741 IOService::waitForService( OSDictionary * matching,
5742 mach_timespec_t * timeout )
5743 {
5744 IOService * result;
5745 uint64_t timeoutNS;
5746
5747 if (timeout) {
5748 timeoutNS = timeout->tv_sec;
5749 timeoutNS *= kSecondScale;
5750 timeoutNS += timeout->tv_nsec;
5751 } else {
5752 timeoutNS = UINT64_MAX;
5753 }
5754
5755 result = waitForMatchingService(matching, timeoutNS);
5756
5757 matching->release();
5758 if (result) {
5759 result->release();
5760 }
5761
5762 return result;
5763 }
5764
5765 __dead2
5766 void
5767 IOService::deliverNotification( const OSSymbol * type,
5768 IOOptionBits orNewState, IOOptionBits andNewState )
5769 {
5770 panic("deliverNotification");
5771 }
5772
5773 OSArray *
5774 IOService::copyNotifiers(const OSSymbol * type,
5775 IOOptionBits orNewState, IOOptionBits andNewState )
5776 {
5777 _IOServiceNotifier * notify;
5778 OSIterator * iter;
5779 OSArray * willSend = NULL;
5780
5781 lockForArbitration();
5782
5783 if ((0 == (__state[0] & kIOServiceInactiveState))
5784 || (type == gIOTerminatedNotification)
5785 || (type == gIOWillTerminateNotification)) {
5786 LOCKREADNOTIFY();
5787
5788 iter = OSCollectionIterator::withCollection((OSOrderedSet *)
5789 gNotifications->getObject( type ));
5790
5791 if (iter) {
5792 while ((notify = (_IOServiceNotifier *) iter->getNextObject())) {
5793 if (matchPassive(notify->matching, 0)
5794 && (kIOServiceNotifyEnable & notify->state)) {
5795 if (NULL == willSend) {
5796 willSend = OSArray::withCapacity(8);
5797 }
5798 if (willSend) {
5799 willSend->setObject( notify );
5800 }
5801 }
5802 }
5803 iter->release();
5804 }
5805 __state[0] = (__state[0] | orNewState) & andNewState;
5806 UNLOCKNOTIFY();
5807 }
5808
5809 unlockForArbitration();
5810
5811 return willSend;
5812 }
5813
5814 IOOptionBits
5815 IOService::getState( void ) const
5816 {
5817 return __state[0];
5818 }
5819
5820 /*
5821 * Helpers to make matching objects for simple cases
5822 */
5823
5824 OSDictionary *
5825 IOService::serviceMatching( const OSString * name,
5826 OSDictionary * table )
5827 {
5828 const OSString * str;
5829
5830 str = OSSymbol::withString(name);
5831 if (!str) {
5832 return NULL;
5833 }
5834
5835 if (!table) {
5836 table = OSDictionary::withCapacity( 2 );
5837 }
5838 if (table) {
5839 table->setObject(gIOProviderClassKey, (OSObject *)str );
5840 }
5841 str->release();
5842
5843 return table;
5844 }
5845
5846 OSDictionary *
5847 IOService::serviceMatching( const char * name,
5848 OSDictionary * table )
5849 {
5850 const OSString * str;
5851
5852 str = OSSymbol::withCString( name );
5853 if (!str) {
5854 return NULL;
5855 }
5856
5857 table = serviceMatching( str, table );
5858 str->release();
5859 return table;
5860 }
5861
5862 OSDictionary *
5863 IOService::nameMatching( const OSString * name,
5864 OSDictionary * table )
5865 {
5866 if (!table) {
5867 table = OSDictionary::withCapacity( 2 );
5868 }
5869 if (table) {
5870 table->setObject( gIONameMatchKey, (OSObject *)name );
5871 }
5872
5873 return table;
5874 }
5875
5876 OSDictionary *
5877 IOService::nameMatching( const char * name,
5878 OSDictionary * table )
5879 {
5880 const OSString * str;
5881
5882 str = OSSymbol::withCString( name );
5883 if (!str) {
5884 return NULL;
5885 }
5886
5887 table = nameMatching( str, table );
5888 str->release();
5889 return table;
5890 }
5891
5892 OSDictionary *
5893 IOService::resourceMatching( const OSString * str,
5894 OSDictionary * table )
5895 {
5896 table = serviceMatching( gIOResourcesKey, table );
5897 if (table) {
5898 table->setObject( gIOResourceMatchKey, (OSObject *) str );
5899 }
5900
5901 return table;
5902 }
5903
5904 OSDictionary *
5905 IOService::resourceMatching( const char * name,
5906 OSDictionary * table )
5907 {
5908 const OSSymbol * str;
5909
5910 str = OSSymbol::withCString( name );
5911 if (!str) {
5912 return NULL;
5913 }
5914
5915 table = resourceMatching( str, table );
5916 str->release();
5917
5918 return table;
5919 }
5920
5921 OSDictionary *
5922 IOService::propertyMatching( const OSSymbol * key, const OSObject * value,
5923 OSDictionary * table )
5924 {
5925 OSDictionary * properties;
5926
5927 properties = OSDictionary::withCapacity( 2 );
5928 if (!properties) {
5929 return NULL;
5930 }
5931 properties->setObject( key, value );
5932
5933 if (!table) {
5934 table = OSDictionary::withCapacity( 2 );
5935 }
5936 if (table) {
5937 table->setObject( gIOPropertyMatchKey, properties );
5938 }
5939
5940 properties->release();
5941
5942 return table;
5943 }
5944
5945 OSDictionary *
5946 IOService::registryEntryIDMatching( uint64_t entryID,
5947 OSDictionary * table )
5948 {
5949 OSNumber * num;
5950
5951 num = OSNumber::withNumber( entryID, 64 );
5952 if (!num) {
5953 return NULL;
5954 }
5955
5956 if (!table) {
5957 table = OSDictionary::withCapacity( 2 );
5958 }
5959 if (table) {
5960 table->setObject( gIORegistryEntryIDKey, num );
5961 }
5962
5963 if (num) {
5964 num->release();
5965 }
5966
5967 return table;
5968 }
5969
5970
5971 /*
5972 * _IOServiceNotifier
5973 */
5974
5975 // wait for all threads, other than the current one,
5976 // to exit the handler
5977
5978 void
5979 _IOServiceNotifier::wait()
5980 {
5981 _IOServiceNotifierInvocation * next;
5982 bool doWait;
5983
5984 do {
5985 doWait = false;
5986 queue_iterate( &handlerInvocations, next,
5987 _IOServiceNotifierInvocation *, link) {
5988 if (next->thread != current_thread()) {
5989 doWait = true;
5990 break;
5991 }
5992 }
5993 if (doWait) {
5994 state |= kIOServiceNotifyWaiter;
5995 SLEEPNOTIFY(this);
5996 }
5997 } while (doWait);
5998 }
5999
6000 void
6001 _IOServiceNotifier::free()
6002 {
6003 assert( queue_empty( &handlerInvocations ));
6004
6005 if (handler == &IOServiceMatchingNotificationHandlerToBlock) {
6006 Block_release(ref);
6007 }
6008
6009 OSObject::free();
6010 }
6011
6012 void
6013 _IOServiceNotifier::remove()
6014 {
6015 LOCKWRITENOTIFY();
6016
6017 if (whence) {
6018 whence->removeObject((OSObject *) this );
6019 whence = NULL;
6020 }
6021 if (matching) {
6022 matching->release();
6023 matching = NULL;
6024 }
6025
6026 state &= ~kIOServiceNotifyEnable;
6027
6028 wait();
6029
6030 UNLOCKNOTIFY();
6031
6032 release();
6033 }
6034
6035 bool
6036 _IOServiceNotifier::disable()
6037 {
6038 bool ret;
6039
6040 LOCKWRITENOTIFY();
6041
6042 ret = (0 != (kIOServiceNotifyEnable & state));
6043 state &= ~kIOServiceNotifyEnable;
6044 if (ret) {
6045 wait();
6046 }
6047
6048 UNLOCKNOTIFY();
6049
6050 return ret;
6051 }
6052
6053 void
6054 _IOServiceNotifier::enable( bool was )
6055 {
6056 LOCKWRITENOTIFY();
6057 if (was) {
6058 state |= kIOServiceNotifyEnable;
6059 } else {
6060 state &= ~kIOServiceNotifyEnable;
6061 }
6062 UNLOCKNOTIFY();
6063 }
6064
6065
6066 /*
6067 * _IOServiceNullNotifier
6068 */
6069
6070 void
6071 _IOServiceNullNotifier::taggedRetain(const void *tag) const
6072 {
6073 }
6074 void
6075 _IOServiceNullNotifier::taggedRelease(const void *tag, const int when) const
6076 {
6077 }
6078 void
6079 _IOServiceNullNotifier::free()
6080 {
6081 }
6082 void
6083 _IOServiceNullNotifier::wait()
6084 {
6085 }
6086 void
6087 _IOServiceNullNotifier::remove()
6088 {
6089 }
6090 void
6091 _IOServiceNullNotifier::enable(bool was)
6092 {
6093 }
6094 bool
6095 _IOServiceNullNotifier::disable()
6096 {
6097 return false;
6098 }
6099
6100 /*
6101 * IOResources
6102 */
6103
6104 IOService *
6105 IOResources::resources( void )
6106 {
6107 IOResources * inst;
6108
6109 inst = new IOResources;
6110 if (inst && !inst->init()) {
6111 inst->release();
6112 inst = NULL;
6113 }
6114
6115 return inst;
6116 }
6117
6118 bool
6119 IOResources::init( OSDictionary * dictionary )
6120 {
6121 // Do super init first
6122 if (!IOService::init()) {
6123 return false;
6124 }
6125
6126 // Allow PAL layer to publish a value
6127 const char *property_name;
6128 int property_value;
6129
6130 pal_get_resource_property( &property_name, &property_value );
6131
6132 if (property_name) {
6133 OSNumber *num;
6134 const OSSymbol * sym;
6135
6136 if ((num = OSNumber::withNumber(property_value, 32)) != NULL) {
6137 if ((sym = OSSymbol::withCString( property_name)) != NULL) {
6138 this->setProperty( sym, num );
6139 sym->release();
6140 }
6141 num->release();
6142 }
6143 }
6144
6145 return true;
6146 }
6147
6148 IOReturn
6149 IOResources::newUserClient(task_t owningTask, void * securityID,
6150 UInt32 type, OSDictionary * properties,
6151 IOUserClient ** handler)
6152 {
6153 return kIOReturnUnsupported;
6154 }
6155
6156 IOWorkLoop *
6157 IOResources::getWorkLoop() const
6158 {
6159 // If we are the resource root
6160 // then use the platform's workloop
6161 if (this == (IOResources *) gIOResources) {
6162 return getPlatform()->getWorkLoop();
6163 } else {
6164 return IOService::getWorkLoop();
6165 }
6166 }
6167
6168 static bool
6169 IOResourcesMatchPropertyTable(IOService * resources, OSDictionary * table)
6170 {
6171 OSObject * prop;
6172 OSString * str;
6173 OSSet * set;
6174 OSIterator * iter;
6175 OSObject * obj;
6176 OSArray * keys;
6177 bool ok = true;
6178
6179 prop = table->getObject( gIOResourceMatchKey );
6180 str = OSDynamicCast( OSString, prop );
6181 if (str) {
6182 ok = (NULL != resources->getProperty( str ));
6183 } else if ((set = OSDynamicCast( OSSet, prop))) {
6184 iter = OSCollectionIterator::withCollection( set );
6185 ok = (iter != NULL);
6186 while (ok && (str = OSDynamicCast( OSString, iter->getNextObject()))) {
6187 ok = (NULL != resources->getProperty( str ));
6188 }
6189
6190 if (iter) {
6191 iter->release();
6192 }
6193 } else if ((prop = table->getObject(gIOResourceMatchedKey))) {
6194 obj = resources->copyProperty(gIOResourceMatchedKey);
6195 keys = OSDynamicCast(OSArray, obj);
6196 ok = false;
6197 if (keys) {
6198 // assuming OSSymbol
6199 ok = ((-1U) != keys->getNextIndexOfObject(prop, 0));
6200 }
6201 OSSafeReleaseNULL(obj);
6202 }
6203
6204 return ok;
6205 }
6206
6207 bool
6208 IOResources::matchPropertyTable( OSDictionary * table )
6209 {
6210 return IOResourcesMatchPropertyTable(this, table);
6211 }
6212
6213 /*
6214 * IOUserResources
6215 */
6216
6217 IOService *
6218 IOUserResources::resources( void )
6219 {
6220 IOUserResources * inst;
6221
6222 inst = OSTypeAlloc(IOUserResources);
6223 if (inst && !inst->init()) {
6224 inst->release();
6225 inst = NULL;
6226 }
6227
6228 return inst;
6229 }
6230
6231 bool
6232 IOUserResources::init( OSDictionary * dictionary )
6233 {
6234 // Do super init first
6235 if (!IOService::init()) {
6236 return false;
6237 }
6238 return true;
6239 }
6240
6241 IOReturn
6242 IOUserResources::newUserClient(task_t owningTask, void * securityID,
6243 UInt32 type, OSDictionary * properties,
6244 IOUserClient ** handler)
6245 {
6246 return kIOReturnUnsupported;
6247 }
6248
6249 IOWorkLoop *
6250 IOUserResources::getWorkLoop() const
6251 {
6252 return getPlatform()->getWorkLoop();
6253 }
6254
6255 bool
6256 IOUserResources::matchPropertyTable( OSDictionary * table )
6257 {
6258 return IOResourcesMatchPropertyTable(this, table);
6259 }
6260
6261 // --
6262
6263 void
6264 IOService::consoleLockTimer(thread_call_param_t p0, thread_call_param_t p1)
6265 {
6266 IOService::updateConsoleUsers(NULL, 0);
6267 }
6268
6269 void
6270 IOService::updateConsoleUsers(OSArray * consoleUsers, IOMessage systemMessage)
6271 {
6272 IORegistryEntry * regEntry;
6273 OSObject * locked = kOSBooleanFalse;
6274 uint32_t idx;
6275 bool publish;
6276 OSDictionary * user;
6277 static IOMessage sSystemPower;
6278 clock_sec_t now = 0;
6279 clock_usec_t microsecs;
6280
6281 regEntry = IORegistryEntry::getRegistryRoot();
6282
6283 if (!gIOChosenEntry) {
6284 gIOChosenEntry = IORegistryEntry::fromPath("/chosen", gIODTPlane);
6285 }
6286
6287 IOLockLock(gIOConsoleUsersLock);
6288
6289 if (systemMessage) {
6290 sSystemPower = systemMessage;
6291 #if HIBERNATION
6292 if (kIOMessageSystemHasPoweredOn == systemMessage) {
6293 uint32_t lockState = IOHibernateWasScreenLocked();
6294 switch (lockState) {
6295 case 0:
6296 break;
6297 case kIOScreenLockLocked:
6298 case kIOScreenLockFileVaultDialog:
6299 gIOConsoleBooterLockState = kOSBooleanTrue;
6300 break;
6301 case kIOScreenLockNoLock:
6302 gIOConsoleBooterLockState = NULL;
6303 break;
6304 case kIOScreenLockUnlocked:
6305 default:
6306 gIOConsoleBooterLockState = kOSBooleanFalse;
6307 break;
6308 }
6309 }
6310 #endif /* HIBERNATION */
6311 }
6312
6313 if (consoleUsers) {
6314 OSNumber * num = NULL;
6315 bool loginLocked = true;
6316
6317 gIOConsoleLoggedIn = false;
6318 for (idx = 0;
6319 (user = OSDynamicCast(OSDictionary, consoleUsers->getObject(idx)));
6320 idx++) {
6321 gIOConsoleLoggedIn |= ((kOSBooleanTrue == user->getObject(gIOConsoleSessionOnConsoleKey))
6322 && (kOSBooleanTrue == user->getObject(gIOConsoleSessionLoginDoneKey)));
6323
6324 loginLocked &= (kOSBooleanTrue == user->getObject(gIOConsoleSessionScreenIsLockedKey));
6325 if (!num) {
6326 num = OSDynamicCast(OSNumber, user->getObject(gIOConsoleSessionScreenLockedTimeKey));
6327 }
6328 }
6329 #if HIBERNATION
6330 if (!loginLocked) {
6331 gIOConsoleBooterLockState = NULL;
6332 }
6333 IOLog("IOConsoleUsers: time(%d) %ld->%d, lin %d, llk %d, \n",
6334 (num != NULL), gIOConsoleLockTime, (num ? num->unsigned32BitValue() : 0),
6335 gIOConsoleLoggedIn, loginLocked);
6336 #endif /* HIBERNATION */
6337 gIOConsoleLockTime = num ? num->unsigned32BitValue() : 0;
6338 }
6339
6340 if (!gIOConsoleLoggedIn
6341 || (kIOMessageSystemWillSleep == sSystemPower)
6342 || (kIOMessageSystemPagingOff == sSystemPower)) {
6343 locked = kOSBooleanTrue;
6344 }
6345 #if HIBERNATION
6346 else if (gIOConsoleBooterLockState) {
6347 locked = gIOConsoleBooterLockState;
6348 }
6349 #endif /* HIBERNATION */
6350 else if (gIOConsoleLockTime) {
6351 clock_get_calendar_microtime(&now, &microsecs);
6352 if (gIOConsoleLockTime > now) {
6353 AbsoluteTime deadline;
6354 clock_interval_to_deadline(gIOConsoleLockTime - now, kSecondScale, &deadline);
6355 thread_call_enter_delayed(gIOConsoleLockCallout, deadline);
6356 } else {
6357 locked = kOSBooleanTrue;
6358 }
6359 }
6360
6361 publish = (consoleUsers || (locked != regEntry->getProperty(gIOConsoleLockedKey)));
6362 if (publish) {
6363 regEntry->setProperty(gIOConsoleLockedKey, locked);
6364 if (consoleUsers) {
6365 regEntry->setProperty(gIOConsoleUsersKey, consoleUsers);
6366 }
6367 OSIncrementAtomic( &gIOConsoleUsersSeed );
6368 }
6369
6370 #if HIBERNATION
6371 if (gIOChosenEntry) {
6372 if (locked == kOSBooleanTrue) {
6373 gIOScreenLockState = kIOScreenLockLocked;
6374 } else if (gIOConsoleLockTime) {
6375 gIOScreenLockState = kIOScreenLockUnlocked;
6376 } else {
6377 gIOScreenLockState = kIOScreenLockNoLock;
6378 }
6379 gIOChosenEntry->setProperty(kIOScreenLockStateKey, &gIOScreenLockState, sizeof(gIOScreenLockState));
6380
6381 IOLog("IOConsoleUsers: gIOScreenLockState %d, hs %d, bs %d, now %ld, sm 0x%x\n",
6382 gIOScreenLockState, gIOHibernateState, (gIOConsoleBooterLockState != NULL), now, systemMessage);
6383 }
6384 #endif /* HIBERNATION */
6385
6386 IOLockUnlock(gIOConsoleUsersLock);
6387
6388 if (publish) {
6389 publishResource( gIOConsoleUsersSeedKey, gIOConsoleUsersSeedValue );
6390
6391 MessageClientsContext context;
6392
6393 context.service = getServiceRoot();
6394 context.type = kIOMessageConsoleSecurityChange;
6395 context.argument = (void *) regEntry;
6396 context.argSize = 0;
6397
6398 applyToInterestNotifiers(getServiceRoot(), gIOConsoleSecurityInterest,
6399 &messageClientsApplier, &context );
6400 }
6401 }
6402
6403 IOReturn
6404 IOResources::setProperties( OSObject * properties )
6405 {
6406 IOReturn err;
6407 const OSSymbol * key;
6408 OSDictionary * dict;
6409 OSCollectionIterator * iter;
6410
6411 err = IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator);
6412 if (kIOReturnSuccess != err) {
6413 return err;
6414 }
6415
6416 dict = OSDynamicCast(OSDictionary, properties);
6417 if (NULL == dict) {
6418 return kIOReturnBadArgument;
6419 }
6420
6421 iter = OSCollectionIterator::withCollection( dict);
6422 if (NULL == iter) {
6423 return kIOReturnBadArgument;
6424 }
6425
6426 while ((key = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
6427 if (gIOConsoleUsersKey == key) {
6428 do{
6429 OSArray * consoleUsers;
6430 consoleUsers = OSDynamicCast(OSArray, dict->getObject(key));
6431 if (!consoleUsers) {
6432 continue;
6433 }
6434 IOService::updateConsoleUsers(consoleUsers, 0);
6435 }while (false);
6436 }
6437
6438 publishResource( key, dict->getObject(key));
6439 }
6440
6441 iter->release();
6442
6443 return kIOReturnSuccess;
6444 }
6445
6446 /*
6447 * Helpers for matching dictionaries.
6448 * Keys existing in matching are checked in properties.
6449 * Keys may be a string or OSCollection of IOStrings
6450 */
6451
6452 bool
6453 IOService::compareProperty( OSDictionary * matching,
6454 const char * key )
6455 {
6456 OSObject * value;
6457 OSObject * prop;
6458 bool ok;
6459
6460 value = matching->getObject( key );
6461 if (value) {
6462 prop = copyProperty(key);
6463 ok = value->isEqualTo(prop);
6464 if (prop) {
6465 prop->release();
6466 }
6467 } else {
6468 ok = true;
6469 }
6470
6471 return ok;
6472 }
6473
6474
6475 bool
6476 IOService::compareProperty( OSDictionary * matching,
6477 const OSString * key )
6478 {
6479 OSObject * value;
6480 OSObject * prop;
6481 bool ok;
6482
6483 value = matching->getObject( key );
6484 if (value) {
6485 prop = copyProperty(key);
6486 ok = value->isEqualTo(prop);
6487 if (prop) {
6488 prop->release();
6489 }
6490 } else {
6491 ok = true;
6492 }
6493
6494 return ok;
6495 }
6496
6497 bool
6498 IOService::compareProperties( OSDictionary * matching,
6499 OSCollection * keys )
6500 {
6501 OSCollectionIterator * iter;
6502 const OSString * key;
6503 bool ok = true;
6504
6505 if (!matching || !keys) {
6506 return false;
6507 }
6508
6509 iter = OSCollectionIterator::withCollection( keys );
6510
6511 if (iter) {
6512 while (ok && (key = OSDynamicCast( OSString, iter->getNextObject()))) {
6513 ok = compareProperty( matching, key );
6514 }
6515
6516 iter->release();
6517 }
6518 keys->release(); // !! consume a ref !!
6519
6520 return ok;
6521 }
6522
6523 /* Helper to add a location matching dict to the table */
6524
6525 OSDictionary *
6526 IOService::addLocation( OSDictionary * table )
6527 {
6528 OSDictionary * dict;
6529
6530 if (!table) {
6531 return NULL;
6532 }
6533
6534 dict = OSDictionary::withCapacity( 1 );
6535 if (dict) {
6536 bool ok = table->setObject( gIOLocationMatchKey, dict );
6537 dict->release();
6538 if (!ok) {
6539 dict = NULL;
6540 }
6541 }
6542
6543 return dict;
6544 }
6545
6546 /*
6547 * Go looking for a provider to match a location dict.
6548 */
6549
6550 IOService *
6551 IOService::matchLocation( IOService * /* client */ )
6552 {
6553 IOService * parent;
6554
6555 parent = getProvider();
6556
6557 if (parent) {
6558 parent = parent->matchLocation( this );
6559 }
6560
6561 return parent;
6562 }
6563
6564 bool
6565 IOService::matchInternal(OSDictionary * table, uint32_t options, uint32_t * did)
6566 {
6567 OSString * matched;
6568 OSObject * obj;
6569 OSString * str;
6570 IORegistryEntry * entry;
6571 OSNumber * num;
6572 bool match = true;
6573 bool changesOK = (0 != (kIOServiceChangesOK & options));
6574 uint32_t count;
6575 uint32_t done;
6576
6577 do{
6578 count = table->getCount();
6579 done = 0;
6580
6581 str = OSDynamicCast(OSString, table->getObject(gIOProviderClassKey));
6582 if (str) {
6583 done++;
6584 match = ((kIOServiceClassDone & options) || (NULL != metaCast(str)));
6585 #if MATCH_DEBUG
6586 match = (0 != metaCast( str ));
6587 if ((kIOServiceClassDone & options) && !match) {
6588 panic("classDone");
6589 }
6590 #endif
6591 if ((!match) || (done == count)) {
6592 break;
6593 }
6594 }
6595
6596 obj = table->getObject( gIONameMatchKey );
6597 if (obj) {
6598 done++;
6599 match = compareNames( obj, changesOK ? &matched : NULL );
6600 if (!match) {
6601 break;
6602 }
6603 if (changesOK && matched) {
6604 // leave a hint as to which name matched
6605 table->setObject( gIONameMatchedKey, matched );
6606 matched->release();
6607 }
6608 if (done == count) {
6609 break;
6610 }
6611 }
6612
6613 str = OSDynamicCast( OSString, table->getObject( gIOLocationMatchKey ));
6614 if (str) {
6615 const OSSymbol * sym;
6616 done++;
6617 match = false;
6618 sym = copyLocation();
6619 if (sym) {
6620 match = sym->isEqualTo( str );
6621 sym->release();
6622 }
6623 if ((!match) || (done == count)) {
6624 break;
6625 }
6626 }
6627
6628 obj = table->getObject( gIOPropertyMatchKey );
6629 if (obj) {
6630 OSDictionary * dict;
6631 OSDictionary * nextDict;
6632 OSIterator * iter;
6633 done++;
6634 match = false;
6635 dict = dictionaryWithProperties();
6636 if (dict) {
6637 nextDict = OSDynamicCast( OSDictionary, obj);
6638 if (nextDict) {
6639 iter = NULL;
6640 } else {
6641 iter = OSCollectionIterator::withCollection(
6642 OSDynamicCast(OSCollection, obj));
6643 }
6644
6645 while (nextDict
6646 || (iter && (NULL != (nextDict = OSDynamicCast(OSDictionary,
6647 iter->getNextObject()))))) {
6648 match = dict->isEqualTo( nextDict, nextDict);
6649 if (match) {
6650 break;
6651 }
6652 nextDict = NULL;
6653 }
6654 dict->release();
6655 if (iter) {
6656 iter->release();
6657 }
6658 }
6659 if ((!match) || (done == count)) {
6660 break;
6661 }
6662 }
6663
6664 obj = table->getObject( gIOPropertyExistsMatchKey );
6665 if (obj) {
6666 OSDictionary * dict;
6667 OSString * nextKey;
6668 OSIterator * iter;
6669 done++;
6670 match = false;
6671 dict = dictionaryWithProperties();
6672 if (dict) {
6673 nextKey = OSDynamicCast( OSString, obj);
6674 if (nextKey) {
6675 iter = NULL;
6676 } else {
6677 iter = OSCollectionIterator::withCollection(
6678 OSDynamicCast(OSCollection, obj));
6679 }
6680
6681 while (nextKey
6682 || (iter && (NULL != (nextKey = OSDynamicCast(OSString,
6683 iter->getNextObject()))))) {
6684 match = (NULL != dict->getObject(nextKey));
6685 if (match) {
6686 break;
6687 }
6688 nextKey = NULL;
6689 }
6690 dict->release();
6691 if (iter) {
6692 iter->release();
6693 }
6694 }
6695 if ((!match) || (done == count)) {
6696 break;
6697 }
6698 }
6699
6700 str = OSDynamicCast( OSString, table->getObject( gIOPathMatchKey ));
6701 if (str) {
6702 done++;
6703 entry = IORegistryEntry::fromPath( str->getCStringNoCopy());
6704 match = (this == entry);
6705 if (entry) {
6706 entry->release();
6707 }
6708 if ((!match) || (done == count)) {
6709 break;
6710 }
6711 }
6712
6713 num = OSDynamicCast( OSNumber, table->getObject( gIORegistryEntryIDKey ));
6714 if (num) {
6715 done++;
6716 match = (getRegistryEntryID() == num->unsigned64BitValue());
6717 if ((!match) || (done == count)) {
6718 break;
6719 }
6720 }
6721
6722 num = OSDynamicCast( OSNumber, table->getObject( gIOMatchedServiceCountKey ));
6723 if (num) {
6724 OSIterator * iter;
6725 IOService * service = NULL;
6726 UInt32 serviceCount = 0;
6727
6728 done++;
6729 iter = getClientIterator();
6730 if (iter) {
6731 while ((service = (IOService *) iter->getNextObject())) {
6732 if (kIOServiceInactiveState & service->__state[0]) {
6733 continue;
6734 }
6735 if (NULL == service->getProperty( gIOMatchCategoryKey )) {
6736 continue;
6737 }
6738 ++serviceCount;
6739 }
6740 iter->release();
6741 }
6742 match = (serviceCount == num->unsigned32BitValue());
6743 if ((!match) || (done == count)) {
6744 break;
6745 }
6746 }
6747
6748 #define propMatch(key) \
6749 obj = table->getObject(key); \
6750 if (obj) \
6751 { \
6752 OSObject * prop; \
6753 done++; \
6754 prop = copyProperty(key); \
6755 match = obj->isEqualTo(prop); \
6756 if (prop) prop->release(); \
6757 if ((!match) || (done == count)) break; \
6758 }
6759 propMatch(gIOBSDNameKey)
6760 propMatch(gIOBSDMajorKey)
6761 propMatch(gIOBSDMinorKey)
6762 propMatch(gIOBSDUnitKey)
6763 #undef propMatch
6764 }while (false);
6765
6766 if (did) {
6767 *did = done;
6768 }
6769 return match;
6770 }
6771
6772 bool
6773 IOService::passiveMatch( OSDictionary * table, bool changesOK )
6774 {
6775 return matchPassive(table, changesOK ? kIOServiceChangesOK : 0);
6776 }
6777
6778 bool
6779 IOService::matchPassive(OSDictionary * table, uint32_t options)
6780 {
6781 IOService * where;
6782 OSDictionary * nextTable;
6783 SInt32 score;
6784 OSNumber * newPri;
6785 bool match = true;
6786 bool matchParent = false;
6787 uint32_t count;
6788 uint32_t done;
6789
6790 assert( table );
6791
6792 #if !CONFIG_EMBEDDED
6793 OSArray* aliasServiceRegIds = NULL;
6794 IOService* foundAlternateService = NULL;
6795 #endif
6796
6797 #if MATCH_DEBUG
6798 OSDictionary * root = table;
6799 #endif
6800
6801 where = this;
6802 do{
6803 do{
6804 count = table->getCount();
6805 if (!(kIOServiceInternalDone & options)) {
6806 match = where->matchInternal(table, options, &done);
6807 // don't call family if we've done all the entries in the table
6808 if ((!match) || (done == count)) {
6809 break;
6810 }
6811 }
6812
6813 // pass in score from property table
6814 score = IOServiceObjectOrder( table, (void *) gIOProbeScoreKey);
6815
6816 // do family specific matching
6817 match = where->matchPropertyTable( table, &score );
6818
6819 if (!match) {
6820 #if IOMATCHDEBUG
6821 if (kIOLogMatch & getDebugFlags( table )) {
6822 LOG("%s: family specific matching fails\n", where->getName());
6823 }
6824 #endif
6825 break;
6826 }
6827
6828 if (kIOServiceChangesOK & options) {
6829 // save the score
6830 newPri = OSNumber::withNumber( score, 32 );
6831 if (newPri) {
6832 table->setObject( gIOProbeScoreKey, newPri );
6833 newPri->release();
6834 }
6835 }
6836
6837 options = 0;
6838 matchParent = false;
6839
6840 nextTable = OSDynamicCast(OSDictionary,
6841 table->getObject( gIOParentMatchKey ));
6842 if (nextTable) {
6843 // look for a matching entry anywhere up to root
6844 match = false;
6845 matchParent = true;
6846 table = nextTable;
6847 break;
6848 }
6849
6850 table = OSDynamicCast(OSDictionary,
6851 table->getObject( gIOLocationMatchKey ));
6852 if (table) {
6853 // look for a matching entry at matchLocation()
6854 match = false;
6855 where = where->getProvider();
6856 if (where && (where = where->matchLocation(where))) {
6857 continue;
6858 }
6859 }
6860 break;
6861 }while (true);
6862
6863 if (match == true) {
6864 break;
6865 }
6866
6867 if (matchParent == true) {
6868 #if !CONFIG_EMBEDDED
6869 // check if service has an alias to search its other "parents" if a parent match isn't found
6870 OSObject * prop = where->copyProperty(gIOServiceLegacyMatchingRegistryIDKey);
6871 OSNumber * alternateRegistryID = OSDynamicCast(OSNumber, prop);
6872 if (alternateRegistryID != NULL) {
6873 if (aliasServiceRegIds == NULL) {
6874 aliasServiceRegIds = OSArray::withCapacity(sizeof(alternateRegistryID));
6875 }
6876 aliasServiceRegIds->setObject(alternateRegistryID);
6877 }
6878 OSSafeReleaseNULL(prop);
6879 #endif
6880 } else {
6881 break;
6882 }
6883
6884 where = where->getProvider();
6885 #if !CONFIG_EMBEDDED
6886 if (where == NULL) {
6887 // there were no matching parent services, check to see if there are aliased services that have a matching parent
6888 if (aliasServiceRegIds != NULL) {
6889 unsigned int numAliasedServices = aliasServiceRegIds->getCount();
6890 if (numAliasedServices != 0) {
6891 OSNumber* alternateRegistryID = OSDynamicCast(OSNumber, aliasServiceRegIds->getObject(numAliasedServices - 1));
6892 if (alternateRegistryID != NULL) {
6893 OSDictionary* alternateMatchingDict = IOService::registryEntryIDMatching(alternateRegistryID->unsigned64BitValue());
6894 aliasServiceRegIds->removeObject(numAliasedServices - 1);
6895 if (alternateMatchingDict != NULL) {
6896 OSSafeReleaseNULL(foundAlternateService);
6897 foundAlternateService = IOService::copyMatchingService(alternateMatchingDict);
6898 alternateMatchingDict->release();
6899 if (foundAlternateService != NULL) {
6900 where = foundAlternateService;
6901 }
6902 }
6903 }
6904 }
6905 }
6906 }
6907 #endif
6908 }while (where != NULL);
6909
6910 #if !CONFIG_EMBEDDED
6911 OSSafeReleaseNULL(foundAlternateService);
6912 OSSafeReleaseNULL(aliasServiceRegIds);
6913 #endif
6914
6915 #if MATCH_DEBUG
6916 if (where != this) {
6917 OSSerialize * s = OSSerialize::withCapacity(128);
6918 root->serialize(s);
6919 kprintf("parent match 0x%llx, %d,\n%s\n", getRegistryEntryID(), match, s->text());
6920 s->release();
6921 }
6922 #endif
6923
6924 return match;
6925 }
6926
6927
6928 IOReturn
6929 IOService::newUserClient( task_t owningTask, void * securityID,
6930 UInt32 type, OSDictionary * properties,
6931 IOUserClient ** handler )
6932 {
6933 const OSSymbol *userClientClass = NULL;
6934 IOUserClient *client;
6935 OSObject *prop;
6936 OSObject *temp;
6937
6938 if (reserved && reserved->uvars && reserved->uvars->userServer) {
6939 return reserved->uvars->userServer->serviceNewUserClient(this, owningTask, securityID, type, properties, handler);
6940 }
6941
6942 if (kIOReturnSuccess == newUserClient( owningTask, securityID, type, handler )) {
6943 return kIOReturnSuccess;
6944 }
6945
6946 // First try my own properties for a user client class name
6947 prop = copyProperty(gIOUserClientClassKey);
6948 if (prop) {
6949 if (OSDynamicCast(OSSymbol, prop)) {
6950 userClientClass = (const OSSymbol *) prop;
6951 } else if (OSDynamicCast(OSString, prop)) {
6952 userClientClass = OSSymbol::withString((OSString *) prop);
6953 if (userClientClass) {
6954 setProperty(gIOUserClientClassKey,
6955 (OSObject *) userClientClass);
6956 }
6957 }
6958 }
6959
6960 // Didn't find one so lets just bomb out now without further ado.
6961 if (!userClientClass) {
6962 OSSafeReleaseNULL(prop);
6963 return kIOReturnUnsupported;
6964 }
6965
6966 // This reference is consumed by the IOServiceOpen call
6967 temp = OSMetaClass::allocClassWithName(userClientClass);
6968 OSSafeReleaseNULL(prop);
6969 if (!temp) {
6970 return kIOReturnNoMemory;
6971 }
6972
6973 if (OSDynamicCast(IOUserClient, temp)) {
6974 client = (IOUserClient *) temp;
6975 } else {
6976 temp->release();
6977 return kIOReturnUnsupported;
6978 }
6979
6980 if (!client->initWithTask(owningTask, securityID, type, properties)) {
6981 client->release();
6982 return kIOReturnBadArgument;
6983 }
6984
6985 if (!client->attach(this)) {
6986 client->release();
6987 return kIOReturnUnsupported;
6988 }
6989
6990 if (!client->start(this)) {
6991 client->detach(this);
6992 client->release();
6993 return kIOReturnUnsupported;
6994 }
6995
6996 *handler = client;
6997 return kIOReturnSuccess;
6998 }
6999
7000 IOReturn
7001 IOService::newUserClient( task_t owningTask, void * securityID,
7002 UInt32 type, IOUserClient ** handler )
7003 {
7004 return kIOReturnUnsupported;
7005 }
7006
7007 IOReturn
7008 IOService::requestProbe( IOOptionBits options )
7009 {
7010 return kIOReturnUnsupported;
7011 }
7012
7013 /*
7014 * Convert an IOReturn to text. Subclasses which add additional
7015 * IOReturn's should override this method and call
7016 * super::stringFromReturn if the desired value is not found.
7017 */
7018
7019 const char *
7020 IOService::stringFromReturn( IOReturn rtn )
7021 {
7022 static const IONamedValue IOReturn_values[] = {
7023 {kIOReturnSuccess, "success" },
7024 {kIOReturnError, "general error" },
7025 {kIOReturnNoMemory, "memory allocation error" },
7026 {kIOReturnNoResources, "resource shortage" },
7027 {kIOReturnIPCError, "Mach IPC failure" },
7028 {kIOReturnNoDevice, "no such device" },
7029 {kIOReturnNotPrivileged, "privilege violation" },
7030 {kIOReturnBadArgument, "invalid argument" },
7031 {kIOReturnLockedRead, "device is read locked" },
7032 {kIOReturnLockedWrite, "device is write locked" },
7033 {kIOReturnExclusiveAccess, "device is exclusive access" },
7034 {kIOReturnBadMessageID, "bad IPC message ID" },
7035 {kIOReturnUnsupported, "unsupported function" },
7036 {kIOReturnVMError, "virtual memory error" },
7037 {kIOReturnInternalError, "internal driver error" },
7038 {kIOReturnIOError, "I/O error" },
7039 {kIOReturnCannotLock, "cannot acquire lock" },
7040 {kIOReturnNotOpen, "device is not open" },
7041 {kIOReturnNotReadable, "device is not readable" },
7042 {kIOReturnNotWritable, "device is not writeable" },
7043 {kIOReturnNotAligned, "alignment error" },
7044 {kIOReturnBadMedia, "media error" },
7045 {kIOReturnStillOpen, "device is still open" },
7046 {kIOReturnRLDError, "rld failure" },
7047 {kIOReturnDMAError, "DMA failure" },
7048 {kIOReturnBusy, "device is busy" },
7049 {kIOReturnTimeout, "I/O timeout" },
7050 {kIOReturnOffline, "device is offline" },
7051 {kIOReturnNotReady, "device is not ready" },
7052 {kIOReturnNotAttached, "device/channel is not attached" },
7053 {kIOReturnNoChannels, "no DMA channels available" },
7054 {kIOReturnNoSpace, "no space for data" },
7055 {kIOReturnPortExists, "device port already exists" },
7056 {kIOReturnCannotWire, "cannot wire physical memory" },
7057 {kIOReturnNoInterrupt, "no interrupt attached" },
7058 {kIOReturnNoFrames, "no DMA frames enqueued" },
7059 {kIOReturnMessageTooLarge, "message is too large" },
7060 {kIOReturnNotPermitted, "operation is not permitted" },
7061 {kIOReturnNoPower, "device is without power" },
7062 {kIOReturnNoMedia, "media is not present" },
7063 {kIOReturnUnformattedMedia, "media is not formatted" },
7064 {kIOReturnUnsupportedMode, "unsupported mode" },
7065 {kIOReturnUnderrun, "data underrun" },
7066 {kIOReturnOverrun, "data overrun" },
7067 {kIOReturnDeviceError, "device error" },
7068 {kIOReturnNoCompletion, "no completion routine" },
7069 {kIOReturnAborted, "operation was aborted" },
7070 {kIOReturnNoBandwidth, "bus bandwidth would be exceeded" },
7071 {kIOReturnNotResponding, "device is not responding" },
7072 {kIOReturnInvalid, "unanticipated driver error" },
7073 {0, NULL }
7074 };
7075
7076 return IOFindNameForValue(rtn, IOReturn_values);
7077 }
7078
7079 /*
7080 * Convert an IOReturn to an errno.
7081 */
7082 int
7083 IOService::errnoFromReturn( IOReturn rtn )
7084 {
7085 if (unix_err(err_get_code(rtn)) == rtn) {
7086 return err_get_code(rtn);
7087 }
7088
7089 switch (rtn) {
7090 // (obvious match)
7091 case kIOReturnSuccess:
7092 return 0;
7093 case kIOReturnNoMemory:
7094 return ENOMEM;
7095 case kIOReturnNoDevice:
7096 return ENXIO;
7097 case kIOReturnVMError:
7098 return EFAULT;
7099 case kIOReturnNotPermitted:
7100 return EPERM;
7101 case kIOReturnNotPrivileged:
7102 return EACCES;
7103 case kIOReturnIOError:
7104 return EIO;
7105 case kIOReturnNotWritable:
7106 return EROFS;
7107 case kIOReturnBadArgument:
7108 return EINVAL;
7109 case kIOReturnUnsupported:
7110 return ENOTSUP;
7111 case kIOReturnBusy:
7112 return EBUSY;
7113 case kIOReturnNoPower:
7114 return EPWROFF;
7115 case kIOReturnDeviceError:
7116 return EDEVERR;
7117 case kIOReturnTimeout:
7118 return ETIMEDOUT;
7119 case kIOReturnMessageTooLarge:
7120 return EMSGSIZE;
7121 case kIOReturnNoSpace:
7122 return ENOSPC;
7123 case kIOReturnCannotLock:
7124 return ENOLCK;
7125
7126 // (best match)
7127 case kIOReturnBadMessageID:
7128 case kIOReturnNoCompletion:
7129 case kIOReturnNotAligned:
7130 return EINVAL;
7131 case kIOReturnNotReady:
7132 return EBUSY;
7133 case kIOReturnRLDError:
7134 return EBADMACHO;
7135 case kIOReturnPortExists:
7136 case kIOReturnStillOpen:
7137 return EEXIST;
7138 case kIOReturnExclusiveAccess:
7139 case kIOReturnLockedRead:
7140 case kIOReturnLockedWrite:
7141 case kIOReturnNotOpen:
7142 case kIOReturnNotReadable:
7143 return EACCES;
7144 case kIOReturnCannotWire:
7145 case kIOReturnNoResources:
7146 return ENOMEM;
7147 case kIOReturnAborted:
7148 case kIOReturnOffline:
7149 case kIOReturnNotResponding:
7150 return EBUSY;
7151 case kIOReturnBadMedia:
7152 case kIOReturnNoMedia:
7153 case kIOReturnNotAttached:
7154 case kIOReturnUnformattedMedia:
7155 return ENXIO; // (media error)
7156 case kIOReturnDMAError:
7157 case kIOReturnOverrun:
7158 case kIOReturnUnderrun:
7159 return EIO; // (transfer error)
7160 case kIOReturnNoBandwidth:
7161 case kIOReturnNoChannels:
7162 case kIOReturnNoFrames:
7163 case kIOReturnNoInterrupt:
7164 return EIO; // (hardware error)
7165 case kIOReturnError:
7166 case kIOReturnInternalError:
7167 case kIOReturnInvalid:
7168 return EIO; // (generic error)
7169 case kIOReturnIPCError:
7170 return EIO; // (ipc error)
7171 default:
7172 return EIO; // (all other errors)
7173 }
7174 }
7175
7176 IOReturn
7177 IOService::message( UInt32 type, IOService * provider,
7178 void * argument )
7179 {
7180 /*
7181 * Generic entry point for calls from the provider. A return value of
7182 * kIOReturnSuccess indicates that the message was received, and where
7183 * applicable, that it was successful.
7184 */
7185
7186 return kIOReturnUnsupported;
7187 }
7188
7189 /*
7190 * Device memory
7191 */
7192
7193 IOItemCount
7194 IOService::getDeviceMemoryCount( void )
7195 {
7196 OSArray * array;
7197 IOItemCount count;
7198
7199 array = OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
7200 if (array) {
7201 count = array->getCount();
7202 } else {
7203 count = 0;
7204 }
7205
7206 return count;
7207 }
7208
7209 IODeviceMemory *
7210 IOService::getDeviceMemoryWithIndex( unsigned int index )
7211 {
7212 OSArray * array;
7213 IODeviceMemory * range;
7214
7215 array = OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
7216 if (array) {
7217 range = (IODeviceMemory *) array->getObject( index );
7218 } else {
7219 range = NULL;
7220 }
7221
7222 return range;
7223 }
7224
7225 IOMemoryMap *
7226 IOService::mapDeviceMemoryWithIndex( unsigned int index,
7227 IOOptionBits options )
7228 {
7229 IODeviceMemory * range;
7230 IOMemoryMap * map;
7231
7232 range = getDeviceMemoryWithIndex( index );
7233 if (range) {
7234 map = range->map( options );
7235 } else {
7236 map = NULL;
7237 }
7238
7239 return map;
7240 }
7241
7242 OSArray *
7243 IOService::getDeviceMemory( void )
7244 {
7245 return OSDynamicCast( OSArray, getProperty( gIODeviceMemoryKey));
7246 }
7247
7248
7249 void
7250 IOService::setDeviceMemory( OSArray * array )
7251 {
7252 setProperty( gIODeviceMemoryKey, array);
7253 }
7254
7255 /*
7256 * For machines where the transfers on an I/O bus can stall because
7257 * the CPU is in an idle mode, These APIs allow a driver to specify
7258 * the maximum bus stall that they can handle. 0 indicates no limit.
7259 */
7260 void
7261 IOService::
7262 setCPUSnoopDelay(UInt32 __unused ns)
7263 {
7264 #if defined(__i386__) || defined(__x86_64__)
7265 ml_set_maxsnoop(ns);
7266 #endif /* defined(__i386__) || defined(__x86_64__) */
7267 }
7268
7269 UInt32
7270 IOService::
7271 getCPUSnoopDelay()
7272 {
7273 #if defined(__i386__) || defined(__x86_64__)
7274 return ml_get_maxsnoop();
7275 #else
7276 return 0;
7277 #endif /* defined(__i386__) || defined(__x86_64__) */
7278 }
7279
7280 #if defined(__i386__) || defined(__x86_64__)
7281 static void
7282 requireMaxCpuDelay(IOService * service, UInt32 ns, UInt32 delayType)
7283 {
7284 static const UInt kNoReplace = -1U; // Must be an illegal index
7285 UInt replace = kNoReplace;
7286 bool setCpuDelay = false;
7287
7288 IORecursiveLockLock(sCpuDelayLock);
7289
7290 UInt count = sCpuDelayData->getLength() / sizeof(CpuDelayEntry);
7291 CpuDelayEntry *entries = (CpuDelayEntry *) sCpuDelayData->getBytesNoCopy();
7292 IOService * holder = NULL;
7293
7294 if (ns) {
7295 const CpuDelayEntry ne = {service, ns, delayType};
7296 holder = service;
7297 // Set maximum delay.
7298 for (UInt i = 0; i < count; i++) {
7299 IOService *thisService = entries[i].fService;
7300 bool sameType = (delayType == entries[i].fDelayType);
7301 if ((service == thisService) && sameType) {
7302 replace = i;
7303 } else if (!thisService) {
7304 if (kNoReplace == replace) {
7305 replace = i;
7306 }
7307 } else if (sameType) {
7308 const UInt32 thisMax = entries[i].fMaxDelay;
7309 if (thisMax < ns) {
7310 ns = thisMax;
7311 holder = thisService;
7312 }
7313 }
7314 }
7315
7316 setCpuDelay = true;
7317 if (kNoReplace == replace) {
7318 sCpuDelayData->appendBytes(&ne, sizeof(ne));
7319 } else {
7320 entries[replace] = ne;
7321 }
7322 } else {
7323 ns = -1U; // Set to max unsigned, i.e. no restriction
7324
7325 for (UInt i = 0; i < count; i++) {
7326 // Clear a maximum delay.
7327 IOService *thisService = entries[i].fService;
7328 if (thisService && (delayType == entries[i].fDelayType)) {
7329 UInt32 thisMax = entries[i].fMaxDelay;
7330 if (service == thisService) {
7331 replace = i;
7332 } else if (thisMax < ns) {
7333 ns = thisMax;
7334 holder = thisService;
7335 }
7336 }
7337 }
7338
7339 // Check if entry found
7340 if (kNoReplace != replace) {
7341 entries[replace].fService = NULL; // Null the entry
7342 setCpuDelay = true;
7343 }
7344 }
7345
7346 if (setCpuDelay) {
7347 if (holder && debug_boot_arg) {
7348 strlcpy(sCPULatencyHolderName[delayType], holder->getName(), sizeof(sCPULatencyHolderName[delayType]));
7349 }
7350
7351 // Must be safe to call from locked context
7352 if (delayType == kCpuDelayBusStall) {
7353 ml_set_maxbusdelay(ns);
7354 } else if (delayType == kCpuDelayInterrupt) {
7355 ml_set_maxintdelay(ns);
7356 }
7357 sCPULatencyHolder[delayType]->setValue(holder ? holder->getRegistryEntryID() : 0);
7358 sCPULatencySet[delayType]->setValue(ns);
7359
7360 OSArray * handlers = sCpuLatencyHandlers[delayType];
7361 IOService * target;
7362 if (handlers) {
7363 for (unsigned int idx = 0;
7364 (target = (IOService *) handlers->getObject(idx));
7365 idx++) {
7366 target->callPlatformFunction(sCPULatencyFunctionName[delayType], false,
7367 (void *) (uintptr_t) ns, holder,
7368 NULL, NULL);
7369 }
7370 }
7371 }
7372
7373 IORecursiveLockUnlock(sCpuDelayLock);
7374 }
7375
7376 static IOReturn
7377 setLatencyHandler(UInt32 delayType, IOService * target, bool enable)
7378 {
7379 IOReturn result = kIOReturnNotFound;
7380 OSArray * array;
7381 unsigned int idx;
7382
7383 IORecursiveLockLock(sCpuDelayLock);
7384
7385 do{
7386 if (enable && !sCpuLatencyHandlers[delayType]) {
7387 sCpuLatencyHandlers[delayType] = OSArray::withCapacity(4);
7388 }
7389 array = sCpuLatencyHandlers[delayType];
7390 if (!array) {
7391 break;
7392 }
7393 idx = array->getNextIndexOfObject(target, 0);
7394 if (!enable) {
7395 if (-1U != idx) {
7396 array->removeObject(idx);
7397 result = kIOReturnSuccess;
7398 }
7399 } else {
7400 if (-1U != idx) {
7401 result = kIOReturnExclusiveAccess;
7402 break;
7403 }
7404 array->setObject(target);
7405
7406 UInt count = sCpuDelayData->getLength() / sizeof(CpuDelayEntry);
7407 CpuDelayEntry *entries = (CpuDelayEntry *) sCpuDelayData->getBytesNoCopy();
7408 UInt32 ns = -1U; // Set to max unsigned, i.e. no restriction
7409 IOService * holder = NULL;
7410
7411 for (UInt i = 0; i < count; i++) {
7412 if (entries[i].fService
7413 && (delayType == entries[i].fDelayType)
7414 && (entries[i].fMaxDelay < ns)) {
7415 ns = entries[i].fMaxDelay;
7416 holder = entries[i].fService;
7417 }
7418 }
7419 target->callPlatformFunction(sCPULatencyFunctionName[delayType], false,
7420 (void *) (uintptr_t) ns, holder,
7421 NULL, NULL);
7422 result = kIOReturnSuccess;
7423 }
7424 }while (false);
7425
7426 IORecursiveLockUnlock(sCpuDelayLock);
7427
7428 return result;
7429 }
7430
7431 #endif /* defined(__i386__) || defined(__x86_64__) */
7432
7433 void
7434 IOService::
7435 requireMaxBusStall(UInt32 __unused ns)
7436 {
7437 #if defined(__i386__) || defined(__x86_64__)
7438 requireMaxCpuDelay(this, ns, kCpuDelayBusStall);
7439 #endif
7440 }
7441
7442 void
7443 IOService::
7444 requireMaxInterruptDelay(uint32_t __unused ns)
7445 {
7446 #if defined(__i386__) || defined(__x86_64__)
7447 requireMaxCpuDelay(this, ns, kCpuDelayInterrupt);
7448 #endif
7449 }
7450
7451 /*
7452 * Device interrupts
7453 */
7454
7455 IOReturn
7456 IOService::resolveInterrupt(IOService *nub, int source)
7457 {
7458 IOInterruptController *interruptController;
7459 OSArray *array;
7460 OSData *data;
7461 OSSymbol *interruptControllerName;
7462 long numSources;
7463 IOInterruptSource *interruptSources;
7464
7465 // Get the parents list from the nub.
7466 array = OSDynamicCast(OSArray, nub->getProperty(gIOInterruptControllersKey));
7467 if (array == NULL) {
7468 return kIOReturnNoResources;
7469 }
7470
7471 // Allocate space for the IOInterruptSources if needed... then return early.
7472 if (nub->_interruptSources == NULL) {
7473 numSources = array->getCount();
7474 interruptSources = (IOInterruptSource *)IOMalloc(
7475 numSources * sizeofAllIOInterruptSource);
7476 if (interruptSources == NULL) {
7477 return kIOReturnNoMemory;
7478 }
7479
7480 bzero(interruptSources, numSources * sizeofAllIOInterruptSource);
7481
7482 nub->_numInterruptSources = numSources;
7483 nub->_interruptSources = interruptSources;
7484 return kIOReturnSuccess;
7485 }
7486
7487 interruptControllerName = OSDynamicCast(OSSymbol, array->getObject(source));
7488 if (interruptControllerName == NULL) {
7489 return kIOReturnNoResources;
7490 }
7491
7492 interruptController = getPlatform()->lookUpInterruptController(interruptControllerName);
7493 if (interruptController == NULL) {
7494 return kIOReturnNoResources;
7495 }
7496
7497 // Get the interrupt numbers from the nub.
7498 array = OSDynamicCast(OSArray, nub->getProperty(gIOInterruptSpecifiersKey));
7499 if (array == NULL) {
7500 return kIOReturnNoResources;
7501 }
7502 data = OSDynamicCast(OSData, array->getObject(source));
7503 if (data == NULL) {
7504 return kIOReturnNoResources;
7505 }
7506
7507 // Set the interruptController and interruptSource in the nub's table.
7508 interruptSources = nub->_interruptSources;
7509 interruptSources[source].interruptController = interruptController;
7510 interruptSources[source].vectorData = data;
7511
7512 return kIOReturnSuccess;
7513 }
7514
7515 IOReturn
7516 IOService::lookupInterrupt(int source, bool resolve, IOInterruptController **interruptController)
7517 {
7518 IOReturn ret;
7519
7520 /* Make sure the _interruptSources are set */
7521 if (_interruptSources == NULL) {
7522 ret = resolveInterrupt(this, source);
7523 if (ret != kIOReturnSuccess) {
7524 return ret;
7525 }
7526 }
7527
7528 /* Make sure the local source number is valid */
7529 if ((source < 0) || (source >= _numInterruptSources)) {
7530 return kIOReturnNoInterrupt;
7531 }
7532
7533 /* Look up the contoller for the local source */
7534 *interruptController = _interruptSources[source].interruptController;
7535
7536 if (*interruptController == NULL) {
7537 if (!resolve) {
7538 return kIOReturnNoInterrupt;
7539 }
7540
7541 /* Try to resolve the interrupt */
7542 ret = resolveInterrupt(this, source);
7543 if (ret != kIOReturnSuccess) {
7544 return ret;
7545 }
7546
7547 *interruptController = _interruptSources[source].interruptController;
7548 }
7549
7550 return kIOReturnSuccess;
7551 }
7552
7553 IOReturn
7554 IOService::registerInterrupt(int source, OSObject *target,
7555 IOInterruptAction handler,
7556 void *refCon)
7557 {
7558 IOInterruptController *interruptController;
7559 IOReturn ret;
7560
7561 ret = lookupInterrupt(source, true, &interruptController);
7562 if (ret != kIOReturnSuccess) {
7563 return ret;
7564 }
7565
7566 /* Register the source */
7567 return interruptController->registerInterrupt(this, source, target,
7568 (IOInterruptHandler)handler,
7569 refCon);
7570 }
7571
7572 static void
7573 IOServiceInterruptActionToBlock( OSObject * target, void * refCon,
7574 IOService * nub, int source )
7575 {
7576 ((IOInterruptActionBlock)(refCon))(nub, source);
7577 }
7578
7579 IOReturn
7580 IOService::registerInterruptBlock(int source, OSObject *target,
7581 IOInterruptActionBlock handler)
7582 {
7583 IOReturn ret;
7584 void * block;
7585
7586 block = Block_copy(handler);
7587 if (!block) {
7588 return kIOReturnNoMemory;
7589 }
7590
7591 ret = registerInterrupt(source, target, &IOServiceInterruptActionToBlock, block);
7592 if (kIOReturnSuccess != ret) {
7593 Block_release(block);
7594 return ret;
7595 }
7596 _interruptSourcesPrivate(this)[source].vectorBlock = block;
7597
7598 return ret;
7599 }
7600
7601 IOReturn
7602 IOService::unregisterInterrupt(int source)
7603 {
7604 IOReturn ret;
7605 IOInterruptController *interruptController;
7606 void *block;
7607
7608 ret = lookupInterrupt(source, false, &interruptController);
7609 if (ret != kIOReturnSuccess) {
7610 return ret;
7611 }
7612
7613 /* Unregister the source */
7614 block = _interruptSourcesPrivate(this)[source].vectorBlock;
7615 ret = interruptController->unregisterInterrupt(this, source);
7616 if ((kIOReturnSuccess == ret) && (block = _interruptSourcesPrivate(this)[source].vectorBlock)) {
7617 _interruptSourcesPrivate(this)[source].vectorBlock = NULL;
7618 Block_release(block);
7619 }
7620
7621 return ret;
7622 }
7623
7624 IOReturn
7625 IOService::addInterruptStatistics(IOInterruptAccountingData * statistics, int source)
7626 {
7627 IOReportLegend * legend = NULL;
7628 IOInterruptAccountingData * oldValue = NULL;
7629 IOInterruptAccountingReporter * newArray = NULL;
7630 char subgroupName[64];
7631 int newArraySize = 0;
7632 int i = 0;
7633
7634 if (source < 0) {
7635 return kIOReturnBadArgument;
7636 }
7637
7638 /*
7639 * We support statistics on a maximum of 256 interrupts per nub; if a nub
7640 * has more than 256 interrupt specifiers associated with it, and tries
7641 * to register a high interrupt index with interrupt accounting, panic.
7642 * Having more than 256 interrupts associated with a single nub is
7643 * probably a sign that something fishy is going on.
7644 */
7645 if (source > IA_INDEX_MAX) {
7646 panic("addInterruptStatistics called for an excessively large index (%d)", source);
7647 }
7648
7649 /*
7650 * TODO: This is ugly (wrapping a lock around an allocation). I'm only
7651 * leaving it as is because the likelihood of contention where we are
7652 * actually growing the array is minimal (we would realistically need
7653 * to be starting a driver for the first time, with an IOReporting
7654 * client already in place). Nonetheless, cleanup that can be done
7655 * to adhere to best practices; it'll make the code more complicated,
7656 * unfortunately.
7657 */
7658 IOLockLock(reserved->interruptStatisticsLock);
7659
7660 /*
7661 * Lazily allocate the statistics array.
7662 */
7663 if (!reserved->interruptStatisticsArray) {
7664 reserved->interruptStatisticsArray = IONew(IOInterruptAccountingReporter, 1);
7665 assert(reserved->interruptStatisticsArray);
7666 reserved->interruptStatisticsArrayCount = 1;
7667 bzero(reserved->interruptStatisticsArray, sizeof(*reserved->interruptStatisticsArray));
7668 }
7669
7670 if (source >= reserved->interruptStatisticsArrayCount) {
7671 /*
7672 * We're still within the range of supported indices, but we are out
7673 * of space in the current array. Do a nasty realloc (because
7674 * IORealloc isn't a thing) here. We'll double the size with each
7675 * reallocation.
7676 *
7677 * Yes, the "next power of 2" could be more efficient; but this will
7678 * be invoked incredibly rarely. Who cares.
7679 */
7680 newArraySize = (reserved->interruptStatisticsArrayCount << 1);
7681
7682 while (newArraySize <= source) {
7683 newArraySize = (newArraySize << 1);
7684 }
7685 newArray = IONew(IOInterruptAccountingReporter, newArraySize);
7686
7687 assert(newArray);
7688
7689 /*
7690 * TODO: This even zeroes the memory it is about to overwrite.
7691 * Shameful; fix it. Not particularly high impact, however.
7692 */
7693 bzero(newArray, newArraySize * sizeof(*newArray));
7694 memcpy(newArray, reserved->interruptStatisticsArray, reserved->interruptStatisticsArrayCount * sizeof(*newArray));
7695 IODelete(reserved->interruptStatisticsArray, IOInterruptAccountingReporter, reserved->interruptStatisticsArrayCount);
7696 reserved->interruptStatisticsArray = newArray;
7697 reserved->interruptStatisticsArrayCount = newArraySize;
7698 }
7699
7700 if (!reserved->interruptStatisticsArray[source].reporter) {
7701 /*
7702 * We don't have a reporter associated with this index yet, so we
7703 * need to create one.
7704 */
7705 /*
7706 * TODO: Some statistics do in fact have common units (time); should this be
7707 * split into separate reporters to communicate this?
7708 */
7709 reserved->interruptStatisticsArray[source].reporter = IOSimpleReporter::with(this, kIOReportCategoryPower, kIOReportUnitNone);
7710
7711 /*
7712 * Each statistic is given an identifier based on the interrupt index (which
7713 * should be unique relative to any single nub) and the statistic involved.
7714 * We should now have a sane (small and positive) index, so start
7715 * constructing the channels for statistics.
7716 */
7717 for (i = 0; i < IA_NUM_INTERRUPT_ACCOUNTING_STATISTICS; i++) {
7718 /*
7719 * TODO: Currently, this does not add channels for disabled statistics.
7720 * Will this be confusing for clients? If so, we should just add the
7721 * channels; we can avoid updating the channels even if they exist.
7722 */
7723 if (IA_GET_STATISTIC_ENABLED(i)) {
7724 reserved->interruptStatisticsArray[source].reporter->addChannel(IA_GET_CHANNEL_ID(source, i), kInterruptAccountingStatisticNameArray[i]);
7725 }
7726 }
7727
7728 /*
7729 * We now need to add the legend for this reporter to the registry.
7730 */
7731 OSObject * prop = copyProperty(kIOReportLegendKey);
7732 legend = IOReportLegend::with(OSDynamicCast(OSArray, prop));
7733 OSSafeReleaseNULL(prop);
7734
7735 /*
7736 * Note that while we compose the subgroup name, we do not need to
7737 * manage its lifecycle (the reporter will handle this).
7738 */
7739 snprintf(subgroupName, sizeof(subgroupName), "%s %d", getName(), source);
7740 subgroupName[sizeof(subgroupName) - 1] = 0;
7741 legend->addReporterLegend(reserved->interruptStatisticsArray[source].reporter, kInterruptAccountingGroupName, subgroupName);
7742 setProperty(kIOReportLegendKey, legend->getLegend());
7743 legend->release();
7744
7745 /*
7746 * TODO: Is this a good idea? Probably not; my assumption is it opts
7747 * all entities who register interrupts into public disclosure of all
7748 * IOReporting channels. Unfortunately, this appears to be as fine
7749 * grain as it gets.
7750 */
7751 setProperty(kIOReportLegendPublicKey, true);
7752 }
7753
7754 /*
7755 * Don't stomp existing entries. If we are about to, panic; this
7756 * probably means we failed to tear down our old interrupt source
7757 * correctly.
7758 */
7759 oldValue = reserved->interruptStatisticsArray[source].statistics;
7760
7761 if (oldValue) {
7762 panic("addInterruptStatistics call for index %d would have clobbered existing statistics", source);
7763 }
7764
7765 reserved->interruptStatisticsArray[source].statistics = statistics;
7766
7767 /*
7768 * Inherit the reporter values for each statistic. The target may
7769 * be torn down as part of the runtime of the service (especially
7770 * for sleep/wake), so we inherit in order to avoid having values
7771 * reset for no apparent reason. Our statistics are ultimately
7772 * tied to the index and the sevice, not to an individual target,
7773 * so we should maintain them accordingly.
7774 */
7775 interruptAccountingDataInheritChannels(reserved->interruptStatisticsArray[source].statistics, reserved->interruptStatisticsArray[source].reporter);
7776
7777 IOLockUnlock(reserved->interruptStatisticsLock);
7778
7779 return kIOReturnSuccess;
7780 }
7781
7782 IOReturn
7783 IOService::removeInterruptStatistics(int source)
7784 {
7785 IOInterruptAccountingData * value = NULL;
7786
7787 if (source < 0) {
7788 return kIOReturnBadArgument;
7789 }
7790
7791 IOLockLock(reserved->interruptStatisticsLock);
7792
7793 /*
7794 * We dynamically grow the statistics array, so an excessively
7795 * large index value has NEVER been registered. This either
7796 * means our cap on the array size is too small (unlikely), or
7797 * that we have been passed a corrupt index (this must be passed
7798 * the plain index into the interrupt specifier list).
7799 */
7800 if (source >= reserved->interruptStatisticsArrayCount) {
7801 panic("removeInterruptStatistics called for index %d, which was never registered", source);
7802 }
7803
7804 assert(reserved->interruptStatisticsArray);
7805
7806 /*
7807 * If there is no existing entry, we are most likely trying to
7808 * free an interrupt owner twice, or we have corrupted the
7809 * index value.
7810 */
7811 value = reserved->interruptStatisticsArray[source].statistics;
7812
7813 if (!value) {
7814 panic("removeInterruptStatistics called for empty index %d", source);
7815 }
7816
7817 /*
7818 * We update the statistics, so that any delta with the reporter
7819 * state is not lost.
7820 */
7821 interruptAccountingDataUpdateChannels(reserved->interruptStatisticsArray[source].statistics, reserved->interruptStatisticsArray[source].reporter);
7822 reserved->interruptStatisticsArray[source].statistics = NULL;
7823 IOLockUnlock(reserved->interruptStatisticsLock);
7824
7825 return kIOReturnSuccess;
7826 }
7827
7828 IOReturn
7829 IOService::getInterruptType(int source, int *interruptType)
7830 {
7831 IOInterruptController *interruptController;
7832 IOReturn ret;
7833
7834 ret = lookupInterrupt(source, true, &interruptController);
7835 if (ret != kIOReturnSuccess) {
7836 return ret;
7837 }
7838
7839 /* Return the type */
7840 return interruptController->getInterruptType(this, source, interruptType);
7841 }
7842
7843 IOReturn
7844 IOService::enableInterrupt(int source)
7845 {
7846 IOInterruptController *interruptController;
7847 IOReturn ret;
7848
7849 ret = lookupInterrupt(source, false, &interruptController);
7850 if (ret != kIOReturnSuccess) {
7851 return ret;
7852 }
7853
7854 /* Enable the source */
7855 return interruptController->enableInterrupt(this, source);
7856 }
7857
7858 IOReturn
7859 IOService::disableInterrupt(int source)
7860 {
7861 IOInterruptController *interruptController;
7862 IOReturn ret;
7863
7864 ret = lookupInterrupt(source, false, &interruptController);
7865 if (ret != kIOReturnSuccess) {
7866 return ret;
7867 }
7868
7869 /* Disable the source */
7870 return interruptController->disableInterrupt(this, source);
7871 }
7872
7873 IOReturn
7874 IOService::causeInterrupt(int source)
7875 {
7876 IOInterruptController *interruptController;
7877 IOReturn ret;
7878
7879 ret = lookupInterrupt(source, false, &interruptController);
7880 if (ret != kIOReturnSuccess) {
7881 return ret;
7882 }
7883
7884 /* Cause an interrupt for the source */
7885 return interruptController->causeInterrupt(this, source);
7886 }
7887
7888 IOReturn
7889 IOService::configureReport(IOReportChannelList *channelList,
7890 IOReportConfigureAction action,
7891 void *result,
7892 void *destination)
7893 {
7894 unsigned cnt;
7895
7896 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
7897 if (channelList->channels[cnt].channel_id == kPMPowerStatesChID) {
7898 if (pwrMgt) {
7899 configurePowerStatesReport(action, result);
7900 } else {
7901 return kIOReturnUnsupported;
7902 }
7903 } else if (channelList->channels[cnt].channel_id == kPMCurrStateChID) {
7904 if (pwrMgt) {
7905 configureSimplePowerReport(action, result);
7906 } else {
7907 return kIOReturnUnsupported;
7908 }
7909 }
7910 }
7911
7912 IOLockLock(reserved->interruptStatisticsLock);
7913
7914 /* The array count is signed (because the interrupt indices are signed), hence the cast */
7915 for (cnt = 0; cnt < (unsigned) reserved->interruptStatisticsArrayCount; cnt++) {
7916 if (reserved->interruptStatisticsArray[cnt].reporter) {
7917 /*
7918 * If the reporter is currently associated with the statistics
7919 * for an event source, we may need to update the reporter.
7920 */
7921 if (reserved->interruptStatisticsArray[cnt].statistics) {
7922 interruptAccountingDataUpdateChannels(reserved->interruptStatisticsArray[cnt].statistics, reserved->interruptStatisticsArray[cnt].reporter);
7923 }
7924
7925 reserved->interruptStatisticsArray[cnt].reporter->configureReport(channelList, action, result, destination);
7926 }
7927 }
7928
7929 IOLockUnlock(reserved->interruptStatisticsLock);
7930
7931 return kIOReturnSuccess;
7932 }
7933
7934 IOReturn
7935 IOService::updateReport(IOReportChannelList *channelList,
7936 IOReportUpdateAction action,
7937 void *result,
7938 void *destination)
7939 {
7940 unsigned cnt;
7941
7942 for (cnt = 0; cnt < channelList->nchannels; cnt++) {
7943 if (channelList->channels[cnt].channel_id == kPMPowerStatesChID) {
7944 if (pwrMgt) {
7945 updatePowerStatesReport(action, result, destination);
7946 } else {
7947 return kIOReturnUnsupported;
7948 }
7949 } else if (channelList->channels[cnt].channel_id == kPMCurrStateChID) {
7950 if (pwrMgt) {
7951 updateSimplePowerReport(action, result, destination);
7952 } else {
7953 return kIOReturnUnsupported;
7954 }
7955 }
7956 }
7957
7958 IOLockLock(reserved->interruptStatisticsLock);
7959
7960 /* The array count is signed (because the interrupt indices are signed), hence the cast */
7961 for (cnt = 0; cnt < (unsigned) reserved->interruptStatisticsArrayCount; cnt++) {
7962 if (reserved->interruptStatisticsArray[cnt].reporter) {
7963 /*
7964 * If the reporter is currently associated with the statistics
7965 * for an event source, we need to update the reporter.
7966 */
7967 if (reserved->interruptStatisticsArray[cnt].statistics) {
7968 interruptAccountingDataUpdateChannels(reserved->interruptStatisticsArray[cnt].statistics, reserved->interruptStatisticsArray[cnt].reporter);
7969 }
7970
7971 reserved->interruptStatisticsArray[cnt].reporter->updateReport(channelList, action, result, destination);
7972 }
7973 }
7974
7975 IOLockUnlock(reserved->interruptStatisticsLock);
7976
7977 return kIOReturnSuccess;
7978 }
7979
7980 uint64_t
7981 IOService::getAuthorizationID( void )
7982 {
7983 return reserved->authorizationID;
7984 }
7985
7986 IOReturn
7987 IOService::setAuthorizationID( uint64_t authorizationID )
7988 {
7989 OSObject * entitlement;
7990 IOReturn status;
7991
7992 entitlement = IOUserClient::copyClientEntitlement( current_task(), "com.apple.private.iokit.IOServiceSetAuthorizationID" );
7993
7994 if (entitlement) {
7995 if (entitlement == kOSBooleanTrue) {
7996 reserved->authorizationID = authorizationID;
7997
7998 status = kIOReturnSuccess;
7999 } else {
8000 status = kIOReturnNotPrivileged;
8001 }
8002
8003 entitlement->release();
8004 } else {
8005 status = kIOReturnNotPrivileged;
8006 }
8007
8008 return status;
8009 }
8010
8011 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
8012
8013
8014 #if __LP64__
8015 OSMetaClassDefineReservedUsed(IOService, 0);
8016 OSMetaClassDefineReservedUsed(IOService, 1);
8017 OSMetaClassDefineReservedUnused(IOService, 2);
8018 OSMetaClassDefineReservedUnused(IOService, 3);
8019 OSMetaClassDefineReservedUnused(IOService, 4);
8020 OSMetaClassDefineReservedUnused(IOService, 5);
8021 OSMetaClassDefineReservedUnused(IOService, 6);
8022 OSMetaClassDefineReservedUnused(IOService, 7);
8023 #else
8024 OSMetaClassDefineReservedUsed(IOService, 0);
8025 OSMetaClassDefineReservedUsed(IOService, 1);
8026 OSMetaClassDefineReservedUsed(IOService, 2);
8027 OSMetaClassDefineReservedUsed(IOService, 3);
8028 OSMetaClassDefineReservedUsed(IOService, 4);
8029 OSMetaClassDefineReservedUsed(IOService, 5);
8030 OSMetaClassDefineReservedUsed(IOService, 6);
8031 OSMetaClassDefineReservedUsed(IOService, 7);
8032 #endif
8033 OSMetaClassDefineReservedUnused(IOService, 8);
8034 OSMetaClassDefineReservedUnused(IOService, 9);
8035 OSMetaClassDefineReservedUnused(IOService, 10);
8036 OSMetaClassDefineReservedUnused(IOService, 11);
8037 OSMetaClassDefineReservedUnused(IOService, 12);
8038 OSMetaClassDefineReservedUnused(IOService, 13);
8039 OSMetaClassDefineReservedUnused(IOService, 14);
8040 OSMetaClassDefineReservedUnused(IOService, 15);
8041 OSMetaClassDefineReservedUnused(IOService, 16);
8042 OSMetaClassDefineReservedUnused(IOService, 17);
8043 OSMetaClassDefineReservedUnused(IOService, 18);
8044 OSMetaClassDefineReservedUnused(IOService, 19);
8045 OSMetaClassDefineReservedUnused(IOService, 20);
8046 OSMetaClassDefineReservedUnused(IOService, 21);
8047 OSMetaClassDefineReservedUnused(IOService, 22);
8048 OSMetaClassDefineReservedUnused(IOService, 23);
8049 OSMetaClassDefineReservedUnused(IOService, 24);
8050 OSMetaClassDefineReservedUnused(IOService, 25);
8051 OSMetaClassDefineReservedUnused(IOService, 26);
8052 OSMetaClassDefineReservedUnused(IOService, 27);
8053 OSMetaClassDefineReservedUnused(IOService, 28);
8054 OSMetaClassDefineReservedUnused(IOService, 29);
8055 OSMetaClassDefineReservedUnused(IOService, 30);
8056 OSMetaClassDefineReservedUnused(IOService, 31);
8057 OSMetaClassDefineReservedUnused(IOService, 32);
8058 OSMetaClassDefineReservedUnused(IOService, 33);
8059 OSMetaClassDefineReservedUnused(IOService, 34);
8060 OSMetaClassDefineReservedUnused(IOService, 35);
8061 OSMetaClassDefineReservedUnused(IOService, 36);
8062 OSMetaClassDefineReservedUnused(IOService, 37);
8063 OSMetaClassDefineReservedUnused(IOService, 38);
8064 OSMetaClassDefineReservedUnused(IOService, 39);
8065 OSMetaClassDefineReservedUnused(IOService, 40);
8066 OSMetaClassDefineReservedUnused(IOService, 41);
8067 OSMetaClassDefineReservedUnused(IOService, 42);
8068 OSMetaClassDefineReservedUnused(IOService, 43);
8069 OSMetaClassDefineReservedUnused(IOService, 44);
8070 OSMetaClassDefineReservedUnused(IOService, 45);
8071 OSMetaClassDefineReservedUnused(IOService, 46);
8072 OSMetaClassDefineReservedUnused(IOService, 47);