#include <workqueue.h>
#include <threads_int.h>
+#define QUEUENEXT(ptr) (*( (void**)(ptr) + Queue->NextOffset/sizeof(void*) ))
+
// === CODE ===
void Workqueue_Init(tWorkqueue *Queue, const char *Name, size_t NextOfset)
{
Queue->Name = Name;
Queue->NextOffset = NextOfset;
+ Queue->Sleeper = NULL;
+ Queue->SleepTail = NULL;
}
void *Workqueue_GetWork(tWorkqueue *Queue)
{
- tThread *us;
-
for( ;; )
{
// Check for work
if(Queue->Head)
{
void *ret = Queue->Head;
- Queue->Head = *( (void**)ret + Queue->NextOffset/sizeof(void*) );
+ Queue->Head = QUEUENEXT( ret );
if(Queue->Tail == ret)
Queue->Tail = NULL;
SHORTREL(&Queue->Protector);
return ret;
}
- // Go to sleep
- SHORTLOCK(&glThreadListLock);
- us = Threads_RemActive();
- us->WaitPointer = Queue;
- us->Status = THREAD_STAT_QUEUESLEEP;
- Queue->Sleeper = us;
- SHORTREL(&Queue->Protector);
- SHORTREL(&glThreadListLock);
-
- // Yield and sleep
- Threads_Yield();
- if(us->Status == THREAD_STAT_QUEUESLEEP) {
- // Why are we awake?!
- }
-
- us->WaitPointer = NULL;
+ Threads_int_Sleep(THREAD_STAT_QUEUESLEEP,
+ Queue, 0,
+ &Queue->Sleeper, &Queue->SleepTail, &Queue->Protector);
}
}
SHORTLOCK(&Queue->Protector);
if( Queue->Tail )
- *( (void**)Queue->Tail + Queue->NextOffset/sizeof(void*) ) = Ptr;
+ QUEUENEXT(Queue->Tail) = Ptr;
else
Queue->Head = Ptr;
Queue->Tail = Ptr;
-
+ QUEUENEXT(Ptr) = NULL;
+
if( Queue->Sleeper )
{
- if( Queue->Sleeper->Status != THREAD_STAT_ACTIVE )
- Threads_AddActive(Queue->Sleeper);
- Queue->Sleeper = NULL;
+ ASSERTC( Queue->Sleeper->Status, !=, THREAD_STAT_ACTIVE );
+ tThread *next_sleeper = Queue->Sleeper->Next;
+ Threads_AddActive(Queue->Sleeper);
+ Queue->Sleeper = next_sleeper;
+ if(!next_sleeper)
+ Queue->SleepTail = NULL;
}
SHORTREL(&Queue->Protector);
}