*/
#include <acess.h>
#include <threads.h>
+#include <threads_int.h>
#include <errno.h>
+#include <mutex.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
// --- Schedulers ---
#define SCHED_UNDEF 0
#define SCHED_RR_SIM 2 // Single Queue Round Robin
#define SCHED_RR_PRI 3 // Multi Queue Round Robin
// Set scheduler type
-#define SCHEDULER_TYPE SCHED_LOTTERY
+#define SCHEDULER_TYPE SCHED_RR_PRI
// === CONSTANTS ===
-#define DEFAULT_QUANTUM 10
+#define DEFAULT_QUANTUM 5
#define DEFAULT_PRIORITY 5
#define MIN_PRIORITY 10
const enum eConfigTypes cCONFIG_TYPES[] = {
SHORTREL( &glThreadListLock );
return -EOK;
+ case THREAD_STAT_SEMAPHORESLEEP: {
+ tSemaphore *sem;
+ tThread *th, *prev=NULL;
+
+ sem = Thread->WaitPointer;
+
+ SHORTLOCK( &sem->Protector );
+
+ // Remove from sleeping queue
+ for( th = sem->Waiting; th; prev = th, th = th->Next )
+ if( th == Thread ) break;
+ if( th )
+ {
+ if(prev)
+ prev->Next = Thread->Next;
+ else
+ sem->Waiting = Thread->Next;
+ if(sem->LastWaiting == Thread)
+ sem->LastWaiting = prev;
+ }
+ else
+ {
+ prev = NULL;
+ for( th = sem->Signaling; th; prev = th, th = th->Next )
+ if( th == Thread ) break;
+ if( !th ) {
+ Log_Warning("Threads", "Thread %p(%i %s) is not on semaphore %p(%s:%s)",
+ Thread, Thread->TID, Thread->ThreadName,
+ sem, sem->ModName, sem->Name);
+ return -EINTERNAL;
+ }
+
+ if(prev)
+ prev->Next = Thread->Next;
+ else
+ sem->Signaling = Thread->Next;
+ if(sem->LastSignaling == Thread)
+ sem->LastSignaling = prev;
+ }
+
+ SHORTLOCK( &glThreadListLock );
+ Threads_AddActive( Thread );
+ SHORTREL( &glThreadListLock );
+
+ #if DEBUG_TRACE_STATE
+ Log("Threads_Sleep: %p(%i %s) woken from semaphore", Thread, Thread->TID, Thread->ThreadName);
+ #endif
+ SHORTREL( &sem->Protector );
+ } return -EOK;
+
case THREAD_STAT_WAITING:
Warning("Threads_Wake - Waiting threads are not currently supported");
return -ENOTIMPL;
// Set state
Thread->Status = THREAD_STAT_ACTIVE;
+// Thread->CurCPU = -1;
// Add to active list
- #if SCHEDULER_TYPE == SCHED_RR_PRI
- Thread->Next = gaActiveThreads[Thread->Priority];
- gaActiveThreads[Thread->Priority] = Thread;
- #else
- Thread->Next = gActiveThreads;
- gActiveThreads = Thread;
- #endif
+ {
+ tThread *tmp, *prev = NULL;
+ #if SCHEDULER_TYPE == SCHED_RR_PRI
+ for( tmp = gaActiveThreads[Thread->Priority]; tmp; prev = tmp, tmp = tmp->Next );
+ if(prev)
+ prev->Next = Thread;
+ else
+ gaActiveThreads[Thread->Priority] = Thread;
+ #else
+ for( tmp = gActiveThreads; tmp; prev = tmp, tmp = tmp->Next );
+ if(prev)
+ prev->Next = Thread;
+ else
+ gActiveThreads = Thread;
+ #endif
+ Thread->Next = NULL;
+ }
// Update bookkeeping
giNumActiveThreads ++;
#endif
{
SHORTREL( &glThreadListLock );
+ Log_Warning("Threads", "Current thread %p(%i %s) is not on active queue",
+ ret, ret->TID, ret->ThreadName
+ );
return NULL;
}
{
tThread *thread = Proc_GetCurThread();
- Log_Log("Threads", "Threads_Fault: thread = %p", thread);
-
if(!thread) return ;
Log_Log("Threads", "Threads_Fault: thread->FaultHandler = %p", thread->FaultHandler);
// Clear Delete Queue
// - I should probably put this in a worker thread to avoid calling free() in the scheduler
// DEFINITELY - free() can deadlock in this case
+ // I'll do it when it becomes an issue
while(gDeleteThreads)
{
thread = gDeleteThreads->Next;
}
gDeleteThreads = thread;
}
-
+
+ // Make sure the current (well, old) thread is marked as de-scheduled
+ if(Last) Last->CurCPU = -1;
+
// No active threads, just take a nap
if(giNumActiveThreads == 0) {
SHORTREL( &glThreadListLock );
else
taken = Sem->Value;
Sem->Value -= taken;
- SHORTREL( &Sem->Protector );
}
else
{
Sem->LastWaiting = us;
}
- #if DEBUG_TRACE_STATE
+ #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 );
- SHORTREL( &Sem->Protector );
while(us->Status == THREAD_STAT_SEMAPHORESLEEP) Threads_Yield();
- // We're only woken when there's something avaliable
+ // We're only woken when there's something avaliable (or a signal arrives)
us->WaitPointer = NULL;
taken = us->RetStatus;
Sem->Value -= given;
- #if DEBUG_TRACE_STATE
+ #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);
Sem->LastSignaling = us;
}
- #if DEBUG_TRACE_STATE
+ #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);
if(toWake->bInstrTrace)
Log("%s(%i) given %i from %p", toWake->ThreadName, toWake->TID, given, Sem);
- #if DEBUG_TRACE_STATE
+ #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);
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 );