+ IOReturn ret;
+ uint32_t loops;
+ char * string = NULL;
+ size_t len;
+ uint64_t time;
+ uint64_t nano;
+
+ time = mach_absolute_time();
+ for (loops = 0; loops < 2; loops++)
+ {
+ ret = waitForState( kIOServiceBusyStateMask, 0, timeout );
+
+ if (loops && (kIOReturnSuccess == ret))
+ {
+ time = mach_absolute_time() - time;
+ absolutetime_to_nanoseconds(*(AbsoluteTime *)&time, &nano);
+ IOLog("busy extended ok[%d], (%llds, %llds), kextd wait(%d): %s\n",
+ loops, timeout / 1000000000ULL, nano / 1000000000ULL, WAITING_KEXTD,
+ string ? string : "");
+ break;
+ }
+ else if (kIOReturnTimeout != ret) break;
+ else if (timeout < 41000000000) break;
+
+ if (!loops)
+ {
+ IORegistryIterator * iter;
+ OSOrderedSet * set;
+ OSOrderedSet * leaves;
+ IOService * next;
+ IOService * nextParent;
+ char * s;
+ size_t l;
+
+ len = 256;
+ string = IONew(char, len);
+ set = NULL;
+ iter = IORegistryIterator::iterateOver(this, gIOServicePlane, kIORegistryIterateRecursively);
+ leaves = OSOrderedSet::withCapacity(4);
+ if (iter) set = iter->iterateAll();
+ if (string && leaves && set)
+ {
+ while ((next = (IOService *) set->getLastObject()))
+ {
+ if (next->getBusyState())
+ {
+ leaves->setObject(next);
+ nextParent = next;
+ while ((nextParent = nextParent->getProvider()))
+ {
+ set->removeObject(nextParent);
+ leaves->removeObject(nextParent);
+ }
+ }
+ set->removeObject(next);
+ }
+ s = string;
+ while ((next = (IOService *) leaves->getLastObject()))
+ {
+ l = snprintf(s, len, "%s'%s'", ((s == string) ? "" : ", "), next->getName());
+ if (l >= len) break;
+ s += l;
+ len -= l;
+ leaves->removeObject(next);
+ }
+ }
+ OSSafeReleaseNULL(leaves);
+ OSSafeReleaseNULL(set);
+ OSSafeReleaseNULL(iter);
+ }
+ if (loops && (kIOWaitQuietPanics & gIOKitDebug))
+ {
+ panic("busy timeout[%d], (%llds), kextd wait(%d): %s",
+ loops, timeout / 1000000000ULL, WAITING_KEXTD,
+ string ? string : "");
+ }
+ else
+ {
+ IOLog("busy timeout[%d], (%llds), kextd wait(%d): %s\n",
+ loops, timeout / 1000000000ULL, WAITING_KEXTD,
+ string ? string : "");
+ }
+ }
+
+ if (string) IODelete(string, char, 256);
+
+ return (ret);