Split up thread.c into thread, process and scheduler files.
This commit is contained in:
parent
e4ca21fa2e
commit
ff7c6309b7
229
sys/kern/process.c
Normal file
229
sys/kern/process.c
Normal file
@ -0,0 +1,229 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <sys/kassert.h>
|
||||
#include <sys/kconfig.h>
|
||||
#include <sys/kdebug.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/ktime.h>
|
||||
#include <sys/mp.h>
|
||||
#include <sys/spinlock.h>
|
||||
#include <sys/thread.h>
|
||||
|
||||
#include <machine/trap.h>
|
||||
#include <machine/pmap.h>
|
||||
|
||||
extern Thread *curProc[MAX_CPUS];
|
||||
|
||||
// Process List
|
||||
Spinlock procLock;
|
||||
uint64_t nextProcessID;
|
||||
ProcessQueue processList;
|
||||
|
||||
// Memory Pools
|
||||
Slab processSlab;
|
||||
|
||||
/*
|
||||
* Process
|
||||
*/
|
||||
|
||||
Process *
|
||||
Process_Create(Process *parent, const char *title)
|
||||
{
|
||||
Process *proc = (Process *)Slab_Alloc(&processSlab);
|
||||
|
||||
if (!proc)
|
||||
return NULL;
|
||||
|
||||
memset(proc, 0, sizeof(*proc));
|
||||
|
||||
proc->pid = nextProcessID++;
|
||||
proc->threads = 0;
|
||||
proc->refCount = 1;
|
||||
TAILQ_INIT(&proc->threadList);
|
||||
|
||||
if (title) {
|
||||
strncpy((char *)&proc->title, title, PROCESS_TITLE_LENGTH);
|
||||
} else {
|
||||
proc->title[0] = '\0';
|
||||
}
|
||||
|
||||
proc->space = PMap_NewAS();
|
||||
if (proc->space == NULL) {
|
||||
Slab_Free(&processSlab, proc);
|
||||
return NULL;
|
||||
}
|
||||
proc->ustackNext = MEM_USERSPACE_STKBASE;
|
||||
|
||||
Spinlock_Init(&proc->lock, "Process Lock", SPINLOCK_TYPE_NORMAL);
|
||||
|
||||
Semaphore_Init(&proc->zombieSemaphore, 0, "Zombie Semaphore");
|
||||
TAILQ_INIT(&proc->zombieQueue);
|
||||
|
||||
Handle_Init(proc);
|
||||
|
||||
proc->parent = parent;
|
||||
if (parent) {
|
||||
Spinlock_Lock(&parent->lock);
|
||||
TAILQ_INSERT_TAIL(&parent->childrenList, proc, siblingList);
|
||||
Spinlock_Unlock(&parent->lock);
|
||||
}
|
||||
TAILQ_INIT(&proc->childrenList);
|
||||
TAILQ_INIT(&proc->zombieProc);
|
||||
Semaphore_Init(&proc->zombieProcSemaphore, 0, "Zombie Process Semaphore");
|
||||
|
||||
Spinlock_Lock(&procLock);
|
||||
TAILQ_INSERT_TAIL(&processList, proc, processList);
|
||||
Spinlock_Unlock(&procLock);
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
static void
|
||||
Process_Destroy(Process *proc)
|
||||
{
|
||||
Handle_Destroy(proc);
|
||||
|
||||
Spinlock_Destroy(&proc->lock);
|
||||
Semaphore_Destroy(&proc->zombieSemaphore);
|
||||
Semaphore_Destroy(&proc->zombieProcSemaphore);
|
||||
PMap_DestroyAS(proc->space);
|
||||
|
||||
// XXX: We need to promote zombie processes to our parent
|
||||
// XXX: Release the semaphore as well
|
||||
|
||||
if (proc->parent) {
|
||||
Spinlock_Lock(&proc->parent->lock);
|
||||
TAILQ_REMOVE(&proc->parent->zombieProc, proc, siblingList);
|
||||
Spinlock_Unlock(&proc->parent->lock);
|
||||
}
|
||||
Spinlock_Lock(&procLock);
|
||||
TAILQ_REMOVE(&processList, proc, processList);
|
||||
Spinlock_Unlock(&procLock);
|
||||
|
||||
Slab_Free(&processSlab, proc);
|
||||
}
|
||||
|
||||
Process *
|
||||
Process_Lookup(uint64_t pid)
|
||||
{
|
||||
Process *p;
|
||||
Process *proc = NULL;
|
||||
|
||||
Spinlock_Lock(&procLock);
|
||||
TAILQ_FOREACH(p, &processList, processList) {
|
||||
if (p->pid == pid) {
|
||||
Process_Retain(p);
|
||||
proc = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Spinlock_Unlock(&procLock);
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
void
|
||||
Process_Retain(Process *proc)
|
||||
{
|
||||
ASSERT(proc->refCount != 0);
|
||||
__sync_fetch_and_add(&proc->refCount, 1);
|
||||
}
|
||||
|
||||
void
|
||||
Process_Release(Process *proc)
|
||||
{
|
||||
ASSERT(proc->refCount != 0);
|
||||
if (__sync_fetch_and_sub(&proc->refCount, 1) == 1) {
|
||||
Process_Destroy(proc);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t
|
||||
Process_Wait(Process *proc, uint64_t pid)
|
||||
{
|
||||
Thread *thr;
|
||||
Thread *thr_temp;
|
||||
Process *p = NULL;
|
||||
uint64_t status;
|
||||
|
||||
// XXX: Need to verify pid exists!
|
||||
|
||||
while (1) {
|
||||
Semaphore_Acquire(&proc->zombieProcSemaphore);
|
||||
// XXX: Forced exit check!
|
||||
|
||||
Spinlock_Lock(&proc->lock);
|
||||
p = TAILQ_FIRST(&proc->zombieProc);
|
||||
if (pid == 0 || p->pid == pid) {
|
||||
TAILQ_REMOVE(&proc->zombieProc, p, siblingList);
|
||||
Spinlock_Unlock(&proc->lock);
|
||||
break;
|
||||
}
|
||||
Spinlock_Unlock(&proc->lock);
|
||||
|
||||
Semaphore_Release(&proc->zombieProcSemaphore);
|
||||
}
|
||||
|
||||
status = (p->pid << 16) | p->exitCode;
|
||||
|
||||
// Release threads
|
||||
TAILQ_FOREACH_SAFE(thr, &p->zombieQueue, schedQueue, thr_temp) {
|
||||
Thread_Release(thr);
|
||||
}
|
||||
|
||||
// Release process
|
||||
Process_Release(p);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugging
|
||||
*/
|
||||
|
||||
void
|
||||
Process_Dump(Process *proc)
|
||||
{
|
||||
kprintf("title %s\n", proc->title);
|
||||
kprintf("pid %llu\n", proc->pid);
|
||||
kprintf("space %016llx\n", proc->space);
|
||||
kprintf("threads %llu\n", proc->threads);
|
||||
kprintf("refCount %d\n", proc->refCount);
|
||||
kprintf("nextFD %llu\n", proc->nextFD);
|
||||
}
|
||||
|
||||
static void
|
||||
Debug_Processes(int argc, const char *argv[])
|
||||
{
|
||||
Process *proc;
|
||||
|
||||
//Spinlock_Lock(&threadLock);
|
||||
|
||||
TAILQ_FOREACH(proc, &processList, processList)
|
||||
{
|
||||
kprintf("Process: %d(%016llx)\n", proc->pid, proc);
|
||||
Process_Dump(proc);
|
||||
}
|
||||
|
||||
//Spinlock_Unlock(&threadLock);
|
||||
}
|
||||
|
||||
REGISTER_DBGCMD(processes, "Display list of processes", Debug_Processes);
|
||||
|
||||
static void
|
||||
Debug_ProcInfo(int argc, const char *argv[])
|
||||
{
|
||||
Thread *thr = curProc[CPU()];
|
||||
|
||||
kprintf("Current Process State:\n");
|
||||
Process_Dump(thr->proc);
|
||||
}
|
||||
|
||||
REGISTER_DBGCMD(procinfo, "Display current process state", Debug_ProcInfo);
|
||||
|
144
sys/kern/sched.c
Normal file
144
sys/kern/sched.c
Normal file
@ -0,0 +1,144 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <sys/kassert.h>
|
||||
#include <sys/kconfig.h>
|
||||
#include <sys/kdebug.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/ktime.h>
|
||||
#include <sys/mp.h>
|
||||
#include <sys/spinlock.h>
|
||||
#include <sys/thread.h>
|
||||
|
||||
#include <machine/trap.h>
|
||||
#include <machine/pmap.h>
|
||||
|
||||
// Scheduler Queues
|
||||
Spinlock schedLock;
|
||||
ThreadQueue waitQueue;
|
||||
ThreadQueue runnableQueue;
|
||||
Thread *curProc[MAX_CPUS];
|
||||
|
||||
/*
|
||||
* Scheduler Functions
|
||||
*/
|
||||
|
||||
Thread *
|
||||
Sched_Current()
|
||||
{
|
||||
Spinlock_Lock(&schedLock);
|
||||
|
||||
Thread *thr = curProc[CPU()];
|
||||
Thread_Retain(thr);
|
||||
|
||||
Spinlock_Unlock(&schedLock);
|
||||
|
||||
return thr;
|
||||
}
|
||||
|
||||
void
|
||||
Sched_SetRunnable(Thread *thr)
|
||||
{
|
||||
Spinlock_Lock(&schedLock);
|
||||
|
||||
if (thr->schedState == SCHED_STATE_WAITING) {
|
||||
thr->waitTime += KTime_GetEpochNS() - thr->waitStart;
|
||||
thr->waitStart = 0;
|
||||
TAILQ_REMOVE(&waitQueue, thr, schedQueue);
|
||||
}
|
||||
thr->schedState = SCHED_STATE_RUNNABLE;
|
||||
TAILQ_INSERT_TAIL(&runnableQueue, thr, schedQueue);
|
||||
|
||||
Spinlock_Unlock(&schedLock);
|
||||
}
|
||||
|
||||
void
|
||||
Sched_SetWaiting(Thread *thr)
|
||||
{
|
||||
Spinlock_Lock(&schedLock);
|
||||
|
||||
thr->schedState = SCHED_STATE_WAITING;
|
||||
TAILQ_INSERT_TAIL(&waitQueue, thr, schedQueue);
|
||||
thr->waitStart = KTime_GetEpochNS();
|
||||
|
||||
Spinlock_Unlock(&schedLock);
|
||||
}
|
||||
|
||||
void
|
||||
Sched_SetZombie(Thread *thr)
|
||||
{
|
||||
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) {
|
||||
// All processes have parents except 'init' and 'kernel'
|
||||
ASSERT(proc->parent != NULL);
|
||||
Spinlock_Lock(&proc->parent->lock);
|
||||
TAILQ_REMOVE(&proc->parent->childrenList, proc, siblingList);
|
||||
TAILQ_INSERT_TAIL(&proc->parent->zombieProc, proc, siblingList);
|
||||
Semaphore_Release(&proc->parent->zombieProcSemaphore);
|
||||
Spinlock_Unlock(&proc->parent->lock);
|
||||
}
|
||||
|
||||
Spinlock_Unlock(&schedLock);
|
||||
}
|
||||
|
||||
static void
|
||||
Sched_Switch(Thread *oldthr, Thread *newthr)
|
||||
{
|
||||
// Load AS
|
||||
PMap_LoadAS(newthr->space);
|
||||
|
||||
Thread_SwitchArch(oldthr, newthr);
|
||||
}
|
||||
|
||||
void
|
||||
Sched_Scheduler()
|
||||
{
|
||||
Thread *prev;
|
||||
Thread *next;
|
||||
|
||||
Spinlock_Lock(&schedLock);
|
||||
|
||||
// Select next thread
|
||||
next = TAILQ_FIRST(&runnableQueue);
|
||||
if (!next) {
|
||||
/*
|
||||
* There may be no other runnable processes on this core. This is a
|
||||
* good opportunity to migrate threads. We should never hit this case
|
||||
* once the OS is up and running because of the idle threads, but just
|
||||
* in case we should assert that we never return to a zombie or waiting
|
||||
* thread.
|
||||
*/
|
||||
ASSERT(curProc[CPU()]->schedState == SCHED_STATE_RUNNING);
|
||||
Spinlock_Unlock(&schedLock);
|
||||
return;
|
||||
}
|
||||
TAILQ_REMOVE(&runnableQueue, next, schedQueue);
|
||||
|
||||
prev = curProc[CPU()];
|
||||
curProc[CPU()] = next;
|
||||
next->schedState = SCHED_STATE_RUNNING;
|
||||
next->ctxSwitches++;
|
||||
|
||||
if (prev->schedState == SCHED_STATE_RUNNING) {
|
||||
prev->schedState = SCHED_STATE_RUNNABLE;
|
||||
TAILQ_INSERT_TAIL(&runnableQueue, prev, schedQueue);
|
||||
}
|
||||
|
||||
Sched_Switch(prev, next);
|
||||
|
||||
Spinlock_Unlock(&schedLock);
|
||||
}
|
||||
|
@ -18,22 +18,29 @@
|
||||
#include <machine/trap.h>
|
||||
#include <machine/pmap.h>
|
||||
|
||||
/*
|
||||
* Unfortunately the thread, process and scheduler code are pretty well
|
||||
* integrated. To avoid poluting the global namespace we import a few symbols
|
||||
* from sched.c and process.c that are required during initialization and
|
||||
* regular execution of the thread code.
|
||||
*/
|
||||
|
||||
/* Globals declared in sched.c */
|
||||
extern Spinlock schedLock;
|
||||
extern ThreadQueue waitQueue;
|
||||
extern ThreadQueue runnableQueue;
|
||||
extern Thread *curProc[MAX_CPUS];
|
||||
|
||||
/* Globals declared in process.c */
|
||||
extern Spinlock procLock;
|
||||
extern uint64_t nextProcessID;
|
||||
extern ProcessQueue processList;
|
||||
extern Slab processSlab;
|
||||
|
||||
// Special Kernel Process
|
||||
Process *kernelProcess;
|
||||
|
||||
// Scheduler Queues
|
||||
Spinlock schedLock;
|
||||
ThreadQueue waitQueue;
|
||||
ThreadQueue runnableQueue;
|
||||
Thread *curProc[MAX_CPUS];
|
||||
|
||||
// Process List
|
||||
Spinlock procLock;
|
||||
uint64_t nextProcessID;
|
||||
ProcessQueue processList;
|
||||
|
||||
// Memory Pools
|
||||
Slab processSlab;
|
||||
Slab threadSlab;
|
||||
|
||||
void Handle_GlobalInit();
|
||||
@ -77,161 +84,6 @@ Thread_InitAP()
|
||||
curProc[CPU()] = apthr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process
|
||||
*/
|
||||
|
||||
Process *
|
||||
Process_Create(Process *parent, const char *title)
|
||||
{
|
||||
Process *proc = (Process *)Slab_Alloc(&processSlab);
|
||||
|
||||
if (!proc)
|
||||
return NULL;
|
||||
|
||||
memset(proc, 0, sizeof(*proc));
|
||||
|
||||
proc->pid = nextProcessID++;
|
||||
proc->threads = 0;
|
||||
proc->refCount = 1;
|
||||
TAILQ_INIT(&proc->threadList);
|
||||
|
||||
if (title) {
|
||||
strncpy((char *)&proc->title, title, PROCESS_TITLE_LENGTH);
|
||||
} else {
|
||||
proc->title[0] = '\0';
|
||||
}
|
||||
|
||||
proc->space = PMap_NewAS();
|
||||
if (proc->space == NULL) {
|
||||
Slab_Free(&processSlab, proc);
|
||||
return NULL;
|
||||
}
|
||||
proc->ustackNext = MEM_USERSPACE_STKBASE;
|
||||
|
||||
Spinlock_Init(&proc->lock, "Process Lock", SPINLOCK_TYPE_NORMAL);
|
||||
|
||||
Semaphore_Init(&proc->zombieSemaphore, 0, "Zombie Semaphore");
|
||||
TAILQ_INIT(&proc->zombieQueue);
|
||||
|
||||
Handle_Init(proc);
|
||||
|
||||
proc->parent = parent;
|
||||
if (parent) {
|
||||
Spinlock_Lock(&parent->lock);
|
||||
TAILQ_INSERT_TAIL(&parent->childrenList, proc, siblingList);
|
||||
Spinlock_Unlock(&parent->lock);
|
||||
}
|
||||
TAILQ_INIT(&proc->childrenList);
|
||||
TAILQ_INIT(&proc->zombieProc);
|
||||
Semaphore_Init(&proc->zombieProcSemaphore, 0, "Zombie Process Semaphore");
|
||||
|
||||
Spinlock_Lock(&procLock);
|
||||
TAILQ_INSERT_TAIL(&processList, proc, processList);
|
||||
Spinlock_Unlock(&procLock);
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
static void
|
||||
Process_Destroy(Process *proc)
|
||||
{
|
||||
Handle_Destroy(proc);
|
||||
|
||||
Spinlock_Destroy(&proc->lock);
|
||||
Semaphore_Destroy(&proc->zombieSemaphore);
|
||||
Semaphore_Destroy(&proc->zombieProcSemaphore);
|
||||
PMap_DestroyAS(proc->space);
|
||||
|
||||
// XXX: We need to promote zombie processes to our parent
|
||||
// XXX: Release the semaphore as well
|
||||
|
||||
if (proc->parent) {
|
||||
Spinlock_Lock(&proc->parent->lock);
|
||||
TAILQ_REMOVE(&proc->parent->zombieProc, proc, siblingList);
|
||||
Spinlock_Unlock(&proc->parent->lock);
|
||||
}
|
||||
Spinlock_Lock(&procLock);
|
||||
TAILQ_REMOVE(&processList, proc, processList);
|
||||
Spinlock_Unlock(&procLock);
|
||||
|
||||
Slab_Free(&processSlab, proc);
|
||||
}
|
||||
|
||||
Process *
|
||||
Process_Lookup(uint64_t pid)
|
||||
{
|
||||
Process *p;
|
||||
Process *proc = NULL;
|
||||
|
||||
Spinlock_Lock(&procLock);
|
||||
TAILQ_FOREACH(p, &processList, processList) {
|
||||
if (p->pid == pid) {
|
||||
Process_Retain(p);
|
||||
proc = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Spinlock_Unlock(&procLock);
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
void
|
||||
Process_Retain(Process *proc)
|
||||
{
|
||||
ASSERT(proc->refCount != 0);
|
||||
__sync_fetch_and_add(&proc->refCount, 1);
|
||||
}
|
||||
|
||||
void
|
||||
Process_Release(Process *proc)
|
||||
{
|
||||
ASSERT(proc->refCount != 0);
|
||||
if (__sync_fetch_and_sub(&proc->refCount, 1) == 1) {
|
||||
Process_Destroy(proc);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t
|
||||
Process_Wait(Process *proc, uint64_t pid)
|
||||
{
|
||||
Thread *thr;
|
||||
Thread *thr_temp;
|
||||
Process *p = NULL;
|
||||
uint64_t status;
|
||||
|
||||
// XXX: Need to verify pid exists!
|
||||
|
||||
while (1) {
|
||||
Semaphore_Acquire(&proc->zombieProcSemaphore);
|
||||
// XXX: Forced exit check!
|
||||
|
||||
Spinlock_Lock(&proc->lock);
|
||||
p = TAILQ_FIRST(&proc->zombieProc);
|
||||
if (pid == 0 || p->pid == pid) {
|
||||
TAILQ_REMOVE(&proc->zombieProc, p, siblingList);
|
||||
Spinlock_Unlock(&proc->lock);
|
||||
break;
|
||||
}
|
||||
Spinlock_Unlock(&proc->lock);
|
||||
|
||||
Semaphore_Release(&proc->zombieProcSemaphore);
|
||||
}
|
||||
|
||||
status = (p->pid << 16) | p->exitCode;
|
||||
|
||||
// Release threads
|
||||
TAILQ_FOREACH_SAFE(thr, &p->zombieQueue, schedQueue, thr_temp) {
|
||||
Thread_Release(thr);
|
||||
}
|
||||
|
||||
// Release process
|
||||
Process_Release(p);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Thread
|
||||
*/
|
||||
@ -422,124 +274,6 @@ Thread_Wait(Thread *thr, uint64_t tid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scheduler Functions
|
||||
*/
|
||||
|
||||
Thread *
|
||||
Sched_Current()
|
||||
{
|
||||
Spinlock_Lock(&schedLock);
|
||||
|
||||
Thread *thr = curProc[CPU()];
|
||||
Thread_Retain(thr);
|
||||
|
||||
Spinlock_Unlock(&schedLock);
|
||||
|
||||
return thr;
|
||||
}
|
||||
|
||||
void
|
||||
Sched_SetRunnable(Thread *thr)
|
||||
{
|
||||
Spinlock_Lock(&schedLock);
|
||||
|
||||
if (thr->schedState == SCHED_STATE_WAITING) {
|
||||
thr->waitTime += KTime_GetEpochNS() - thr->waitStart;
|
||||
thr->waitStart = 0;
|
||||
TAILQ_REMOVE(&waitQueue, thr, schedQueue);
|
||||
}
|
||||
thr->schedState = SCHED_STATE_RUNNABLE;
|
||||
TAILQ_INSERT_TAIL(&runnableQueue, thr, schedQueue);
|
||||
|
||||
Spinlock_Unlock(&schedLock);
|
||||
}
|
||||
|
||||
void
|
||||
Sched_SetWaiting(Thread *thr)
|
||||
{
|
||||
Spinlock_Lock(&schedLock);
|
||||
|
||||
thr->schedState = SCHED_STATE_WAITING;
|
||||
TAILQ_INSERT_TAIL(&waitQueue, thr, schedQueue);
|
||||
thr->waitStart = KTime_GetEpochNS();
|
||||
|
||||
Spinlock_Unlock(&schedLock);
|
||||
}
|
||||
|
||||
void
|
||||
Sched_SetZombie(Thread *thr)
|
||||
{
|
||||
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) {
|
||||
// All processes have parents except 'init' and 'kernel'
|
||||
ASSERT(proc->parent != NULL);
|
||||
Spinlock_Lock(&proc->parent->lock);
|
||||
TAILQ_REMOVE(&proc->parent->childrenList, proc, siblingList);
|
||||
TAILQ_INSERT_TAIL(&proc->parent->zombieProc, proc, siblingList);
|
||||
Semaphore_Release(&proc->parent->zombieProcSemaphore);
|
||||
Spinlock_Unlock(&proc->parent->lock);
|
||||
}
|
||||
|
||||
Spinlock_Unlock(&schedLock);
|
||||
}
|
||||
|
||||
static void
|
||||
Sched_Switch(Thread *oldthr, Thread *newthr)
|
||||
{
|
||||
// Load AS
|
||||
PMap_LoadAS(newthr->space);
|
||||
|
||||
Thread_SwitchArch(oldthr, newthr);
|
||||
}
|
||||
|
||||
void
|
||||
Sched_Scheduler()
|
||||
{
|
||||
Thread *prev;
|
||||
Thread *next;
|
||||
|
||||
Spinlock_Lock(&schedLock);
|
||||
|
||||
// Select next thread
|
||||
next = TAILQ_FIRST(&runnableQueue);
|
||||
if (!next) {
|
||||
/*
|
||||
* There may be no other runnable processes on this core. This is a
|
||||
* good opportunity to migrate threads. We should never hit this case
|
||||
* once the OS is up and running because of the idle threads, but just
|
||||
* in case we should assert that we never return to a zombie or waiting
|
||||
* thread.
|
||||
*/
|
||||
ASSERT(curProc[CPU()]->schedState == SCHED_STATE_RUNNING);
|
||||
Spinlock_Unlock(&schedLock);
|
||||
return;
|
||||
}
|
||||
TAILQ_REMOVE(&runnableQueue, next, schedQueue);
|
||||
|
||||
prev = curProc[CPU()];
|
||||
curProc[CPU()] = next;
|
||||
next->schedState = SCHED_STATE_RUNNING;
|
||||
next->ctxSwitches++;
|
||||
|
||||
if (prev->schedState == SCHED_STATE_RUNNING) {
|
||||
prev->schedState = SCHED_STATE_RUNNABLE;
|
||||
TAILQ_INSERT_TAIL(&runnableQueue, prev, schedQueue);
|
||||
}
|
||||
|
||||
Sched_Switch(prev, next);
|
||||
|
||||
Spinlock_Unlock(&schedLock);
|
||||
}
|
||||
|
||||
extern TaskStateSegment64 TSS[MAX_CPUS];
|
||||
|
||||
void
|
||||
@ -556,17 +290,6 @@ ThreadKThreadEntry(TrapFrame *tf)
|
||||
* Debugging
|
||||
*/
|
||||
|
||||
void
|
||||
Process_Dump(Process *proc)
|
||||
{
|
||||
kprintf("title %s\n", proc->title);
|
||||
kprintf("pid %llu\n", proc->pid);
|
||||
kprintf("space %016llx\n", proc->space);
|
||||
kprintf("threads %llu\n", proc->threads);
|
||||
kprintf("refCount %d\n", proc->refCount);
|
||||
kprintf("nextFD %llu\n", proc->nextFD);
|
||||
}
|
||||
|
||||
void
|
||||
Thread_Dump(Thread *thr)
|
||||
{
|
||||
@ -608,24 +331,6 @@ Debug_Threads(int argc, const char *argv[])
|
||||
|
||||
REGISTER_DBGCMD(threads, "Display list of threads", Debug_Threads);
|
||||
|
||||
static void
|
||||
Debug_Processes(int argc, const char *argv[])
|
||||
{
|
||||
Process *proc;
|
||||
|
||||
//Spinlock_Lock(&threadLock);
|
||||
|
||||
TAILQ_FOREACH(proc, &processList, processList)
|
||||
{
|
||||
kprintf("Process: %d(%016llx)\n", proc->pid, proc);
|
||||
Process_Dump(proc);
|
||||
}
|
||||
|
||||
//Spinlock_Unlock(&threadLock);
|
||||
}
|
||||
|
||||
REGISTER_DBGCMD(processes, "Display list of processes", Debug_Processes);
|
||||
|
||||
static void
|
||||
Debug_ThreadInfo(int argc, const char *argv[])
|
||||
{
|
||||
@ -637,14 +342,3 @@ Debug_ThreadInfo(int argc, const char *argv[])
|
||||
|
||||
REGISTER_DBGCMD(threadinfo, "Display current thread state", Debug_ThreadInfo);
|
||||
|
||||
static void
|
||||
Debug_ProcInfo(int argc, const char *argv[])
|
||||
{
|
||||
Thread *thr = curProc[CPU()];
|
||||
|
||||
kprintf("Current Process State:\n");
|
||||
Process_Dump(thr->proc);
|
||||
}
|
||||
|
||||
REGISTER_DBGCMD(procinfo, "Display current process state", Debug_ProcInfo);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user