]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IOPMinformeeList.cpp
xnu-4903.270.47.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPMinformeeList.cpp
index 2ba440a145087c2f5bc51f54c831bd925042870c..18cf810ed0e61fb0840ea717f6ca496fba9b2cb4 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
- * 
+ *
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -22,7 +22,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 #include <IOKit/pwr_mgt/IOPM.h>
 #include <IOKit/pwr_mgt/IOPMinformee.h>
 
 #define super OSObject
-OSDefineMetaClassAndStructors(IOPMinformeeList,OSObject)
+OSDefineMetaClassAndStructors(IOPMinformeeList, OSObject)
 
 //*********************************************************************************
 // init
 //
 //*********************************************************************************
-void IOPMinformeeList::initialize ( void )
+void
+IOPMinformeeList::initialize( void )
+{
+       firstItem = NULL;
+       length = 0;
+}
+
+//******************************************************************************
+// getSharedRecursiveLock
+//
+//******************************************************************************
+IORecursiveLock *
+IOPMinformeeList::getSharedRecursiveLock( void )
+{
+       static IORecursiveLock *sharedListLock = NULL;
+
+       /* A running system could have 50-60+ instances of IOPMInformeeList.
+        * They'll share this lock, since list insertion and removal is relatively
+        * rare, and generally tied to major events like device discovery.
+        *
+        * getSharedRecursiveLock() is called from IOStartIOKit to initialize
+        * the sharedListLock before any IOPMinformeeLists are instantiated.
+        *
+        * The IOPMinformeeList class will be around for the lifetime of the system,
+        * we don't worry about freeing this lock.
+        */
+
+       if (NULL == sharedListLock) {
+               sharedListLock = IORecursiveLockAlloc();
+       }
+       return sharedListLock;
+}
+
+//*********************************************************************************
+// appendNewInformee
+//
+//*********************************************************************************
+IOPMinformee *
+IOPMinformeeList::appendNewInformee( IOService * newObject )
 {
-    firstItem = NULL;
-    length = 0;
+       IOPMinformee * newInformee;
+
+       if (!newObject) {
+               return NULL;
+       }
+
+       newInformee = IOPMinformee::withObject(newObject);
+
+       if (!newInformee) {
+               return NULL;
+       }
+
+       if (IOPMNoErr == addToList(newInformee)) {
+               return newInformee;
+       } else {
+               return NULL;
+       }
 }
 
+
 //*********************************************************************************
 // addToList
+// *OBSOLETE* do not call from outside of this file.
+// Try appendNewInformee() instead
+//*********************************************************************************
+IOReturn
+IOPMinformeeList::addToList( IOPMinformee * newInformee )
+{
+       IOPMinformee * nextInformee;
+       IORecursiveLock    *listLock = getSharedRecursiveLock();
+
+       if (!listLock) {
+               return kIOReturnError;
+       }
+
+       IORecursiveLockLock(listLock);
+       nextInformee = firstItem;
+
+       // Is new object already in the list?
+       while (nextInformee != NULL) {
+               if (nextInformee->whatObject == newInformee->whatObject) {
+                       // object is present; just exit
+                       goto unlock_and_exit;
+               }
+               nextInformee = nextInList(nextInformee);
+       }
+
+       // add it to the front of the list
+       newInformee->nextInList = firstItem;
+       firstItem = newInformee;
+       length++;
+
+unlock_and_exit:
+       IORecursiveLockUnlock(listLock);
+       return IOPMNoErr;
+}
+
+
+//*********************************************************************************
+// removeFromList
 //
+// Find the item in the list, unlink it, and free it.
 //*********************************************************************************
 
-IOReturn IOPMinformeeList::addToList ( IOPMinformee * newInformee )
+IOReturn
+IOPMinformeeList::removeFromList( IOService * theItem )
 {
-    IOPMinformee * nextInformee;
-    nextInformee = firstItem;                          // Is new object already in the list?
-    while (  nextInformee != NULL ) {
-        if ( nextInformee->whatObject == newInformee->whatObject ) {
-            return IOPMNoErr;                          // yes, just return
-        }
-        nextInformee = nextInList(nextInformee);
-    }
-    newInformee->nextInList = firstItem;               // add it to list
-    firstItem = newInformee;
-    length += 1;
-    return IOPMNoErr;
+       IOPMinformee * item = firstItem;
+       IOPMinformee * temp;
+       IORecursiveLock    *listLock = getSharedRecursiveLock();
+
+       if (NULL == item) {
+               return IOPMNoErr;
+       }
+       if (!listLock) {
+               return kIOReturnError;
+       }
+
+       IORecursiveLockLock( listLock );
+
+       if (item->whatObject == theItem) {
+               firstItem = item->nextInList;
+               length--;
+               item->release();
+               goto unlock_and_exit;
+       }
+
+       while (item->nextInList != NULL) {
+               if (item->nextInList->whatObject == theItem) {
+                       temp = item->nextInList;
+                       item->nextInList = temp->nextInList;
+                       length--;
+                       temp->release();
+                       goto unlock_and_exit;
+               }
+               item = item->nextInList;
+       }
+
+unlock_and_exit:
+       IORecursiveLockUnlock(listLock);
+       return IOPMNoErr;
 }
 
 
