Ejemplo n.º 1
0
/* virtual */ bool IOWorkLoop::runEventSources()
{
    bool res = false;
    bool traceWL = (gIOKitTrace & kIOTraceWorkLoops) ? true : false;
    bool traceES = (gIOKitTrace & kIOTraceEventSources) ? true : false;
    
    closeGate();
    if (ISSETP(&fFlags, kLoopTerminate))
		goto abort;
	
    if (traceWL)
    	IOTimeStampStartConstant(IODBG_WORKLOOP(IOWL_WORK), (uintptr_t) this);
	
    bool more;
    do {
		CLRP(&fFlags, kLoopRestart);
		more = false;
		IOInterruptState is = IOSimpleLockLockDisableInterrupt(workToDoLock);
		workToDo = false;
		IOSimpleLockUnlockEnableInterrupt(workToDoLock, is);
		/* NOTE: only loop over event sources in eventChain. Bypass "passive" event sources for performance */
		for (IOEventSource *evnt = eventChain; evnt; evnt = evnt->getNext()) {
			
			if (traceES)
				IOTimeStampStartConstant(IODBG_WORKLOOP(IOWL_CLIENT), (uintptr_t) this, (uintptr_t) evnt);
			
			more |= evnt->checkForWork();
			
			if (traceES)
				IOTimeStampEndConstant(IODBG_WORKLOOP(IOWL_CLIENT), (uintptr_t) this, (uintptr_t) evnt);
			
			if (ISSETP(&fFlags, kLoopTerminate))
				goto abort;
			else if (fFlags & kLoopRestart) {
				more = true;
				break;
			}
		}
    } while (more);
	
    res = true;
	
    if (traceWL)
    	IOTimeStampEndConstant(IODBG_WORKLOOP(IOWL_WORK), (uintptr_t) this);
	
abort:
    openGate();
    return res;
}
Ejemplo n.º 2
0
void IOInterruptController::timeStampInterruptHandlerInternal(bool isStart, IOInterruptVectorNumber vectorNumber, IOInterruptVector *vector)
{
  uint64_t providerID = 0;
  vm_offset_t unslidHandler = 0;
  vm_offset_t unslidTarget = 0;

  IOService * provider = getProvider();

  if (provider) {
    providerID = provider->getRegistryEntryID();
  }

  if (vector) {
    unslidHandler = VM_KERNEL_UNSLIDE((vm_offset_t)vector->handler);
    unslidTarget = VM_KERNEL_UNSLIDE_OR_PERM((vm_offset_t)vector->target);
  }


  if (isStart) {
    IOTimeStampStartConstant(IODBG_INTC(IOINTC_HANDLER), (uintptr_t)vectorNumber, (uintptr_t)unslidHandler,
                           (uintptr_t)unslidTarget, (uintptr_t)providerID);
  } else {
    IOTimeStampEndConstant(IODBG_INTC(IOINTC_HANDLER), (uintptr_t)vectorNumber, (uintptr_t)unslidHandler,
                           (uintptr_t)unslidTarget, (uintptr_t)providerID);
  }
}
void IOFilterInterruptEventSource::signalInterrupt()
{
	bool trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false;
    
    IOStatisticsInterrupt();
    producerCount++;
	
	if (trace)
	    IOTimeStampStartConstant(IODBG_INTES(IOINTES_SEMA), (uintptr_t) this, (uintptr_t) owner);
    
    signalWorkAvailable();
	
	if (trace)
	    IOTimeStampEndConstant(IODBG_INTES(IOINTES_SEMA), (uintptr_t) this, (uintptr_t) owner);
	
}
Ejemplo n.º 4
0
IOReturn IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
						      IOService * nub,
						      int /*source*/)
{
  IOInterruptVectorNumber vectorNumber;
  IOInterruptVector *vector;
  
  for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) {
    vector = &vectors[vectorNumber];
    
    vector->interruptActive = 1;
	if (!vector->interruptDisabledSoft) {
	  
	  // Call the handler if it exists.
	  if (vector->interruptRegistered) {
		  
		  bool	trace = (gIOKitTrace & kIOTraceInterrupts) ? true : false;
		  
		  if (trace)
			  IOTimeStampStartConstant(IODBG_INTC(IOINTC_HANDLER),
									   (uintptr_t) vectorNumber, (uintptr_t) vector->handler, (uintptr_t)vector->target);
		  
		  // Call handler.
		  vector->handler(vector->target, vector->refCon, vector->nub, vector->source);
		  
		  if (trace)
			  IOTimeStampEndConstant(IODBG_INTC(IOINTC_HANDLER),
									 (uintptr_t) vectorNumber, (uintptr_t) vector->handler, (uintptr_t)vector->target);
		  
		}
	}
    
    vector->interruptActive = 0;
  }
  
  // if any of the vectors are dissabled, then dissable this controller.
  IOSimpleLockLock(controllerLock);
  if (vectorsEnabled != vectorsRegistered) {
    nub->disableInterrupt(0);
    controllerDisabled = 1;
  }
  IOSimpleLockUnlock(controllerLock);
  
  return kIOReturnSuccess;
}
void IOFilterInterruptEventSource::disableInterruptOccurred
    (void */*refcon*/, IOService *prov, int source)
{
    bool 	filterRes;
    uint64_t	startTime = 0;
    uint64_t	endTime = 0;
	bool	trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false;
	
	if (trace)
		IOTimeStampStartConstant(IODBG_INTES(IOINTES_FILTER),
					 VM_KERNEL_UNSLIDE(filterAction), (uintptr_t) owner, (uintptr_t) this, (uintptr_t) workLoop);

    if (IOInterruptEventSource::reserved->statistics) {
        if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelTimeIndex)) {
            startTime = mach_absolute_time();
        }
    }
    
    // Call the filter.
    filterRes = (*filterAction)(owner, this);

    if (IOInterruptEventSource::reserved->statistics) {
        if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelCountIndex)) {
            IA_ADD_VALUE(&IOInterruptEventSource::reserved->statistics->interruptStatistics[kInterruptAccountingFirstLevelCountIndex], 1);
        }

        if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelTimeIndex)) {
            endTime = mach_absolute_time();
            IA_ADD_VALUE(&IOInterruptEventSource::reserved->statistics->interruptStatistics[kInterruptAccountingFirstLevelTimeIndex], endTime - startTime);
        }
    }

	if (trace)
		IOTimeStampEndConstant(IODBG_INTES(IOINTES_FILTER),
				       VM_KERNEL_UNSLIDE(filterAction), (uintptr_t) owner, (uintptr_t) this, (uintptr_t) workLoop);
	
    if (filterRes) {
        prov->disableInterrupt(source);	/* disable the interrupt */
        signalInterrupt();
    }
}
Ejemplo n.º 6
0
IOReturn IOCommandGate::attemptAction(Action inAction,
                                      void *arg0, void *arg1,
                                      void *arg2, void *arg3)
{
    IOReturn res;
    IOWorkLoop * wl;

    if (!inAction)
        return kIOReturnBadArgument;
    if (!(wl = workLoop))
        return kIOReturnNotReady;

    // Try to close the gate if can't get return immediately.
    if (!wl->tryCloseGate())
        return kIOReturnCannotLock;

    // If the command gate is disabled then sleep until we get a wakeup
    if (!wl->onThread() && !enabled)
        res = kIOReturnNotPermitted;
    else {
		
        bool trace = ( gIOKitTrace & kIOTraceCommandGates ) ? true : false;
		
        if (trace)
            IOTimeStampStartConstant(IODBG_CMDQ(IOCMDQ_ACTION),
				     VM_KERNEL_UNSLIDE(inAction), (uintptr_t) owner);
        
        IOStatisticsActionCall();
        
        res = (*inAction)(owner, arg0, arg1, arg2, arg3);
		
        if (trace)
            IOTimeStampEndConstant(IODBG_CMDQ(IOCMDQ_ACTION),
				   VM_KERNEL_UNSLIDE(inAction), (uintptr_t) owner);
    }

    wl->openGate();

    return res;
}
Ejemplo n.º 7
0
// 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();
        }
