1c1dac77fSApple OSS Distributions /* 2*a3bb9fccSApple OSS Distributions * Copyright (c) 1998-2014 Apple Inc. All rights reserved. 3c1dac77fSApple OSS Distributions * 4e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5c1dac77fSApple OSS Distributions * 6e13b1fa5SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code 7e13b1fa5SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License 8e13b1fa5SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in 9e13b1fa5SApple OSS Distributions * compliance with the License. The rights granted to you under the License 10e13b1fa5SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of, 11e13b1fa5SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to 12e13b1fa5SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any 13e13b1fa5SApple OSS Distributions * terms of an Apple operating system software license agreement. 14c1dac77fSApple OSS Distributions * 15e13b1fa5SApple OSS Distributions * Please obtain a copy of the License at 16e13b1fa5SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file. 17e13b1fa5SApple OSS Distributions * 18e13b1fa5SApple OSS Distributions * The Original Code and all software distributed under the License are 19e13b1fa5SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20c1dac77fSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21c1dac77fSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22e13b1fa5SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23e13b1fa5SApple OSS Distributions * Please see the License for the specific language governing rights and 24e13b1fa5SApple OSS Distributions * limitations under the License. 25c1dac77fSApple OSS Distributions * 26e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27c1dac77fSApple OSS Distributions */ 28c1dac77fSApple OSS Distributions 29c1dac77fSApple OSS Distributions #include <IOKit/IOInterruptEventSource.h> 30855239e5SApple OSS Distributions #include <IOKit/IOKitDebug.h> 31c1dac77fSApple OSS Distributions #include <IOKit/IOLib.h> 32c1dac77fSApple OSS Distributions #include <IOKit/IOService.h> 33c1dac77fSApple OSS Distributions #include <IOKit/IOInterrupts.h> 34c1dac77fSApple OSS Distributions #include <IOKit/IOTimeStamp.h> 35c1dac77fSApple OSS Distributions #include <IOKit/IOWorkLoop.h> 36*a3bb9fccSApple OSS Distributions #include <IOKit/IOInterruptAccountingPrivate.h> 37c1dac77fSApple OSS Distributions 38855239e5SApple OSS Distributions #if IOKITSTATS 39c1dac77fSApple OSS Distributions 40855239e5SApple OSS Distributions #define IOStatisticsInitializeCounter() \ 41c1dac77fSApple OSS Distributions do { \ 42855239e5SApple OSS Distributions IOStatistics::setCounterType(IOEventSource::reserved->counter, kIOStatisticsInterruptEventSourceCounter); \ 43c1dac77fSApple OSS Distributions } while (0) 44c1dac77fSApple OSS Distributions 45855239e5SApple OSS Distributions #define IOStatisticsCheckForWork() \ 46c1dac77fSApple OSS Distributions do { \ 47855239e5SApple OSS Distributions IOStatistics::countInterruptCheckForWork(IOEventSource::reserved->counter); \ 48c1dac77fSApple OSS Distributions } while (0) 49c1dac77fSApple OSS Distributions 50855239e5SApple OSS Distributions #define IOStatisticsInterrupt() \ 51c1dac77fSApple OSS Distributions do { \ 52855239e5SApple OSS Distributions IOStatistics::countInterrupt(IOEventSource::reserved->counter); \ 53c1dac77fSApple OSS Distributions } while (0) 54c1dac77fSApple OSS Distributions 55855239e5SApple OSS Distributions #else 56855239e5SApple OSS Distributions 57855239e5SApple OSS Distributions #define IOStatisticsInitializeCounter() 58855239e5SApple OSS Distributions #define IOStatisticsCheckForWork() 59855239e5SApple OSS Distributions #define IOStatisticsInterrupt() 60855239e5SApple OSS Distributions 61855239e5SApple OSS Distributions #endif // IOKITSTATS 62c1dac77fSApple OSS Distributions 63c1dac77fSApple OSS Distributions #define super IOEventSource 64c1dac77fSApple OSS Distributions 65c1dac77fSApple OSS Distributions OSDefineMetaClassAndStructors(IOInterruptEventSource, IOEventSource) 66c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 0); 67c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 1); 68c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 2); 69c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 3); 70c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 4); 71c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 5); 72c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 6); 73c1dac77fSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptEventSource, 7); 74c1dac77fSApple OSS Distributions 75c1dac77fSApple OSS Distributions bool IOInterruptEventSource::init(OSObject *inOwner, 76368ad365SApple OSS Distributions Action inAction, 77368ad365SApple OSS Distributions IOService *inProvider, 78368ad365SApple OSS Distributions int inIntIndex) 79c1dac77fSApple OSS Distributions { 80c1dac77fSApple OSS Distributions bool res = true; 81c1dac77fSApple OSS Distributions 82c1dac77fSApple OSS Distributions if ( !super::init(inOwner, (IOEventSourceAction) inAction) ) 83c1dac77fSApple OSS Distributions return false; 84c1dac77fSApple OSS Distributions 85*a3bb9fccSApple OSS Distributions reserved = IONew(ExpansionData, 1); 86*a3bb9fccSApple OSS Distributions 87*a3bb9fccSApple OSS Distributions if (!reserved) { 88*a3bb9fccSApple OSS Distributions return false; 89*a3bb9fccSApple OSS Distributions } 90*a3bb9fccSApple OSS Distributions 91*a3bb9fccSApple OSS Distributions bzero(reserved, sizeof(ExpansionData)); 92*a3bb9fccSApple OSS Distributions 93c1dac77fSApple OSS Distributions provider = inProvider; 94c1dac77fSApple OSS Distributions producerCount = consumerCount = 0; 95c1dac77fSApple OSS Distributions autoDisable = explicitDisable = false; 96855239e5SApple OSS Distributions intIndex = ~inIntIndex; 97c1dac77fSApple OSS Distributions 98c1dac77fSApple OSS Distributions // Assumes inOwner holds a reference(retain) on the provider 99c1dac77fSApple OSS Distributions if (inProvider) { 100*a3bb9fccSApple OSS Distributions if (IA_ANY_STATISTICS_ENABLED) { 101*a3bb9fccSApple OSS Distributions /* 102*a3bb9fccSApple OSS Distributions * We only treat this as an "interrupt" if it has a provider; if it does, 103*a3bb9fccSApple OSS Distributions * set up the objects necessary to track interrupt statistics. Interrupt 104*a3bb9fccSApple OSS Distributions * event sources without providers are most likely being used as simple 105*a3bb9fccSApple OSS Distributions * event source in order to poke at workloops and kick off work. 106*a3bb9fccSApple OSS Distributions * 107*a3bb9fccSApple OSS Distributions * We also avoid try to avoid interrupt accounting overhead if none of 108*a3bb9fccSApple OSS Distributions * the statistics are enabled. 109*a3bb9fccSApple OSS Distributions */ 110*a3bb9fccSApple OSS Distributions reserved->statistics = IONew(IOInterruptAccountingData, 1); 111*a3bb9fccSApple OSS Distributions 112*a3bb9fccSApple OSS Distributions if (!reserved->statistics) { 113*a3bb9fccSApple OSS Distributions /* 114*a3bb9fccSApple OSS Distributions * We rely on the free() routine to clean up after us if init fails 115*a3bb9fccSApple OSS Distributions * midway. 116*a3bb9fccSApple OSS Distributions */ 117*a3bb9fccSApple OSS Distributions return false; 118*a3bb9fccSApple OSS Distributions } 119*a3bb9fccSApple OSS Distributions 120*a3bb9fccSApple OSS Distributions bzero(reserved->statistics, sizeof(IOInterruptAccountingData)); 121*a3bb9fccSApple OSS Distributions 122*a3bb9fccSApple OSS Distributions reserved->statistics->owner = this; 123*a3bb9fccSApple OSS Distributions } 124*a3bb9fccSApple OSS Distributions 125855239e5SApple OSS Distributions res = (kIOReturnSuccess == registerInterruptHandler(inProvider, inIntIndex)); 126*a3bb9fccSApple OSS Distributions 127*a3bb9fccSApple OSS Distributions if (res) { 128855239e5SApple OSS Distributions intIndex = inIntIndex; 129855239e5SApple OSS Distributions } 130*a3bb9fccSApple OSS Distributions } 131c1dac77fSApple OSS Distributions 132855239e5SApple OSS Distributions IOStatisticsInitializeCounter(); 133855239e5SApple OSS Distributions 134855239e5SApple OSS Distributions return res; 135855239e5SApple OSS Distributions } 136855239e5SApple OSS Distributions 137855239e5SApple OSS Distributions IOReturn IOInterruptEventSource::registerInterruptHandler(IOService *inProvider, 138855239e5SApple OSS Distributions int inIntIndex) 139855239e5SApple OSS Distributions { 140855239e5SApple OSS Distributions IOReturn ret; 141855239e5SApple OSS Distributions int intType; 142c1dac77fSApple OSS Distributions IOInterruptAction intHandler; 143c1dac77fSApple OSS Distributions 144855239e5SApple OSS Distributions ret = inProvider->getInterruptType(inIntIndex, &intType); 145855239e5SApple OSS Distributions if (kIOReturnSuccess != ret) 146855239e5SApple OSS Distributions return (ret); 147855239e5SApple OSS Distributions 148c1dac77fSApple OSS Distributions autoDisable = (intType == kIOInterruptTypeLevel); 149c1dac77fSApple OSS Distributions if (autoDisable) { 15014e3d835SApple OSS Distributions intHandler = OSMemberFunctionCast(IOInterruptAction, 15114e3d835SApple OSS Distributions this, &IOInterruptEventSource::disableInterruptOccurred); 152c1dac77fSApple OSS Distributions } 153c1dac77fSApple OSS Distributions else 15414e3d835SApple OSS Distributions intHandler = OSMemberFunctionCast(IOInterruptAction, 15514e3d835SApple OSS Distributions this, &IOInterruptEventSource::normalInterruptOccurred); 156c1dac77fSApple OSS Distributions 157855239e5SApple OSS Distributions ret = provider->registerInterrupt(inIntIndex, this, intHandler); 158c1dac77fSApple OSS Distributions 159*a3bb9fccSApple OSS Distributions /* 160*a3bb9fccSApple OSS Distributions * Add statistics to the provider. The setWorkLoop convention should ensure 161*a3bb9fccSApple OSS Distributions * that we always go down the unregister path before we register (outside of 162*a3bb9fccSApple OSS Distributions * init()), so we don't have to worry that we will invoke addInterruptStatistics 163*a3bb9fccSApple OSS Distributions * erroneously. 164*a3bb9fccSApple OSS Distributions */ 165*a3bb9fccSApple OSS Distributions if ((ret == kIOReturnSuccess) && (reserved->statistics)) { 166*a3bb9fccSApple OSS Distributions /* 167*a3bb9fccSApple OSS Distributions * Stash the normal index value, for the sake of debugging. 168*a3bb9fccSApple OSS Distributions */ 169*a3bb9fccSApple OSS Distributions reserved->statistics->interruptIndex = inIntIndex; 170*a3bb9fccSApple OSS Distributions 171*a3bb9fccSApple OSS Distributions /* 172*a3bb9fccSApple OSS Distributions * We need to hook the interrupt information up to the provider so that it 173*a3bb9fccSApple OSS Distributions * can find the statistics for this interrupt when desired. The provider is 174*a3bb9fccSApple OSS Distributions * responsible for maintaining the reporter for a particular interrupt, and 175*a3bb9fccSApple OSS Distributions * needs a handle on the statistics so that it can request that the reporter 176*a3bb9fccSApple OSS Distributions * be updated as needed. Errors are considered "soft" for the moment (it 177*a3bb9fccSApple OSS Distributions * will either panic, or fail in a way such that we can still service the 178*a3bb9fccSApple OSS Distributions * interrupt). 179*a3bb9fccSApple OSS Distributions */ 180*a3bb9fccSApple OSS Distributions provider->addInterruptStatistics(reserved->statistics, inIntIndex); 181*a3bb9fccSApple OSS Distributions 182*a3bb9fccSApple OSS Distributions /* 183*a3bb9fccSApple OSS Distributions * Add the statistics object to the global list of statistics objects; this 184*a3bb9fccSApple OSS Distributions * is an aid to debugging (we can trivially find statistics for all eligible 185*a3bb9fccSApple OSS Distributions * interrupts, and dump them; potentially helpful if the system is wedged 186*a3bb9fccSApple OSS Distributions * due to interrupt activity). 187*a3bb9fccSApple OSS Distributions */ 188*a3bb9fccSApple OSS Distributions interruptAccountingDataAddToList(reserved->statistics); 189*a3bb9fccSApple OSS Distributions } 190*a3bb9fccSApple OSS Distributions 191855239e5SApple OSS Distributions return (ret); 192c1dac77fSApple OSS Distributions } 193c1dac77fSApple OSS Distributions 194*a3bb9fccSApple OSS Distributions void 195*a3bb9fccSApple OSS Distributions IOInterruptEventSource::unregisterInterruptHandler(IOService *inProvider, 196*a3bb9fccSApple OSS Distributions int inIntIndex) 197*a3bb9fccSApple OSS Distributions { 198*a3bb9fccSApple OSS Distributions if (reserved->statistics) { 199*a3bb9fccSApple OSS Distributions interruptAccountingDataRemoveFromList(reserved->statistics); 200*a3bb9fccSApple OSS Distributions provider->removeInterruptStatistics(reserved->statistics->interruptIndex); 201*a3bb9fccSApple OSS Distributions } 202*a3bb9fccSApple OSS Distributions 203*a3bb9fccSApple OSS Distributions provider->unregisterInterrupt(inIntIndex); 204*a3bb9fccSApple OSS Distributions } 205*a3bb9fccSApple OSS Distributions 206*a3bb9fccSApple OSS Distributions 207c1dac77fSApple OSS Distributions IOInterruptEventSource * 208c1dac77fSApple OSS Distributions IOInterruptEventSource::interruptEventSource(OSObject *inOwner, 209c1dac77fSApple OSS Distributions Action inAction, 210c1dac77fSApple OSS Distributions IOService *inProvider, 211c1dac77fSApple OSS Distributions int inIntIndex) 212c1dac77fSApple OSS Distributions { 213c1dac77fSApple OSS Distributions IOInterruptEventSource *me = new IOInterruptEventSource; 214c1dac77fSApple OSS Distributions 215c1dac77fSApple OSS Distributions if (me && !me->init(inOwner, inAction, inProvider, inIntIndex)) { 216368ad365SApple OSS Distributions me->release(); 217c1dac77fSApple OSS Distributions return 0; 218c1dac77fSApple OSS Distributions } 219c1dac77fSApple OSS Distributions 220c1dac77fSApple OSS Distributions return me; 221c1dac77fSApple OSS Distributions } 222c1dac77fSApple OSS Distributions 223c1dac77fSApple OSS Distributions void IOInterruptEventSource::free() 224c1dac77fSApple OSS Distributions { 225855239e5SApple OSS Distributions if (provider && intIndex >= 0) 226*a3bb9fccSApple OSS Distributions unregisterInterruptHandler(provider, intIndex); 227*a3bb9fccSApple OSS Distributions 228*a3bb9fccSApple OSS Distributions if (reserved) { 229*a3bb9fccSApple OSS Distributions if (reserved->statistics) { 230*a3bb9fccSApple OSS Distributions IODelete(reserved->statistics, IOInterruptAccountingData, 1); 231*a3bb9fccSApple OSS Distributions } 232*a3bb9fccSApple OSS Distributions 233*a3bb9fccSApple OSS Distributions IODelete(reserved, ExpansionData, 1); 234*a3bb9fccSApple OSS Distributions } 235c1dac77fSApple OSS Distributions 236c1dac77fSApple OSS Distributions super::free(); 237c1dac77fSApple OSS Distributions } 238c1dac77fSApple OSS Distributions 239c1dac77fSApple OSS Distributions void IOInterruptEventSource::enable() 240c1dac77fSApple OSS Distributions { 241855239e5SApple OSS Distributions if (provider && intIndex >= 0) { 242c1dac77fSApple OSS Distributions provider->enableInterrupt(intIndex); 243c1dac77fSApple OSS Distributions explicitDisable = false; 244e13b1fa5SApple OSS Distributions enabled = true; 245c1dac77fSApple OSS Distributions } 246c1dac77fSApple OSS Distributions } 247c1dac77fSApple OSS Distributions 248c1dac77fSApple OSS Distributions void IOInterruptEventSource::disable() 249c1dac77fSApple OSS Distributions { 250855239e5SApple OSS Distributions if (provider && intIndex >= 0) { 251c1dac77fSApple OSS Distributions provider->disableInterrupt(intIndex); 252c1dac77fSApple OSS Distributions explicitDisable = true; 253e13b1fa5SApple OSS Distributions enabled = false; 254c1dac77fSApple OSS Distributions } 255c1dac77fSApple OSS Distributions } 256c1dac77fSApple OSS Distributions 257855239e5SApple OSS Distributions void IOInterruptEventSource::setWorkLoop(IOWorkLoop *inWorkLoop) 258855239e5SApple OSS Distributions { 259186b8fceSApple OSS Distributions if (inWorkLoop) super::setWorkLoop(inWorkLoop); 260855239e5SApple OSS Distributions 261186b8fceSApple OSS Distributions if (provider) { 262855239e5SApple OSS Distributions if (!inWorkLoop) { 263855239e5SApple OSS Distributions if (intIndex >= 0) { 264*a3bb9fccSApple OSS Distributions /* 265*a3bb9fccSApple OSS Distributions * It isn't necessarily safe to wait until free() to unregister the interrupt; 266*a3bb9fccSApple OSS Distributions * our provider may disappear. 267*a3bb9fccSApple OSS Distributions */ 268*a3bb9fccSApple OSS Distributions unregisterInterruptHandler(provider, intIndex); 269855239e5SApple OSS Distributions intIndex = ~intIndex; 270855239e5SApple OSS Distributions } 271855239e5SApple OSS Distributions } else if ((intIndex < 0) && (kIOReturnSuccess == registerInterruptHandler(provider, ~intIndex))) { 272855239e5SApple OSS Distributions intIndex = ~intIndex; 273855239e5SApple OSS Distributions } 274855239e5SApple OSS Distributions } 275855239e5SApple OSS Distributions 276186b8fceSApple OSS Distributions if (!inWorkLoop) super::setWorkLoop(inWorkLoop); 277186b8fceSApple OSS Distributions } 278186b8fceSApple OSS Distributions 279c1dac77fSApple OSS Distributions const IOService *IOInterruptEventSource::getProvider() const 280c1dac77fSApple OSS Distributions { 281c1dac77fSApple OSS Distributions return provider; 282c1dac77fSApple OSS Distributions } 283c1dac77fSApple OSS Distributions 284c1dac77fSApple OSS Distributions int IOInterruptEventSource::getIntIndex() const 285c1dac77fSApple OSS Distributions { 286c1dac77fSApple OSS Distributions return intIndex; 287c1dac77fSApple OSS Distributions } 288c1dac77fSApple OSS Distributions 289c1dac77fSApple OSS Distributions bool IOInterruptEventSource::getAutoDisable() const 290c1dac77fSApple OSS Distributions { 291c1dac77fSApple OSS Distributions return autoDisable; 292c1dac77fSApple OSS Distributions } 293c1dac77fSApple OSS Distributions 294c1dac77fSApple OSS Distributions bool IOInterruptEventSource::checkForWork() 295c1dac77fSApple OSS Distributions { 296*a3bb9fccSApple OSS Distributions uint64_t startSystemTime = 0; 297*a3bb9fccSApple OSS Distributions uint64_t endSystemTime = 0; 298*a3bb9fccSApple OSS Distributions uint64_t startCPUTime = 0; 299*a3bb9fccSApple OSS Distributions uint64_t endCPUTime = 0; 300c1dac77fSApple OSS Distributions unsigned int cacheProdCount = producerCount; 301c1dac77fSApple OSS Distributions int numInts = cacheProdCount - consumerCount; 302c1dac77fSApple OSS Distributions IOInterruptEventAction intAction = (IOInterruptEventAction) action; 303855239e5SApple OSS Distributions bool trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false; 304c1dac77fSApple OSS Distributions 305855239e5SApple OSS Distributions IOStatisticsCheckForWork(); 306c1dac77fSApple OSS Distributions 307855239e5SApple OSS Distributions if ( numInts > 0 ) 308855239e5SApple OSS Distributions { 309855239e5SApple OSS Distributions if (trace) 310855239e5SApple OSS Distributions IOTimeStampStartConstant(IODBG_INTES(IOINTES_ACTION), 311d0c1fef6SApple OSS Distributions VM_KERNEL_UNSLIDE(intAction), (uintptr_t) owner, (uintptr_t) this, (uintptr_t) workLoop); 312855239e5SApple OSS Distributions 313*a3bb9fccSApple OSS Distributions if (reserved->statistics) { 314*a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) { 315*a3bb9fccSApple OSS Distributions startSystemTime = mach_absolute_time(); 316*a3bb9fccSApple OSS Distributions } 317*a3bb9fccSApple OSS Distributions 318*a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) { 319*a3bb9fccSApple OSS Distributions startCPUTime = thread_get_runtime_self(); 320*a3bb9fccSApple OSS Distributions } 321*a3bb9fccSApple OSS Distributions } 322*a3bb9fccSApple OSS Distributions 323855239e5SApple OSS Distributions // Call the handler 324c1dac77fSApple OSS Distributions (*intAction)(owner, this, numInts); 325855239e5SApple OSS Distributions 326*a3bb9fccSApple OSS Distributions if (reserved->statistics) { 327*a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCountIndex)) { 328*a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCountIndex], 1); 329*a3bb9fccSApple OSS Distributions } 330*a3bb9fccSApple OSS Distributions 331*a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) { 332*a3bb9fccSApple OSS Distributions endCPUTime = thread_get_runtime_self(); 333*a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCPUTimeIndex], endCPUTime - startCPUTime); 334*a3bb9fccSApple OSS Distributions } 335*a3bb9fccSApple OSS Distributions 336*a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) { 337*a3bb9fccSApple OSS Distributions endSystemTime = mach_absolute_time(); 338*a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelSystemTimeIndex], endSystemTime - startSystemTime); 339*a3bb9fccSApple OSS Distributions } 340*a3bb9fccSApple OSS Distributions } 341*a3bb9fccSApple OSS Distributions 342855239e5SApple OSS Distributions if (trace) 343855239e5SApple OSS Distributions IOTimeStampEndConstant(IODBG_INTES(IOINTES_ACTION), 344d0c1fef6SApple OSS Distributions VM_KERNEL_UNSLIDE(intAction), (uintptr_t) owner, (uintptr_t) this, (uintptr_t) workLoop); 345c1dac77fSApple OSS Distributions 346c1dac77fSApple OSS Distributions consumerCount = cacheProdCount; 347c1dac77fSApple OSS Distributions if (autoDisable && !explicitDisable) 348c1dac77fSApple OSS Distributions enable(); 349c1dac77fSApple OSS Distributions } 350855239e5SApple OSS Distributions 351855239e5SApple OSS Distributions else if ( numInts < 0 ) 352855239e5SApple OSS Distributions { 353855239e5SApple OSS Distributions if (trace) 354855239e5SApple OSS Distributions IOTimeStampStartConstant(IODBG_INTES(IOINTES_ACTION), 355d0c1fef6SApple OSS Distributions VM_KERNEL_UNSLIDE(intAction), (uintptr_t) owner, (uintptr_t) this, (uintptr_t) workLoop); 356855239e5SApple OSS Distributions 357*a3bb9fccSApple OSS Distributions if (reserved->statistics) { 358*a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) { 359*a3bb9fccSApple OSS Distributions startSystemTime = mach_absolute_time(); 360*a3bb9fccSApple OSS Distributions } 361*a3bb9fccSApple OSS Distributions 362*a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) { 363*a3bb9fccSApple OSS Distributions startCPUTime = thread_get_runtime_self(); 364*a3bb9fccSApple OSS Distributions } 365*a3bb9fccSApple OSS Distributions } 366*a3bb9fccSApple OSS Distributions 367855239e5SApple OSS Distributions // Call the handler 368c1dac77fSApple OSS Distributions (*intAction)(owner, this, -numInts); 369855239e5SApple OSS Distributions 370*a3bb9fccSApple OSS Distributions if (reserved->statistics) { 371*a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCountIndex)) { 372*a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCountIndex], 1); 373*a3bb9fccSApple OSS Distributions } 374*a3bb9fccSApple OSS Distributions 375*a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) { 376*a3bb9fccSApple OSS Distributions endCPUTime = thread_get_runtime_self(); 377*a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCPUTimeIndex], endCPUTime - startCPUTime); 378*a3bb9fccSApple OSS Distributions } 379*a3bb9fccSApple OSS Distributions 380*a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) { 381*a3bb9fccSApple OSS Distributions endSystemTime = mach_absolute_time(); 382*a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelSystemTimeIndex], endSystemTime - startSystemTime); 383*a3bb9fccSApple OSS Distributions } 384*a3bb9fccSApple OSS Distributions } 385*a3bb9fccSApple OSS Distributions 386855239e5SApple OSS Distributions if (trace) 387855239e5SApple OSS Distributions IOTimeStampEndConstant(IODBG_INTES(IOINTES_ACTION), 388d0c1fef6SApple OSS Distributions VM_KERNEL_UNSLIDE(intAction), (uintptr_t) owner, (uintptr_t) this, (uintptr_t) workLoop); 389c1dac77fSApple OSS Distributions 390c1dac77fSApple OSS Distributions consumerCount = cacheProdCount; 391c1dac77fSApple OSS Distributions if (autoDisable && !explicitDisable) 392c1dac77fSApple OSS Distributions enable(); 393c1dac77fSApple OSS Distributions } 394c1dac77fSApple OSS Distributions 395c1dac77fSApple OSS Distributions return false; 396c1dac77fSApple OSS Distributions } 397c1dac77fSApple OSS Distributions 398c1dac77fSApple OSS Distributions void IOInterruptEventSource::normalInterruptOccurred 399c1dac77fSApple OSS Distributions (void */*refcon*/, IOService */*prov*/, int /*source*/) 400c1dac77fSApple OSS Distributions { 401855239e5SApple OSS Distributions bool trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false; 402c1dac77fSApple OSS Distributions 403855239e5SApple OSS Distributions IOStatisticsInterrupt(); 404c1dac77fSApple OSS Distributions producerCount++; 405c1dac77fSApple OSS Distributions 406855239e5SApple OSS Distributions if (trace) 407855239e5SApple OSS Distributions IOTimeStampStartConstant(IODBG_INTES(IOINTES_SEMA), (uintptr_t) this, (uintptr_t) owner); 408c1dac77fSApple OSS Distributions 409*a3bb9fccSApple OSS Distributions if (reserved->statistics) { 410*a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelCountIndex)) { 411*a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingFirstLevelCountIndex], 1); 412*a3bb9fccSApple OSS Distributions } 413*a3bb9fccSApple OSS Distributions } 414*a3bb9fccSApple OSS Distributions 415855239e5SApple OSS Distributions signalWorkAvailable(); 416855239e5SApple OSS Distributions 417855239e5SApple OSS Distributions if (trace) 418855239e5SApple OSS Distributions IOTimeStampEndConstant(IODBG_INTES(IOINTES_SEMA), (uintptr_t) this, (uintptr_t) owner); 419c1dac77fSApple OSS Distributions } 420c1dac77fSApple OSS Distributions 421c1dac77fSApple OSS Distributions void IOInterruptEventSource::disableInterruptOccurred 422c1dac77fSApple OSS Distributions (void */*refcon*/, IOService *prov, int source) 423c1dac77fSApple OSS Distributions { 424855239e5SApple OSS Distributions bool trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false; 425c1dac77fSApple OSS Distributions 426c1dac77fSApple OSS Distributions prov->disableInterrupt(source); /* disable the interrupt */ 427c1dac77fSApple OSS Distributions 428855239e5SApple OSS Distributions IOStatisticsInterrupt(); 429c1dac77fSApple OSS Distributions producerCount++; 430c1dac77fSApple OSS Distributions 431855239e5SApple OSS Distributions if (trace) 432855239e5SApple OSS Distributions IOTimeStampStartConstant(IODBG_INTES(IOINTES_SEMA), (uintptr_t) this, (uintptr_t) owner); 433c1dac77fSApple OSS Distributions 434*a3bb9fccSApple OSS Distributions if (reserved->statistics) { 435*a3bb9fccSApple OSS Distributions if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelCountIndex)) { 436*a3bb9fccSApple OSS Distributions IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingFirstLevelCountIndex], 1); 437*a3bb9fccSApple OSS Distributions } 438*a3bb9fccSApple OSS Distributions } 439*a3bb9fccSApple OSS Distributions 440855239e5SApple OSS Distributions signalWorkAvailable(); 441855239e5SApple OSS Distributions 442855239e5SApple OSS Distributions if (trace) 443855239e5SApple OSS Distributions IOTimeStampEndConstant(IODBG_INTES(IOINTES_SEMA), (uintptr_t) this, (uintptr_t) owner); 444c1dac77fSApple OSS Distributions } 445c1dac77fSApple OSS Distributions 446c1dac77fSApple OSS Distributions void IOInterruptEventSource::interruptOccurred 447c1dac77fSApple OSS Distributions (void *refcon, IOService *prov, int source) 448c1dac77fSApple OSS Distributions { 449c1dac77fSApple OSS Distributions if (autoDisable && prov) 450c1dac77fSApple OSS Distributions disableInterruptOccurred(refcon, prov, source); 451c1dac77fSApple OSS Distributions else 452c1dac77fSApple OSS Distributions normalInterruptOccurred(refcon, prov, source); 453c1dac77fSApple OSS Distributions } 454855239e5SApple OSS Distributions 455855239e5SApple OSS Distributions IOReturn IOInterruptEventSource::warmCPU 456855239e5SApple OSS Distributions (uint64_t abstime) 457855239e5SApple OSS Distributions { 458855239e5SApple OSS Distributions 459855239e5SApple OSS Distributions return ml_interrupt_prewarm(abstime); 460855239e5SApple OSS Distributions } 461