kern
changeset 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 | c7bd6ec7b946 |
children | b4b7198986a6 |
files | Makefile include/kdef.h src/klibc/errno.h src/proc.c src/proc.h src/sched.c src/sched.h src/syscall.c src/syscall.h src/timer.c src/timer.h src/vm.c src/vm.h |
diffstat | 13 files changed, 265 insertions(+), 44 deletions(-) [+] |
line diff
1.1 --- a/Makefile Thu Oct 13 05:22:35 2011 +0300 1.2 +++ b/Makefile Sat Oct 15 07:45:56 2011 +0300 1.3 @@ -1,4 +1,5 @@ 1.4 ifneq ($(shell uname -m), i386) 1.5 + # -m32 instructs the compiler to produce 32bit code 1.6 ccemu = -m32 1.7 1.8 ifeq ($(shell uname -s), FreeBSD) 1.9 @@ -18,11 +19,10 @@ 1.10 1.11 CC = gcc 1.12 1.13 -inc = -Isrc -Isrc/klibc -Isrc/boot 1.14 +inc = -Isrc -Isrc/klibc -Isrc/boot -Iinclude 1.15 1.16 # -nostdinc instructs the compiler to ignore standard include directories 1.17 -# -m32 instructs the compiler to produce 32bit code (in case we have a 64bit compiler) 1.18 -CFLAGS = $(ccemu) -Wall -g -nostdinc -fno-builtin $(inc) 1.19 +CFLAGS = $(ccemu) -Wall -g -nostdinc -fno-builtin $(inc) -DKERNEL 1.20 ASFLAGS = $(ccemu) -g -nostdinc -fno-builtin $(inc) 1.21 1.22 bin = kernel.elf
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/include/kdef.h Sat Oct 15 07:45:56 2011 +0300 2.3 @@ -0,0 +1,55 @@ 2.4 +/* definitions that must be in-sync between kernel and user space */ 2.5 +#ifndef KERNEL_DEFS_H_ 2.6 +#define KERNEL_DEFS_H_ 2.7 + 2.8 +/* --- defines for sys/wait.h */ 2.9 +#if defined(KERNEL) || defined(KDEF_WAIT_H) 2.10 +#define WNOHANG 1 2.11 + 2.12 +#define WEXITSTATUS(s) ((s) & _WSTATUS_MASK) 2.13 +#define WCOREDUMP(s) ((s) & _WCORE_BIT) 2.14 + 2.15 +#define WIFEXITED(s) (_WREASON(s) == _WREASON_EXITED) 2.16 +#define WIFSIGNALED(s) (_WREASON(s) == _WREASON_SIGNALED) 2.17 + 2.18 +/* implementation details */ 2.19 +#define _WSTATUS_MASK 0xff 2.20 + 2.21 +#define _WREASON_SHIFT 8 2.22 +#define _WREASON_MASK 0xf00 2.23 +#define _WREASON(s) (((s) & _WREASON_MASK) >> _WREASON_SHIFT) 2.24 + 2.25 +#define _WREASON_EXITED 1 2.26 +#define _WREASON_SIGNALED 2 2.27 + 2.28 +#define _WCORE_BIT 0x1000 2.29 +#endif /* sys/wait.h */ 2.30 + 2.31 + 2.32 + 2.33 +/* --- defines for errno.h */ 2.34 +#if defined(KERNEL) || defined(KDEF_ERRNO_H) 2.35 +#define EAGAIN 1 2.36 +#define EINVAL 2 2.37 +#define ECHILD 3 2.38 +#endif /* errno.h */ 2.39 + 2.40 + 2.41 +/* --- defines for syscall.h */ 2.42 +#if defined(KERNEL) || defined(KDEF_SYSCALL_H) 2.43 + 2.44 +#define SYSCALL_INT 0x80 2.45 + 2.46 +#define SYS_HELLO 0 2.47 +#define SYS_SLEEP 1 2.48 +#define SYS_FORK 2 2.49 +#define SYS_EXIT 3 2.50 +#define SYS_WAITPID 4 2.51 +#define SYS_GETPID 5 2.52 +#define SYS_GETPPID 6 2.53 + 2.54 +#define NUM_SYSCALLS 7 2.55 + 2.56 +#endif /* syscall.h */ 2.57 + 2.58 +#endif /* KERNEL_DEFS_H_ */
3.1 --- a/src/klibc/errno.h Thu Oct 13 05:22:35 2011 +0300 3.2 +++ b/src/klibc/errno.h Sat Oct 15 07:45:56 2011 +0300 3.3 @@ -1,6 +1,9 @@ 3.4 #ifndef ERRNO_H_ 3.5 #define ERRNO_H_ 3.6 3.7 -#define EAGAIN 1 3.8 +/* all kernel-definitions that should be shared with user space 3.9 + * are in include/kdef.h 3.10 + */ 3.11 +#include "kdef.h" 3.12 3.13 #endif /* ERRNO_H_ */
4.1 --- a/src/proc.c Thu Oct 13 05:22:35 2011 +0300 4.2 +++ b/src/proc.c Sat Oct 15 07:45:56 2011 +0300 4.3 @@ -12,6 +12,7 @@ 4.4 #include "syscall.h" 4.5 #include "sched.h" 4.6 #include "tss.h" 4.7 +#include "kdef.h" 4.8 4.9 #define FLAGS_INTR_BIT (1 << 9) 4.10 4.11 @@ -138,7 +139,7 @@ 4.12 intr_ret(ifrm); 4.13 } 4.14 4.15 -int fork(void) 4.16 +int sys_fork(void) 4.17 { 4.18 int i, pid; 4.19 struct process *p, *parent; 4.20 @@ -189,8 +190,13 @@ 4.21 /* initialize the rest of the process structure */ 4.22 p->id = pid; 4.23 p->parent = parent->id; 4.24 + p->child_list = 0; 4.25 p->next = p->prev = 0; 4.26 4.27 + /* add to the child list */ 4.28 + p->sib_next = parent->child_list; 4.29 + parent->child_list = p; 4.30 + 4.31 /* will be copied on write */ 4.32 p->user_stack_pg = parent->user_stack_pg; 4.33 4.34 @@ -203,6 +209,105 @@ 4.35 return pid; 4.36 } 4.37 4.38 +int sys_exit(int status) 4.39 +{ 4.40 + struct process *p, *child; 4.41 + 4.42 + p = get_current_proc(); 4.43 + 4.44 + /* TODO deliver SIGCHLD to the parent */ 4.45 + 4.46 + /* find any child processes and make init adopt them */ 4.47 + child = p->child_list; 4.48 + while(child) { 4.49 + child->parent = 1; 4.50 + child = child->sib_next; 4.51 + } 4.52 + 4.53 + cleanup_vm(p); 4.54 + 4.55 + /* remove it from the runqueue */ 4.56 + remove_proc(p->id); 4.57 + 4.58 + /* make it a zombie until its parent reaps it */ 4.59 + p->state = STATE_ZOMBIE; 4.60 + p->exit_status = (status & _WSTATUS_MASK) | (_WREASON_EXITED << _WREASON_SHIFT); 4.61 + 4.62 + /* wakeup any processes waiting for it 4.63 + * we're waking up the parent's address, because waitpid waits 4.64 + * on it's own process struct, not knowing which child will die 4.65 + * first. 4.66 + */ 4.67 + wakeup(get_process(p->parent)); 4.68 + return 0; 4.69 +} 4.70 + 4.71 +int sys_waitpid(int pid, int *status, int opt) 4.72 +{ 4.73 + struct process *p, *child; 4.74 + 4.75 + p = get_current_proc(); 4.76 + 4.77 +restart: 4.78 + if(pid <= 0) { 4.79 + /* search for zombie children */ 4.80 + child = p->child_list; 4.81 + while(child) { 4.82 + if(child->state == STATE_ZOMBIE) { 4.83 + break; 4.84 + } 4.85 + child = child->sib_next; 4.86 + } 4.87 + } else { 4.88 + if(!(child = get_process(pid)) || child->parent != p->id) { 4.89 + return -ECHILD; 4.90 + } 4.91 + if(child->state != STATE_ZOMBIE) { 4.92 + child = 0; 4.93 + } 4.94 + } 4.95 + 4.96 + /* found ? */ 4.97 + if(child) { 4.98 + int res; 4.99 + struct process *prev, dummy; 4.100 + 4.101 + if(status) { 4.102 + *status = child->exit_status; 4.103 + } 4.104 + res = child->id; 4.105 + 4.106 + /* remove it from our children list */ 4.107 + dummy.sib_next = p->child_list; 4.108 + prev = &dummy; 4.109 + while(prev->next) { 4.110 + if(prev->next == child) { 4.111 + prev->next = child->next; 4.112 + break; 4.113 + } 4.114 + } 4.115 + p->child_list = dummy.next; 4.116 + 4.117 + /* invalidate the id */ 4.118 + child->id = 0; 4.119 + return res; 4.120 + } 4.121 + 4.122 + /* not found, wait or sod off */ 4.123 + if(!(opt & WNOHANG)) { 4.124 + /* wait on our own process struct because 4.125 + * we have no way of knowing which child will 4.126 + * die first. 4.127 + * exit will wakeup the parent structure... 4.128 + */ 4.129 + wait(p); 4.130 + /* done waiting, restart waitpid */ 4.131 + goto restart; 4.132 + } 4.133 + 4.134 + return 0; /* he's not dead jim */ 4.135 +} 4.136 + 4.137 void context_switch(int pid) 4.138 { 4.139 static struct process *prev, *new; 4.140 @@ -262,5 +367,25 @@ 4.141 4.142 struct process *get_process(int pid) 4.143 { 4.144 - return &proc[pid]; 4.145 + struct process *p = proc + pid; 4.146 + if(p->id != pid) { 4.147 + printf("get_process called with invalid pid: %d\n", pid); 4.148 + return 0; 4.149 + } 4.150 + return p; 4.151 } 4.152 + 4.153 +int sys_getpid(void) 4.154 +{ 4.155 + return cur_pid; 4.156 +} 4.157 + 4.158 +int sys_getppid(void) 4.159 +{ 4.160 + struct process *p = get_current_proc(); 4.161 + 4.162 + if(!p) { 4.163 + return 0; 4.164 + } 4.165 + return p->parent; 4.166 +}
5.1 --- a/src/proc.h Thu Oct 13 05:22:35 2011 +0300 5.2 +++ b/src/proc.h Sat Oct 15 07:45:56 2011 +0300 5.3 @@ -27,6 +27,8 @@ 5.4 int id, parent; 5.5 enum proc_state state; 5.6 5.7 + int exit_status; 5.8 + 5.9 /* when blocked it's waiting for a wakeup on this address */ 5.10 void *wait_addr; 5.11 5.12 @@ -44,12 +46,17 @@ 5.13 5.14 struct context ctx; 5.15 5.16 + struct process *child_list; 5.17 + 5.18 struct process *next, *prev; /* for the scheduler queues */ 5.19 + struct process *sib_next; /* for the sibling list */ 5.20 }; 5.21 5.22 void init_proc(void); 5.23 5.24 -int fork(void); 5.25 +int sys_fork(void); 5.26 +int sys_exit(int status); 5.27 +int sys_waitpid(int pid, int *status, int opt); 5.28 5.29 void context_switch(int pid); 5.30 5.31 @@ -58,6 +65,9 @@ 5.32 struct process *get_current_proc(void); 5.33 struct process *get_process(int pid); 5.34 5.35 +int sys_getpid(void); 5.36 +int sys_getppid(void); 5.37 + 5.38 /* defined in proc-asm.S */ 5.39 uint32_t get_instr_ptr(void); 5.40 uint32_t get_caller_instr_ptr(void);
6.1 --- a/src/sched.c Thu Oct 13 05:22:35 2011 +0300 6.2 +++ b/src/sched.c Sat Oct 15 07:45:56 2011 +0300 6.3 @@ -75,6 +75,20 @@ 6.4 set_intr_state(istate); 6.5 } 6.6 6.7 +void remove_proc(int pid) 6.8 +{ 6.9 + int istate; 6.10 + struct process *proc; 6.11 + 6.12 + istate = get_intr_state(); 6.13 + disable_intr(); 6.14 + 6.15 + proc = get_process(pid); 6.16 + remove(&runq, proc); 6.17 + 6.18 + set_intr_state(istate); 6.19 +} 6.20 + 6.21 /* block the process until we get a wakeup call for address ev */ 6.22 void wait(void *wait_addr) 6.23 {
7.1 --- a/src/sched.h Thu Oct 13 05:22:35 2011 +0300 7.2 +++ b/src/sched.h Sat Oct 15 07:45:56 2011 +0300 7.3 @@ -6,6 +6,7 @@ 7.4 void schedule(void); 7.5 7.6 void add_proc(int pid); 7.7 +void remove_proc(int pid); 7.8 7.9 void wait(void *wait_addr); 7.10 void wakeup(void *wait_addr);
8.1 --- a/src/syscall.c Thu Oct 13 05:22:35 2011 +0300 8.2 +++ b/src/syscall.c Sat Oct 15 07:45:56 2011 +0300 8.3 @@ -10,16 +10,16 @@ 8.4 static void syscall(int inum); 8.5 8.6 static int sys_hello(void); 8.7 -static int sys_sleep(int sec); 8.8 -static int sys_fork(void); 8.9 -static int sys_getpid(void); 8.10 8.11 void init_syscall(void) 8.12 { 8.13 sys_func[SYS_HELLO] = sys_hello; 8.14 - sys_func[SYS_SLEEP] = sys_sleep; 8.15 - sys_func[SYS_FORK] = sys_fork; 8.16 - sys_func[SYS_GETPID] = sys_getpid; 8.17 + sys_func[SYS_SLEEP] = sys_sleep; /* timer.c */ 8.18 + sys_func[SYS_FORK] = sys_fork; /* proc.c */ 8.19 + sys_func[SYS_EXIT] = sys_exit; /* proc.c */ 8.20 + sys_func[SYS_WAITPID] = sys_waitpid; /* proc.c */ 8.21 + sys_func[SYS_GETPID] = sys_getpid; /* proc.c */ 8.22 + sys_func[SYS_GETPPID] = sys_getppid; /* proc.c */ 8.23 8.24 interrupt(SYSCALL_INT, syscall); 8.25 } 8.26 @@ -41,6 +41,12 @@ 8.27 * so that it'll be restored into eax before returning to userland. 8.28 */ 8.29 frm->regs.eax = sys_func[idx](frm->regs.ebx, frm->regs.ecx, frm->regs.edx, frm->regs.esi, frm->regs.edi); 8.30 + 8.31 + /* we don't necessarily want to return to the same process 8.32 + * might have blocked or exited or whatever, so call schedule 8.33 + * to decide what's going to run next. 8.34 + */ 8.35 + schedule(); 8.36 } 8.37 8.38 static int sys_hello(void) 8.39 @@ -48,23 +54,3 @@ 8.40 printf("process %d says hello!\n", get_current_pid()); 8.41 return 0; 8.42 } 8.43 - 8.44 -static int sys_sleep(int sec) 8.45 -{ 8.46 - printf("process %d will sleep for %d seconds\n", get_current_pid(), sec); 8.47 - sleep(sec * 1000); /* timer.c */ 8.48 - return 0; 8.49 -} 8.50 - 8.51 -static int sys_fork(void) 8.52 -{ 8.53 - printf("process %d is forking\n", get_current_pid()); 8.54 - return fork(); /* proc.c */ 8.55 -} 8.56 - 8.57 -static int sys_getpid(void) 8.58 -{ 8.59 - int pid = get_current_pid(); 8.60 - printf("process %d getpid\n", pid); 8.61 - return pid; 8.62 -}
9.1 --- a/src/syscall.h Thu Oct 13 05:22:35 2011 +0300 9.2 +++ b/src/syscall.h Sat Oct 15 07:45:56 2011 +0300 9.3 @@ -1,15 +1,8 @@ 9.4 #ifndef SYSCALL_H_ 9.5 #define SYSCALL_H_ 9.6 9.7 -#define SYSCALL_INT 0x80 9.8 - 9.9 -/* when we get rid of test_proc.S we'll turn this into an enum */ 9.10 -#define SYS_HELLO 0 9.11 -#define SYS_SLEEP 1 9.12 -#define SYS_FORK 2 9.13 -#define SYS_GETPID 3 9.14 - 9.15 -#define NUM_SYSCALLS 4 9.16 +#define KDEF_SYSCALL_H 9.17 +#include "kdef.h" 9.18 9.19 #ifndef ASM 9.20 void init_syscall(void);
10.1 --- a/src/timer.c Thu Oct 13 05:22:35 2011 +0300 10.2 +++ b/src/timer.c Sat Oct 15 07:45:56 2011 +0300 10.3 @@ -75,13 +75,20 @@ 10.4 interrupt(IRQ_TO_INTR(0), timer_handler); 10.5 } 10.6 10.7 +int sys_sleep(int sec) 10.8 +{ 10.9 + printf("process %d will sleep for %d seconds\n", get_current_pid(), sec); 10.10 + sleep(sec * 1000); /* timer.c */ 10.11 + 10.12 + /* TODO if interrupted, return the remaining seconds */ 10.13 + return 0; 10.14 +} 10.15 + 10.16 void sleep(unsigned long msec) 10.17 { 10.18 int ticks, tsum, istate; 10.19 struct timer_event *ev, *node; 10.20 10.21 - printf("sleep(%lu)\n", msec); 10.22 - 10.23 if((ticks = MSEC_TO_TICKS(msec)) <= 0) { 10.24 return; 10.25 }
11.1 --- a/src/timer.h Thu Oct 13 05:22:35 2011 +0300 11.2 +++ b/src/timer.h Sat Oct 15 07:45:56 2011 +0300 11.3 @@ -5,6 +5,7 @@ 11.4 11.5 void init_timer(void); 11.6 11.7 +int sys_sleep(int sec); 11.8 void sleep(unsigned long msec); 11.9 11.10 #endif /* _TIMER_H_ */
12.1 --- a/src/vm.c Thu Oct 13 05:22:35 2011 +0300 12.2 +++ b/src/vm.c Sat Oct 15 07:45:56 2011 +0300 12.3 @@ -803,6 +803,28 @@ 12.4 pdest->ctx.pgtbl_paddr = paddr; 12.5 } 12.6 12.7 +/* cleanup_vm called by exit to clean up any memory used by the process */ 12.8 +void cleanup_vm(struct process *p) 12.9 +{ 12.10 + struct rbnode *vmnode; 12.11 + 12.12 + /* go through the vm map and reduce refcounts all around 12.13 + * when a ref goes to 0, free the physical page 12.14 + */ 12.15 + rb_begin(&p->vmmap); 12.16 + while((vmnode = rb_next(&p->vmmap))) { 12.17 + struct vm_page *page = vmnode->data; 12.18 + if(--page->nref <= 0) { 12.19 + /* free the physical page if nref goes to 0 */ 12.20 + free_phys_page(PAGE_TO_ADDR(page->ppage)); 12.21 + } 12.22 + } 12.23 + 12.24 + /* destroying the tree will free the nodes */ 12.25 + rb_destroy(&p->vmmap); 12.26 +} 12.27 + 12.28 + 12.29 int get_page_bit(int pgnum, uint32_t bit, int wholepath) 12.30 { 12.31 int tidx = PAGE_TO_PGTBL(pgnum);
13.1 --- a/src/vm.h Thu Oct 13 05:22:35 2011 +0300 13.2 +++ b/src/vm.h Sat Oct 15 07:45:56 2011 +0300 13.3 @@ -78,7 +78,11 @@ 13.4 int pgalloc_vrange(int start, int num); 13.5 void pgfree(int start, int num); 13.6 13.7 +/* don't be fooled by the fact these two accept process arguments 13.8 + * they in fact work only for the "current" process (psrc and p) 13.9 + */ 13.10 void clone_vm(struct process *pdest, struct process *psrc, int cow); 13.11 +void cleanup_vm(struct process *p); 13.12 13.13 int get_page_bit(int pgnum, uint32_t bit, int wholepath); 13.14 void set_page_bit(int pgnum, uint32_t bit, int wholepath);