1 /* 2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 #include <IOKit/pwr_mgt/IOPM.h> 29 #include <IOKit/pwr_mgt/IOPMinformeeList.h> 30 #include <IOKit/pwr_mgt/IOPMinformee.h> 31 32 #define super OSObject 33 OSDefineMetaClassAndStructors(IOPMinformeeList, OSObject) 34 35 //********************************************************************************* 36 // init 37 // 38 //********************************************************************************* 39 void 40 IOPMinformeeList::initialize( void ) 41 { 42 firstItem = NULL; 43 length = 0; 44 } 45 46 //****************************************************************************** 47 // getSharedRecursiveLock 48 // 49 //****************************************************************************** 50 IORecursiveLock * 51 IOPMinformeeList::getSharedRecursiveLock( void ) 52 { 53 static IORecursiveLock *sharedListLock = NULL; 54 55 /* A running system could have 50-60+ instances of IOPMInformeeList. 56 * They'll share this lock, since list insertion and removal is relatively 57 * rare, and generally tied to major events like device discovery. 58 * 59 * getSharedRecursiveLock() is called from IOStartIOKit to initialize 60 * the sharedListLock before any IOPMinformeeLists are instantiated. 61 * 62 * The IOPMinformeeList class will be around for the lifetime of the system, 63 * we don't worry about freeing this lock. 64 */ 65 66 if (NULL == sharedListLock) { 67 sharedListLock = IORecursiveLockAlloc(); 68 } 69 return sharedListLock; 70 } 71 72 //********************************************************************************* 73 // appendNewInformee 74 // 75 //********************************************************************************* 76 IOPMinformee * 77 IOPMinformeeList::appendNewInformee( IOService * newObject ) 78 { 79 IOPMinformee * newInformee; 80 81 if (!newObject) { 82 return NULL; 83 } 84 85 newInformee = IOPMinformee::withObject(newObject); 86 87 if (!newInformee) { 88 return NULL; 89 } 90 91 if (IOPMNoErr == addToList(newInformee)) { 92 return newInformee; 93 } else { 94 newInformee->release(); 95 return NULL; 96 } 97 } 98 99 100 //********************************************************************************* 101 // addToList 102 // *OBSOLETE* do not call from outside of this file. 103 // Try appendNewInformee() instead 104 //********************************************************************************* 105 IOReturn 106 IOPMinformeeList::addToList( IOPMinformee * newInformee ) 107 { 108 IORecursiveLock *listLock = getSharedRecursiveLock(); 109 IOReturn ret = kIOReturnError; 110 111 if (!listLock) { 112 return ret; 113 } 114 115 IORecursiveLockLock(listLock); 116 117 // Is new object already in the list? 118 if (findItem(newInformee->whatObject) != NULL) { 119 // object is present; just exit 120 goto unlock_and_exit; 121 } 122 123 // add it to the front of the list 124 newInformee->nextInList = firstItem; 125 firstItem = newInformee; 126 length++; 127 ret = IOPMNoErr; 128 129 unlock_and_exit: 130 IORecursiveLockUnlock(listLock); 131 return ret; 132 } 133 134 135 //********************************************************************************* 136 // removeFromList 137 // 138 // Find the item in the list, unlink it, and free it. 139 //********************************************************************************* 140 141 IOReturn 142 IOPMinformeeList::removeFromList( IOService * theItem ) 143 { 144 IOPMinformee * item = firstItem; 145 IOPMinformee * temp; 146 IORecursiveLock *listLock = getSharedRecursiveLock(); 147 148 if (NULL == item) { 149 return IOPMNoErr; 150 } 151 if (!listLock) { 152 return kIOReturnError; 153 } 154 155 IORecursiveLockLock( listLock ); 156 157 if (item->whatObject == theItem) { 158 firstItem = item->nextInList; 159 length--; 160 item->release(); 161 goto unlock_and_exit; 162 } 163 164 while (item->nextInList != NULL) { 165 if (item->nextInList->whatObject == theItem) { 166 temp = item->nextInList; 167 item->nextInList = temp->nextInList; 168 length--; 169 temp->release(); 170 goto unlock_and_exit; 171 } 172 item = item->nextInList; 173 } 174 175 unlock_and_exit: 176 IORecursiveLockUnlock(listLock); 177 return IOPMNoErr; 178 } 179 180 181 //********************************************************************************* 182 // firstInList 183 // 184 //********************************************************************************* 185 186 IOPMinformee * 187 IOPMinformeeList::firstInList( void ) 188 { 189 return firstItem; 190 } 191 192 //********************************************************************************* 193 // nextInList 194 // 195 //********************************************************************************* 196 197 IOPMinformee * 198 IOPMinformeeList::nextInList( IOPMinformee * currentItem ) 199 { 200 if (currentItem != NULL) { 201 return currentItem->nextInList; 202 } 203 return NULL; 204 } 205 206 //********************************************************************************* 207 // numberOfItems 208 // 209 //********************************************************************************* 210 211 unsigned long 212 IOPMinformeeList::numberOfItems( void ) 213 { 214 return length; 215 } 216 217 //********************************************************************************* 218 // findItem 219 // 220 // Look through the list for the one which points to the object identified 221 // by the parameter. Return a pointer to the list item or NULL. 222 //********************************************************************************* 223 224 IOPMinformee * 225 IOPMinformeeList::findItem( IOService * driverOrChild ) 226 { 227 IOPMinformee * nextObject; 228 229 nextObject = firstInList(); 230 while (nextObject != NULL) { 231 if (nextObject->whatObject == driverOrChild) { 232 return nextObject; 233 } 234 nextObject = nextInList(nextObject); 235 } 236 return NULL; 237 } 238 239 240 241 //********************************************************************************* 242 // free 243 // 244 // Free all items in the list, and then free the list itself 245 //********************************************************************************* 246 247 void 248 IOPMinformeeList::free(void ) 249 { 250 IOPMinformee * next = firstItem; 251 252 while (next != NULL) { 253 firstItem = next->nextInList; 254 length--; 255 next->release(); 256 next = firstItem; 257 } 258 super::free(); 259 } 260