Kernel - Split Mutexes/Semaphores out
authorJohn Hodge <[email protected]>
Fri, 11 Nov 2011 09:00:03 +0000 (17:00 +0800)
committerJohn Hodge <[email protected]>
Fri, 11 Nov 2011 09:00:03 +0000 (17:00 +0800)
- Working on being able to clean up arch data in threads

Kernel/Makefile
Kernel/arch/x86/proc.c
Kernel/include/hal_proc.h
Kernel/include/threads_int.h
Kernel/messages.c
Kernel/mutex.c [new file with mode: 0644]
Kernel/semaphore.c [new file with mode: 0644]
Kernel/threads.c

index 93ad6b6..287d01a 100644 (file)
@@ -42,10 +42,9 @@ BUILDINFO_SRC := $(OBJDIR)buildinfo.c$(OBJSUFFIX)
 
 OBJ := $(addprefix arch/$(ARCHDIR)/,$(A_OBJ))
 OBJ += heap.o drvutil.o logging.o debug.o lib.o adt.o time.o
-OBJ += messages.o modules.o syscalls.o system.o threads.o
-OBJ += $(addprefix vfs/fs/, $(addsuffix .o,$(FILESYSTEMS)))
+OBJ += messages.o modules.o syscalls.o system.o
+OBJ += threads.o mutex.o semaphore.o
 OBJ += drv/vterm.o drv/proc.o drv/fifo.o drv/iocache.o drv/pci.o
-#OBJ += drv/kb.o drv/dma.o drv/vga.o
 OBJ += binary.o bin/elf.o bin/pe.o
 OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/dir.o vfs/io.o vfs/mount.o
 OBJ += vfs/memfile.o vfs/nodecache.o vfs/handle.o vfs/select.o vfs/mmap.o
index 8efe2a8..cdb51b6 100644 (file)
@@ -48,7 +48,6 @@ extern void   NewTaskHeader(tThread *Thread, void *Fcn, int nArgs, ...);      // Actual
 extern Uint    Proc_CloneInt(Uint *ESP, Uint32 *CR3);
 extern Uint32  gaInitPageDir[1024];    // start.asm
 extern char    Kernel_Stack_Top[];
-extern tShortSpinlock  glThreadListLock;
 extern int     giNumCPUs;
 extern int     giNextTID;
 extern tThread gThreadZero;
@@ -557,6 +556,14 @@ void Proc_ChangeStack(void)
        __asm__ __volatile__ ("mov %0, %%ebp"::"r"(ebp));
 }
 