@@ -69,9 +185,10 @@ IOReturn IOPMinformeeList::addToList ( IOPMinformee * newInformee )
 //
 //*********************************************************************************
 
-IOPMinformee * IOPMinformeeList::firstInList ( void )
+IOPMinformee *
+IOPMinformeeList::firstInList( void )
 {
-    return firstItem;
+       return firstItem;
 }
 
 //*********************************************************************************
@@ -79,12 +196,13 @@ IOPMinformee * IOPMinformeeList::firstInList ( void )
 //
 //*********************************************************************************
 
-IOPMinformee * IOPMinformeeList::nextInList ( IOPMinformee * currentItem )
+IOPMinformee *
+IOPMinformeeList::nextInList( IOPMinformee * currentItem )
 {
-    if ( currentItem != NULL ) {
-       return (currentItem->nextInList);
-    }
-    return NULL;
+       if (currentItem != NULL) {
+               return currentItem->nextInList;
+       }
+       return NULL;
 }
 
 //*********************************************************************************
@@ -92,9 +210,10 @@ IOPMinformee * IOPMinformeeList::nextInList ( IOPMinformee * currentItem )
 //
 //*********************************************************************************
 
-unsigned long IOPMinformeeList::numberOfItems ( void )
+unsigned long
+IOPMinformeeList::numberOfItems( void )
 {
-    return length;
+       return length;
 }
 
 //*********************************************************************************
@@ -104,70 +223,39 @@ unsigned long IOPMinformeeList::numberOfItems ( void )
 // by the parameter.  Return a pointer to the list item or NULL.
 //*********************************************************************************
 
-IOPMinformee * IOPMinformeeList::findItem ( IOService * driverOrChild )
+IOPMinformee *
+IOPMinformeeList::findItem( IOService * driverOrChild )
 {
-    IOPMinformee * nextObject;
-
-    nextObject = firstInList();
-    while (  nextObject != NULL ) {
-        if ( nextObject->whatObject == driverOrChild ) {
-            return nextObject;
-        }
-        nextObject = nextInList(nextObject);
-    }
-    return NULL;
-}
-
-
-//*********************************************************************************
-// removeFromList
-//
-// Find the item in the list, unlink it, and free it.
-//*********************************************************************************
+       IOPMinformee * nextObject;
 
-IOReturn IOPMinformeeList::removeFromList ( IOService * theItem )
-{
-    IOPMinformee * item = firstItem;
-    IOPMinformee * temp;
-
-    if ( item != NULL ) {
-        if ( item->whatObject == theItem ) {
-            firstItem = item->nextInList;
-            length--;
-            item->release();
-            return IOPMNoErr;
-        }
-        while ( item->nextInList != NULL ) {
-            if ( item->nextInList->whatObject == theItem ) {
-                temp = item->nextInList;
-                item->nextInList = temp->nextInList;
-                length--;
-                temp->release();
-                return IOPMNoErr;
-            }
-            item = item->nextInList;
-        }
-    }
-    return IOPMNoErr;
+       nextObject = firstInList();
+       while (nextObject != NULL) {
+               if (nextObject->whatObject == driverOrChild) {
+                       return nextObject;
+               }
+               nextObject = nextInList(nextObject);
+       }
+       return NULL;
 }
 
 
+
 //*********************************************************************************
 // free
 //
 // Free all items in the list, and then free the list itself
 //*********************************************************************************
 
-void IOPMinformeeList::free (void )
+void
+IOPMinformeeList::free(void )
 {
-    IOPMinformee * next = firstItem;
-
-    while ( next != NULL ) {
-        firstItem = next->nextInList;
-        length--;
-        next->release();
-        next = firstItem;        
-    }
-super::free();
-}
+       IOPMinformee * next = firstItem;
 
+       while (next != NULL) {
+               firstItem = next->nextInList;
+               length--;
+               next->release();
+               next = firstItem;
+       }
+       super::free();
+}