2 * Copyright (c) 2001-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_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 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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include "IOPMWorkArbiter.h"
30 #include "IOKit/IOLocks.h"
32 #define super IOEventSource
33 OSDefineMetaClassAndStructors(IOPMWorkArbiter
, IOEventSource
);
35 /*************************************************************************/
37 void * _dequeue(void ** inList
, SInt32 inOffset
)
43 oldListHead
= *inList
;
44 if (oldListHead
== NULL
) {
48 newListHead
= *(void **) (((char *) oldListHead
) + inOffset
);
49 } while (! OSCompareAndSwap((UInt32
)oldListHead
,
50 (UInt32
)newListHead
, (UInt32
*)inList
));
54 /*************************************************************************/
56 void _enqueue(void ** inList
, void * inNewLink
, SInt32 inOffset
)
59 void * newListHead
= inNewLink
;
60 void ** newLinkNextPtr
= (void **) (((char *) inNewLink
) + inOffset
);
63 oldListHead
= *inList
;
64 *newLinkNextPtr
= oldListHead
;
65 } while (! OSCompareAndSwap((UInt32
)oldListHead
, (UInt32
)newListHead
,
69 /*************************************************************************/
70 IOPMWorkArbiter
*IOPMWorkArbiter::pmWorkArbiter(
71 IOPMrootDomain
*inOwner
)
73 IOPMWorkArbiter
*me
= new IOPMWorkArbiter
;
75 if(me
&& !me
->init((OSObject
*)inOwner
, 0) )
84 /*************************************************************************/
85 bool IOPMWorkArbiter::init(OSObject
*owner
, Action action
)
87 if(!(super::init(owner
, (IOEventSource::Action
) action
)))
91 fRootDomain
= (IOPMrootDomain
*)owner
;
93 if (!(tmpLock
= IOLockAlloc())) {
94 panic("IOPMWorkArbiter::init can't alloc lock");
100 /*************************************************************************/
101 bool IOPMWorkArbiter::clamshellStateChangeOccurred(uint32_t messageValue
)
103 PMEventEntry
*new_one
= NULL
;
105 new_one
= (PMEventEntry
*)IOMalloc(sizeof(PMEventEntry
));
106 if(!new_one
) return false;
108 new_one
->actionType
= IOPMWorkArbiter::kRootDomainClamshellChanged
;
109 new_one
->target
= (IOService
*)fRootDomain
;
110 new_one
->intArgument
= messageValue
;
111 new_one
->target
->retain();
114 _enqueue((void **)&events
, (void *)new_one
, 0);
115 IOLockUnlock(tmpLock
);
116 signalWorkAvailable();
122 /*************************************************************************/
123 // checkForWork() is called in a gated context
124 bool IOPMWorkArbiter::checkForWork()
126 PMEventEntry
*theNode
;
127 IOService
*theTarget
;
130 // Dequeue and process the state change request
132 if((theNode
= (PMEventEntry
*)_dequeue((void **)&events
, 0)))
134 IOLockUnlock(tmpLock
);
135 theTarget
= theNode
->target
;
136 theAction
= theNode
->actionType
;
140 case kRootDomainClamshellChanged
:
141 theTarget
->messageClients(
142 kIOPMMessageClamshellStateChange
,
143 (void *)theNode
->intArgument
);
148 theTarget
->release();
149 IOFree((void *)theNode
, sizeof(PMEventEntry
));
152 IOLockUnlock(tmpLock
);
154 // Return true if there's more work to be done
155 if(events
) return true;