+ while( victim ) {
+
+ doPhase2 = victim->lockForArbitration( true );
+ if( doPhase2) {
+ doPhase2 = (0 != (kIOServiceInactiveState & victim->__state[0]));
+ if( doPhase2) {
+ doPhase2 = (0 == (victim->__state[1] & kIOServiceTermPhase2State))
+ && (0 == (victim->__state[1] & kIOServiceConfigState));
+ if( doPhase2)
+ victim->__state[1] |= kIOServiceTermPhase2State;
+ }
+ victim->unlockForArbitration();
+ }
+ if( doPhase2) {
+ if( 0 == victim->getClient()) {
+ // no clients - will go to finalize
+ IOLockLock( gJobsLock );
+ gIOFinalizeList->tailQ( victim );
+ IOLockUnlock( gJobsLock );
+ } else {
+ _workLoopAction( (IOWorkLoop::Action) &actionWillTerminate,
+ victim, (void *) options, (void *) doPhase2List );
+ }
+ didPhase2List->headQ( victim );
+ }
+ victim->release();
+ victim = (IOService *) doPhase2List->getObject(0);
+ if( victim) {
+ victim->retain();
+ doPhase2List->removeObject(0);
+ }
+ }
+
+ while( (victim = (IOService *) didPhase2List->getObject(0)) ) {
+
+ if( victim->lockForArbitration( true )) {
+ victim->__state[1] |= kIOServiceTermPhase3State;
+ victim->unlockForArbitration();
+ }
+ _workLoopAction( (IOWorkLoop::Action) &actionDidTerminate,
+ victim, (void *) options );
+ didPhase2List->removeObject(0);
+ }
+ IOLockLock( gJobsLock );
+ }
+
+ // phase 3
+ do {
+ doPhase3 = false;
+ // finalize leaves
+ while( (victim = (IOService *) gIOFinalizeList->getObject(0))) {
+
+ IOLockUnlock( gJobsLock );
+ _workLoopAction( (IOWorkLoop::Action) &actionFinalize,
+ victim, (void *) options );
+ IOLockLock( gJobsLock );
+ // hold off free
+ freeList->setObject( victim );
+ // safe if finalize list is append only
+ gIOFinalizeList->removeObject(0);
+ }
+
+ for( idx = 0;
+ (!doPhase3) && (client = (IOService *) gIOStopList->getObject(idx)); ) {
+
+ provider = (IOService *) gIOStopProviderList->getObject(idx);
+ assert( provider );
+
+ if( !provider->isChild( client, gIOServicePlane )) {
+ // may be multiply queued - nop it
+ TLOG("%s::nop stop(%s)\n", client->getName(), provider->getName());
+ } else {
+ // not ready for stop if it has clients, skip it
+ if( (client->__state[1] & kIOServiceTermPhase3State) && client->getClient()) {
+ TLOG("%s::defer stop(%s)\n", client->getName(), provider->getName());
+ idx++;
+ continue;
+ }
+
+ IOLockUnlock( gJobsLock );
+ _workLoopAction( (IOWorkLoop::Action) &actionStop,
+ provider, (void *) client );
+ IOLockLock( gJobsLock );
+ // check the finalize list now
+ doPhase3 = true;
+ }
+ // hold off free
+ freeList->setObject( client );
+ freeList->setObject( provider );
+
+ // safe if stop list is append only
+ gIOStopList->removeObject( idx );
+ gIOStopProviderList->removeObject( idx );
+ idx = 0;