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 IOPMinformeeList::initialize ( void )
40 {
41     firstItem = NULL;
42     length = 0;
43 }
44 
45 //******************************************************************************
46 // getSharedRecursiveLock
47 //
48 //******************************************************************************
49 IORecursiveLock *IOPMinformeeList::getSharedRecursiveLock( void )
50 {
51     static IORecursiveLock *sharedListLock = NULL;
52 
53     /* A running system could have 50-60+ instances of IOPMInformeeList.
54      * They'll share this lock, since list insertion and removal is relatively
55      * rare, and generally tied to major events like device discovery.
56      *
57      * getSharedRecursiveLock() is called from IOStartIOKit to initialize
58      * the sharedListLock before any IOPMinformeeLists are instantiated.
59      *
60      * The IOPMinformeeList class will be around for the lifetime of the system,
61      * we don't worry about freeing this lock.
62      */
63 
64     if ( NULL == sharedListLock )
65     {
66         sharedListLock = IORecursiveLockAlloc();
67     }
68     return sharedListLock;
69 }
70 
71  //*********************************************************************************
72 // appendNewInformee
73  //
74  //*********************************************************************************
75 IOPMinformee *IOPMinformeeList::appendNewInformee ( IOService * newObject )
76 {
77     IOPMinformee * newInformee;
78 
79     if (!newObject)
80         return NULL;
81 
82     newInformee = IOPMinformee::withObject (newObject);
83 
84     if (!newInformee)
85         return NULL;
86 
87     if( IOPMNoErr == addToList (newInformee))
88         return newInformee;
89     else
90         return NULL;
91 }
92 
93 
94 //*********************************************************************************
95 // addToList
96 // *OBSOLETE* do not call from outside of this file.
97 // Try appendNewInformee() instead
98 //*********************************************************************************
99 IOReturn IOPMinformeeList::addToList ( IOPMinformee * newInformee )
100 {
101     IOPMinformee * nextInformee;
102     IORecursiveLock    *listLock = getSharedRecursiveLock();
103 
104     if(!listLock)
105         return kIOReturnError;
106 
107     IORecursiveLockLock(listLock);
108     nextInformee = firstItem;
109 
110     // Is new object already in the list?
111     while (  nextInformee != NULL )
112     {
113         if ( nextInformee->whatObject == newInformee->whatObject )
114         {
115             // object is present; just exit
116             goto unlock_and_exit;
117         }
118         nextInformee = nextInList(nextInformee);
119     }
120 
121     // add it to the front of the list
122     newInformee->nextInList = firstItem;
123     firstItem = newInformee;
124     length++;
125 
126 unlock_and_exit:
127     IORecursiveLockUnlock(listLock);
128     return IOPMNoErr;
129 }
130 
131 
132 //*********************************************************************************
133 // removeFromList
134 //
135 // Find the item in the list, unlink it, and free it.
136 //*********************************************************************************
137 
138 IOReturn IOPMinformeeList::removeFromList ( IOService * theItem )
139 {
140     IOPMinformee * item = firstItem;
141     IOPMinformee * temp;
142     IORecursiveLock    *listLock = getSharedRecursiveLock();
143 
144     if ( NULL == item )
145         return IOPMNoErr;
146     if(!listLock)
147         return kIOReturnError;
148 
149     IORecursiveLockLock( listLock );
150 
151     if ( item->whatObject == theItem )
152     {
153         firstItem = item->nextInList;
154         length--;
155         item->release();
156         goto unlock_and_exit;
157     }
158 
159     while ( item->nextInList != NULL )
160     {
161         if ( item->nextInList->whatObject == theItem )
162         {
163             temp = item->nextInList;
164             item->nextInList = temp->nextInList;
165             length--;
166             temp->release();
167             goto unlock_and_exit;
168         }
169         item = item->nextInList;
170     }
171 
172 unlock_and_exit:
173     IORecursiveLockUnlock(listLock);
174     return IOPMNoErr;
175 }
176 
177 
178 //*********************************************************************************
179 // firstInList
180 //
181 //*********************************************************************************
182 
183 IOPMinformee * IOPMinformeeList::firstInList ( void )
184 {
185     return firstItem;
186 }
187 
188 //*********************************************************************************
189 // nextInList
190 //
191 //*********************************************************************************
192 
193 IOPMinformee * IOPMinformeeList::nextInList ( IOPMinformee * currentItem )
194 {
195     if ( currentItem != NULL ) {
196        return (currentItem->nextInList);
197     }
198     return NULL;
199 }
200 
201 //*********************************************************************************
202 // numberOfItems
203 //
204 //*********************************************************************************
205 
206 unsigned long IOPMinformeeList::numberOfItems ( void )
207 {
208     return length;
209 }
210 
211 //*********************************************************************************
212 // findItem
213 //
214 // Look through the list for the one which points to the object identified
215 // by the parameter.  Return a pointer to the list item or NULL.
216 //*********************************************************************************
217 
218 IOPMinformee * IOPMinformeeList::findItem ( IOService * driverOrChild )
219 {
220     IOPMinformee * nextObject;
221 
222     nextObject = firstInList();
223     while (  nextObject != NULL ) {
224         if ( nextObject->whatObject == driverOrChild ) {
225             return nextObject;
226         }
227         nextObject = nextInList(nextObject);
228     }
229     return NULL;
230 }
231 
232 
233 
234 //*********************************************************************************
235 // free
236 //
237 // Free all items in the list, and then free the list itself
238 //*********************************************************************************
239 
240 void IOPMinformeeList::free (void )
241 {
242     IOPMinformee * next = firstItem;
243 
244     while ( next != NULL ) {
245         firstItem = next->nextInList;
246         length--;
247         next->release();
248         next = firstItem;
249     }
250 super::free();
251 }
252 
253