From: John Hodge Date: Tue, 29 Nov 2011 15:18:41 +0000 (+0800) Subject: Kernel - Added a FIFO to thread code X-Git-Tag: rel0.14~56 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=836dfa601a62228d07c0509d12996e962a073313;p=tpg%2Facess2.git Kernel - Added a FIFO to thread code --- diff --git a/Kernel/include/threads_int.h b/Kernel/include/threads_int.h index 4cc11ec6..6516b35a 100644 --- a/Kernel/include/threads_int.h +++ b/Kernel/include/threads_int.h @@ -78,6 +78,7 @@ enum { 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 @@ -90,6 +91,7 @@ static const char * const casTHREAD_STAT[] = { "THREAD_STAT_SLEEPING", "THREAD_STAT_MUTEXSLEEP", "THREAD_STAT_SEMAPHORESLEEP", + "THREAD_STAT_QUEUESLEEP", "THREAD_STAT_WAITING", "THREAD_STAT_PREINIT", "THREAD_STAT_ZOMBIE", diff --git a/Kernel/include/workqueue.h b/Kernel/include/workqueue.h new file mode 100644 index 00000000..ff0c7f4c --- /dev/null +++ b/Kernel/include/workqueue.h @@ -0,0 +1,31 @@ +/** + * Acess2 Kernel + * - By John Hodge (thePowersGang) + * + * workqueue.h + * - FIFO Queue + */ +#ifndef _WORKQUEUE_H_ +#define _WORKQUEUE_H_ + +#include + +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 + diff --git a/Kernel/workqueue.c b/Kernel/workqueue.c new file mode 100644 index 00000000..38bf932c --- /dev/null +++ b/Kernel/workqueue.c @@ -0,0 +1,75 @@ +/* + * Acess2 Kernel + * - By John Hodge (thePowersGang) + * + * workqueue.c + * - Worker FIFO Queue (Single Consumer, Interrupt Producer) + */ +#include +#include +#include + +// === 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); +}