Ejemplo n.º 8
0
IOReturn IOCommandGate::runAction(Action inAction,
                                  void *arg0, void *arg1,
                                  void *arg2, void *arg3)
{
    IOWorkLoop * wl;
    uintptr_t  * sleepersP;

    if (!inAction)
        return kIOReturnBadArgument;
    if (!(wl = workLoop))
        return kIOReturnNotReady;

    // closeGate is recursive needn't worry if we already hold the lock.
    wl->closeGate();
    sleepersP = (uintptr_t *) &reserved;

    // If the command gate is disabled and we aren't on the workloop thread
    // itself then sleep until we get enabled.
    IOReturn res;
    if (!wl->onThread())
    {
	while (!enabled)
	{
            IOReturn sleepResult = kIOReturnSuccess;
	    if (workLoop)
	    {
		*sleepersP |= kSleepersWaitEnabled;
		sleepResult = wl->sleepGate(&enabled, THREAD_ABORTSAFE);
		*sleepersP &= ~kSleepersWaitEnabled;
	    }
	    bool wakeupTearDown = (!workLoop || (0 != (*sleepersP & kSleepersRemoved)));
	    if ((kIOReturnSuccess != sleepResult) || wakeupTearDown) {
		wl->openGate();

		 if (wakeupTearDown)
		     wl->wakeupGate(sleepersP, false);	// No further resources used

		return kIOReturnAborted;
	    }
	}
    }

    bool trace = ( gIOKitTrace & kIOTraceCommandGates ) ? true : false;
	
    if (trace) IOTimeStampStartConstant(IODBG_CMDQ(IOCMDQ_ACTION),
					 VM_KERNEL_UNSLIDE(inAction), (uintptr_t) owner);
	
    IOStatisticsActionCall();
	
    // Must be gated and on the work loop or enabled

    *sleepersP += kSleepersActions;
    res = (*inAction)(owner, arg0, arg1, arg2, arg3);
    *sleepersP -= kSleepersActions;

    if (trace) IOTimeStampEndConstant(IODBG_CMDQ(IOCMDQ_ACTION),
				       VM_KERNEL_UNSLIDE(inAction), (uintptr_t) owner);

    if (kSleepersRemoved == ((kSleepersActionsMask|kSleepersRemoved) & *sleepersP))
    {
        // no actions outstanding
	*sleepersP &= ~kSleepersRemoved;
	super::setWorkLoop(0);
    }
    
    wl->openGate();
	
    return res;
}