IOWorkLoop * IOFWUserLocalIsochPort::createRealtimeThread() { IOWorkLoop * workloop = IOWorkLoop::workLoop() ; if ( workloop ) { // Boost isoc workloop into realtime range thread_time_constraint_policy_data_t constraints; AbsoluteTime time; nanoseconds_to_absolutetime(625000, &time); constraints.period = AbsoluteTime_to_scalar(&time); nanoseconds_to_absolutetime(60000, &time); constraints.computation = AbsoluteTime_to_scalar(&time); nanoseconds_to_absolutetime(1250000, &time); constraints.constraint = AbsoluteTime_to_scalar(&time); constraints.preemptible = TRUE; { IOThread thread; thread = workloop->getThread(); thread_policy_set( thread, THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t) & constraints, THREAD_TIME_CONSTRAINT_POLICY_COUNT ); } } return workloop ; }
void IOFireWireController::processTimeout(IOTimerEventSource *src) { // complete() might take significant time, enough to cause // a later command to timeout too, so we loop here until there is no timeout. while (fTimeoutQ.fHead) { AbsoluteTime now, dead; IOFWGetAbsoluteTime(&now); #if 0 IOLog("processTimeout, time is %llx\n", AbsoluteTime_to_scalar(&now)); { IOFWCommand *t = fTimeoutQ.fHead; while(t) { AbsoluteTime d = t->getDeadline(); IOLog("%s:%p deadline %lx:%lx\n", t->getMetaClass()->getClassName(), t, AbsoluteTime_to_scalar(&d)); t = t->getNext(); } } #endif dead = fTimeoutQ.fHead->getDeadline(); if(CMP_ABSOLUTETIME(&dead, &now) == 1) break; // Command with earliest deadline is OK. // Make sure there isn't a packet waiting. fFWIM->handleInterrupts( NULL, 1 ); fFWIM->flushWaitingPackets(); // Which may have changed the queue - see if earliest deadline has changed. if(!fTimeoutQ.fHead) break; if(CMP_ABSOLUTETIME(&dead, &fTimeoutQ.fHead->getDeadline()) != 0) continue; //IOLog("Cmd 0x%x timing out\r", fTimeoutQ.fHead); FWTrace( kFWTController, kTPControllerTimeoutQProcessTimeout, (uintptr_t)fFWIM, (uintptr_t)(fTimeoutQ.fHead), 0, 0 ); fTimeoutQ.fHead->cancel(kIOReturnTimeout); }; if(fTimeoutQ.fHead) { src->wakeAtTime(fTimeoutQ.fHead->getDeadline()); //AbsoluteTime now; //IOFWGetAbsoluteTime(&now); //IOLog("processTimeout, timeoutQ waketime %lx:%lx (now %llx)\n", // fTimeoutQ.fHead->getDeadline().hi, fTimeoutQ.fHead->getDeadline().lo, AbsoluteTime_to_scalar(&now)); } else { //IOLog("processTimeout, timeoutQ empty\n"); src->cancelTimeout(); } }
void IOHIKeyboard::setRepeat(unsigned eventType, unsigned keyCode) // Description: Set up or tear down key repeat operations. The method // that locks _deviceLock is a bit higher on the call stack. // This method is invoked as a side effect of our own // invocation of _keyMap->translateKeyCode(). // Preconditions: // * _deviceLock should be held upon entry. { KeyboardReserved *tempReservedStruct; if ( _isRepeat == false ) // make sure we're not already repeating { tempReservedStruct = GetKeyboardReservedStructEventForService(this); if ((eventType == NX_KEYDOWN) && (tempReservedStruct && (tempReservedStruct->repeatMode == true))) // Start repeat { // Set this key to repeat (push out last key if present) _downRepeatTime = _initialKeyRepeat; // + _lastEventTime; _codeToRepeat = keyCode; // reschedule key repeat event here scheduleAutoRepeat(); } else if (((eventType == NX_KEYUP) && (_codeToRepeat == keyCode)) || (tempReservedStruct && (tempReservedStruct->repeatMode == false))) // End repeat { AbsoluteTime_to_scalar(&_downRepeatTime) = 0; _codeToRepeat = (unsigned)-1; scheduleAutoRepeat(); } } }
void IOHIKeyboard::scheduleAutoRepeat() // Description: Schedule a procedure to be called when a timeout has expired // so that we can generate a repeated key. // Preconditions: // * _deviceLock should be held on entry { KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); if ( _calloutPending == true ) { if (tempReservedStruct) { thread_call_cancel(tempReservedStruct->repeat_thread_call); } _calloutPending = false; } if ( AbsoluteTime_to_scalar(&_downRepeatTime) ) { AbsoluteTime deadline; clock_absolutetime_interval_to_deadline(_downRepeatTime, &deadline); if (tempReservedStruct) { thread_call_enter_delayed(tempReservedStruct->repeat_thread_call, deadline); } _calloutPending = true; } }
static IOReturn IOPolledFilePollersIODone(IOPolledFilePollers * vars, bool abortable) { IOReturn err = kIOReturnSuccess; int32_t idx = 0; IOPolledInterface * poller; AbsoluteTime deadline; if (!vars->io) return (kIOReturnSuccess); abortable &= vars->abortable; clock_interval_to_deadline(2000, kMillisecondScale, &deadline); while (-1 == vars->ioStatus) { for (idx = 0; (poller = (IOPolledInterface *) vars->pollers->getObject(idx)); idx++) { IOReturn newErr; newErr = poller->checkForWork(); if ((newErr == kIOReturnAborted) && !abortable) newErr = kIOReturnSuccess; if (kIOReturnSuccess == err) err = newErr; } if ((false) && (kIOReturnSuccess == err) && (mach_absolute_time() > AbsoluteTime_to_scalar(&deadline))) { HIBLOG("IOPolledInterface::forced timeout\n"); vars->ioStatus = kIOReturnTimeout; } } vars->io = false; #if HIBERNATION if ((kIOReturnSuccess == err) && abortable && hibernate_should_abort()) { err = kIOReturnAborted; HIBLOG("IOPolledInterface::checkForWork sw abort\n"); } #endif if (err) { HIBLOG("IOPolledInterface::checkForWork[%d] 0x%x\n", idx, err); } else { err = vars->ioStatus; if (kIOReturnSuccess != err) HIBLOG("IOPolledInterface::ioStatus 0x%x\n", err); } return (err); }
//============================================================================== // IOHIDEvent::withBytes //============================================================================== IOHIDEvent * IOHIDEvent::withBytes( const void * bytes, IOByteCount size) { IOHIDSystemQueueElement * queueElement= NULL; IOHIDEvent * parent = NULL; UInt32 index = 0; UInt32 total = 0; UInt32 offset = 0; if ( !bytes || !size ) return NULL; queueElement = (IOHIDSystemQueueElement *)bytes; total = size - sizeof(IOHIDSystemQueueElement); for (index=0; index<queueElement->eventCount && offset<total; index++) { IOHIDEventData * eventData = (IOHIDEventData *)(queueElement->payload + queueElement->attributeLength + offset); IOHIDEvent * event = IOHIDEvent::withType(eventData->type); if ( !event ) continue; bcopy(eventData, event->_data, event->_data->size); AbsoluteTime_to_scalar(&(event->_timeStamp)) = queueElement->timeStamp; AbsoluteTime_to_scalar(&(event->_creationTimeStamp)) = queueElement->creationTimeStamp; event->_options = queueElement->options; event->_senderID = queueElement->senderID; if ( !parent ) parent = event; else { //Append event here; event->release(); } offset += eventData->size; } return parent; }
void IOHIKeyboard::setDeviceFlags(unsigned flags) // Description: Set device event flags. In this world, there is only // one keyboard device so device flags == global flags. { if (_eventFlags != flags) { _eventFlags = flags; // RY: On Modifier change, we should // reset the auto repeat timer AbsoluteTime_to_scalar(&_downRepeatTime) = 0; _codeToRepeat = (unsigned)-1; scheduleAutoRepeat(); } }
// Timeout handler function. This function is called by the kernel when // the timeout interval expires. // void IOTimerEventSource::timeout(void *self) { IOTimerEventSource *me = (IOTimerEventSource *) self; IOStatisticsTimeout(); if (me->enabled && me->action) { IOWorkLoop * wl = me->workLoop; if (wl) { Action doit; wl->closeGate(); IOStatisticsCloseGate(); doit = (Action) me->action; if (doit && me->enabled && AbsoluteTime_to_scalar(&me->abstime)) { bool trace = (gIOKitTrace & kIOTraceTimers) ? true : false; if (trace) IOTimeStampStartConstant(IODBG_TIMES(IOTIMES_ACTION), (uintptr_t) doit, (uintptr_t) me->owner); (*doit)(me->owner, me); #if CONFIG_DTRACE DTRACE_TMR3(iotescallout__expire, Action, doit, OSObject, me->owner, void, me->workLoop); #endif if (trace) IOTimeStampEndConstant(IODBG_TIMES(IOTIMES_ACTION), (uintptr_t) doit, (uintptr_t) me->owner); } IOStatisticsOpenGate(); wl->openGate(); }
void IOHIKeyboard::autoRepeat() // Description: Repeat the currently pressed key and schedule ourselves // to be called again after another interval elapses. // Preconditions: // * Should only be executed on callout thread // * _deviceLock should be unlocked on entry. { KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); IOLockLock( _deviceLock); if (( _calloutPending == false ) || ((tempReservedStruct) && tempReservedStruct->dispatchEventCalled )) { IOLockUnlock( _deviceLock); return; } _calloutPending = false; _isRepeat = true; if (tempReservedStruct) tempReservedStruct->dispatchEventCalled = true; if ( AbsoluteTime_to_scalar(&_downRepeatTime) ) { // Device is due to generate a repeat if (_keyMap) _keyMap->translateKeyCode(_codeToRepeat, /* direction */ true, /* keyBits */ _keyState); _downRepeatTime = _keyRepeat; } if (tempReservedStruct) tempReservedStruct->dispatchEventCalled = false; _isRepeat = false; scheduleAutoRepeat(); IOLockUnlock( _deviceLock); }
void IOFireWireController::timeoutQ::headChanged(IOFWCommand *oldHead) { #if 0 { IOFWCommand *t = fHead; if(oldHead) IOLog("IOFireWireController::timeoutQ::headChanged(%s:%p)\n", oldHead->getMetaClass()->getClassName(), oldHead); else IOLog("IOFireWireController::timeoutQ::headChanged(0)\n"); while(t) { AbsoluteTime d = t->getDeadline(); IOLog("%s:%p deadline %llx\n", t->getMetaClass()->getClassName(), t, AbsoluteTime_to_scalar(&d)); t = t->getNext(); } } #endif if(!fHead) { //IOLog("timeoutQ empty\n"); fTimer->cancelTimeout(); } else { fTimer->wakeAtTime(fHead->getDeadline()); //AbsoluteTime now; //IOFWGetAbsoluteTime(&now); //IOLog("timeoutQ waketime %lx:%lx (now %lx:%lx)\n", // fHead->getDeadline().hi, fHead->getDeadline().lo, now.hi, now.lo); } }
IOReturn AppleUHCIIsochTransferDescriptor::UpdateFrameList(AbsoluteTime timeStamp) { UInt32 statFlags; IOUSBIsocFrame *pFrames; IOUSBLowLatencyIsocFrame *pLLFrames; IOReturn frStatus = kIOReturnSuccess; UInt16 frActualCount = 0; UInt16 frReqCount; statFlags = USBToHostLong(GetSharedLogical()->ctrlStatus); frActualCount = UHCI_TD_GET_ACTLEN(statFlags); // warning - this method can run at primary interrupt time, which can cause a panic if it logs too much // USBLog(7, "AppleUHCIIsochTransferDescriptor[%p]::UpdateFrameList statFlags (%x)", this, statFlags); pFrames = _pFrames; if (!pFrames) // this will be the case for the dummy TD return kIOReturnSuccess; pLLFrames = (IOUSBLowLatencyIsocFrame*)_pFrames; if (_lowLatency) { frReqCount = pLLFrames[_frameIndex].frReqCount; } else { frReqCount = pFrames[_frameIndex].frReqCount; } if (statFlags & kUHCI_TD_ACTIVE) { frStatus = kIOUSBNotSent2Err; } else if (statFlags & kUHCI_TD_CRCTO) { frStatus = kIOReturnNotResponding; } else if (statFlags & kUHCI_TD_DBUF) // data buffer (PCI error) { if (_pEndpoint->direction == kUSBOut) frStatus = kIOUSBBufferUnderrunErr; else frStatus = kIOUSBBufferOverrunErr; } else if (statFlags & kUHCI_TD_BABBLE) { if (_pEndpoint->direction == kUSBOut) frStatus = kIOReturnNotResponding; // babble on OUT. this should never happen else frStatus = kIOReturnOverrun; } else if (statFlags & kUHCI_TD_STALLED) // if STALL happens on Isoch, it is most likely covered by one of the other bits above { frStatus = kIOUSBWrongPIDErr; } else { if (frActualCount != frReqCount) { if (_pEndpoint->direction == kUSBOut) { // warning - this method can run at primary interrupt time, which can cause a panic if it logs too much // USBLog(7, "AppleUHCIIsochTransferDescriptor[%p]::UpdateFrameList - (OUT) reqCount (%d) actCount (%d)", this, frReqCount, frActualCount); frStatus = kIOUSBBufferUnderrunErr; // this better have generated a DBUF or other error } else if (_pEndpoint->direction == kUSBIn) { // warning - this method can run at primary interrupt time, which can cause a panic if it logs too much // USBLog(7, "AppleUHCIIsochTransferDescriptor[%p]::UpdateFrameList - (IN) reqCount (%d) actCount (%d)", this, frReqCount, frActualCount); frStatus = kIOReturnUnderrun; // benign error } } } if (alignBuffer && alignBuffer->userBuffer && alignBuffer->vaddr && (_pEndpoint->direction == kUSBIn)) { // i can't log in here because this is called at interrupt time // i know that this is OK for Low Latency because the buffer will be allocated in low memory and wont' be bounced alignBuffer->userBuffer->writeBytes(alignBuffer->userOffset, (void*)alignBuffer->vaddr, frActualCount); alignBuffer->actCount = frActualCount; } if (_lowLatency) { if ( _requestFromRosettaClient ) { pLLFrames[_frameIndex].frActCount = OSSwapInt16(frActualCount); pLLFrames[_frameIndex].frReqCount = OSSwapInt16(pLLFrames[_frameIndex].frReqCount); AbsoluteTime_to_scalar(&pLLFrames[_frameIndex].frTimeStamp) = OSSwapInt64(AbsoluteTime_to_scalar(&timeStamp)); pLLFrames[_frameIndex].frStatus = OSSwapInt32(frStatus); } else { pLLFrames[_frameIndex].frActCount = frActualCount; pLLFrames[_frameIndex].frTimeStamp = timeStamp; pLLFrames[_frameIndex].frStatus = frStatus; #ifdef __LP64__ USBTrace( kUSBTUHCIInterrupts, kTPUHCIUpdateFrameList , (uintptr_t)((_pEndpoint->direction << 24) | ( _pEndpoint->functionAddress << 8) | _pEndpoint->endpointNumber), (uintptr_t)&pLLFrames[_frameIndex], (uintptr_t)frActualCount, (uintptr_t)timeStamp ); #else USBTrace( kUSBTUHCIInterrupts, kTPUHCIUpdateFrameList , (uintptr_t)((_pEndpoint->direction << 24) | ( _pEndpoint->functionAddress << 8) | _pEndpoint->endpointNumber), (uintptr_t)&pLLFrames[_frameIndex], (uintptr_t)(timeStamp.hi), (uintptr_t)timeStamp.lo ); #endif } } else { if ( _requestFromRosettaClient ) { pFrames[_frameIndex].frActCount = OSSwapInt16(frActualCount); pFrames[_frameIndex].frReqCount = OSSwapInt16(pFrames[_frameIndex].frReqCount); pFrames[_frameIndex].frStatus = OSSwapInt32(frStatus); } else { pFrames[_frameIndex].frActCount = frActualCount; pFrames[_frameIndex].frStatus = frStatus; } } if (frStatus != kIOReturnSuccess) { if (frStatus != kIOReturnUnderrun) { _pEndpoint->accumulatedStatus = frStatus; } else if (_pEndpoint->accumulatedStatus == kIOReturnSuccess) { _pEndpoint->accumulatedStatus = kIOReturnUnderrun; } } return frStatus; }