+void Proc_ClearThread(tThread *Thread)
+{
+       if(Thread->SavedState.SSE) {
+               free(Thread->SavedState.SSE);
+               Thread->SavedState.SSE = NULL;
+       }
+}
+
 int Proc_NewKThread(void (*Fcn)(void*), void *Data)
 {
        Uint    esp;
index c807934..0df0556 100644 (file)
@@ -23,6 +23,10 @@ extern void  ArchThreads_Init(void);
  * \brief Start preemptive multithreading (if needed)
  */
 extern void    Proc_Start(void);
+/**
+ * \brief Called just before a thread is freed
+ */
+extern void    Proc_ClearThread(tThread *Thread);
 /**
  * \brief Get the ID of this CPU
  * \return Zero based CPU ID
index 124f51a..64b2986 100644 (file)
@@ -99,6 +99,7 @@ static const char * const casTHREAD_STAT[] = {
 
 // === GLOBALS ===
 extern BOOL    gaThreads_NoTaskSwitch[MAX_CPUS];
+extern tShortSpinlock  glThreadListLock;
 
 // === FUNCTIONS ===
 extern tThread *Proc_GetCurThread(void);
index 05f75f1..2c0e448 100644 (file)
@@ -11,9 +11,6 @@
 #include <threads_int.h>
 #include <errno.h>
 
-// === IMPORTS ===
-extern tShortSpinlock  glThreadListLock;
-
 // === CODE ===
 /**
  * \fn int Proc_SendMessage(Uint *Err, Uint Dest, int Length, void *Data)
diff --git a/Kernel/mutex.c b/Kernel/mutex.c
new file mode 100644 (file)
index 0000000..4b4c4e4
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * mutex.c
+ * - Mutexes
+ */
+#include <acess.h>
+#include <threads_int.h>
+#include <mutex.h>
+
+// === PROTOTYPES ===
+#if 0
+ int   Mutex_Acquire(tMutex *Mutex);
+void   Mutex_Release(tMutex *Mutex);
+ int   Mutex_IsLocked(tMutex *Mutex);
+#endif
+
+// === CODE ===
+//
+// Acquire mutex (see mutex.h for documentation)
+//
+int Mutex_Acquire(tMutex *Mutex)
+{
+       tThread *us = Proc_GetCurThread();
+       
+       // Get protector
+       SHORTLOCK( &Mutex->Protector );
+       
+       //Log("Mutex_Acquire: (%p)", Mutex);
+       
+       // Check if the lock is already held
+       if( Mutex->Owner ) {
+               SHORTLOCK( &glThreadListLock );
+               // - Remove from active list
+               us = Threads_RemActive();
+               us->Next = NULL;
+               // - Mark as sleeping
+               us->Status = THREAD_STAT_MUTEXSLEEP;
+               us->WaitPointer = Mutex;
+               
+               // - Add to waiting
+               if(Mutex->LastWaiting) {
+                       Mutex->LastWaiting->Next = us;
+                       Mutex->LastWaiting = us;
+               }
+               else {
+                       Mutex->Waiting = us;
+                       Mutex->LastWaiting = us;
+               }
+               
+               #if DEBUG_TRACE_STATE
+               Log("%p (%i %s) waiting on mutex %p",
+                       us, us->TID, us->ThreadName, Mutex);
+               #endif
+               
+               #if 0
+               {
+                        int    i = 0;
+                       tThread *t;
+                       for( t = Mutex->Waiting; t; t = t->Next, i++ )
+                               Log("[%i] (tMutex)%p->Waiting[%i] = %p (%i %s)", us->TID, Mutex, i,
+                                       t, t->TID, t->ThreadName);
+               }
+               #endif
+               
+               SHORTREL( &glThreadListLock );
+               SHORTREL( &Mutex->Protector );
+               while(us->Status == THREAD_STAT_MUTEXSLEEP)     Threads_Yield();
+               // We're only woken when we get the lock
+               us->WaitPointer = NULL;
+       }
+       // Ooh, let's take it!
+       else {
+               Mutex->Owner = us;
+               SHORTREL( &Mutex->Protector );
+       }
+       
+       #if 0
+       extern tMutex   glPhysAlloc;
+       if( Mutex != &glPhysAlloc )
+               LogF("Mutex %p taken by %i %p\n", Mutex, us->TID, __builtin_return_address(0));
+       #endif
+       
+       return 0;
+}
+
+// Release a mutex
+void Mutex_Release(tMutex *Mutex)
+{
+       SHORTLOCK( &Mutex->Protector );
+       //Log("Mutex_Release: (%p)", Mutex);
+       if( Mutex->Waiting ) {
+               Mutex->Owner = Mutex->Waiting;  // Set owner
+               Mutex->Waiting = Mutex->Waiting->Next;  // Next!
+               // Reset ->LastWaiting to NULL if we have just removed the last waiting thread
+               // 2010-10-02 21:50 - Comemerating the death of the longest single
+               //                    blocker in the Acess2 history. REMEMBER TO
+               //                    FUCKING MAINTAIN YOUR FUCKING LISTS DIPWIT
+               if( Mutex->LastWaiting == Mutex->Owner )
+                       Mutex->LastWaiting = NULL;
+               
+               // Wake new owner
+               SHORTLOCK( &glThreadListLock );
+               if( Mutex->Owner->Status != THREAD_STAT_ACTIVE )
+                       Threads_AddActive(Mutex->Owner);
+               SHORTREL( &glThreadListLock );
+       }
+       else {
+               Mutex->Owner = NULL;
+       }
+       SHORTREL( &Mutex->Protector );
+       
+       #if 0
+       extern tMutex   glPhysAlloc;
+       if( Mutex != &glPhysAlloc )
+               LogF("Mutex %p released by %i %p\n", Mutex, Threads_GetTID(), __builtin_return_address(0));
+       #endif
+}
+
+// Check if a mutex is locked
+int Mutex_IsLocked(tMutex *Mutex)
+{
+       return Mutex->Owner != NULL;
+}
+
+// === EXPORTS ===
+EXPORT(Mutex_Acquire);
+EXPORT(Mutex_Release);
+EXPORT(Mutex_IsLocked);
diff --git a/Kernel/semaphore.c b/Kernel/semaphore.c
new file mode 100644 (file)
index 0000000..b73ce02
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * semaphore.c
+ * - Semaphores
+ */
+#include <acess.h>
+#include <semaphore.h>
+#include <threads_int.h>
+
+#define SEMAPHORE_DEBUG        0       // Debug semaphores
+
+// === CODE ===
+//
+// Initialise a semaphore
+//
+void Semaphore_Init(tSemaphore *Sem, int Value, int MaxValue, const char *Module, const char *Name)
+{
+       memset(Sem, 0, sizeof(tSemaphore));
+       Sem->Value = Value;
+       Sem->ModName = Module;
+       Sem->Name = Name;
+       Sem->MaxValue = MaxValue;
+}
+//
+// Wait for items to be avaliable
+//
+int Semaphore_Wait(tSemaphore *Sem, int MaxToTake)
+{
+       tThread *us;
+        int    taken;
+       if( MaxToTake < 0 ) {
+               Log_Warning("Threads", "Semaphore_Wait: User bug - MaxToTake(%i) < 0, Sem=%p(%s)",
+                       MaxToTake, Sem, Sem->Name);
+       }
+       
+       SHORTLOCK( &Sem->Protector );
+       
+       // Check if there's already items avaliable
+       if( Sem->Value > 0 ) {
+               // Take what we need
+               if( MaxToTake && Sem->Value > MaxToTake )
+                       taken = MaxToTake;
+               else
+                       taken = Sem->Value;
+               Sem->Value -= taken;
+       }
+       else
+       {
+               SHORTLOCK( &glThreadListLock );
+               
+               // - Remove from active list
+               us = Threads_RemActive();
+               us->Next = NULL;
+               // - Mark as sleeping
+               us->Status = THREAD_STAT_SEMAPHORESLEEP;
+               us->WaitPointer = Sem;
+               us->RetStatus = MaxToTake;      // Use RetStatus as a temp variable
+               
+               // - Add to waiting
+               if(Sem->LastWaiting) {
+                       Sem->LastWaiting->Next = us;
+                       Sem->LastWaiting = us;
+               }
+               else {
+                       Sem->Waiting = us;
+                       Sem->LastWaiting = us;
+               }
+               
+               #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG
+               Log("%p (%i %s) waiting on semaphore %p %s:%s",
+                       us, us->TID, us->ThreadName,
+                       Sem, Sem->ModName, Sem->Name);
+               #endif
+               
+               SHORTREL( &Sem->Protector );    // Release first to make sure it is released
+               SHORTREL( &glThreadListLock );
+               while( us->Status == THREAD_STAT_SEMAPHORESLEEP )
+               {
+                       Threads_Yield();
+                       if(us->Status == THREAD_STAT_SEMAPHORESLEEP)
+                               Log_Warning("Threads", "Semaphore %p %s:%s re-schedulued while asleep",
+                                       Sem, Sem->ModName, Sem->Name);
+               }
+               #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG
+               Log("Semaphore %p %s:%s woken", Sem, Sem->ModName, Sem->Name);
+               #endif
+               // We're only woken when there's something avaliable (or a signal arrives)
+               us->WaitPointer = NULL;
+               
+               taken = us->RetStatus;
+               
+               // Get the lock again
+               SHORTLOCK( &Sem->Protector );
+       }
+       
+       // While there is space, and there are thread waiting
+       // wake the first thread and give it what it wants (or what's left)
+       while( (Sem->MaxValue == 0 || Sem->Value < Sem->MaxValue) && Sem->Signaling )
+       {
+                int    given;
+               tThread *toWake = Sem->Signaling;
+               
+               Sem->Signaling = Sem->Signaling->Next;
+               // Reset ->LastWaiting to NULL if we have just removed the last waiting thread
+               if( Sem->Signaling == NULL )
+                       Sem->LastSignaling = NULL;
+               
+               // Figure out how much to give
+               if( toWake->RetStatus && Sem->Value + toWake->RetStatus < Sem->MaxValue )
+                       given = toWake->RetStatus;
+               else
+                       given = Sem->MaxValue - Sem->Value;
+               Sem->Value -= given;
+               
+               
+               #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG
+               Log("%p (%i %s) woken by wait on %p %s:%s",
+                       toWake, toWake->TID, toWake->ThreadName,
+                       Sem, Sem->ModName, Sem->Name);
+               #endif
+               
+               // Save the number we gave to the thread's status
+               toWake->RetStatus = given;
+               
+               // Wake the sleeper
+               SHORTLOCK( &glThreadListLock );
+               if( toWake->Status != THREAD_STAT_ACTIVE )
+                       Threads_AddActive(toWake);
+               SHORTREL( &glThreadListLock );
+       }
+       SHORTREL( &Sem->Protector );
+       
+       #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG
+       Log("Semaphore %p %s:%s took %i by wait",
+               Sem, Sem->ModName, Sem->Name, taken);
+       #endif
+
+       return taken;
+}
+
+//
+// Add items to a semaphore
+//
+int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd)
+{
+        int    given;
+        int    added;
+       
+       if( AmmountToAdd < 0 ) {
+               Log_Warning("Threads", "Semaphore_Signal: User bug - AmmountToAdd(%i) < 0, Sem=%p(%s)",
+                       AmmountToAdd, Sem, Sem->Name);
+       }
+       SHORTLOCK( &Sem->Protector );
+       
+       // Check if we have to block
+       if( Sem->MaxValue && Sem->Value == Sem->MaxValue )
+       {
+               tThread *us;
+               #if 0
+               Log_Debug("Threads", "Semaphore_Signal: IDLE Sem = %s:%s", Sem->ModName, Sem->Name);
+               Log_Debug("Threads", "Semaphore_Signal: Sem->Value(%i) == Sem->MaxValue(%i)", Sem->Value, Sem->MaxValue);
+               #endif
+               
+               SHORTLOCK( &glThreadListLock );
+               // - Remove from active list
+               us = Threads_RemActive();
+               us->Next = NULL;
+               // - Mark as sleeping
+               us->Status = THREAD_STAT_SEMAPHORESLEEP;
+               us->WaitPointer = Sem;
+               us->RetStatus = AmmountToAdd;   // Use RetStatus as a temp variable
+               
+               // - Add to waiting
+               if(Sem->LastSignaling) {
+                       Sem->LastSignaling->Next = us;
+                       Sem->LastSignaling = us;
+               }
+               else {
+                       Sem->Signaling = us;
+                       Sem->LastSignaling = us;
+               }
+               
+               #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG
+               Log("%p (%i %s) signaling semaphore %p %s:%s",
+                       us, us->TID, us->ThreadName,
+                       Sem, Sem->ModName, Sem->Name);
+               #endif
+               
+               SHORTREL( &glThreadListLock );  
+               SHORTREL( &Sem->Protector );
+               while(us->Status == THREAD_STAT_SEMAPHORESLEEP) Threads_Yield();
+               // We're only woken when there's something avaliable
+               us->WaitPointer = NULL;
+               
+               added = us->RetStatus;
+               
+               // Get the lock again
+               SHORTLOCK( &Sem->Protector );
+       }
+       // Non blocking
+       else
+       {
+               // Figure out how much we need to take off
+               if( Sem->MaxValue && Sem->Value + AmmountToAdd > Sem->MaxValue)
+                       added = Sem->MaxValue - Sem->Value;
+               else
+                       added = AmmountToAdd;
+               Sem->Value += added;
+       }
+       
+       // While there are items avaliable, and there are thread waiting
+       // wake the first thread and give it what it wants (or what's left)
+       while( Sem->Value && Sem->Waiting )
+       {
+               tThread *toWake = Sem->Waiting;
+               
+               // Remove thread from list (double ended, so clear LastWaiting if needed)
+               Sem->Waiting = Sem->Waiting->Next;
+               if( Sem->Waiting == NULL )
+                       Sem->LastWaiting = NULL;
+               
+               // Figure out how much to give to woken thread
+               // - Requested count is stored in ->RetStatus
+               if( toWake->RetStatus && Sem->Value > toWake->RetStatus )
+                       given = toWake->RetStatus;
+               else
+                       given = Sem->Value;
+               Sem->Value -= given;
+               
+               // Save the number we gave to the thread's status
+               toWake->RetStatus = given;
+               
+               if(toWake->bInstrTrace)
+                       Log("%s(%i) given %i from %p", toWake->ThreadName, toWake->TID, given, Sem);
+               #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG
+               Log("%p (%i %s) woken by signal on %p %s:%s",
+                       toWake, toWake->TID, toWake->ThreadName,
+                       Sem, Sem->ModName, Sem->Name);
+               #endif
+               
+               // Wake the sleeper
+               if( toWake->Status != THREAD_STAT_ACTIVE )
+                       Threads_AddActive(toWake);
+               else
+                       Warning("Thread %p (%i %s) is already awake", toWake, toWake->TID, toWake->ThreadName);
+       }
+       SHORTREL( &Sem->Protector );
+       
+       return added;
+}
+
+//
+// Get the current value of a semaphore
+//
+int Semaphore_GetValue(tSemaphore *Sem)
+{
+       return Sem->Value;
+}
+
+// === EXPORTS ===
+EXPORT(Semaphore_Init);
+EXPORT(Semaphore_Wait);
+EXPORT(Semaphore_Signal);
index 2f8d933..d1f3a75 100644 (file)
@@ -7,14 +7,12 @@
 #include <threads.h>
 #include <threads_int.h>
 #include <errno.h>
