Cleaning up a pile of bugs

This commit is contained in:
Ali Mashtizadeh 2023-09-05 22:18:10 -04:00
parent b508aaca27
commit 3bde8dd084
7 changed files with 54 additions and 12 deletions

View File

@ -41,6 +41,12 @@ Critical_Exit()
} }
} }
uint32_t
Critical_Level()
{
return lockLevel[CPU()];
}
static void static void
Debug_Critical(int argc, const char *argv[]) Debug_Critical(int argc, const char *argv[])
{ {

View File

@ -30,6 +30,7 @@ typedef struct Spinlock
void Critical_Init(); void Critical_Init();
void Critical_Enter(); void Critical_Enter();
void Critical_Exit(); void Critical_Exit();
uint32_t Critical_Level();
void Spinlock_EarlyInit(); void Spinlock_EarlyInit();
void Spinlock_Init(Spinlock *lock, const char *name, uint64_t type); void Spinlock_Init(Spinlock *lock, const char *name, uint64_t type);

View File

@ -47,6 +47,12 @@ Mutex_Destroy(Mutex *mtx)
void void
Mutex_Lock(Mutex *mtx) Mutex_Lock(Mutex *mtx)
{ {
/*
* You cannot hold a spinlock while trying to acquire a Mutex that may
* sleep!
*/
ASSERT(Critical_Level() == 0);
Spinlock_Lock(&mtx->lock); Spinlock_Lock(&mtx->lock);
while (mtx->status == MTX_STATUS_LOCKED) { while (mtx->status == MTX_STATUS_LOCKED) {
WaitChannel_Lock(&mtx->chan); WaitChannel_Lock(&mtx->chan);

View File

@ -189,9 +189,18 @@ Process_Wait(Process *proc, uint64_t pid)
status = (p->pid << 16) | p->exitCode; status = (p->pid << 16) | p->exitCode;
// Release threads // Release threads
TAILQ_FOREACH_SAFE(thr, &p->zombieQueue, schedQueue, thr_temp) { Spinlock_Lock(&proc->lock);
while (!TAILQ_EMPTY(&p->zombieQueue)) {
thr = TAILQ_FIRST(&p->zombieQueue);
TAILQ_REMOVE(&p->zombieQueue, thr, schedQueue);
Spinlock_Unlock(&proc->lock);
ASSERT(thr->proc->pid != 1);
Thread_Release(thr); Thread_Release(thr);
Spinlock_Lock(&proc->lock);
} }
Spinlock_Unlock(&proc->lock);
// Release process // Release process
Process_Release(p); Process_Release(p);

View File

@ -65,6 +65,8 @@ Sched_SetWaiting(Thread *thr)
{ {
Spinlock_Lock(&schedLock); Spinlock_Lock(&schedLock);
ASSERT(thr->schedState == SCHED_STATE_RUNNING);
thr->schedState = SCHED_STATE_WAITING; thr->schedState = SCHED_STATE_WAITING;
TAILQ_INSERT_TAIL(&waitQueue, thr, schedQueue); TAILQ_INSERT_TAIL(&waitQueue, thr, schedQueue);
thr->waitStart = KTime_GetEpochNS(); thr->waitStart = KTime_GetEpochNS();
@ -77,13 +79,6 @@ Sched_SetZombie(Thread *thr)
{ {
Process *proc = thr->proc; Process *proc = thr->proc;
Spinlock_Lock(&schedLock);
thr->schedState = SCHED_STATE_ZOMBIE;
Spinlock_Lock(&proc->lock);
TAILQ_INSERT_TAIL(&proc->zombieQueue, thr, schedQueue);
Spinlock_Unlock(&proc->lock);
if (proc->threads == 1) { if (proc->threads == 1) {
// All processes have parents except 'init' and 'kernel' // All processes have parents except 'init' and 'kernel'
ASSERT(proc->parent != NULL); ASSERT(proc->parent != NULL);
@ -95,10 +90,22 @@ Sched_SetZombie(Thread *thr)
Spinlock_Unlock(&proc->parent->lock); Spinlock_Unlock(&proc->parent->lock);
CV_Signal(&proc->zombieProcPCV); CV_Signal(&proc->zombieProcPCV);
CV_Signal(&proc->parent->zombieProcCV); CV_Signal(&proc->parent->zombieProcCV);
Mutex_Unlock(&proc->parent->zombieProcLock);
} }
/*
* Set as zombie just before releasing the zombieProcLock in case we had to
* sleep to acquire the zombieProcLock.
*/
Spinlock_Lock(&schedLock);
thr->schedState = SCHED_STATE_ZOMBIE;
Spinlock_Unlock(&schedLock); Spinlock_Unlock(&schedLock);
Spinlock_Lock(&proc->lock);
TAILQ_INSERT_TAIL(&proc->zombieQueue, thr, schedQueue);
Spinlock_Unlock(&proc->lock);
if (proc->threads == 1)
Mutex_Unlock(&proc->parent->zombieProcLock);
} }
static void static void
@ -132,6 +139,7 @@ Sched_Scheduler()
Spinlock_Unlock(&schedLock); Spinlock_Unlock(&schedLock);
return; return;
} }
ASSERT(next->schedState == SCHED_STATE_RUNNABLE);
TAILQ_REMOVE(&runnableQueue, next, schedQueue); TAILQ_REMOVE(&runnableQueue, next, schedQueue);
prev = curProc[CPU()]; prev = curProc[CPU()];

View File

@ -192,6 +192,9 @@ Thread_Destroy(Thread *thr)
{ {
Process *proc = thr->proc; Process *proc = thr->proc;
// Don't free kernel threads
ASSERT(proc->pid != 1);
// Free userspace stack // Free userspace stack
Spinlock_Lock(&proc->lock); Spinlock_Lock(&proc->lock);
@ -201,10 +204,11 @@ Thread_Destroy(Thread *thr)
// Free AS // Free AS
PAlloc_Release((void *)thr->kstack); PAlloc_Release((void *)thr->kstack);
Slab_Free(&threadSlab, thr);
// Release process handle // Release process handle
Process_Release(thr->proc); Process_Release(thr->proc);
Slab_Free(&threadSlab, thr);
} }
Thread * Thread *
@ -262,6 +266,7 @@ Thread_Wait(Thread *thr, uint64_t tid)
return SYSCALL_PACK(0, status); return SYSCALL_PACK(0, status);
} }
// XXXURGENT
TAILQ_FOREACH(t, &thr->proc->zombieQueue, schedQueue) { TAILQ_FOREACH(t, &thr->proc->zombieQueue, schedQueue) {
if (t->tid == tid) { if (t->tid == tid) {
TAILQ_REMOVE(&thr->proc->zombieQueue, t, schedQueue); TAILQ_REMOVE(&thr->proc->zombieQueue, t, schedQueue);
@ -293,12 +298,20 @@ ThreadKThreadEntry(TrapFrame *tf) __NO_LOCK_ANALYSIS
void void
Thread_Dump(Thread *thr) Thread_Dump(Thread *thr)
{ {
const char *states[] = {
"NULL",
"RUNNABLE",
"RUNNING",
"WAITING",
"ZOMBIE"
};
// Thread_DumpArch(thr) // Thread_DumpArch(thr)
kprintf("space %016llx\n", thr->space); kprintf("space %016llx\n", thr->space);
kprintf("kstack %016llx\n", thr->kstack); kprintf("kstack %016llx\n", thr->kstack);
kprintf("tid %llu\n", thr->tid); kprintf("tid %llu\n", thr->tid);
kprintf("refCount %d\n", thr->refCount); kprintf("refCount %d\n", thr->refCount);
kprintf("state %d\n", thr->schedState); kprintf("state %s\n", states[thr->schedState]);
kprintf("ctxswtch %llu\n", thr->ctxSwitches); kprintf("ctxswtch %llu\n", thr->ctxSwitches);
kprintf("utime %llu\n", thr->userTime); kprintf("utime %llu\n", thr->userTime);
kprintf("ktime %llu\n", thr->kernTime); kprintf("ktime %llu\n", thr->kernTime);

View File

@ -118,7 +118,6 @@ WaitChannel_WakeAll(WaitChannel *wchan)
Spinlock_Lock(&wchan->lock); Spinlock_Lock(&wchan->lock);
TAILQ_FOREACH_SAFE(thr, &wchan->chanQueue, chanQueue, thrTemp) { TAILQ_FOREACH_SAFE(thr, &wchan->chanQueue, chanQueue, thrTemp) {
thr = TAILQ_FIRST(&wchan->chanQueue);
TAILQ_REMOVE(&wchan->chanQueue, thr, chanQueue); TAILQ_REMOVE(&wchan->chanQueue, thr, chanQueue);
Sched_SetRunnable(thr); Sched_SetRunnable(thr);
Thread_Release(thr); Thread_Release(thr);