IOFilterInterruptEventSource.cpp [plain text]
#include <IOKit/IOFilterInterruptEventSource.h>
#include <IOKit/IOService.h>
#include <IOKit/IOKitDebug.h>
#include <IOKit/IOTimeStamp.h>
#include <IOKit/IOWorkLoop.h>
#include <IOKit/IOInterruptAccountingPrivate.h>
#if IOKITSTATS
#define IOStatisticsInitializeCounter() \
do { \
IOStatistics::setCounterType(IOEventSource::reserved->counter, kIOStatisticsFilterInterruptEventSourceCounter); \
} while (0)
#define IOStatisticsInterrupt() \
do { \
IOStatistics::countInterrupt(IOEventSource::reserved->counter); \
} while (0)
#else
#define IOStatisticsInitializeCounter()
#define IOStatisticsInterrupt()
#endif
#define super IOInterruptEventSource
OSDefineMetaClassAndStructors
(IOFilterInterruptEventSource, IOInterruptEventSource)
OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 0);
OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 1);
OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 2);
OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 3);
OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 4);
OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 5);
OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 6);
OSMetaClassDefineReservedUnused(IOFilterInterruptEventSource, 7);
bool IOFilterInterruptEventSource::init(OSObject *inOwner,
Action inAction,
IOService *inProvider,
int inIntIndex)
{
return false;
}
IOInterruptEventSource *
IOFilterInterruptEventSource::interruptEventSource(OSObject *inOwner,
Action inAction,
IOService *inProvider,
int inIntIndex)
{
return 0;
}
bool
IOFilterInterruptEventSource::init(OSObject *inOwner,
Action inAction,
Filter inFilterAction,
IOService *inProvider,
int inIntIndex)
{
if ( !super::init(inOwner, inAction, inProvider, inIntIndex) )
return false;
if (!inFilterAction)
return false;
filterAction = inFilterAction;
IOStatisticsInitializeCounter();
return true;
}
IOFilterInterruptEventSource *IOFilterInterruptEventSource
::filterInterruptEventSource(OSObject *inOwner,
Action inAction,
Filter inFilterAction,
IOService *inProvider,
int inIntIndex)
{
IOFilterInterruptEventSource *me = new IOFilterInterruptEventSource;
if (me
&& !me->init(inOwner, inAction, inFilterAction, inProvider, inIntIndex)) {
me->release();
return 0;
}
return me;
}
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);
}
IOFilterInterruptEventSource::Filter
IOFilterInterruptEventSource::getFilterAction() const
{
return filterAction;
}
void IOFilterInterruptEventSource::normalInterruptOccurred
(void *, IOService *, int )
{
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();
}
}
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)
signalInterrupt();
}
void IOFilterInterruptEventSource::disableInterruptOccurred
(void *, 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();
}
}
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);
signalInterrupt();
}
}