X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/8f6c56a50524aa785f7e596d52dddfb331e18961..b7266188b87f3620ec3f9f717e57194a7dd989fe:/iokit/Kernel/IOWorkLoop.cpp diff --git a/iokit/Kernel/IOWorkLoop.cpp b/iokit/Kernel/IOWorkLoop.cpp index f2c11d948..688a7c013 100644 --- a/iokit/Kernel/IOWorkLoop.cpp +++ b/iokit/Kernel/IOWorkLoop.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1998-2007 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -32,21 +32,29 @@ HISTORY 1998-7-13 Godfrey van der Linden(gvdl) Created. */ + +#include #include #include #include #include #include +#include #define super OSObject OSDefineMetaClassAndStructors(IOWorkLoop, OSObject); // Block of unused functions intended for future use -OSMetaClassDefineReservedUsed(IOWorkLoop, 0); - +#if __LP64__ +OSMetaClassDefineReservedUnused(IOWorkLoop, 0); OSMetaClassDefineReservedUnused(IOWorkLoop, 1); OSMetaClassDefineReservedUnused(IOWorkLoop, 2); +#else +OSMetaClassDefineReservedUsed(IOWorkLoop, 0); +OSMetaClassDefineReservedUsed(IOWorkLoop, 1); +OSMetaClassDefineReservedUsed(IOWorkLoop, 2); +#endif OSMetaClassDefineReservedUnused(IOWorkLoop, 3); OSMetaClassDefineReservedUnused(IOWorkLoop, 4); OSMetaClassDefineReservedUnused(IOWorkLoop, 5); @@ -54,54 +62,93 @@ OSMetaClassDefineReservedUnused(IOWorkLoop, 6); OSMetaClassDefineReservedUnused(IOWorkLoop, 7); enum IOWorkLoopState { kLoopRestart = 0x1, kLoopTerminate = 0x2 }; +#ifdef __ppc__ static inline void SETP(void *addr, unsigned int flag) { unsigned int *num = (unsigned int *) addr; *num |= flag; } static inline void CLRP(void *addr, unsigned int flag) { unsigned int *num = (unsigned int *) addr; *num &= ~flag; } static inline bool ISSETP(void *addr, unsigned int flag) { unsigned int *num = (unsigned int *) addr; return (*num & flag) != 0; } +#else +static inline void SETP(void *addr, unsigned int flag) + { unsigned char *num = (unsigned char *) addr; *num |= flag; } +static inline void CLRP(void *addr, unsigned int flag) + { unsigned char *num = (unsigned char *) addr; *num &= ~flag; } +static inline bool ISSETP(void *addr, unsigned int flag) + { unsigned char *num = (unsigned char *) addr; return (*num & flag) != 0; } +#endif #define fFlags loopRestart + bool IOWorkLoop::init() { // The super init and gateLock allocation MUST be done first if ( !super::init() ) return false; + + if ( gateLock == NULL ) { + if ( !( gateLock = IORecursiveLockAlloc()) ) + return false; + } + + if ( workToDoLock == NULL ) { + if ( !(workToDoLock = IOSimpleLockAlloc()) ) + return false; + IOSimpleLockInit(workToDoLock); + workToDo = false; + } - if ( !(gateLock = IORecursiveLockAlloc()) ) - return false; - - if ( !(workToDoLock = IOSimpleLockAlloc()) ) - return false; - - controlG = IOCommandGate:: - commandGate(this, (IOCommandGate::Action) &IOWorkLoop::_maintRequest); - if ( !controlG ) - return false; - - IOSimpleLockInit(workToDoLock); - workToDo = false; - - // Point the controlGate at the workLoop. Usually addEventSource - // does this automatically. The problem is in this case addEventSource - // uses the control gate and it has to be bootstrapped. - controlG->setWorkLoop(this); - if (addEventSource(controlG) != kIOReturnSuccess) - return false; + if ( controlG == NULL ) { + controlG = IOCommandGate::commandGate( + this, + OSMemberFunctionCast( + IOCommandGate::Action, + this, + &IOWorkLoop::_maintRequest)); + + if ( !controlG ) + return false; + // Point the controlGate at the workLoop. Usually addEventSource + // does this automatically. The problem is in this case addEventSource + // uses the control gate and it has to be bootstrapped. + controlG->setWorkLoop(this); + if (addEventSource(controlG) != kIOReturnSuccess) + return false; + } - workThread = IOCreateThread((thread_continue_t)threadMainContinuation, this); - if (!workThread) - return false; + if ( workThread == NULL ) { + thread_continue_t cptr = OSMemberFunctionCast( + thread_continue_t, + this, + &IOWorkLoop::threadMain); + if (KERN_SUCCESS != kernel_thread_start(cptr, this, &workThread)) + return false; + } return true; } IOWorkLoop * IOWorkLoop::workLoop() +{ + return IOWorkLoop::workLoopWithOptions(0); +} + +IOWorkLoop * +IOWorkLoop::workLoopWithOptions(IOOptionBits options) { IOWorkLoop *me = new IOWorkLoop; + if (me && options) { + me->reserved = IONew(ExpansionData, 1); + if (!me->reserved) { + me->release(); + return 0; + } + me->reserved->options = options; + } + if (me && !me->init()) { me->release(); return 0; @@ -120,7 +167,7 @@ void IOWorkLoop::free() IOInterruptState is; // If we are here then we must be trying to shut down this work loop - // in this case disable all of the event source, mark the loop for + // in this case disable all of the event source, mark the loop // as terminating and wakeup the work thread itself and return // Note: we hold the gate across the entire operation mainly for the // benefit of our event sources so we can disable them cleanly. @@ -146,9 +193,9 @@ void IOWorkLoop::free() } eventChain = 0; - // Either we have a partial initialisation to clean up - // or we the workThread itself is performing hari-kari. - // either way clean up all of our resources and return. + // Either we have a partial initialization to clean up + // or the workThread itself is performing hari-kari. + // Either way clean up all of our resources and return. if (controlG) { controlG->release(); @@ -164,6 +211,10 @@ void IOWorkLoop::free() IORecursiveLockFree(gateLock); gateLock = 0; } + if (reserved) { + IODelete(reserved, ExpansionData, 1); + reserved = 0; + } super::free(); } @@ -246,52 +297,61 @@ do { \ #endif /* KDEBUG */ -void IOWorkLoop::threadMainContinuation(IOWorkLoop *self) -{ - self->threadMain(); -} - -void IOWorkLoop::threadMain() +/* virtual */ bool IOWorkLoop::runEventSources() { - CLRP(&fFlags, kLoopRestart); - - for (;;) { - bool more; - IOInterruptState is; + bool res = false; + closeGate(); + if (ISSETP(&fFlags, kLoopTerminate)) + goto abort; IOTimeWorkS(); + bool more; + do { + CLRP(&fFlags, kLoopRestart); + more = false; + IOInterruptState is = IOSimpleLockLockDisableInterrupt(workToDoLock); + workToDo = false; + IOSimpleLockUnlockEnableInterrupt(workToDoLock, is); + for (IOEventSource *evnt = eventChain; evnt; evnt = evnt->getNext()) { + + IOTimeClientS(); + more |= evnt->checkForWork(); + IOTimeClientE(); + + if (ISSETP(&fFlags, kLoopTerminate)) + goto abort; + else if (fFlags & kLoopRestart) { + more = true; + break; + } + } + } while (more); - closeGate(); - if (ISSETP(&fFlags, kLoopTerminate)) - goto exitThread; - - do { - workToDo = more = false; - for (IOEventSource *event = eventChain; event; event = event->getNext()) { - - IOTimeClientS(); - more |= event->checkForWork(); - IOTimeClientE(); - - if (ISSETP(&fFlags, kLoopTerminate)) - goto exitThread; - else if (fFlags & kLoopRestart) { - CLRP(&fFlags, kLoopRestart); - continue; - } - } - } while (more); - + res = true; IOTimeWorkE(); - openGate(); +abort: + openGate(); + return res; +} + +/* virtual */ void IOWorkLoop::threadMain() +{ +restartThread: + do { + if ( !runEventSources() ) + goto exitThread; - is = IOSimpleLockLockDisableInterrupt(workToDoLock); + IOInterruptState is = IOSimpleLockLockDisableInterrupt(workToDoLock); if ( !ISSETP(&fFlags, kLoopTerminate) && !workToDo) { assert_wait((void *) &workToDo, false); IOSimpleLockUnlockEnableInterrupt(workToDoLock, is); - - thread_block_parameter((thread_continue_t)threadMainContinuation, this); + thread_continue_t cptr = NULL; + if (!reserved || !(kPreciousStack & reserved->options)) + cptr = OSMemberFunctionCast( + thread_continue_t, this, &IOWorkLoop::threadMain); + thread_block_parameter(cptr, this); + goto restartThread; /* NOTREACHED */ } @@ -299,16 +359,15 @@ void IOWorkLoop::threadMain() // to commit suicide. But no matter // Clear the simple lock and retore the interrupt state IOSimpleLockUnlockEnableInterrupt(workToDoLock, is); - if (workToDo) - continue; - else - break; - } + } while(workToDo); exitThread: + thread_t thread = workThread; workThread = 0; // Say we don't have a loop and free ourselves free(); - IOExitThread(); + + thread_deallocate(thread); + (void) thread_terminate(thread); } IOThread IOWorkLoop::getThread() const @@ -357,6 +416,11 @@ int IOWorkLoop::sleepGate(void *event, UInt32 interuptibleType) return IORecursiveLockSleep(gateLock, event, interuptibleType); } +int IOWorkLoop::sleepGate(void *event, AbsoluteTime deadline, UInt32 interuptibleType) +{ + return IORecursiveLockSleepDeadline(gateLock, event, deadline, interuptibleType); +} + void IOWorkLoop::wakeupGate(void *event, bool oneThread) { IORecursiveLockWakeup(gateLock, event, oneThread); @@ -378,7 +442,7 @@ IOReturn IOWorkLoop::runAction(Action inAction, OSObject *target, IOReturn IOWorkLoop::_maintRequest(void *inC, void *inD, void *, void *) { - maintCommandEnum command = (maintCommandEnum) (vm_address_t) inC; + maintCommandEnum command = (maintCommandEnum) (uintptr_t) inC; IOEventSource *inEvent = (IOEventSource *) inD; IOReturn res = kIOReturnSuccess;