2023-08-21 22:38:51 +00:00
|
|
|
|
|
|
|
#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);
|
2023-09-02 21:51:10 +00:00
|
|
|
Mutex_Init(&proc->zombieProcLock, "Zombie Process Lock");
|
|
|
|
CV_Init(&proc->zombieProcCV, "Zombie Process CV");
|
2023-08-21 22:38:51 +00:00
|
|
|
|
|
|
|
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);
|
2023-09-02 21:51:10 +00:00
|
|
|
CV_Destroy(&proc->zombieProcCV);
|
|
|
|
Mutex_Destroy(&proc->zombieProcLock);
|
2023-08-21 22:38:51 +00:00
|
|
|
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!
|
|
|
|
|
2023-09-02 21:51:10 +00:00
|
|
|
Mutex_Lock(&proc->zombieProcLock);
|
2023-08-21 22:38:51 +00:00
|
|
|
while (1) {
|
|
|
|
p = TAILQ_FIRST(&proc->zombieProc);
|
2023-09-02 21:51:10 +00:00
|
|
|
if (p != NULL && (pid == 0 || p->pid == pid)) {
|
2023-08-21 22:38:51 +00:00
|
|
|
TAILQ_REMOVE(&proc->zombieProc, p, siblingList);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-09-02 21:51:10 +00:00
|
|
|
CV_Wait(&proc->zombieProcCV, &proc->zombieProcLock);
|
2023-08-21 22:38:51 +00:00
|
|
|
}
|
2023-09-02 21:51:10 +00:00
|
|
|
Mutex_Unlock(&proc->zombieProcLock);
|
2023-08-21 22:38:51 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|