]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IOWorkLoop.cpp
xnu-4570.61.1.tar.gz
[apple/xnu.git] / iokit / Kernel / IOWorkLoop.cpp
index 51045a234cfe441eb52768a62bf6af452a3e72a9..a5eb8518145a35c8328f575d97ad0d11aa6a135b 100644 (file)
 #include <IOKit/IOEventSource.h>
 #include <IOKit/IOInterruptEventSource.h>
 #include <IOKit/IOCommandGate.h>
+#include <IOKit/IOCommandPool.h>
 #include <IOKit/IOTimeStamp.h>
 #include <IOKit/IOKitDebug.h>
 #include <libkern/OSDebug.h>
+#include <kern/thread.h>
 
 #define super OSObject
 
@@ -83,11 +85,12 @@ do { \
 #define IOStatisticsOpenGate() \
 do { \
        IOStatistics::countWorkLoopOpenGate(reserved->counter); \
+        if (reserved->lockInterval) lockTime();                 \
 } while(0)
-
 #define IOStatisticsCloseGate() \
 do { \
-       IOStatistics::countWorkLoopCloseGate(reserved->counter); \
+       IOStatistics::countWorkLoopCloseGate(reserved->counter);                    \
+        if (reserved->lockInterval) reserved->lockTime = mach_absolute_time();      \
 } while(0)
 
 #define IOStatisticsAttachEventSource() \
@@ -126,11 +129,7 @@ bool IOWorkLoop::init()
                
                bzero(reserved,sizeof(ExpansionData));
        }
-       
-#if DEBUG
-       OSBacktrace ( reserved->allocationBacktrace, sizeof ( reserved->allocationBacktrace ) / sizeof ( reserved->allocationBacktrace[0] ) );
-#endif
-       
+
     if ( gateLock == NULL ) {
         if ( !( gateLock = IORecursiveLockAlloc()) )
             return false;
@@ -143,11 +142,6 @@ bool IOWorkLoop::init()
         workToDo = false;
     }
 
-    if (!reserved) {
-        reserved = IONew(ExpansionData, 1);
-        reserved->options = 0;
-    }
-       
     IOStatisticsRegisterCounter();
 
     if ( controlG == NULL ) {
@@ -177,6 +171,7 @@ bool IOWorkLoop::init()
             return false;
     }
 
+    (void) thread_set_tag(workThread, THREAD_TAG_IOWORKLOOP);
     return true;
 }
 
@@ -229,7 +224,7 @@ void IOWorkLoop::free()
 
         is = IOSimpleLockLockDisableInterrupt(workToDoLock);
        SETP(&fFlags, kLoopTerminate);
-        thread_wakeup_one((void *) &workToDo);
+        thread_wakeup_thread((void *) &workToDo, workThread);
         IOSimpleLockUnlockEnableInterrupt(workToDoLock, is);
 
        openGate();
@@ -258,6 +253,7 @@ void IOWorkLoop::free()
        // Either way clean up all of our resources and return.
        
        if (controlG) {
+           controlG->workLoop = 0;
            controlG->release();
            controlG = 0;
        }
@@ -285,6 +281,13 @@ void IOWorkLoop::free()
 
 IOReturn IOWorkLoop::addEventSource(IOEventSource *newEvent)
 {
+    if ((workThread)
+      && !thread_has_thread_name(workThread)
+      && (newEvent->owner)
+      && !OSDynamicCast(IOCommandPool, newEvent->owner)) {
+        thread_set_thread_name(workThread, newEvent->owner->getMetaClass()->getClassName());
+    }
+
     return controlG->runCommand((void *) mAddEvent, (void *) newEvent);
 }
     
@@ -347,7 +350,7 @@ void IOWorkLoop::disableAllInterrupts() const
                goto abort;
        
     if (traceWL)
