2 * Copyright (c) 2001-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 #include "IOPMWorkArbiter.h"
32 #include "IOKit/IOLocks.h"
34 #define super IOEventSource
35 OSDefineMetaClassAndStructors(IOPMWorkArbiter
, IOEventSource
);
37 /*************************************************************************/
39 void * _dequeue(void ** inList
, SInt32 inOffset
)
45 oldListHead
= *inList
;
46 if (oldListHead
== NULL
) {
50 newListHead
= *(void **) (((char *) oldListHead
) + inOffset
);
51 } while (! OSCompareAndSwap((UInt32
)oldListHead
,
52 (UInt32
)newListHead
, (UInt32
*)inList
));
56 /*************************************************************************/
58 void _enqueue(void ** inList
, void * inNewLink
, SInt32 inOffset
)
61 void * newListHead
= inNewLink
;
62 void ** newLinkNextPtr
= (void **) (((char *) inNewLink
) + inOffset
);
65 oldListHead
= *inList
;
66 *newLinkNextPtr
= oldListHead
;
67 } while (! OSCompareAndSwap((UInt32
)oldListHead
, (UInt32
)newListHead
,
71 /*************************************************************************/
72 IOPMWorkArbiter
*IOPMWorkArbiter::pmWorkArbiter(
73 IOPMrootDomain
*inOwner
)
75 IOPMWorkArbiter
*me
= new IOPMWorkArbiter
;
77 if(me
&& !me
->init((OSObject
*)inOwner
, 0) )
86 /*************************************************************************/
87 bool IOPMWorkArbiter::init(OSObject
*owner
, Action action
)
89 if(!(super::init(owner
, (IOEventSource::Action
) action
)))
93 fRootDomain
= (IOPMrootDomain
*)owner
;
95 if (!(tmpLock
= IOLockAlloc())) {
96 panic("IOPMWorkArbiter::init can't alloc lock");
101 /*************************************************************************/
102 bool IOPMWorkArbiter::driverAckedOccurred(IOService
*inTarget
)
104 PMEventEntry
*new_one
= NULL
;
106 new_one
= (PMEventEntry
*)IOMalloc(sizeof(PMEventEntry
));
107 if(!new_one
) return false;
109 new_one
->actionType
= IOPMWorkArbiter::kDriverAcked
;
110 new_one
->target
= inTarget
;
114 _enqueue((void **)&events
, (void *)new_one
, 0);
115 IOLockUnlock(tmpLock
);
116 signalWorkAvailable();
121 /*************************************************************************/
122 bool IOPMWorkArbiter::allAckedOccurred(IOService
*inTarget
)
124 PMEventEntry
*new_one
= NULL
;
126 new_one
= (PMEventEntry
*)IOMalloc(sizeof(PMEventEntry
));
127 if(!new_one
) return false;
129 new_one
->actionType
= IOPMWorkArbiter::kAllAcked
;
130 new_one
->target
= inTarget
;
134 _enqueue((void **)&events
, (void *)new_one
, 0);
135 IOLockUnlock(tmpLock
);
136 signalWorkAvailable();
141 /*************************************************************************/
142 bool IOPMWorkArbiter::clamshellStateChangeOccurred(uint32_t messageValue
)
144 PMEventEntry
*new_one
= NULL
;
146 new_one
= (PMEventEntry
*)IOMalloc(sizeof(PMEventEntry
));
147 if(!new_one
) return false;
149 new_one
->actionType
= IOPMWorkArbiter::kRootDomainClamshellChanged
;
150 new_one
->target
= (IOService
*)fRootDomain
;
151 new_one
->intArgument
= messageValue
;
154 _enqueue((void **)&events
, (void *)new_one
, 0);
155 IOLockUnlock(tmpLock
);
156 signalWorkAvailable();
162 /*************************************************************************/
163 void IOPMWorkArbiter::checkForWorkThreadFunc(void *refcon
)
165 PMEventEntry
*theNode
= (PMEventEntry
*)refcon
;
166 IOService
*theTarget
;
170 theTarget
= theNode
->target
;
171 theAction
= theNode
->actionType
;
172 IOFree(theNode
, sizeof(PMEventEntry
));
178 theTarget
->all_acked_threaded();
182 theTarget
->driver_acked_threaded();
189 /*************************************************************************/
190 // checkForWork() is called in a gated context
191 bool IOPMWorkArbiter::checkForWork()
193 PMEventEntry
*theNode
;
194 IOService
*theTarget
;
197 // Dequeue and process the state change request
199 if((theNode
= (PMEventEntry
*)_dequeue((void **)&events
, 0)))
201 IOLockUnlock(tmpLock
);
202 theTarget
= theNode
->target
;
203 theAction
= theNode
->actionType
;
204 IOFree((void *)theNode
, sizeof(PMEventEntry
));
209 theTarget
->all_acked_threaded();
213 theTarget
->driver_acked_threaded();
216 case kRootDomainClamshellChanged
:
217 theTarget
->messageClients(
218 kIOPMMessageClamshellStateChange
,
219 (void *)theNode
->intArgument
);
224 IOLockUnlock(tmpLock
);
226 // Return true if there's more work to be done
227 if(events
) return true;
232 /*************************************************************************/
234 /*************************************************************************/
236 /*************************************************************************/
238 /*************************************************************************/
241 #define super OSObject
243 PMWorkerThread *PMWorkerThread::workerThread( IOPMWorkArbiter *inArbiter )
245 PMWorkerThread * inst;
247 if( !(inst = new PMWorkerThread) )
253 inst->arbiter = inArbiter;
255 if( !(IOCreateThread((IOThreadFunc) &PMWorkerThread::main, inst)) )
267 void PMWorkerThread::free( void )
272 void PMWorkerThread::main( PMWorkerThread * self )
280 IOTakeLock( gJobsLock );
282 if( !(job = (PMWorkUnit *) gJobs->copyNextJob()) )
284 IOUnlock( gJobsLock );
285 semaphore_wait( gJobsSemaphore );
286 IOTakeLock( gJobsLock );
288 job = (PMWorkUnit *) gJobs->copyNextJob();
291 IOUnlock( gJobsLock );
302 who->doServiceMatch();