mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
scheduler: pid refcount
This commit is contained in:
@@ -46,10 +46,12 @@ typedef struct thread_t {
|
||||
spinlock_t sleeplock;
|
||||
int wakeupreason;
|
||||
bool shouldexit;
|
||||
void *kernelarg;
|
||||
} thread_t;
|
||||
|
||||
typedef struct proc_t {
|
||||
spinlock_t lock;
|
||||
int refcount;
|
||||
int status;
|
||||
int state;
|
||||
struct proc_t *sibling;
|
||||
@@ -77,6 +79,13 @@ typedef struct proc_t {
|
||||
#include <arch/cpu.h>
|
||||
|
||||
#define UMASK(mode) ((mode) & ~_cpu()->thread->proc->umask)
|
||||
#define PROC_HOLD(v) __atomic_add_fetch(&(v)->refcount, 1, __ATOMIC_SEQ_CST)
|
||||
#define PROC_RELEASE(v) {\
|
||||
if (__atomic_sub_fetch(&(v)->refcount, 1, __ATOMIC_SEQ_CST) == 0) {\
|
||||
sched_inactiveproc(v); \
|
||||
(v) = NULL; \
|
||||
} \
|
||||
}
|
||||
|
||||
extern proc_t *sched_initproc;
|
||||
|
||||
@@ -101,5 +110,6 @@ void sched_destroythread(thread_t *);
|
||||
void sched_targetcpu(struct cpu_t *cpu);
|
||||
void sched_sleepus(size_t us);
|
||||
void sched_apentry();
|
||||
void sched_inactiveproc(proc_t *proc);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -51,6 +51,7 @@ proc_t *sched_newproc() {
|
||||
SPINLOCK_INIT(proc->lock);
|
||||
SPINLOCK_INIT(proc->nodeslock);
|
||||
proc->fdcount = 3;
|
||||
proc->refcount = 1;
|
||||
proc->fdfirst = 3;
|
||||
SPINLOCK_INIT(proc->fdlock);
|
||||
SEMAPHORE_INIT(&proc->waitsem, 0);
|
||||
@@ -87,8 +88,11 @@ thread_t *sched_newthread(void *ip, size_t kstacksize, int priority, proc_t *pro
|
||||
thread->vmmctx = proc ? NULL : &vmm_kernelctx;
|
||||
thread->proc = proc;
|
||||
thread->priority = priority;
|
||||
if (proc)
|
||||
if (proc) {
|
||||
// each thread holds one reference to proc
|
||||
PROC_HOLD(proc);
|
||||
thread->tid = __atomic_fetch_add(&currpid, 1, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
|
||||
CTX_INIT(&thread->context, proc != NULL, true);
|
||||
@@ -229,9 +233,15 @@ __attribute__((noreturn)) void sched_stopcurrentthread() {
|
||||
switchthread(next);
|
||||
}
|
||||
|
||||
// called when all threads in a process have exited
|
||||
void sched_procexit() {
|
||||
proc_t *proc = _cpu()->thread->proc;
|
||||
|
||||
// the process is going to be referenced by the child list, hold it
|
||||
// it only holds it now because it has to have running threads to be in the list
|
||||
// which hold a reference. it won't now since its a zombie, which is why it will be held
|
||||
PROC_HOLD(proc);
|
||||
|
||||
// close fds
|
||||
for (int fd = 0; fd < proc->fdcount; ++fd)
|
||||
fd_close(fd);
|
||||
@@ -245,6 +255,7 @@ void sched_procexit() {
|
||||
proc->state = SCHED_PROC_STATE_ZOMBIE;
|
||||
proc_t *lastchild = proc->child;
|
||||
|
||||
|
||||
spinlock_acquire(&sched_initproc->lock);
|
||||
|
||||
bool haszombie = false;
|
||||
@@ -270,6 +281,14 @@ void sched_procexit() {
|
||||
semaphore_signal(&sched_initproc->waitsem);
|
||||
}
|
||||
|
||||
void sched_inactiveproc(proc_t *proc) {
|
||||
// proc refcount 0, we can free the structure
|
||||
// TODO remove from the pid list
|
||||
|
||||
printf("destroying proc!\n");
|
||||
sched_destroyproc(proc);
|
||||
}
|
||||
|
||||
static void threadexit_internal(context_t *) {
|
||||
thread_t *thread = _cpu()->thread;
|
||||
// we don't need to access the current thread anymore, as any state will be ignored and we are running on the scheduler stack
|
||||
@@ -301,6 +320,7 @@ __attribute__((noreturn)) void sched_threadexit() {
|
||||
|
||||
sched_procexit();
|
||||
vmm_destroycontext(oldctx);
|
||||
PROC_RELEASE(proc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -628,8 +648,11 @@ void sched_runinit() {
|
||||
|
||||
thread_t *uthread = sched_newthread(entry, PAGE_SIZE * 16, 1, proc, stack);
|
||||
__assert(uthread);
|
||||
|
||||
uthread->vmmctx = vmmctx;
|
||||
sched_queue(uthread);
|
||||
|
||||
VOP_RELEASE(initnode);
|
||||
// proc starts with 1 refcount, release it here as to only have the thread reference
|
||||
PROC_RELEASE(proc);
|
||||
}
|
||||
|
||||
@@ -57,6 +57,8 @@ syscallret_t syscall_fork(context_t *ctx) {
|
||||
ret.ret = nproc->pid;
|
||||
|
||||
sched_queue(nthread);
|
||||
// proc starts with 1 refcount, release it here as to only have the thread reference
|
||||
PROC_RELEASE(nproc);
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
|
||||
@@ -75,6 +75,7 @@ syscallret_t syscall_waitpid(context_t *context, pid_t pid, int *status, int opt
|
||||
ret.errno = 0;
|
||||
|
||||
__assert(iterator);
|
||||
sched_destroyproc(iterator);
|
||||
// process will no longer be referenced by the child list
|
||||
PROC_RELEASE(iterator);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user