*/
#include "IOPMPowerStateQueue.h"
-#include "IOKit/IOLocks.h"
-#undef super
-#define super IOEventSource
-OSDefineMetaClassAndStructors(IOPMPowerStateQueue, IOEventSource);
-
-#ifdef __i386__ /* ppc does this right and doesn't need these routines */
-static
-void * OSDequeueAtomic(void ** inList, SInt32 inOffset)
-{
- void * oldListHead;
- void * newListHead;
-
- do {
- oldListHead = *inList;
- if (oldListHead == NULL) {
- break;
- }
-
- newListHead = *(void **) (((char *) oldListHead) + inOffset);
- } while (! OSCompareAndSwap((UInt32)oldListHead,
- (UInt32)newListHead, (UInt32 *)inList));
- return oldListHead;
-}
-
-static
-void OSEnqueueAtomic(void ** inList, void * inNewLink, SInt32 inOffset)
-{
- void * oldListHead;
- void * newListHead = inNewLink;
- void ** newLinkNextPtr = (void **) (((char *) inNewLink) + inOffset);
-
- do {
- oldListHead = *inList;
- *newLinkNextPtr = oldListHead;
- } while (! OSCompareAndSwap((UInt32)oldListHead, (UInt32)newListHead,
- (UInt32 *)inList));
-}
-#endif /* __i386__ */
+#define super IOEventSource
+OSDefineMetaClassAndStructors( IOPMPowerStateQueue, IOEventSource )
-IOPMPowerStateQueue *IOPMPowerStateQueue::PMPowerStateQueue(OSObject *inOwner)
+IOPMPowerStateQueue * IOPMPowerStateQueue::PMPowerStateQueue(
+ OSObject * inOwner, Action inAction )
{
- IOPMPowerStateQueue *me = new IOPMPowerStateQueue;
+ IOPMPowerStateQueue * me = new IOPMPowerStateQueue;
- if(me && !me->init(inOwner, 0) )
+ if (me && !me->init(inOwner, inAction))
{
me->release();
return NULL;
return me;
}
-bool IOPMPowerStateQueue::init(OSObject *owner, Action action)
+bool IOPMPowerStateQueue::init( OSObject * inOwner, Action inAction )
{
- if(!(super::init(owner, (IOEventSource::Action) action))) return false;
+ if (!inAction || !(super::init(inOwner, inAction)))
+ return false;
+
+ queue_init( &queueHead );
+
+ queueLock = IOLockAlloc();
+ if (!queueLock)
+ return false;
- // Queue of powerstate changes
- changes = NULL;
-#ifdef __i386__
- if (!(tmpLock = IOLockAlloc())) panic("IOPMPowerStateQueue::init can't alloc lock");
-#endif
return true;
}
-
-bool IOPMPowerStateQueue::unIdleOccurred(IOService *inTarget, unsigned long inState)
+bool IOPMPowerStateQueue::submitPowerEvent(
+ uint32_t eventType,
+ void * arg0,
+ uint64_t arg1 )
{
- PowerChangeEntry *new_one = NULL;
-
- new_one = (PowerChangeEntry *)IOMalloc(sizeof(PowerChangeEntry));
- if(!new_one) return false;
-
- new_one->actionType = IOPMPowerStateQueue::kUnIdle;
- new_one->state = inState;
- new_one->target = inTarget;
-
- // Change to queue
-#ifdef __i386__
- IOLockLock(tmpLock);
-#endif
- OSEnqueueAtomic((void **)&changes, (void *)new_one, 0);
-#ifdef __i386__
- IOLockUnlock(tmpLock);
-#endif
+ PowerEventEntry * entry;
+
+ entry = IONew(PowerEventEntry, 1);
+ if (!entry)
+ return false;
+
+ entry->eventType = eventType;
+ entry->arg0 = arg0;
+ entry->arg1 = arg1;
+
+ IOLockLock(queueLock);
+ queue_enter(&queueHead, entry, PowerEventEntry *, chain);
+ IOLockUnlock(queueLock);
signalWorkAvailable();
return true;
}
-// checkForWork() is called in a gated context
-bool IOPMPowerStateQueue::checkForWork()
+bool IOPMPowerStateQueue::checkForWork( void )
{
- PowerChangeEntry *theNode;
- int theState;
- IOService *theTarget;
- UInt16 theAction;
-
- // Dequeue and process the state change request
-#ifdef __i386__
- IOLockLock(tmpLock);
-#endif
- if((theNode = (PowerChangeEntry *)OSDequeueAtomic((void **)&changes, 0)))
- {
-#ifdef __i386__
- IOLockUnlock(tmpLock);
-#endif
- theState = theNode->state;
- theTarget = theNode->target;
- theAction = theNode->actionType;
- IOFree((void *)theNode, sizeof(PowerChangeEntry));
-
- switch (theAction)
- {
- case kUnIdle:
- theTarget->command_received((void *)theState, 0, 0, 0);
- break;
- }
- }
-#ifdef __i386__
- else {
- IOLockUnlock(tmpLock);
- }
-#endif
- // Return true if there's more work to be done
- if(changes) return true;
- else return false;
+ IOPMPowerStateQueueAction queueAction = (IOPMPowerStateQueueAction) action;
+ PowerEventEntry * entry;
+
+ IOLockLock(queueLock);
+ while (!queue_empty(&queueHead))
+ {
+ queue_remove_first(&queueHead, entry, PowerEventEntry *, chain);
+ IOLockUnlock(queueLock);
+
+ (*queueAction)(owner, entry->eventType, entry->arg0, entry->arg1);
+ IODelete(entry, PowerEventEntry, 1);
+
+ IOLockLock(queueLock);
+ }
+ IOLockUnlock(queueLock);
+
+ return false;
}