mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 06:58:22 +00:00
scheduler: pid refcount
This commit is contained in:
@@ -46,10 +46,12 @@ typedef struct thread_t {
|
|||||||
spinlock_t sleeplock;
|
spinlock_t sleeplock;
|
||||||
int wakeupreason;
|
int wakeupreason;
|
||||||
bool shouldexit;
|
bool shouldexit;
|
||||||
|
void *kernelarg;
|
||||||
} thread_t;
|
} thread_t;
|
||||||
|
|
||||||
typedef struct proc_t {
|
typedef struct proc_t {
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
int refcount;
|
||||||
int status;
|
int status;
|
||||||
int state;
|
int state;
|
||||||
struct proc_t *sibling;
|
struct proc_t *sibling;
|
||||||
@@ -77,6 +79,13 @@ typedef struct proc_t {
|
|||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
|
|
||||||
#define UMASK(mode) ((mode) & ~_cpu()->thread->proc->umask)
|
#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;
|
extern proc_t *sched_initproc;
|
||||||
|
|
||||||
@@ -101,5 +110,6 @@ void sched_destroythread(thread_t *);
|
|||||||
void sched_targetcpu(struct cpu_t *cpu);
|
void sched_targetcpu(struct cpu_t *cpu);
|
||||||
void sched_sleepus(size_t us);
|
void sched_sleepus(size_t us);
|
||||||
void sched_apentry();
|
void sched_apentry();
|
||||||
|
void sched_inactiveproc(proc_t *proc);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ proc_t *sched_newproc() {
|
|||||||
SPINLOCK_INIT(proc->lock);
|
SPINLOCK_INIT(proc->lock);
|
||||||
SPINLOCK_INIT(proc->nodeslock);
|
SPINLOCK_INIT(proc->nodeslock);
|
||||||
proc->fdcount = 3;
|
proc->fdcount = 3;
|
||||||
|
proc->refcount = 1;
|
||||||
proc->fdfirst = 3;
|
proc->fdfirst = 3;
|
||||||
SPINLOCK_INIT(proc->fdlock);
|
SPINLOCK_INIT(proc->fdlock);
|
||||||
SEMAPHORE_INIT(&proc->waitsem, 0);
|
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->vmmctx = proc ? NULL : &vmm_kernelctx;
|
||||||
thread->proc = proc;
|
thread->proc = proc;
|
||||||
thread->priority = priority;
|
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);
|
thread->tid = __atomic_fetch_add(&currpid, 1, __ATOMIC_SEQ_CST);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CTX_INIT(&thread->context, proc != NULL, true);
|
CTX_INIT(&thread->context, proc != NULL, true);
|
||||||
@@ -229,9 +233,15 @@ __attribute__((noreturn)) void sched_stopcurrentthread() {
|
|||||||
switchthread(next);
|
switchthread(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// called when all threads in a process have exited
|
||||||
void sched_procexit() {
|
void sched_procexit() {
|
||||||
proc_t *proc = _cpu()->thread->proc;
|
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
|
// close fds
|
||||||
for (int fd = 0; fd < proc->fdcount; ++fd)
|
for (int fd = 0; fd < proc->fdcount; ++fd)
|
||||||
fd_close(fd);
|
fd_close(fd);
|
||||||
@@ -245,6 +255,7 @@ void sched_procexit() {
|
|||||||
proc->state = SCHED_PROC_STATE_ZOMBIE;
|
proc->state = SCHED_PROC_STATE_ZOMBIE;
|
||||||
proc_t *lastchild = proc->child;
|
proc_t *lastchild = proc->child;
|
||||||
|
|
||||||
|
|
||||||
spinlock_acquire(&sched_initproc->lock);
|
spinlock_acquire(&sched_initproc->lock);
|
||||||
|
|
||||||
bool haszombie = false;
|
bool haszombie = false;
|
||||||
@@ -270,6 +281,14 @@ void sched_procexit() {
|
|||||||
semaphore_signal(&sched_initproc->waitsem);
|
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 *) {
|
static void threadexit_internal(context_t *) {
|
||||||
thread_t *thread = _cpu()->thread;
|
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
|
// 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();
|
sched_procexit();
|
||||||
vmm_destroycontext(oldctx);
|
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);
|
thread_t *uthread = sched_newthread(entry, PAGE_SIZE * 16, 1, proc, stack);
|
||||||
__assert(uthread);
|
__assert(uthread);
|
||||||
|
|
||||||
uthread->vmmctx = vmmctx;
|
uthread->vmmctx = vmmctx;
|
||||||
sched_queue(uthread);
|
sched_queue(uthread);
|
||||||
|
|
||||||
VOP_RELEASE(initnode);
|
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;
|
ret.ret = nproc->pid;
|
||||||
|
|
||||||
sched_queue(nthread);
|
sched_queue(nthread);
|
||||||
|
// proc starts with 1 refcount, release it here as to only have the thread reference
|
||||||
|
PROC_RELEASE(nproc);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ syscallret_t syscall_waitpid(context_t *context, pid_t pid, int *status, int opt
|
|||||||
ret.errno = 0;
|
ret.errno = 0;
|
||||||
|
|
||||||
__assert(iterator);
|
__assert(iterator);
|
||||||
sched_destroyproc(iterator);
|
// process will no longer be referenced by the child list
|
||||||
|
PROC_RELEASE(iterator);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user