waitpid: remake the thread deallocation loop and fix a few stupid mistakes

This commit is contained in:
Matheus
2023-01-01 10:30:15 -03:00
parent 814ee1f69a
commit 76435ad9a1
+13 -31
View File
@@ -22,21 +22,19 @@ syscallret syscall_waitpid(pid_t pid, int *status, int options){
retv.errno = EFAULT; retv.errno = EFAULT;
return retv; return retv;
} }
if(options != 0){ if(options != 0){
console_write(UNSUPPORTED, strlen(UNSUPPORTED)); console_write(UNSUPPORTED, strlen(UNSUPPORTED));
retv.errno = ENOSYS; retv.errno = ENOSYS;
return retv; return retv;
} }
if(pid < -1 || pid == 0){ if(pid < -1 || pid == 0){
console_write(UNSUPPORTED_PG, strlen(UNSUPPORTED_PG)); console_write(UNSUPPORTED_PG, strlen(UNSUPPORTED_PG));
retv.errno = ENOSYS; retv.errno = ENOSYS;
return retv; return retv;
} }
proc_t* proc = arch_getcls()->thread->proc; proc_t* proc = arch_getcls()->thread->proc;
bool loop = true; bool loop = true;
@@ -68,17 +66,17 @@ syscallret syscall_waitpid(pid_t pid, int *status, int options){
} }
spinlock_release(&proc->lock); spinlock_release(&proc->lock);
if(loop){ if(loop){
event_wait(&proc->childevent, true); event_wait(&proc->childevent, true);
loop = false; loop = false;
continue; continue;
} }
else break; else break;
} }
if(!child){ if(!child){
spinlock_release(&proc->lock); spinlock_release(&proc->lock);
@@ -94,7 +92,6 @@ syscallret syscall_waitpid(pid_t pid, int *status, int options){
else{ else{
proc->child = child->sibling; proc->child = child->sibling;
} }
if(status){ if(status){
retv.errno = u_memcpy(status, &child->status, sizeof(*status)); retv.errno = u_memcpy(status, &child->status, sizeof(*status));
@@ -103,40 +100,25 @@ syscallret syscall_waitpid(pid_t pid, int *status, int options){
} }
int threadc = proc->threadcount; int threadc = child->threadcount;
// free all the threads // free all the threads
while(proc->threadcount){ for(int t = 0; t < threadc; ++t){
for(int t = 0; t < threadc; ++t){ thread_t* thread = child->threads[t];
thread_t* thread = proc->threads[t];
// XXX possible race condition here?
if(thread->state != THREAD_STATE_DEAD) free(thread->regs);
continue; free(thread->kernelstackbase);
vmm_destroy(thread->ctx);
free(thread->regs); thread->state = THREAD_STATE_DESTROYED;
free(thread->kernelstackbase);
vmm_destroy(thread->ctx);
thread->state = THREAD_STATE_DESTROYED;
}
arch_interrupt_disable();
sched_yield();
arch_interrupt_enable();
} }
for(int t = 0; t < threadc; ++t){ for(int t = 0; t < threadc; ++t){
thread_t* thread = proc->threads[t]; thread_t* thread = child->threads[t];
if(thread->state != THREAD_STATE_DESTROYED) if(thread->state != THREAD_STATE_DESTROYED)
_panic("Freeing non-destroyed thread", NULL); _panic("Freeing non-destroyed thread", NULL);
@@ -144,9 +126,9 @@ syscallret syscall_waitpid(pid_t pid, int *status, int options){
free(thread); free(thread);
} }
free(child); free(child);
retv.ret = child->pid; retv.ret = child->pid;
retv.errno = 0; retv.errno = 0;
return retv; return retv;