+ uint64_t startSystemTime = 0;
+ uint64_t endSystemTime = 0;
+ uint64_t startCPUTime = 0;
+ uint64_t endCPUTime = 0;
+ unsigned int cacheProdCount = producerCount;
+ int numInts = cacheProdCount - consumerCount;
+ IOEventSource::Action intAction = action;
+ ActionBlock intActionBlock = (ActionBlock) actionBlock;
+ void *address;
+ bool trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false;
+
+ if (kActionBlock & flags) {
+ address = ptrauth_nop_cast(void *, _Block_get_invoke_fn((struct Block_layout *)intActionBlock));
+ } else {
+ address = ptrauth_nop_cast(void *, intAction);
+ }
+
+ IOStatisticsCheckForWork();
+
+ if (numInts > 0) {
+ if (trace) {
+ IOTimeStampStartConstant(IODBG_INTES(IOINTES_ACTION),
+ VM_KERNEL_ADDRHIDE(address),
+ VM_KERNEL_ADDRHIDE(owner),
+ VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop));
+ }
+
+ if (reserved->statistics) {
+ if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) {
+ startSystemTime = mach_absolute_time();
+ }
+
+ if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) {
+ startCPUTime = thread_get_runtime_self();
+ }
+ }
+
+ // Call the handler
+ if (kActionBlock & flags) {
+ (intActionBlock)(this, numInts);
+ } else {
+ ((IOInterruptEventAction)intAction)(owner, this, numInts);
+ }
+
+ if (reserved->statistics) {
+ if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCountIndex)) {
+ IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCountIndex], 1);
+ }
+
+ if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) {
+ endCPUTime = thread_get_runtime_self();
+ IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCPUTimeIndex], endCPUTime - startCPUTime);
+ }
+
+ if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) {
+ endSystemTime = mach_absolute_time();
+ IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelSystemTimeIndex], endSystemTime - startSystemTime);
+ }
+ }
+
+ if (trace) {
+ IOTimeStampEndConstant(IODBG_INTES(IOINTES_ACTION),
+ VM_KERNEL_ADDRHIDE(address),
+ VM_KERNEL_ADDRHIDE(owner),
+ VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop));
+ }
+
+ consumerCount = cacheProdCount;
+ if (autoDisable && !explicitDisable) {
+ enable();
+ }
+ } else if (numInts < 0) {
+ if (trace) {
+ IOTimeStampStartConstant(IODBG_INTES(IOINTES_ACTION),
+ VM_KERNEL_ADDRHIDE(address),
+ VM_KERNEL_ADDRHIDE(owner),
+ VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop));
+ }
+
+ if (reserved->statistics) {
+ if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) {
+ startSystemTime = mach_absolute_time();
+ }
+
+ if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) {
+ startCPUTime = thread_get_runtime_self();
+ }
+ }
+
+ // Call the handler
+ if (kActionBlock & flags) {
+ (intActionBlock)(this, numInts);
+ } else {
+ ((IOInterruptEventAction)intAction)(owner, this, numInts);
+ }
+
+ if (reserved->statistics) {
+ if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCountIndex)) {
+ IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCountIndex], 1);
+ }
+
+ if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelCPUTimeIndex)) {
+ endCPUTime = thread_get_runtime_self();
+ IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelCPUTimeIndex], endCPUTime - startCPUTime);
+ }
+
+ if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingSecondLevelSystemTimeIndex)) {
+ endSystemTime = mach_absolute_time();
+ IA_ADD_VALUE(&reserved->statistics->interruptStatistics[kInterruptAccountingSecondLevelSystemTimeIndex], endSystemTime - startSystemTime);
+ }
+ }
+
+ if (trace) {
+ IOTimeStampEndConstant(IODBG_INTES(IOINTES_ACTION),
+ VM_KERNEL_ADDRHIDE(address),
+ VM_KERNEL_ADDRHIDE(owner),
+ VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop));
+ }
+
+ consumerCount = cacheProdCount;
+ if (autoDisable && !explicitDisable) {
+ enable();
+ }
+ }
+
+ return false;