From 08d202b4817cd0cd7e03677a04791730e02773ee Mon Sep 17 00:00:00 2001 From: hinus Date: Thu, 12 Aug 2021 08:16:24 +0800 Subject: [PATCH] Title: System call 'waitpid' Issue: https://gitee.com/hinus/linux_kernel_011/issues/I450PK Description: System call 'waitpid' --- include/linux/sys.h | 4 +-- include/sys/wait.h | 18 ++++++++++ kernel/exit.c | 88 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 107 insertions(+), 3 deletions(-) diff --git a/include/linux/sys.h b/include/linux/sys.h index baad2a4..2f292bf 100644 --- a/include/linux/sys.h +++ b/include/linux/sys.h @@ -5,7 +5,7 @@ extern int sys_read(); extern int sys_write(); extern int sys_open(); extern int sys_close(); -//extern int sys_waitpid(); +extern int sys_waitpid(); //extern int sys_creat(); //extern int sys_link(); //extern int sys_unlink(); @@ -94,7 +94,7 @@ fn_ptr sys_call_table[] = { sys_write, sys_open, sys_close, - 0, //sys_waitpid, + sys_waitpid, 0, //sys_creat, 0, //sys_link, diff --git a/include/sys/wait.h b/include/sys/wait.h index e34e095..d6c3360 100644 --- a/include/sys/wait.h +++ b/include/sys/wait.h @@ -1,6 +1,24 @@ #ifndef _SYS_WAIT_H #define _SYS_WAIT_H +#include +#define _LOW(v) ( (v) & 0377) +#define _HIGH(v) ( ((v) >> 8) & 0377) + +/* options for waitpid, WUNTRACED not supported */ +#define WNOHANG 1 +#define WUNTRACED 2 + +#define WIFEXITED(s) (!((s)&0xFF)) +#define WIFSTOPPED(s) (((s)&0xFF)==0x7F) +#define WEXITSTATUS(s) (((s)>>8)&0xFF) +#define WTERMSIG(s) ((s)&0x7F) +#define WCOREDUMP(s) ((s)&0x80) +#define WSTOPSIG(s) (((s)>>8)&0xFF) +#define WIFSIGNALED(s) (((unsigned int)(s)-1 & 0xFFFF) < 0xFF) + +pid_t wait(int *stat_loc); +pid_t waitpid(pid_t pid, int *stat_loc, int options); #endif diff --git a/kernel/exit.c b/kernel/exit.c index 0364109..8b36d3e 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -12,6 +12,32 @@ extern int sys_pause(); extern int sys_close(int fd); +void release(struct task_struct * p) { + int i; + + if (!p) + return; + if (p == current) { + printk("task releasing itself\n\r"); + return; + } + for (i=1 ; ip_osptr) + p->p_osptr->p_ysptr = p->p_ysptr; + if (p->p_ysptr) + p->p_ysptr->p_osptr = p->p_osptr; + else + p->p_pptr->p_cptr = p->p_osptr; + free_page((long)p); + schedule(); + return; + } + } + panic("trying to release non-existent task"); +} + static inline int send_sig(long sig,struct task_struct * p,int priv) { if (!p) return -EINVAL; @@ -114,7 +140,7 @@ void do_exit(long code) { current->p_pptr->signal |= (1<<(SIGCHLD-1)); - if (p = current->p_cptr) { + if ((p = current->p_cptr)) { while (1) { p->p_pptr = task[1]; if (p->state == TASK_ZOMBIE) @@ -165,3 +191,63 @@ int sys_exit(int error_code) { return 0; } +int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options) { + int flag; + struct task_struct *p; + unsigned long oldblocked; + + verify_area(stat_addr,4); +repeat: + flag=0; + for (p = current->p_cptr ; p ; p = p->p_osptr) { + if (pid>0) { + if (p->pid != pid) + continue; + } + else if (!pid) { + if (p->pgrp != current->pgrp) + continue; + } + else if (pid != -1) { + if (p->pgrp != -pid) + continue; + } + + switch (p->state) { + case TASK_STOPPED: + if (!(options & WUNTRACED) || + !p->exit_code) + continue; + put_fs_long((p->exit_code << 8) | 0x7f, stat_addr); + p->exit_code = 0; + return p->pid; + case TASK_ZOMBIE: + current->cutime += p->utime; + current->cstime += p->stime; + flag = p->pid; + put_fs_long(p->exit_code, stat_addr); + release(p); + return flag; + default: + flag=1; + continue; + } + } + + if (flag) { + if (options & WNOHANG) + return 0; + current->state=TASK_INTERRUPTIBLE; + oldblocked = current->blocked; + current->blocked &= ~(1<<(SIGCHLD-1)); + schedule(); + current->blocked = oldblocked; + if (current->signal & ~(current->blocked | (1<<(SIGCHLD-1)))) + return -ERESTARTSYS; + else + goto repeat; + } + + return -ECHILD; +} + -- Gitee