kern

diff src/proc.c @ 72:3941e82b07f2

- implemented syscalls: exit, waitpid, getppid - moved sys_whatever functions out of syscall.c into more reasonable files - putting all the definitions that must be synced with userland to include/kdef.h
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 15 Oct 2011 07:45:56 +0300
parents b45e2d5f0ae1
children 8b21fe04ba2c
line diff
     1.1 --- a/src/proc.c	Thu Oct 13 05:22:35 2011 +0300
     1.2 +++ b/src/proc.c	Sat Oct 15 07:45:56 2011 +0300
     1.3 @@ -12,6 +12,7 @@
     1.4  #include "syscall.h"
     1.5  #include "sched.h"
     1.6  #include "tss.h"
     1.7 +#include "kdef.h"
     1.8  
     1.9  #define	FLAGS_INTR_BIT	(1 << 9)
    1.10  
    1.11 @@ -138,7 +139,7 @@
    1.12  	intr_ret(ifrm);
    1.13  }
    1.14  
    1.15 -int fork(void)
    1.16 +int sys_fork(void)
    1.17  {
    1.18  	int i, pid;
    1.19  	struct process *p, *parent;
    1.20 @@ -189,8 +190,13 @@
    1.21  	/* initialize the rest of the process structure */
    1.22  	p->id = pid;
    1.23  	p->parent = parent->id;
    1.24 +	p->child_list = 0;
    1.25  	p->next = p->prev = 0;
    1.26  
    1.27 +	/* add to the child list */
    1.28 +	p->sib_next = parent->child_list;
    1.29 +	parent->child_list = p;
    1.30 +
    1.31  	/* will be copied on write */
    1.32  	p->user_stack_pg = parent->user_stack_pg;
    1.33  
    1.34 @@ -203,6 +209,105 @@
    1.35  	return pid;
    1.36  }
    1.37  
    1.38 +int sys_exit(int status)
    1.39 +{
    1.40 +	struct process *p, *child;
    1.41 +
    1.42 +	p = get_current_proc();
    1.43 +
    1.44 +	/* TODO deliver SIGCHLD to the parent */
    1.45 +
    1.46 +	/* find any child processes and make init adopt them */
    1.47 +	child = p->child_list;
    1.48 +	while(child) {
    1.49 +		child->parent = 1;
    1.50 +		child = child->sib_next;
    1.51 +	}
    1.52 +
    1.53 +	cleanup_vm(p);
    1.54 +
    1.55 +	/* remove it from the runqueue */
    1.56 +	remove_proc(p->id);
    1.57 +
    1.58 +	/* make it a zombie until its parent reaps it */
    1.59 +	p->state = STATE_ZOMBIE;
    1.60 +	p->exit_status = (status & _WSTATUS_MASK) | (_WREASON_EXITED << _WREASON_SHIFT);
    1.61 +
    1.62 +	/* wakeup any processes waiting for it
    1.63 +	 * we're waking up the parent's address, because waitpid waits
    1.64 +	 * on it's own process struct, not knowing which child will die
    1.65 +	 * first.
    1.66 +	 */
    1.67 +	wakeup(get_process(p->parent));
    1.68 +	return 0;
    1.69 +}
    1.70 +
    1.71 +int sys_waitpid(int pid, int *status, int opt)
    1.72 +{
    1.73 +	struct process *p, *child;
    1.74 +
    1.75 +	p = get_current_proc();
    1.76 +
    1.77 +restart:
    1.78 +	if(pid <= 0) {
    1.79 +		/* search for zombie children */
    1.80 +		child = p->child_list;
    1.81 +		while(child) {
    1.82 +			if(child->state == STATE_ZOMBIE) {
    1.83 +				break;
    1.84 +			}
    1.85 +			child = child->sib_next;
    1.86 +		}
    1.87 +	} else {
    1.88 +		if(!(child = get_process(pid)) || child->parent != p->id) {
    1.89 +			return -ECHILD;
    1.90 +		}
    1.91 +		if(child->state != STATE_ZOMBIE) {
    1.92 +			child = 0;
    1.93 +		}
    1.94 +	}
    1.95 +
    1.96 +	/* found ? */
    1.97 +	if(child) {
    1.98 +		int res;
    1.99 +		struct process *prev, dummy;
   1.100 +
   1.101 +		if(status) {
   1.102 +			*status = child->exit_status;
   1.103 +		}
   1.104 +		res = child->id;
   1.105 +
   1.106 +		/* remove it from our children list */
   1.107 +		dummy.sib_next = p->child_list;
   1.108 +		prev = &dummy;
   1.109 +		while(prev->next) {
   1.110 +			if(prev->next == child) {
   1.111 +				prev->next = child->next;
   1.112 +				break;
   1.113 +			}
   1.114 +		}
   1.115 +		p->child_list = dummy.next;
   1.116 +
   1.117 +		/* invalidate the id */
   1.118 +		child->id = 0;
   1.119 +		return res;
   1.120 +	}
   1.121 +
   1.122 +	/* not found, wait or sod off */
   1.123 +	if(!(opt & WNOHANG)) {
   1.124 +		/* wait on our own process struct because
   1.125 +		 * we have no way of knowing which child will
   1.126 +		 * die first.
   1.127 +		 * exit will wakeup the parent structure...
   1.128 +		 */
   1.129 +		wait(p);
   1.130 +		/* done waiting, restart waitpid */
   1.131 +		goto restart;
   1.132 +	}
   1.133 +
   1.134 +	return 0;	/* he's not dead jim */
   1.135 +}
   1.136 +
   1.137  void context_switch(int pid)
   1.138  {
   1.139  	static struct process *prev, *new;
   1.140 @@ -262,5 +367,25 @@
   1.141  
   1.142  struct process *get_process(int pid)
   1.143  {
   1.144 -	return &proc[pid];
   1.145 +	struct process *p = proc + pid;
   1.146 +	if(p->id != pid) {
   1.147 +		printf("get_process called with invalid pid: %d\n", pid);
   1.148 +		return 0;
   1.149 +	}
   1.150 +	return p;
   1.151  }
   1.152 +
   1.153 +int sys_getpid(void)
   1.154 +{
   1.155 +	return cur_pid;
   1.156 +}
   1.157 +
   1.158 +int sys_getppid(void)
   1.159 +{
   1.160 +	struct process *p = get_current_proc();
   1.161 +
   1.162 +	if(!p) {
   1.163 +		return 0;
   1.164 +	}
   1.165 +	return p->parent;
   1.166 +}