From e2277feaba2d0e354d6d9e4e737b2feb45b0106d Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 11 Aug 2013 11:10:14 +0800 Subject: [PATCH] Kernel - Planning SMP fix with sleep edge case --- KernelLand/Kernel/semaphore.c | 9 +++++++-- KernelLand/Kernel/threads.c | 33 +++++++++++++++++++++++++++++++++ KernelLand/Kernel/workqueue.c | 6 ++++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/KernelLand/Kernel/semaphore.c b/KernelLand/Kernel/semaphore.c index 1111967a..e8175741 100644 --- a/KernelLand/Kernel/semaphore.c +++ b/KernelLand/Kernel/semaphore.c @@ -50,6 +50,11 @@ int Semaphore_Wait(tSemaphore *Sem, int MaxToTake) } else { + #if 0 + Threads_int_Sleep(THREAD_STAT_SEMAPHORESLEEP, + Sem, MaxToTake, + &Sem->Waiting, &Sem->LastWaiting, &Sem->Protector); + #endif SHORTLOCK( &glThreadListLock ); // - Remove from active list @@ -75,9 +80,9 @@ int Semaphore_Wait(tSemaphore *Sem, int MaxToTake) us, us->TID, us->ThreadName, Sem, Sem->ModName, Sem->Name); #endif - - SHORTREL( &Sem->Protector ); // Release first to make sure it is released + SHORTREL( &Sem->Protector ); SHORTREL( &glThreadListLock ); + // NOTE: This can break in SMP // Sleep until woken (either by getting what we need, or a timer event) Threads_int_WaitForStatusEnd( THREAD_STAT_SEMAPHORESLEEP ); // We're only woken when there's something avaliable (or a signal arrives) diff --git a/KernelLand/Kernel/threads.c b/KernelLand/Kernel/threads.c index 67a2f637..9f760703 100644 --- a/KernelLand/Kernel/threads.c +++ b/KernelLand/Kernel/threads.c @@ -732,6 +732,39 @@ void Threads_int_WaitForStatusEnd(enum eThreadStatus Status) } } +void Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock) +{ + SHORTLOCK( &glThreadListLock ); + tThread *us = Threads_RemActive(); + us->Next = NULL; + // - Mark as sleeping + us->Status = Status; + us->WaitPointer = Ptr; + us->RetStatus = Num; // Use RetStatus as a temp variable + + // - Add to waiting + if( ListTail ) { + if(*ListTail) { + (*ListTail)->Next = us; + *ListTail = us; + } + else { + *ListHead = us; + *ListTail = us; + } + } + else { + *ListHead = us; + } + + //if( Proc_ThreadSync(us) ) + // return ; + SHORTREL( &glThreadListLock ); + if( Lock ) + SHORTLOCK( Lock ); + Threads_int_WaitForStatusEnd(Status); +} + /** * \fn void Threads_Sleep(void) * \brief Take the current process off the run queue diff --git a/KernelLand/Kernel/workqueue.c b/KernelLand/Kernel/workqueue.c index 2cd6a258..2083bde7 100644 --- a/KernelLand/Kernel/workqueue.c +++ b/KernelLand/Kernel/workqueue.c @@ -36,12 +36,18 @@ void *Workqueue_GetWork(tWorkqueue *Queue) return ret; } + #if 0 + Threads_int_Sleep(THREAD_STAT_QUEUESLEEP, + Queue, 0, + &Queue->Sleeper, NULL, &Queue->Protector); + #endif // Go to sleep SHORTLOCK(&glThreadListLock); us = Threads_RemActive(); us->WaitPointer = Queue; us->Status = THREAD_STAT_QUEUESLEEP; Queue->Sleeper = us; + SHORTREL(&Queue->Protector); SHORTREL(&glThreadListLock); -- 2.20.1