THREAD_STAT_SLEEPING, // Message Sleep
THREAD_STAT_MUTEXSLEEP, // Mutex Sleep
THREAD_STAT_SEMAPHORESLEEP, // Semaphore Sleep
+ THREAD_STAT_QUEUESLEEP, // Queue
THREAD_STAT_WAITING, // ??? (Waiting for a thread)
THREAD_STAT_PREINIT, // Being created
THREAD_STAT_ZOMBIE, // Died/Killed, but parent not informed
"THREAD_STAT_SLEEPING",
"THREAD_STAT_MUTEXSLEEP",
"THREAD_STAT_SEMAPHORESLEEP",
+ "THREAD_STAT_QUEUESLEEP",
"THREAD_STAT_WAITING",
"THREAD_STAT_PREINIT",
"THREAD_STAT_ZOMBIE",
--- /dev/null
+/**
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * workqueue.h
+ * - FIFO Queue
+ */
+#ifndef _WORKQUEUE_H_
+#define _WORKQUEUE_H_
+
+#include <acess.h>
+
+typedef struct sWorkqueue tWorkqueue;
+
+struct sWorkqueue
+{
+ tShortSpinlock Protector;
+ const char *Name;
+ int NextOffset;
+
+ void *Head;
+ void *Tail;
+ struct sThread *Sleeper;
+};
+
+extern void Workqueue_Init(tWorkqueue *Queue, const char *Name, size_t NextOfset);
+extern void *Workqueue_GetWork(tWorkqueue *Queue);
+extern void Workqueue_AddWork(tWorkqueue *Queue, void *Ptr);
+
+#endif
+
--- /dev/null
+/*
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * workqueue.c
+ * - Worker FIFO Queue (Single Consumer, Interrupt Producer)
+ */
+#include <acess.h>
+#include <workqueue.h>
+#include <threads_int.h>
+
+// === CODE ===
+void Workqueue_Init(tWorkqueue *Queue, const char *Name, size_t NextOfset)
+{
+ Queue->Name = Name;
+ Queue->NextOffset = NextOfset;
+}
+
+void *Workqueue_GetWork(tWorkqueue *Queue)
+{
+ tThread *us;
+
+ for( ;; )
+ {
+ // Check for work
+ SHORTLOCK(&Queue->Protector);
+ if(Queue->Head)
+ {
+ void *ret = Queue->Head;
+ Queue->Head = *(void**)( (char*)ret + Queue->NextOffset );
+ 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;
+ }
+}
+
+void Workqueue_AddWork(tWorkqueue *Queue, void *Ptr)
+{
+ SHORTLOCK(&Queue->Protector);
+
+ if( Queue->Tail )
+ *(void**)( (char*)Queue->Tail + Queue->NextOffset ) = Ptr;
+ else
+ Queue->Head = Ptr;
+ Queue->Tail = Ptr;
+
+ if( Queue->Sleeper )
+ {
+ SHORTLOCK( &glThreadListLock );
+ if( Queue->Sleeper->Status != THREAD_STAT_ACTIVE )
+ Threads_AddActive(Queue->Sleeper);
+ SHORTREL( &glThreadListLock );
+ Queue->Sleeper = NULL;
+ }
+ SHORTREL(&Queue->Protector);
+}