Implement kernel semaphores
This commit is contained in:
parent
4d3eefa3e7
commit
29dd4d3af8
@ -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
29
sys/include/semaphore.h
Normal 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__ */
|
||||
|
@ -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
111
sys/kern/semaphore.c
Normal 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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user