-#include <mutex.h>
-#include <semaphore.h>
 #include <hal_proc.h>
+#include <semaphore.h>
 
 // Configuration
 #define DEBUG_TRACE_TICKETS    0       // Trace ticket counts
 #define DEBUG_TRACE_STATE      0       // Trace state changes (sleep/wake)
-#define SEMAPHORE_DEBUG        0       // Debug semaphores
 
 // --- Schedulers ---
 #define SCHED_UNDEF    0
@@ -72,11 +70,6 @@ tGID Threads_GetGID(void);
 #endif
 void   Threads_Dump(void);
 void   Threads_DumpActive(void);
-#if 0
- int   Mutex_Acquire(tMutex *Mutex);
-void   Mutex_Release(tMutex *Mutex);
- int   Mutex_IsLocked(tMutex *Mutex);
-#endif
 
 // === GLOBALS ===
 // -- Core Thread --
@@ -1340,366 +1333,6 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last)
        return thread;
 }
 
-// Acquire mutex (see mutex.h for documentation)
-int Mutex_Acquire(tMutex *Mutex)
-{
-       tThread *us = Proc_GetCurThread();
-       
-       // Get protector
-       SHORTLOCK( &Mutex->Protector );
-       
-       //Log("Mutex_Acquire: (%p)", Mutex);
-       
-       // Check if the lock is already held
-       if( Mutex->Owner ) {
-               SHORTLOCK( &glThreadListLock );
-               // - Remove from active list
-               us = Threads_RemActive();
-               us->Next = NULL;
-               // - Mark as sleeping
-               us->Status = THREAD_STAT_MUTEXSLEEP;
-               us->WaitPointer = Mutex;
-               
-               // - Add to waiting
-               if(Mutex->LastWaiting) {
-                       Mutex->LastWaiting->Next = us;
-                       Mutex->LastWaiting = us;
-               }
-               else {
-                       Mutex->Waiting = us;
-                       Mutex->LastWaiting = us;
-               }
-               
-               #if DEBUG_TRACE_STATE
-               Log("%p (%i %s) waiting on mutex %p",
-                       us, us->TID, us->ThreadName, Mutex);
-               #endif
-               
-               #if 0
-               {
-                        int    i = 0;
-                       tThread *t;
-                       for( t = Mutex->Waiting; t; t = t->Next, i++ )
-                               Log("[%i] (tMutex)%p->Waiting[%i] = %p (%i %s)", us->TID, Mutex, i,
-                                       t, t->TID, t->ThreadName);
-               }
-               #endif
-               
-               SHORTREL( &glThreadListLock );
-               SHORTREL( &Mutex->Protector );
-               while(us->Status == THREAD_STAT_MUTEXSLEEP)     Threads_Yield();
-               // We're only woken when we get the lock
-               us->WaitPointer = NULL;
-       }
-       // Ooh, let's take it!
-       else {
-               Mutex->Owner = us;
-               SHORTREL( &Mutex->Protector );
-       }
-       
-       #if 0
-       extern tMutex   glPhysAlloc;
-       if( Mutex != &glPhysAlloc )
-               LogF("Mutex %p taken by %i %p\n", Mutex, us->TID, __builtin_return_address(0));
-       #endif
-       
-       return 0;
-}
-
-// Release a mutex
-void Mutex_Release(tMutex *Mutex)
-{
-       SHORTLOCK( &Mutex->Protector );
-       //Log("Mutex_Release: (%p)", Mutex);
-       if( Mutex->Waiting ) {
-               Mutex->Owner = Mutex->Waiting;  // Set owner
-               Mutex->Waiting = Mutex->Waiting->Next;  // Next!
-               // Reset ->LastWaiting to NULL if we have just removed the last waiting thread
-               // 2010-10-02 21:50 - Comemerating the death of the longest single
-               //                    blocker in the Acess2 history. REMEMBER TO
-               //                    FUCKING MAINTAIN YOUR FUCKING LISTS DIPWIT
-               if( Mutex->LastWaiting == Mutex->Owner )
-                       Mutex->LastWaiting = NULL;
-               
-               // Wake new owner
-               SHORTLOCK( &glThreadListLock );
-               if( Mutex->Owner->Status != THREAD_STAT_ACTIVE )
-                       Threads_AddActive(Mutex->Owner);
-               SHORTREL( &glThreadListLock );
-       }
-       else {
-               Mutex->Owner = NULL;
-       }
-       SHORTREL( &Mutex->Protector );
-       
-       #if 0
-       extern tMutex   glPhysAlloc;
-       if( Mutex != &glPhysAlloc )
-               LogF("Mutex %p released by %i %p\n", Mutex, Threads_GetTID(), __builtin_return_address(0));
-       #endif
-}
-
-// Check if a mutex is locked
-int Mutex_IsLocked(tMutex *Mutex)
-{
-       return Mutex->Owner != NULL;
-}
-
-//
-// Initialise a semaphore
-//
-void Semaphore_Init(tSemaphore *Sem, int Value, int MaxValue, const char *Module, const char *Name)
-{
-       memset(Sem, 0, sizeof(tSemaphore));
-       Sem->Value = Value;
-       Sem->ModName = Module;
-       Sem->Name = Name;
-       Sem->MaxValue = MaxValue;
-}
-//
-// Wait for items to be avaliable
-//
-int Semaphore_Wait(tSemaphore *Sem, int MaxToTake)
-{
-       tThread *us;
-        int    taken;
-       if( MaxToTake < 0 ) {
-               Log_Warning("Threads", "Semaphore_Wait: User bug - MaxToTake(%i) < 0, Sem=%p(%s)",
-                       MaxToTake, Sem, Sem->Name);
-       }
-       
-       SHORTLOCK( &Sem->Protector );
-       
-       // Check if there's already items avaliable
-       if( Sem->Value > 0 ) {
-               // Take what we need
-               if( MaxToTake && Sem->Value > MaxToTake )
-                       taken = MaxToTake;
-               else
-                       taken = Sem->Value;
-               Sem->Value -= taken;
-       }
-       else
-       {
-               SHORTLOCK( &glThreadListLock );
-               
-               // - Remove from active list
-               us = Threads_RemActive();
-               us->Next = NULL;
-               // - Mark as sleeping
-               us->Status = THREAD_STAT_SEMAPHORESLEEP;
-               us->WaitPointer = Sem;
-               us->RetStatus = MaxToTake;      // Use RetStatus as a temp variable
-               
-               // - Add to waiting
-               if(Sem->LastWaiting) {
-                       Sem->LastWaiting->Next = us;
-                       Sem->LastWaiting = us;
-               }
-               else {
-                       Sem->Waiting = us;
-                       Sem->LastWaiting = us;
-               }
-               
-               #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG
-               Log("%p (%i %s) waiting on semaphore %p %s:%s",
-                       us, us->TID, us->ThreadName,
-                       Sem, Sem->ModName, Sem->Name);
-               #endif
-               
-               SHORTREL( &Sem->Protector );    // Release first to make sure it is released
-               SHORTREL( &glThreadListLock );
-               while( us->Status == THREAD_STAT_SEMAPHORESLEEP )
-               {
-                       Threads_Yield();
-                       if(us->Status == THREAD_STAT_SEMAPHORESLEEP)
-                               Log_Warning("Threads", "Semaphore %p %s:%s re-schedulued while asleep",
-                                       Sem, Sem->ModName, Sem->Name);
-               }
-               #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG
-               Log("Semaphore %p %s:%s woken", Sem, Sem->ModName, Sem->Name);
-               #endif
-               // We're only woken when there's something avaliable (or a signal arrives)
-               us->WaitPointer = NULL;
-               
-               taken = us->RetStatus;
-               
-               // Get the lock again
-               SHORTLOCK( &Sem->Protector );
-       }
-       
-       // While there is space, and there are thread waiting
-       // wake the first thread and give it what it wants (or what's left)
-       while( (Sem->MaxValue == 0 || Sem->Value < Sem->MaxValue) && Sem->Signaling )
-       {
-                int    given;
-               tThread *toWake = Sem->Signaling;
-               
-               Sem->Signaling = Sem->Signaling->Next;
-               // Reset ->LastWaiting to NULL if we have just removed the last waiting thread
-               if( Sem->Signaling == NULL )
-                       Sem->LastSignaling = NULL;
-               
-               // Figure out how much to give
-               if( toWake->RetStatus && Sem->Value + toWake->RetStatus < Sem->MaxValue )
-                       given = toWake->RetStatus;
-               else
-                       given = Sem->MaxValue - Sem->Value;
-               Sem->Value -= given;
-               
-               
-               #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG
-               Log("%p (%i %s) woken by wait on %p %s:%s",
-                       toWake, toWake->TID, toWake->ThreadName,
-                       Sem, Sem->ModName, Sem->Name);
-               #endif
-               
-               // Save the number we gave to the thread's status
-               toWake->RetStatus = given;
-               
-               // Wake the sleeper
-               SHORTLOCK( &glThreadListLock );
-               if( toWake->Status != THREAD_STAT_ACTIVE )
-                       Threads_AddActive(toWake);
-               SHORTREL( &glThreadListLock );
-       }
-       SHORTREL( &Sem->Protector );
-       
-       #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG
-       Log("Semaphore %p %s:%s took %i by wait",
-               Sem, Sem->ModName, Sem->Name, taken);
-       #endif
-
-       return taken;
-}
-
-//
-// Add items to a semaphore
-//
-int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd)
-{
-        int    given;
-        int    added;
-       
-       if( AmmountToAdd < 0 ) {
-               Log_Warning("Threads", "Semaphore_Signal: User bug - AmmountToAdd(%i) < 0, Sem=%p(%s)",
-                       AmmountToAdd, Sem, Sem->Name);
-       }
-       SHORTLOCK( &Sem->Protector );
-       
-       // Check if we have to block
-       if( Sem->MaxValue && Sem->Value == Sem->MaxValue )
-       {
-               tThread *us;
-               #if 0
-               Log_Debug("Threads", "Semaphore_Signal: IDLE Sem = %s:%s", Sem->ModName, Sem->Name);
-               Log_Debug("Threads", "Semaphore_Signal: Sem->Value(%i) == Sem->MaxValue(%i)", Sem->Value, Sem->MaxValue);
-               #endif
-               
-               SHORTLOCK( &glThreadListLock );
-               // - Remove from active list
-               us = Threads_RemActive();
-               us->Next = NULL;
-               // - Mark as sleeping
-               us->Status = THREAD_STAT_SEMAPHORESLEEP;
-               us->WaitPointer = Sem;
-               us->RetStatus = AmmountToAdd;   // Use RetStatus as a temp variable
-               
-               // - Add to waiting
-               if(Sem->LastSignaling) {
-                       Sem->LastSignaling->Next = us;
-                       Sem->LastSignaling = us;
-               }
-               else {
-                       Sem->Signaling = us;
-                       Sem->LastSignaling = us;
-               }
-               
-               #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG
-               Log("%p (%i %s) signaling semaphore %p %s:%s",
-                       us, us->TID, us->ThreadName,
-                       Sem, Sem->ModName, Sem->Name);
-               #endif
-               
-               SHORTREL( &glThreadListLock );  
-               SHORTREL( &Sem->Protector );
-               while(us->Status == THREAD_STAT_SEMAPHORESLEEP) Threads_Yield();
-               // We're only woken when there's something avaliable
-               us->WaitPointer = NULL;
-               
-               added = us->RetStatus;
-               
-               // Get the lock again
-               SHORTLOCK( &Sem->Protector );
-       }
-       // Non blocking
-       else
-       {
-               // Figure out how much we need to take off
-               if( Sem->MaxValue && Sem->Value + AmmountToAdd > Sem->MaxValue)
-                       added = Sem->MaxValue - Sem->Value;
-               else
-                       added = AmmountToAdd;
-               Sem->Value += added;
-       }
-       
-       // While there are items avaliable, and there are thread waiting
-       // wake the first thread and give it what it wants (or what's left)
-       while( Sem->Value && Sem->Waiting )
-       {
-               tThread *toWake = Sem->Waiting;
-               
-               // Remove thread from list (double ended, so clear LastWaiting if needed)
-               Sem->Waiting = Sem->Waiting->Next;
-               if( Sem->Waiting == NULL )
-                       Sem->LastWaiting = NULL;
-               
-               // Figure out how much to give to woken thread
-               // - Requested count is stored in ->RetStatus
-               if( toWake->RetStatus && Sem->Value > toWake->RetStatus )
-                       given = toWake->RetStatus;
-               else
-                       given = Sem->Value;
-               Sem->Value -= given;
-               
-               // Save the number we gave to the thread's status
-               toWake->RetStatus = given;
-               
-               if(toWake->bInstrTrace)
-                       Log("%s(%i) given %i from %p", toWake->ThreadName, toWake->TID, given, Sem);
-               #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG
-               Log("%p (%i %s) woken by signal on %p %s:%s",
-                       toWake, toWake->TID, toWake->ThreadName,
-                       Sem, Sem->ModName, Sem->Name);
-               #endif
-               
-               // Wake the sleeper
-//             SHORTLOCK( &glThreadListLock );
-               if( toWake->Status != THREAD_STAT_ACTIVE )
-                       Threads_AddActive(toWake);
-               else
-                       Warning("Thread %p (%i %s) is already awake", toWake, toWake->TID, toWake->ThreadName);
-//             SHORTREL( &glThreadListLock );
-       }
-       SHORTREL( &Sem->Protector );
-       
-       return added;
-}
-
-//
-// Get the current value of a semaphore
-//
-int Semaphore_GetValue(tSemaphore *Sem)
-{
-       return Sem->Value;
-}
-
 // === EXPORTS ===
 EXPORT(Threads_GetUID);
 EXPORT(Threads_GetGID);
-EXPORT(Mutex_Acquire);
-EXPORT(Mutex_Release);
-EXPORT(Mutex_IsLocked);
-EXPORT(Semaphore_Init);
-EXPORT(Semaphore_Wait);
-EXPORT(Semaphore_Signal);

UCC git Repository :: git.ucc.asn.au