/* sleep indefinitely */ static void pet_idle(void) { IOLockLock(pet_lock); IOLockSleep(pet_lock, &pet_actionid, THREAD_UNINT); IOLockUnlock(pet_lock); }
IOInterruptController *IOPlatformExpert::lookUpInterruptController(OSSymbol *name) { OSObject *object; IOLockLock(gIOInterruptControllersLock); while (1) { object = gIOInterruptControllers->getObject(name); if (object != 0) break; IOLockSleep(gIOInterruptControllersLock, gIOInterruptControllers, THREAD_UNINT); } IOLockUnlock(gIOInterruptControllersLock); return OSDynamicCast(IOInterruptController, object); }
//process // block/allow, or ask user and put thread to sleep kern_return_t process(void *cookie, socket_t so, const struct sockaddr *to) { //result kern_return_t result = kIOReturnError; //event firewallEvent event = {0}; //rule int action = RULE_STATE_NOT_FOUND; //awake reason int reason = 0; //socket type int socketType = 0; //length of socket type int socketTypeLength = 0; //process name char processName[PATH_MAX] = {0}; //what does rule say? // loop until we have an answer while(true) { //reset bzero(&event, sizeof(event)); //extract action action = ((struct cookieStruct*)cookie)->ruleAction; //get process name proc_selfname(processName, PATH_MAX); //block? if(RULE_STATE_BLOCK == action) { //dbg msg IOLog("LULU: rule says block for %s (pid: %d)\n", processName, proc_selfpid()); //gtfo! result = EPERM; //all done goto bail; } //allow? else if(RULE_STATE_ALLOW == action) { //dbg msg IOLog("LULU: rule says allow for %s (pid: %d)\n", processName, proc_selfpid()); //ok result = kIOReturnSuccess; //all done goto bail; } //not found // ->ask daemon and sleep for response else if(RULE_STATE_NOT_FOUND == action) { //dbg msg IOLog("LULU: no rule found for %s (pid: %d)\n", processName, proc_selfpid()); //zero out bzero(&event, sizeof(firewallEvent)); //set type event.networkOutEvent.type = EVENT_NETWORK_OUT; //add pid event.networkOutEvent.pid = proc_selfpid(); //init length socketTypeLength = sizeof(socketType); //get socket type sock_getsockopt(so, SOL_SOCKET, SO_TYPE, &socketType, &socketTypeLength); //save type event.networkOutEvent.socketType = socketType; //UDP sockets destination socket might be null // so grab via 'getpeername' and save as 'remote addr' if(NULL == to) { //copy into 'remote addr' for user mode if(0 != sock_getpeername(so, (struct sockaddr*)&(event.networkOutEvent.remoteAddress), sizeof(event.networkOutEvent.remoteAddress))) { //err msg IOLog("LULU ERROR: sock_getpeername() failed"); //bail goto bail; } } //copy remote socket for user mode else { //add remote (destination) socket addr memcpy(&(event.networkOutEvent.remoteAddress), to, sizeof(event.networkOutEvent.remoteAddress)); } //queue it up sharedDataQueue->enqueue_tail(&event, sizeof(firewallEvent)); //dbg msg IOLog("LULU: queued response to user mode, now going to sleep!\n"); //lock IOLockLock(ruleEventLock); //sleep reason = IOLockSleep(ruleEventLock, &ruleEventLock, THREAD_ABORTSAFE); //TODO: fix panic, think if kext is unloaded (sets ruleEventLock to NULL) this can still wake up? // "Preemption level underflow, possible cause unlocking an unlocked mutex or spinlock" // seems to happen when process is killed or kext unloaded while in the IOLockSleep!? //unlock IOLockUnlock(ruleEventLock); //thread wakeup cuz of signal, etc // ->just bail (process likely exited, etc) if(THREAD_AWAKENED != reason) { //dbg msg IOLog("LULU: thread awoke, but because of %d!\n", reason); //gtfo! result = EPERM; //all done goto bail; } //dbg msg IOLog("LULU: thread awoke, will check/process response\n"); //try get rule action again // ->not found, block, allow, etc ((struct cookieStruct*)(cookie))->ruleAction = queryRule(proc_selfpid()); //loop to (re)process } }//while bail: return result; }
bool BrcmPatchRAM::performUpgrade() { BrcmFirmwareStore* firmwareStore; OSArray* instructions = NULL; OSCollectionIterator* iterator = NULL; OSData* data; #ifdef DEBUG DeviceState previousState = kUnknown; #endif IOLockLock(mCompletionLock); mDeviceState = kInitialize; while (true) { #ifdef DEBUG if (mDeviceState != kInstructionWrite && mDeviceState != kInstructionWritten) DebugLog("[%04x:%04x]: State \"%s\" --> \"%s\".\n", mVendorId, mProductId, getState(previousState), getState(mDeviceState)); previousState = mDeviceState; #endif // Break out when done if (mDeviceState == kUpdateAborted || mDeviceState == kUpdateComplete) break; // Note on following switch/case: // use 'break' when a response from io completion callback is expected // use 'continue' when a change of state with no expected response (loop again) switch (mDeviceState) { case kInitialize: hciCommand(&HCI_VSC_READ_VERBOSE_CONFIG, sizeof(HCI_VSC_READ_VERBOSE_CONFIG)); break; case kFirmwareVersion: // Unable to retrieve firmware store if (!(firmwareStore = getFirmwareStore())) { mDeviceState = kUpdateAborted; continue; } instructions = firmwareStore->getFirmware(OSDynamicCast(OSString, getProperty(kFirmwareKey))); // Unable to retrieve firmware instructions if (!instructions) { mDeviceState = kUpdateAborted; continue; } // Initiate firmware upgrade hciCommand(&HCI_VSC_DOWNLOAD_MINIDRIVER, sizeof(HCI_VSC_DOWNLOAD_MINIDRIVER)); break; case kMiniDriverComplete: // Write firmware data to bulk pipe iterator = OSCollectionIterator::withCollection(instructions); if (!iterator) { mDeviceState = kUpdateAborted; continue; } // If this IOSleep is not issued, the device is not ready to receive // the firmware instructions and we will deadlock due to lack of // responses. IOSleep(10); // Write first 2 instructions to trigger response if ((data = OSDynamicCast(OSData, iterator->getNextObject()))) bulkWrite(data->getBytesNoCopy(), data->getLength()); if ((data = OSDynamicCast(OSData, iterator->getNextObject()))) bulkWrite(data->getBytesNoCopy(), data->getLength()); break; case kInstructionWrite: // should never happen, but would cause a crash if (!iterator) { mDeviceState = kUpdateAborted; continue; } if ((data = OSDynamicCast(OSData, iterator->getNextObject()))) bulkWrite(data->getBytesNoCopy(), data->getLength()); else // Firmware data fully written hciCommand(&HCI_VSC_END_OF_RECORD, sizeof(HCI_VSC_END_OF_RECORD)); break; case kInstructionWritten: mDeviceState = kInstructionWrite; continue; case kFirmwareWritten: hciCommand(&HCI_RESET, sizeof(HCI_RESET)); break; case kResetComplete: resetDevice(); getDeviceStatus(); mDeviceState = kUpdateComplete; continue; case kUnknown: case kUpdateComplete: case kUpdateAborted: DebugLog("Error: kUnkown/kUpdateComplete/kUpdateAborted cases should be unreachable.\n"); break; } // queue async read if (!continuousRead()) { mDeviceState = kUpdateAborted; continue; } // wait for completion of the async read IOLockSleep(mCompletionLock, NULL, 0); } IOLockUnlock(mCompletionLock); OSSafeRelease(iterator); return mDeviceState == kUpdateComplete; }
void sleep(void *event) { IOLockSleep(fWaitLock, event, THREAD_UNINT); }