Add waitchannels into the kernel.
This commit is contained in:
parent
1c2848207d
commit
52377a980c
@ -62,6 +62,7 @@ src_common = [
|
|||||||
"kern/thread.c",
|
"kern/thread.c",
|
||||||
"kern/vfs.c",
|
"kern/vfs.c",
|
||||||
"kern/vfsuio.c",
|
"kern/vfsuio.c",
|
||||||
|
"kern/waitchannel.c",
|
||||||
"dev/ahci.c",
|
"dev/ahci.c",
|
||||||
"dev/console.c",
|
"dev/console.c",
|
||||||
"dev/e1000.c",
|
"dev/e1000.c",
|
||||||
|
@ -150,6 +150,7 @@ Machine_EarlyInit()
|
|||||||
Spinlock_EarlyInit();
|
Spinlock_EarlyInit();
|
||||||
Critical_Init();
|
Critical_Init();
|
||||||
Critical_Enter();
|
Critical_Enter();
|
||||||
|
WaitChannel_EarlyInit();
|
||||||
Console_Init();
|
Console_Init();
|
||||||
PAlloc_Init();
|
PAlloc_Init();
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <sys/handle.h>
|
#include <sys/handle.h>
|
||||||
#include <sys/ktimer.h>
|
#include <sys/ktimer.h>
|
||||||
|
#include <sys/waitchannel.h>
|
||||||
|
|
||||||
struct Thread;
|
struct Thread;
|
||||||
typedef struct Thread Thread;
|
typedef struct Thread Thread;
|
||||||
@ -41,6 +42,9 @@ typedef struct Thread {
|
|||||||
KTimerEvent *timerEvt; // Timer event for wakeups
|
KTimerEvent *timerEvt; // Timer event for wakeups
|
||||||
uintptr_t exitValue;
|
uintptr_t exitValue;
|
||||||
TAILQ_ENTRY(Thread) semaQueue; // Semaphore Queue
|
TAILQ_ENTRY(Thread) semaQueue; // Semaphore Queue
|
||||||
|
// Wait Channels
|
||||||
|
WaitChannel *chan;
|
||||||
|
TAILQ_ENTRY(Thread) chanQueue;
|
||||||
// Statistics
|
// Statistics
|
||||||
uint64_t ctxSwitches;
|
uint64_t ctxSwitches;
|
||||||
uint64_t userTime;
|
uint64_t userTime;
|
||||||
|
27
sys/include/waitchannel.h
Normal file
27
sys/include/waitchannel.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
#ifndef __WAITCHANNEL_H__
|
||||||
|
#define __WAITCHANNEL_H__
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include <sys/queue.h>
|
||||||
|
|
||||||
|
#define WAITCHANNEL_NAMELEN 32
|
||||||
|
|
||||||
|
typedef struct WaitChannel
|
||||||
|
{
|
||||||
|
Spinlock lock;
|
||||||
|
char name[WAITCHANNEL_NAMELEN];
|
||||||
|
LIST_ENTRY(WaitChannel) chanList;
|
||||||
|
TAILQ_HEAD(WaitQueue, Thread) chanQueue;
|
||||||
|
} WaitChannel;
|
||||||
|
|
||||||
|
void WaitChannel_EarlyInit();
|
||||||
|
void WaitChannel_Init(WaitChannel *lock, const char *name);
|
||||||
|
void WaitChannel_Destroy(WaitChannel *lock);
|
||||||
|
void WaitChannel_Lock(WaitChannel *lock) __LOCK_EX(lock->lock);
|
||||||
|
void WaitChannel_Sleep(WaitChannel *lock) __UNLOCK_EX(lock->lock);
|
||||||
|
void WaitChannel_Wake(WaitChannel *lock);
|
||||||
|
void WaitChannel_WakeAll(WaitChannel *lock);
|
||||||
|
|
||||||
|
#endif /* __WAITCHANNEL_H__ */
|
||||||
|
|
128
sys/kern/waitchannel.c
Normal file
128
sys/kern/waitchannel.c
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include <sys/kassert.h>
|
||||||
|
#include <sys/kdebug.h>
|
||||||
|
#include <sys/queue.h>
|
||||||
|
#include <sys/thread.h>
|
||||||
|
#include <sys/spinlock.h>
|
||||||
|
#include <sys/waitchannel.h>
|
||||||
|
|
||||||
|
Spinlock chanListLock;
|
||||||
|
LIST_HEAD(ChanListHead, WaitChannel) chanList = LIST_HEAD_INITIALIZER(chanList);
|
||||||
|
|
||||||
|
void
|
||||||
|
WaitChannel_EarlyInit()
|
||||||
|
{
|
||||||
|
Spinlock_Init(&chanListLock, "WaitChannel List", SPINLOCK_TYPE_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WaitChannel_Init(WaitChannel *wchan, const char *name)
|
||||||
|
{
|
||||||
|
TAILQ_INIT(&wchan->chanQueue);
|
||||||
|
strncpy(&wchan->name[0], name, WAITCHANNEL_NAMELEN);
|
||||||
|
Spinlock_Init(&wchan->lock, name, SPINLOCK_TYPE_NORMAL);
|
||||||
|
|
||||||
|
Spinlock_Lock(&chanListLock);
|
||||||
|
LIST_INSERT_HEAD(&chanList, wchan, chanList);
|
||||||
|
Spinlock_Unlock(&chanListLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WaitChannel_Destroy(WaitChannel *wchan)
|
||||||
|
{
|
||||||
|
ASSERT(TAILQ_EMPTY(&wchan->chanQueue));
|
||||||
|
|
||||||
|
Spinlock_Lock(&chanListLock);
|
||||||
|
LIST_REMOVE(wchan, chanList);
|
||||||
|
Spinlock_Unlock(&chanListLock);
|
||||||
|
|
||||||
|
Spinlock_Destroy(&wchan->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WaitChannel_Lock --
|
||||||
|
*
|
||||||
|
* Acquires the wait channel lock.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
WaitChannel_Lock(WaitChannel *wchan)
|
||||||
|
{
|
||||||
|
Spinlock_Lock(&wchan->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WaitChannel_Sleep --
|
||||||
|
*
|
||||||
|
* Places the current thread to asleep while releasing the wait channel
|
||||||
|
* lock.
|
||||||
|
*
|
||||||
|
* Side Effect:
|
||||||
|
* Retains a reference to thread until the thread is woken up.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
WaitChannel_Sleep(WaitChannel *wchan)
|
||||||
|
{
|
||||||
|
Thread *thr = Sched_Current();
|
||||||
|
|
||||||
|
Sched_SetWaiting(thr);
|
||||||
|
TAILQ_INSERT_TAIL(&wchan->chanQueue, thr, chanQueue);
|
||||||
|
Spinlock_Unlock(&wchan->lock);
|
||||||
|
|
||||||
|
Sched_Scheduler();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WaitChannel_Wake --
|
||||||
|
*
|
||||||
|
* Wake up a single thread.
|
||||||
|
*
|
||||||
|
* Side Effects:
|
||||||
|
* Releases the thread reference once complete.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
WaitChannel_Wake(WaitChannel *wchan)
|
||||||
|
{
|
||||||
|
Thread *thr;
|
||||||
|
|
||||||
|
Spinlock_Lock(&wchan->lock);
|
||||||
|
|
||||||
|
thr = TAILQ_FIRST(&wchan->chanQueue);
|
||||||
|
TAILQ_REMOVE(&wchan->chanQueue, thr, chanQueue);
|
||||||
|
Sched_SetRunnable(thr);
|
||||||
|
Thread_Release(thr);
|
||||||
|
|
||||||
|
Spinlock_Unlock(&wchan->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WaitChannel_WakeAll --
|
||||||
|
*
|
||||||
|
* Wakes up all threads currently sleeping on the wait channel.
|
||||||
|
*
|
||||||
|
* Side Effects:
|
||||||
|
* Releases all thread references.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
WaitChannel_WakeAll(WaitChannel *wchan)
|
||||||
|
{
|
||||||
|
Thread *thr;
|
||||||
|
Thread *thrTemp;
|
||||||
|
|
||||||
|
Spinlock_Lock(&wchan->lock);
|
||||||
|
|
||||||
|
TAILQ_FOREACH_SAFE(thr, &wchan->chanQueue, chanQueue, thrTemp) {
|
||||||
|
thr = TAILQ_FIRST(&wchan->chanQueue);
|
||||||
|
TAILQ_REMOVE(&wchan->chanQueue, thr, chanQueue);
|
||||||
|
Sched_SetRunnable(thr);
|
||||||
|
Thread_Release(thr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Spinlock_Unlock(&wchan->lock);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user