-       IOTimeStampStartConstant(IODBG_WORKLOOP(IOWL_WORK), (uintptr_t) this);
+               IOTimeStampStartConstant(IODBG_WORKLOOP(IOWL_WORK), VM_KERNEL_ADDRHIDE(this));
        
     bool more;
     do {
@@ -360,12 +363,12 @@ void IOWorkLoop::disableAllInterrupts() const
                for (IOEventSource *evnt = eventChain; evnt; evnt = evnt->getNext()) {
                        
                        if (traceES)
-                               IOTimeStampStartConstant(IODBG_WORKLOOP(IOWL_CLIENT), (uintptr_t) this, (uintptr_t) evnt);
+                               IOTimeStampStartConstant(IODBG_WORKLOOP(IOWL_CLIENT), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(evnt));
                        
                        more |= evnt->checkForWork();
                        
                        if (traceES)
-                               IOTimeStampEndConstant(IODBG_WORKLOOP(IOWL_CLIENT), (uintptr_t) this, (uintptr_t) evnt);
+                               IOTimeStampEndConstant(IODBG_WORKLOOP(IOWL_CLIENT), VM_KERNEL_ADDRHIDE(this), VM_KERNEL_ADDRHIDE(evnt));
                        
                        if (ISSETP(&fFlags, kLoopTerminate))
                                goto abort;
@@ -379,7 +382,7 @@ void IOWorkLoop::disableAllInterrupts() const
     res = true;
        
     if (traceWL)
-       IOTimeStampEndConstant(IODBG_WORKLOOP(IOWL_WORK), (uintptr_t) this);
+               IOTimeStampEndConstant(IODBG_WORKLOOP(IOWL_WORK), VM_KERNEL_ADDRHIDE(this));
        
 abort:
     openGate();
@@ -442,7 +445,7 @@ void IOWorkLoop::signalWorkAvailable()
     if (workToDoLock) {
         IOInterruptState is = IOSimpleLockLockDisableInterrupt(workToDoLock);
         workToDo = true;
-        thread_wakeup_one((void *) &workToDo);
+        thread_wakeup_thread((void *) &workToDo, workThread);
         IOSimpleLockUnlockEnableInterrupt(workToDoLock, is);
     }
 }
@@ -556,14 +559,16 @@ IOReturn IOWorkLoop::_maintRequest(void *inC, void *inD, void *, void *)
 
     case mRemoveEvent:
         if (inEvent->getWorkLoop()) {
+               IOStatisticsDetachEventSource();
+               
                if (eventSourcePerformsWork(inEvent)) {
                                if (eventChain == inEvent)
                                        eventChain = inEvent->getNext();
                                else {
-                                       IOEventSource *event, *next;
+                                       IOEventSource *event, *next = 0;
                
                                        event = eventChain;
-                                       while ((next = event->getNext()) && next != inEvent)
+                                       if (event) while ((next = event->getNext()) && (next != inEvent))
                                                event = next;
                
                                        if (!next) {
@@ -577,10 +582,10 @@ IOReturn IOWorkLoop::_maintRequest(void *inC, void *inD, void *, void *)
                                if (passiveEventChain == inEvent)
                                        passiveEventChain = inEvent->getNext();
                                else {
-                                       IOEventSource *event, *next;
+                                       IOEventSource *event, *next = 0;
                
                                        event = passiveEventChain;
-                                       while ((next = event->getNext()) && next != inEvent)
+                                       if (event) while ((next = event->getNext()) && (next != inEvent))
                                                event = next;
                
                                        if (!next) {
@@ -595,7 +600,6 @@ IOReturn IOWorkLoop::_maintRequest(void *inC, void *inD, void *, void *)
             inEvent->setNext(0);
             inEvent->release();
             SETP(&fFlags, kLoopRestart);
-            IOStatisticsDetachEventSource();
         }
         break;
 
@@ -629,7 +633,10 @@ IOWorkLoop::eventSourcePerformsWork(IOEventSource *inEventSource)
         * checkForWork() here. We're just testing to see if it's the same or not.
         *
         */
-       if (controlG) {
+
+       if (IOEventSource::kPassive & inEventSource->flags) result = false;
+       else if (IOEventSource::kActive & inEventSource->flags) result = true;
+       else if (controlG) {
                void *  ptr1;
                void *  ptr2;
                
@@ -642,3 +649,25 @@ IOWorkLoop::eventSourcePerformsWork(IOEventSource *inEventSource)
        
     return result;
 }
+
+void
+IOWorkLoop::lockTime(void)
+{
+    uint64_t time;
+    time = mach_absolute_time() - reserved->lockTime;
+    if (time > reserved->lockInterval)
+    {
+        absolutetime_to_nanoseconds(time, &time);
+        if (kTimeLockPanics & reserved->options) panic("IOWorkLoop %p lock time %qd us", this, time / 1000ULL);
+        else                     OSReportWithBacktrace("IOWorkLoop %p lock time %qd us", this, time / 1000ULL);
+    }
+}
+
+void
+IOWorkLoop::setMaximumLockTime(uint64_t interval, uint32_t options)
+{
+    IORecursiveLockLock(gateLock);
+    reserved->lockInterval = interval;
+    reserved->options = (reserved->options & ~kTimeLockPanics) | (options & kTimeLockPanics);
+    IORecursiveLockUnlock(gateLock);
+}