]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IOFilterInterruptEventSource.cpp
xnu-4903.231.4.tar.gz
[apple/xnu.git] / iokit / Kernel / IOFilterInterruptEventSource.cpp
index f4f73e2b4c1b3a371ddf791b5915590af1d8916e..f3c61367b3fdc26042992e8b9a655aa619a244f9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1998-2010 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
 #include <IOKit/IOKitDebug.h>
 #include <IOKit/IOTimeStamp.h>
 #include <IOKit/IOWorkLoop.h>
+#include <IOKit/IOInterruptAccountingPrivate.h>
+#include <libkern/Block.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 /* IOKITSTATS */
 
 #define super IOInterruptEventSource
 
@@ -79,6 +100,9 @@ IOFilterInterruptEventSource::init(OSObject *inOwner,
         return false;
 
     filterAction = inFilterAction;
+
+    IOStatisticsInitializeCounter();
+       
     return true;
 }
 
@@ -100,19 +124,53 @@ IOFilterInterruptEventSource *IOFilterInterruptEventSource
     return me;
 }
 
+
+IOFilterInterruptEventSource *IOFilterInterruptEventSource
+::filterInterruptEventSource(OSObject *inOwner,
+                             IOService *inProvider,
+                             int inIntIndex,
+                             ActionBlock inAction,
+                             FilterBlock inFilterAction)
+{
+    IOFilterInterruptEventSource *me = new IOFilterInterruptEventSource;
+
+    FilterBlock filter = Block_copy(inFilterAction);
+    if (!filter) return 0;
+
+    if (me
+    && !me->init(inOwner, (Action) NULL, (Filter) filter, inProvider, inIntIndex)) {
+        me->release();
+           Block_release(filter);
+        return 0;
+    }
+    me->flags |= kFilterBlock;
+    me->setActionBlock((IOEventSource::ActionBlock) inAction);
+
+    return me;
+}
+
+
+void IOFilterInterruptEventSource::free( void )
+{
+       if ((kFilterBlock & flags) && filterActionBlock) Block_release(filterActionBlock);
+
+    super::free();
+}
+
 void IOFilterInterruptEventSource::signalInterrupt()
 {
        bool trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false;
-
+    
+    IOStatisticsInterrupt();
     producerCount++;
-
+       
        if (trace)
-           IOTimeStampStartConstant(IODBG_INTES(IOINTES_SEMA), (uintptr_t) this, (uintptr_t) owner);
+           IOTimeStampStartConstant(IODBG_INTES(IOINTES_SEMA), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(owner));
     
     signalWorkAvailable();
        
        if (trace)
-           IOTimeStampEndConstant(IODBG_INTES(IOINTES_SEMA), (uintptr_t) this, (uintptr_t) owner);
+           IOTimeStampEndConstant(IODBG_INTES(IOINTES_SEMA), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(owner));
        
 }
 
@@ -120,29 +178,55 @@ void IOFilterInterruptEventSource::signalInterrupt()
 IOFilterInterruptEventSource::Filter
 IOFilterInterruptEventSource::getFilterAction() const
 {
+       if (kFilterBlock & flags) return NULL;
     return filterAction;
 }
 
-
-
+IOFilterInterruptEventSource::FilterBlock
+IOFilterInterruptEventSource::getFilterActionBlock() const
+{
+       if (kFilterBlock & flags) return filterActionBlock;
+       return (NULL);
+}
 
 void IOFilterInterruptEventSource::normalInterruptOccurred
     (void */*refcon*/, IOService */*prov*/, int /*source*/)
 {
-    bool filterRes;
+    bool       filterRes;
+    uint64_t   startTime = 0;
+    uint64_t   endTime = 0;
        bool    trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false;
-
+       
        if (trace)
                IOTimeStampStartConstant(IODBG_INTES(IOINTES_FILTER),
-                                                                (uintptr_t) filterAction, (uintptr_t) owner, (uintptr_t) this, (uintptr_t) workLoop);
+                                        VM_KERNEL_UNSLIDE(filterAction), VM_KERNEL_ADDRHIDE(owner), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop));
 
+    if (IOInterruptEventSource::reserved->statistics) {
+        if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelTimeIndex)) {
+            startTime = mach_absolute_time();
+        }
+    }
+    
     // Call the filter.
-    filterRes = (*filterAction)(owner, this);
+    if (kFilterBlock & flags) filterRes = (filterActionBlock)(this);
+    else                      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),
-                                                          (uintptr_t) filterAction, (uintptr_t) owner, (uintptr_t) this, (uintptr_t) workLoop);
-
+                               VM_KERNEL_ADDRHIDE(filterAction), VM_KERNEL_ADDRHIDE(owner),
+                               VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop));
+       
     if (filterRes)
         signalInterrupt();
 }
@@ -150,20 +234,40 @@ void IOFilterInterruptEventSource::normalInterruptOccurred
 void IOFilterInterruptEventSource::disableInterruptOccurred
     (void */*refcon*/, IOService *prov, int source)
 {
-    bool filterRes;
+    bool       filterRes;
+    uint64_t   startTime = 0;
+    uint64_t   endTime = 0;
        bool    trace = (gIOKitTrace & kIOTraceIntEventSource) ? true : false;
-
+       
        if (trace)
                IOTimeStampStartConstant(IODBG_INTES(IOINTES_FILTER),
-                                                                (uintptr_t) filterAction, (uintptr_t) owner, (uintptr_t) this, (uintptr_t) workLoop);
+                                        VM_KERNEL_UNSLIDE(filterAction), VM_KERNEL_ADDRHIDE(owner), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop));
 
+    if (IOInterruptEventSource::reserved->statistics) {
+        if (IA_GET_STATISTIC_ENABLED(kInterruptAccountingFirstLevelTimeIndex)) {
+            startTime = mach_absolute_time();
+        }
+    }
+    
     // Call the filter.
-    filterRes = (*filterAction)(owner, this);
-       
+    if (kFilterBlock & flags) filterRes = (filterActionBlock)(this);
+    else                      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),
-                                                          (uintptr_t) filterAction, (uintptr_t) owner, (uintptr_t) this, (uintptr_t) workLoop);
-
+                                      VM_KERNEL_UNSLIDE(filterAction), VM_KERNEL_ADDRHIDE(owner), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(workLoop));
+       
     if (filterRes) {
         prov->disableInterrupt(source);        /* disable the interrupt */
         signalInterrupt();