Implement kernel semaphores

This commit is contained in:
Ali Mashtizadeh 2015-01-18 13:48:16 -08:00
parent 4d3eefa3e7
commit 29dd4d3af8
6 changed files with 150 additions and 1 deletions

View File

@ -49,6 +49,7 @@ src_common = [
"kern/nic.c",
"kern/palloc.c",
"kern/printf.c",
"kern/semaphore.c",
"kern/sga.c",
"kern/slab.c",
"kern/spinlock.c",

29
sys/include/semaphore.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef __SEMAPHORE_H__
#define __SEMAPHORE_H__
#include <sys/queue.h>
#include <sys/spinlock.h>
#define SEMAPHORE_NAMELEN 32
struct Thread;
typedef struct Semaphore
{
Spinlock lock;
char name[SEMAPHORE_NAMELEN];
int count;
TAILQ_HEAD(SemaThreadQueue,Thread) waiters;
LIST_ENTRY(Semaphore) semaphoreList;
} Semaphore;
void Semaphore_Init(Semaphore *sema, int count, const char *name);
void Semaphore_Destroy(Semaphore *sema);
void Semaphore_Acquire(Semaphore *sema);
// bool TimedAcquire(Semaphore *sema, uint64_t timeout);
void Semaphore_Release(Semaphore *sema);
bool Semaphore_TryAcquire(Semaphore *sema);
#endif /* __SEMAPHORE_H__ */

View File

@ -9,6 +9,8 @@
struct Thread;
typedef struct Thread Thread;
#include <sys/semaphore.h>
#include <machine/pmap.h>
#include <machine/thread.h>
@ -32,6 +34,7 @@ typedef struct Thread {
TAILQ_ENTRY(Thread) schedQueue;
KTimerEvent *timerEvt; // Timer event for wakeups
uintptr_t exitValue;
TAILQ_ENTRY(Thread) semaQueue; // Semaphore Queue
// Statistics
uint64_t ctxSwitches;
uint64_t userTime;
@ -50,6 +53,7 @@ typedef struct Process {
// Threads
uint64_t threads;
TAILQ_HEAD(ThreadListHead, Thread) threadList;
Semaphore zombieSemaphore;
TAILQ_HEAD(ZombieQueueHead, Thread) zombieQueue;
// Handles
uint64_t nextFD;

111
sys/kern/semaphore.c Normal file
View File

@ -0,0 +1,111 @@
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <sys/kassert.h>
#include <sys/kconfig.h>
#include <sys/kdebug.h>
#include <sys/ktime.h>
#include <sys/mp.h>
#include <sys/spinlock.h>
#include <sys/semaphore.h>
#include <sys/thread.h>
Spinlock semaListLock = { 0, 0, 0, 0, 0, 0, "Semaphore List" };
LIST_HEAD(SemaListHead, Semaphore) semaList = LIST_HEAD_INITIALIZER(semaList);
extern uint64_t ticksPerSecond;
void
Semaphore_Init(Semaphore *sema, int count, const char *name)
{
Spinlock_Init(&sema->lock, name);
sema->count = count;
strncpy(&sema->name[0], name, SEMAPHORE_NAMELEN);
TAILQ_INIT(&sema->waiters);
Spinlock_Lock(&semaListLock);
LIST_INSERT_HEAD(&semaList, sema, semaphoreList);
Spinlock_Unlock(&semaListLock);
}
void
Semaphore_Destroy(Semaphore *sema)
{
Spinlock_Lock(&semaListLock);
LIST_REMOVE(sema, semaphoreList);
Spinlock_Unlock(&semaListLock);
}
void
Semaphore_Acquire(Semaphore *sema)
{
Thread *cur = Thread_Current();
while (1) {
Spinlock_Lock(&sema->lock);
if (sema->count > 0) {
sema->count -= 1;
Spinlock_Unlock(&sema->lock);
return;
}
// Add to sleeper list
TAILQ_INSERT_TAIL(&sema->waiters, cur, semaQueue);
Thread_SetWaiting(cur);
Spinlock_Unlock(&sema->lock);
Thread_Scheduler();
}
}
void
Semaphore_Release(Semaphore *sema)
{
Thread *thr;
Spinlock_Lock(&sema->lock);
sema->count += 1;
// Wakeup thread
thr = TAILQ_FIRST(&sema->waiters);
if (thr != NULL) {
TAILQ_REMOVE(&sema->waiters, thr, semaQueue);
Thread_SetRunnable(thr);
}
Spinlock_Unlock(&sema->lock);
}
bool
Semaphore_TryAcquire(Semaphore *sema)
{
Spinlock_Lock(&sema->lock);
if (sema->count > 0) {
sema->count -= 1;
Spinlock_Unlock(&sema->lock);
return true;
}
Spinlock_Unlock(&sema->lock);
return false;
}
void
Debug_Semaphores(int argc, const char *argv[])
{
Semaphore *sema;
Spinlock_Lock(&semaListLock);
kprintf("%-36s Count\n", "Lock Name");
LIST_FOREACH(sema, &semaList, semaphoreList)
{
kprintf("%-36s %8d\n", sema->name, sema->count);
}
Spinlock_Unlock(&semaListLock);
}
REGISTER_DBGCMD(semaphores, "Display list of semaphores", Debug_Semaphores);

View File

@ -309,6 +309,7 @@ Syscall_ThreadExit(uint64_t status)
cur->exitValue = status;
Thread_SetZombie(cur);
Semaphore_Release(&cur->proc->zombieSemaphore);
Thread_Scheduler();
// Should not return
@ -348,6 +349,7 @@ Syscall_ThreadWait(uint64_t tid)
{
Thread *cur = Thread_Current();
Semaphore_Acquire(&cur->proc->zombieSemaphore);
return Thread_Wait(cur, tid);
}

View File

@ -122,7 +122,6 @@ Thread_CreateProcess()
proc->pid = nextProcessID++;
proc->threads = 0;
TAILQ_INIT(&proc->threadList);
TAILQ_INIT(&proc->zombieQueue);
proc->space = PMap_NewAS();
if (proc->space == NULL) {
@ -131,6 +130,9 @@ Thread_CreateProcess()
}
proc->ustackNext = MEM_USERSPACE_STKBASE;
Semaphore_Init(&proc->zombieSemaphore, 0, "Zombie Semaphore");
TAILQ_INIT(&proc->zombieQueue);
Handle_Init(proc);
TAILQ_INSERT_TAIL(&processList, proc, processList);