From 5755206f9f632aa8d5794d44de7e5ec675eeddd1 Mon Sep 17 00:00:00 2001 From: TianhuaTao <taotianhua@outlook.com> Date: Sat, 10 Apr 2021 21:25:15 +0800 Subject: [PATCH] add lab6-smp --- os/console.c | 6 +- os/defs.h | 16 ++- os/file.c | 53 ++++++++++ os/file.h | 42 ++++++++ os/kalloc.c | 3 +- os/loader.c | 2 +- os/log.h | 12 +-- os/main.c | 7 ++ os/pipe.c | 113 ++++++++++++++++++++ os/proc.c | 62 +++++++++-- os/proc.h | 6 +- os/syscall.c | 239 ++++++++++++++++++++++++++++++++++++++---- os/syscall_ids.h | 2 + os/timer.c | 2 +- os/vm.c | 22 ++-- user/include/unistd.h | 5 +- user/lib/stdio.c | 5 +- user/lib/syscall.c | 8 +- user/src/pipetest.c | 43 ++++++++ user/src/user_shell.c | 3 + 20 files changed, 594 insertions(+), 57 deletions(-) create mode 100644 os/file.c create mode 100644 os/file.h create mode 100644 os/pipe.c create mode 100644 user/src/pipetest.c diff --git a/os/console.c b/os/console.c index 83d96dc..1989295 100644 --- a/os/console.c +++ b/os/console.c @@ -2,4 +2,8 @@ void consputc(int c) { console_putchar(c); -} \ No newline at end of file +} + +char consgetc() { + return console_getchar(); +} diff --git a/os/defs.h b/os/defs.h index 76bcd24..66ab11e 100644 --- a/os/defs.h +++ b/os/defs.h @@ -4,6 +4,8 @@ #include "types.h" struct context; struct proc; +struct file; +struct pipe; // panic.c void loop(); @@ -16,7 +18,7 @@ void shutdown(); void set_timer(uint64 stime); // console.c - +void consoleinit(void); void consputc(int); // printf.c @@ -65,6 +67,7 @@ int exec(char*); int wait(int, int*); struct proc* allocproc(); void init_scheduler(); +int fdalloc(struct file *); // kalloc.c @@ -93,12 +96,23 @@ int map1page(pagetable_t pagetable, uint64 va, uint64 pa, int perm); pte_t *walk(pagetable_t pagetable, uint64 va, int alloc); void kvminithart(); +void debugwalk(pagetable_t, int); + // timer.c uint64 get_cycle(); void timerinit(); void set_next_timer(); uint64 get_time_ms(); +// pipe.c +int pipealloc(struct file *, struct file *); +void pipeclose(struct pipe *, int); +int piperead(struct pipe *, uint64, int); +int pipewrite(struct pipe *, uint64, int); + +// file.c +void fileclose(struct file *); +struct file* filealloc(); // number of elements in fixed-size array #define NELEM(x) (sizeof(x) / sizeof((x)[0])) diff --git a/os/file.c b/os/file.c new file mode 100644 index 0000000..48b7c9c --- /dev/null +++ b/os/file.c @@ -0,0 +1,53 @@ +#include "types.h" +#include "file.h" +#include "proc.h" +#include "defs.h" + +#define FILE_MAX (128*16) +struct file filepool[FILE_MAX]; + +void +fileclose(struct file *f) +{ + if(f->ref < 1) + panic("fileclose"); + if(--f->ref > 0) { + return; + } + + if(f->type == FD_PIPE){ + pipeclose(f->pipe, f->writable); + } + f->off = 0; + f->readable = 0; + f->writable = 0; + f->ref = 0; + f->type = FD_NONE; +} + +struct file* filealloc() { + for(int i = 0; i < FILE_MAX; ++i) { + if(filepool[i].ref == 0) { + filepool[i].ref = 1; + return &filepool[i]; + } + } + return 0; +} + +int init_mailbox(struct mailbox* mb){ + void* buf_pa = kalloc(); + if(buf_pa == 0 ){ + return 0; + } + init_spin_lock(&mb->lock); + mb->mailbuf =buf_pa; + for (int i = 0; i < MAX_MAIL_IN_BOX; i++) + { + mb->length[i] = 0; + mb->valid[i] = 0; + } + mb->head = 0; + return 1; +} + diff --git a/os/file.h b/os/file.h new file mode 100644 index 0000000..dd7fad9 --- /dev/null +++ b/os/file.h @@ -0,0 +1,42 @@ +#ifndef __FILE_H__ +#define __FILE_H__ + +#include "types.h" +#include "lock.h" +// pipe.h +#define PIPESIZE 512 + +struct pipe { + char data[PIPESIZE]; + uint nread; // number of bytes read + uint nwrite; // number of bytes written + int readopen; // read fd is still open + int writeopen; // write fd is still open + struct spinlock lock; +}; + +// file.h +struct file { + enum { FD_NONE = 0, FD_PIPE} type; + int ref; // reference count + char readable; + char writable; + struct pipe *pipe; // FD_PIPE + uint off; // FD_INODE +}; + +typedef char mail_t[256]; +# define MAX_MAIL_IN_BOX (16) +struct mailbox{ + mail_t* mailbuf; // 4KB, 16 mail + int valid[MAX_MAIL_IN_BOX]; + int length[MAX_MAIL_IN_BOX]; + int head; + struct spinlock lock; +}; + +int init_mailbox(struct mailbox* mb); + +extern struct file filepool[128 * 16]; + +#endif //!__FILE_H__ \ No newline at end of file diff --git a/os/kalloc.c b/os/kalloc.c index fd3e09b..d97560c 100644 --- a/os/kalloc.c +++ b/os/kalloc.c @@ -68,8 +68,9 @@ kalloc(void) if (l) { kmem.freelist = l->next; - memset((char *)l, 5, PGSIZE); // fill with junk } release(&kmem.lock); + if(l) + memset((char *)l, 5, PGSIZE); // fill with junk return (void *)l; } \ No newline at end of file diff --git a/os/loader.c b/os/loader.c index fb9cf2b..9af4b6f 100644 --- a/os/loader.c +++ b/os/loader.c @@ -7,7 +7,7 @@ static int app_cur, app_num; static uint64 *app_info_ptr; extern char _app_num[], _app_names[]; const uint64 BASE_ADDRESS = 0x1000; // user text start -char names[20][100]; +char names[40][100]; void batchinit() { diff --git a/os/log.h b/os/log.h index 9045dc5..1c8bf12 100644 --- a/os/log.h +++ b/os/log.h @@ -58,23 +58,23 @@ enum LOG_COLOR #if defined(USE_LOG_WARN) -#define warnf(fmt, ...) printf("\x1b[%dm[%s] " fmt "\x1b[0m\n", YELLOW, "WARN", ##__VA_ARGS__); +#define warnf(fmt, ...) printf("\x1b[%dm[%s] " fmt "\x1b[0m\n", YELLOW, "WARN", ##__VA_ARGS__) #else #define warnf(fmt, ...) #endif // #if defined(USE_LOG_ERROR) -#define errorf(fmt, ...) printf("\x1b[%dm[%s] " fmt "\x1b[0m\n", RED, "ERROR", ##__VA_ARGS__); +#define errorf(fmt, ...) printf("\x1b[%dm[%s] " fmt "\x1b[0m\n", RED, "ERROR", ##__VA_ARGS__) #else #define errorf(fmt, ...) #endif // #if defined(USE_LOG_DEBUG) -#define debugf(fmt, ...) printf("\x1b[%dm[%s] " fmt "\x1b[0m\n", GREEN, "DEBUG", ##__VA_ARGS__); +#define debugf(fmt, ...) printf("\x1b[%dm[%s] " fmt "\x1b[0m\n", GREEN, "DEBUG", ##__VA_ARGS__) -#define debugcore(fmt, ...) printf("\x1b[%dm[%s %d] " fmt "\x1b[0m\n", GREEN, "DEBUG", cpuid(), ##__VA_ARGS__); +#define debugcore(fmt, ...) printf("\x1b[%dm[%s %d] " fmt "\x1b[0m\n", GREEN, "DEBUG", cpuid(), ##__VA_ARGS__) #define phex(var_name) debugf(#var_name "=%p", var_name) #else @@ -84,14 +84,14 @@ enum LOG_COLOR #if defined(USE_LOG_TRACE) -#define tracef(fmt, ...) printf("\x1b[%dm[%s] " fmt "\x1b[0m\n", GRAY, "TRACE", ##__VA_ARGS__); +#define tracef(fmt, ...) printf("\x1b[%dm[%s] " fmt "\x1b[0m\n", GRAY, "TRACE", ##__VA_ARGS__) #else #define tracef(fmt, ...) #endif // #if defined(USE_LOG_INFO) -#define infof(fmt, ...) printf("\x1b[%dm[%s] " fmt "\x1b[0m\n", BLUE, "INFO", ##__VA_ARGS__); +#define infof(fmt, ...) printf("\x1b[%dm[%s] " fmt "\x1b[0m\n", BLUE, "INFO", ##__VA_ARGS__) #else #define infof(fmt, ...) #endif // diff --git a/os/main.c b/os/main.c index 69830e6..f09f004 100644 --- a/os/main.c +++ b/os/main.c @@ -19,6 +19,7 @@ void clean_bss() } volatile static int first_hart = 1; +volatile static int all_started = 0; void start_hart(uint64 hartid, uint64 start_addr, uint64 a1); void hart_bootcamp(uint64 hartid, uint64 a1) { @@ -39,6 +40,7 @@ void wait_all_boot() while (!booted[i]) ; } + all_started = 1; } void init_booted() { @@ -103,6 +105,11 @@ void main(uint64 hartid, uint64 a1) { hart_bootcamp(hartid, a1); } + while (!all_started) + { + ; // wait until all hard started + } + tracef("start scheduler!"); scheduler(); debugf("core %d halt", cpuid()); diff --git a/os/pipe.c b/os/pipe.c new file mode 100644 index 0000000..10a9aad --- /dev/null +++ b/os/pipe.c @@ -0,0 +1,113 @@ +#include "riscv.h" +#include "defs.h" +#include "proc.h" +#include "file.h" + +int +pipealloc(struct file *f0, struct file *f1) +{ + struct pipe *pi; + pi = 0; + if((pi = (struct pipe*)kalloc()) == 0) + goto bad; + pi->readopen = 1; + pi->writeopen = 1; + pi->nwrite = 0; + pi->nread = 0; + init_spin_lock(&pi->lock); + f0->type = FD_PIPE; + f0->readable = 1; + f0->writable = 0; + f0->pipe = pi; + f1->type = FD_PIPE; + f1->readable = 0; + f1->writable = 1; + f1->pipe = pi; + return 0; +bad: + if(pi) + kfree((char*)pi); + return -1; +} + +void +pipeclose(struct pipe *pi, int writable) +{ + acquire(&pi->lock); + if(writable){ + pi->writeopen = 0; + } else { + pi->readopen = 0; + } + if(pi->readopen == 0 && pi->writeopen == 0){ + release(&pi->lock); + kfree((char*)pi); + }else + release(&pi->lock); +} + +int +pipewrite(struct pipe *pi, uint64 addr, int n) +{ + int w = 0; + uint64 size; + struct proc *p = curr_proc(); + if(n <= 0) { + panic("invalid read num"); + } + acquire(&pi->lock); + while(w < n){ + if(pi->readopen == 0){ + return -1; + } + if(pi->nwrite == pi->nread + PIPESIZE){ //DOC: pipewrite-full + release(&pi->lock); + yield(); + acquire(&pi->lock); + } else { + size = MIN(MIN(n - w, pi->nread + PIPESIZE - pi->nwrite), PIPESIZE - (pi->nwrite % PIPESIZE)); + if(copyin(p->pagetable, &pi->data[pi->nwrite % PIPESIZE], addr + w, size) < 0) { + panic("copyin"); + } + pi->nwrite += size; + w += size; + } + } + release(&pi->lock); + + return w; +} + +int +piperead(struct pipe *pi, uint64 addr, int n) +{ + int r = 0; + uint64 size = -1; + struct proc *p = curr_proc(); + if(n <= 0) { + panic("invalid read num"); + } + acquire(&pi->lock); + while(pi->nread == pi->nwrite) { + if(pi->writeopen) + { + release(&pi->lock); + yield(); + acquire(&pi->lock); + } + else + return -1; + } + while(r < n && size != 0) { //DOC: piperead-copy + if(pi->nread == pi->nwrite) + break; + size = MIN(MIN(n - r, pi->nwrite - pi->nread), PIPESIZE - (pi->nread % PIPESIZE)); + if(copyout(p->pagetable, addr + r, &pi->data[pi->nread % PIPESIZE], size) < 0) { + panic("copyout"); + } + pi->nread += size; + r += size; + } + release(&pi->lock); + return r; +} diff --git a/os/proc.c b/os/proc.c index 4fca0ba..ebfa68f 100644 --- a/os/proc.c +++ b/os/proc.c @@ -4,6 +4,7 @@ #include "timer.h" #include "log.h" #include "riscv.h" +#include "file.h" #include "memory_layout.h" struct proc pool[NPROC]; @@ -21,6 +22,20 @@ struct proc *curr_proc() } // struct proc idle[NCPU]; +struct proc* findproc(int pid) +{ + struct proc *p = NULL; + acquire(&pool_lock); + for(p = pool; p < &pool[NPROC]; p++) { + if(p->state != UNUSED && p->pid == pid) { + break; + } + } + release(&pool_lock); + return p; +} + + void procinit(void) { struct proc *p; @@ -41,6 +56,7 @@ void procinit(void) int allocpid() { + // TODO: add lock static int PID = 1; return PID++; } @@ -93,6 +109,12 @@ freeproc(struct proc *p) proc_freepagetable(p->pagetable, p->sz); p->pagetable = 0; p->state = UNUSED; + for(int i = 0; i < FD_MAX; ++i) { + if(p->files[i] != 0) { + fileclose(p->files[i]); + p->files[i] = 0; + } + } } @@ -127,7 +149,7 @@ found: } memset(&p->context, 0, sizeof(p->context)); memset((void *)p->kstack, 0, KSTACK_SIZE); - debugf("memset done"); + // debugf("memset done"); p->context.ra = (uint64)usertrapret; // used in swtch() p->context.sp = p->kstack + KSTACK_SIZE; @@ -136,7 +158,10 @@ found: p->priority = 16; p->cpu_time = 0; p->last_start_time = 0; - debugf("before return"); + if(init_mailbox(&p->mb)==0){ + panic("init mailbox failed"); + } + // debugf("before return"); return p; } // Return this CPU's cpu struct. @@ -234,7 +259,7 @@ void scheduler(void) } else { - debugcore("no proc to run"); + // debugcore("no proc to run"); // break; } } @@ -263,7 +288,7 @@ void sched(void) // p->state = UNUSED; // // exit(-1); // } - infof("before swtch"); + // infof("before swtch"); swtch(&p->context, &mycpu()->context); } @@ -279,16 +304,17 @@ fork(void) int pid; struct proc *np; struct proc *p = curr_proc(); - debugf("inside fork"); + // debugf("inside fork"); // Allocate process. if((np = allocproc()) == 0){ panic("allocproc\n"); } - debugf("inside fork allocproc done"); + // debugf("inside fork allocproc done"); // Copy user memory from parent to child. if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){ + release(&np->lock); panic("uvmcopy\n"); } np->sz = p->sz; @@ -296,6 +322,11 @@ fork(void) // copy saved user registers. *(np->trapframe) = *(p->trapframe); + for(int i = 0; i < FD_MAX; ++i) + if(p->files[i] != 0 && p->files[i]->type != FD_NONE) { + p->files[i]->ref++; + np->files[i] = p->files[i]; + } // Cause fork to return 0 in the child. np->trapframe->a0 = 0; pid = np->pid; @@ -303,6 +334,8 @@ fork(void) np->parent = p; + + np->state = RUNNABLE; release(&np->lock); return pid; @@ -367,6 +400,7 @@ int spawn(char* filename){ } // info("load\n"); loader(id, np); + release(&np->lock); return pid; } @@ -398,7 +432,7 @@ wait(int pid, int* code) return -1; } - debugf("pid %d keep waiting", p->pid); + // debugf("pid %d keep waiting", p->pid); p->state = RUNNABLE; sched(); } @@ -415,4 +449,16 @@ void exit(int code) { } debugf("before sched"); sched(); -} \ No newline at end of file +} + +int fdalloc(struct file* f) { + struct proc* p = curr_proc(); + // fd = 0 is reserved for stdio/stdout + for(int i = 1; i < FD_MAX; ++i) { + if(p->files[i] == 0) { + p->files[i] = f; + return i; + } + } + return -1; +} diff --git a/os/proc.h b/os/proc.h index 61ac685..3da3081 100644 --- a/os/proc.h +++ b/os/proc.h @@ -4,11 +4,12 @@ #include "ucore.h" #include "lock.h" - +#include "file.h" #define NPROC (256) #define KSTACK_SIZE (4096) #define USTACK_SIZE (4096) #define TRAPFRAME_SIZE (4096) +#define FD_MAX (16) enum procstate { UNUSED, @@ -43,7 +44,10 @@ struct proc uint64 priority; uint64 cpu_time; // ms, user and kernel uint64 last_start_time; // ms + struct file* files[16]; + struct mailbox mb; }; +struct proc* findproc(int pid); struct proc *curr_proc(); int spawn(char* filename); diff --git a/os/syscall.c b/os/syscall.c index 1122410..8016814 100644 --- a/os/syscall.c +++ b/os/syscall.c @@ -5,34 +5,20 @@ #include "log.h" #include "timer.h" #include "riscv.h" +#include "file.h" #define min(a, b) a < b ? a : b; -/** - * return TRUE if [sout, eout) contains [sin, ein) - */ -inline int contains(char *sout, char *eout, char *sin, char *ein) -{ - return (sout <= sin && sin < eout) && (sout <= ein && ein <= eout) && sin <= ein; -} - -uint64 sys_write(int fd, uint64 va, uint len) -{ - if (fd != 1) - return -1; +uint64 console_write(uint64 va, uint64 len) { struct proc *p = curr_proc(); char str[200]; int size = copyinstr(p->pagetable, str, va, MIN(len, 200)); - // debug("size = %d\n", size); for(int i = 0; i < size; ++i) { console_putchar(str[i]); } return size; } -uint64 sys_read(int fd, uint64 va, uint64 len) { - if (fd != 0) - return -1; - // read from stdin is blocking +uint64 console_read(uint64 va, uint64 len) { struct proc *p = curr_proc(); char str[200]; for(int i = 0; i < len; ++i) { @@ -47,6 +33,84 @@ uint64 sys_read(int fd, uint64 va, uint64 len) { return len; } +/** + * return TRUE if [sout, eout) contains [sin, ein) + */ +inline int contains(char *sout, char *eout, char *sin, char *ein) +{ + return (sout <= sin && sin < eout) && (sout <= ein && ein <= eout) && sin <= ein; +} + +uint64 sys_write(int fd, uint64 va, uint64 len) { + if(fd == 1) { + return console_write(va, len); + } + if(fd>=FD_MAX){ + return -1; + } + infof("fd=%d\n", fd); + struct proc *p = curr_proc(); + struct file *f = p->files[fd]; + if(f==0){ + return -1; + } + if(f->type == FD_PIPE) { + debugf("write to pipe at %p\n", f->pipe); + return pipewrite(f->pipe, va, len); + } + errorf("unknown file type %d\n", f->type); + panic("syswrite: unknown file type\n"); + return -1; +} + +uint64 sys_read(int fd, uint64 va, uint64 len) { + if(fd == 0) { + return console_read(va, len); + } + if(fd>=FD_MAX){ + return -1; + } + struct proc *p = curr_proc(); + struct file *f = p->files[fd]; + if(f==0){ + return -1; + } + if(f->type == FD_PIPE) { + debugf("read to pipe at %p\n", f->pipe); + return piperead(f->pipe, va, len); + } + errorf("unknown file type %d\n", f->type); + panic("sysread: unknown file type\n"); + return -1; +} + +uint64 +sys_pipe(uint64 fdarray) { + infof("init pipe\n"); + struct proc *p = curr_proc(); + uint64 fd0, fd1; + struct file* f0, *f1; + if(f0 < 0 || f1 < 0) { + return -1; + } + f0 = filealloc(); + f1 = filealloc(); + if(pipealloc(f0, f1) < 0) + return -1; + fd0 = fdalloc(f0); + fd1 = fdalloc(f1); + if(copyout(p->pagetable, fdarray, (char*)&fd0, sizeof(fd0)) < 0 || + copyout(p->pagetable, fdarray+sizeof(uint64), (char *)&fd1, sizeof(fd1)) < 0){ + fileclose(f0); + fileclose(f1); + p->files[fd0] = 0; + p->files[fd1] = 0; + return -1; + } + return 0; +} + + uint64 sys_exit(int code) { @@ -108,7 +172,19 @@ int64 sys_gettimeofday(uint64 *timeval, int tz){ return 0; } - +uint64 sys_close(int fd) { + if(fd == 0) + return 0; + struct proc *p = curr_proc(); + struct file *f = p->files[fd]; + if(f->type != FD_PIPE) { + errorf("unknown file type %d\n", f->type); + panic("fileclose: unknown file type\n"); + } + fileclose(f); + p->files[fd] = 0; + return 0; +} int64 sys_mmap(void* start, uint64 len, int prot){ if(len ==0) return 0; @@ -191,13 +267,124 @@ int64 sys_munmap(void* start, uint64 len){ int sys_spawn(char* filename){ return spawn(filename); } +int sys_mailread(void* buf, int len){ + infof("mailread\n"); + if(len>256){ + len = 256; + } + if(len<0){ + return -1; + } + struct proc* p = curr_proc(); + + struct mailbox *inbox = &(p->mb); + + acquire(&inbox->lock); + if(len == 0){ + for (int i = 0; i < MAX_MAIL_IN_BOX; i++) + { + if(inbox->valid[i]){ + release(&inbox->lock); + return 0; + } + } + release(&inbox->lock); + return -1; + } + + + // read head mail + int head_idx = inbox->head; + if (inbox->valid[head_idx]){ + int msg_len = inbox->length[head_idx]; + int copy_len = min(msg_len, len); + int eret = copyout(p->pagetable, (uint64)buf, inbox->mailbuf[head_idx], copy_len); + if (eret <0){ + infof("copyout failed\n"); + release(&inbox->lock); + return -1; + } + inbox->valid[inbox->head] = 0; + inbox->head+=1; + inbox->head = (inbox->head) % MAX_MAIL_IN_BOX; + release(&inbox->lock) + infof("read mail %d bytes\n", copy_len); + return copy_len; + }else{ + // mail box is empty + release(&inbox->lock); + infof("mail box is empty\n"); + return -1; + } + + +} + +int sys_mailwrite(int pid, void*buf, int len){ + infof("mailwrite\n"); + if(len>256){ + len = 256; + } + if(len<0){ + return -1; + } + struct proc* cur_p = curr_proc(); + + struct proc* p = findproc(pid); + if( p == 0 ){return -1;} + struct mailbox *dest = &(p->mb); + + acquire(&dest->lock); + + if (len == 0 ){ + for (int i = 0; i < MAX_MAIL_IN_BOX; i++) + { + if(!(dest->valid[i])){ + // empty slot + release(&dest->lock); + return 0; + } + } + release(&dest->lock); + return -1; + } + + + // write mail + int head_idx = dest->head; + for (int j = 0; j < MAX_MAIL_IN_BOX; j++) + { + if (dest->valid[j] != 0){ + // not empty, find next + }else{ + // empty, write to this one + int eret = copyin(cur_p->pagetable, dest->mailbuf[j], (uint64)buf, len); + if(eret <0){ + infof("copyin failed\n"); + release(&dest->lock); + return -1; + } + dest->valid[j] = 1; + dest->length[j]=len; + release(&dest->lock); + return len; + } + head_idx+=1; + head_idx = head_idx % MAX_MAIL_IN_BOX; + } + + // all filled + release(&dest->lock); + return -1; + +} void syscall() { struct proc *p = curr_proc(); struct trapframe *trapframe = p->trapframe; int id = trapframe->a7, ret; uint64 args[7] = {trapframe->a0, trapframe->a1, trapframe->a2, trapframe->a3, trapframe->a4, trapframe->a5, trapframe->a6}; - if (id != SYS_write){ + if (id != SYS_write && id != SYS_read){ debugf("syscall %d args:%p %p %p %p %p %p %p\n", id, args[0], args[1], args[2], args[3], args[4], args[5], args[6]);} switch (id) { case SYS_write: @@ -247,10 +434,22 @@ void syscall() { case SYS_spawn: ret = sys_spawn((char*)args[0]); break; + case SYS_pipe2: + ret = sys_pipe(args[0]); + break; + case SYS_close: + ret = sys_close(args[0]); + break; + case SYS_mailread: + ret = sys_mailread((void*)args[0], args[1]); + break; + case SYS_mailwrite: + ret = sys_mailwrite(args[0], (void*)args[1], args[2]); + break; default: ret = -1; warnf("unknown syscall %d\n", id); } trapframe->a0 = ret; - if (id != SYS_write){debugf("syscall ret %d\n", ret);} + if (id != SYS_write && id != SYS_read){debugf("syscall ret %d\n", ret);} } \ No newline at end of file diff --git a/os/syscall_ids.h b/os/syscall_ids.h index 5fdca9a..4e40da4 100644 --- a/os/syscall_ids.h +++ b/os/syscall_ids.h @@ -282,6 +282,8 @@ #define SYS_rseq 293 #define SYS_kexec_file_load 294 #define SYS_spawn 400 +#define SYS_mailread 401 +#define SYS_mailwrite 402 #define SYS_pidfd_send_signal 424 #define SYS_io_uring_setup 425 #define SYS_io_uring_enter 426 diff --git a/os/timer.c b/os/timer.c index d3696fc..6de2300 100644 --- a/os/timer.c +++ b/os/timer.c @@ -19,7 +19,7 @@ void timerinit() { /// Set the next timer interrupt void set_next_timer() { // 100Hz @ QEMU - uint64 timebase = CPU_FREQ / TICKS_PER_SEC; + const uint64 timebase = CPU_FREQ / TICKS_PER_SEC; set_timer(get_cycle() + timebase); } diff --git a/os/vm.c b/os/vm.c index dcc83c6..74f81b6 100644 --- a/os/vm.c +++ b/os/vm.c @@ -144,11 +144,11 @@ int mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm) uint64 a, last; pte_t *pte; - debugf("va=%p->pa=%p, size=%p, UXWR=%d%d%d%d", va, pa, size, - HAS_BIT(perm, PTE_U), - HAS_BIT(perm, PTE_X), - HAS_BIT(perm, PTE_W), - HAS_BIT(perm, PTE_R)); + // debugf("va=%p->pa=%p, size=%p, UXWR=%d%d%d%d", va, pa, size, + // HAS_BIT(perm, PTE_U), + // HAS_BIT(perm, PTE_X), + // HAS_BIT(perm, PTE_W), + // HAS_BIT(perm, PTE_R)); a = PGROUNDDOWN(va); last = PGROUNDDOWN(va + size - 1); // int cnt =0 ; @@ -178,11 +178,11 @@ int map1page(pagetable_t pagetable, uint64 va, uint64 pa, int perm) uint64 a; pte_t *pte; uint64 size = PGSIZE; - debugf("va=%p->pa=%p, size=%p, UXWR=%d%d%d%d", va, pa, size, - HAS_BIT(perm, PTE_U), - HAS_BIT(perm, PTE_X), - HAS_BIT(perm, PTE_W), - HAS_BIT(perm, PTE_R)); + // debugf("va=%p->pa=%p, size=%p, UXWR=%d%d%d%d", va, pa, size, + // HAS_BIT(perm, PTE_U), + // HAS_BIT(perm, PTE_X), + // HAS_BIT(perm, PTE_W), + // HAS_BIT(perm, PTE_R)); a = PGROUNDDOWN(va); if ((pte = walk(pagetable, a, 1)) == 0) @@ -243,7 +243,7 @@ uvmcreate() // uvmfree(pagetable, 0); // return 0; // } - debugf("map user trampoline\n"); + // debugf("map user trampoline\n"); return pagetable; } diff --git a/user/include/unistd.h b/user/include/unistd.h index 826f134..65b73cd 100644 --- a/user/include/unistd.h +++ b/user/include/unistd.h @@ -5,8 +5,8 @@ int open(const char*, int, int); -ssize_t read(int, void*, size_t); -ssize_t write(int, const void*, size_t); +ssize_t read(int, void*, unsigned long long); +ssize_t write(int, const void*, unsigned long long); int close(int); pid_t getpid(void); @@ -15,6 +15,7 @@ void exit(int); int fork(void); int exec(char*); int wait(int, int*); +int pipe(void*); uint64 get_time(); int sleep(unsigned long long); #endif // __UNISTD_H__ diff --git a/user/lib/stdio.c b/user/lib/stdio.c index cb11643..d5196b8 100644 --- a/user/lib/stdio.c +++ b/user/lib/stdio.c @@ -11,8 +11,9 @@ int getchar() { int putchar(int c) { - char byte = c; - return write(stdout, &byte, 1); + static char put[2] = {0, 0}; + put[0] = c; + return write(stdout, put, 1); } int puts(const char* s) diff --git a/user/lib/syscall.c b/user/lib/syscall.c index 6dd236a..d562224 100644 --- a/user/lib/syscall.c +++ b/user/lib/syscall.c @@ -11,11 +11,11 @@ int close(int fd) { return syscall(SYS_close, fd); } -ssize_t read(int fd, void *buf, size_t len) { +ssize_t read(int fd, void *buf, unsigned long long len) { return syscall(SYS_read, fd, buf, len); } -ssize_t write(int fd, const void *buf, size_t len) { +ssize_t write(int fd, const void *buf, unsigned long long len) { return syscall(SYS_write, fd, buf, len); } @@ -53,4 +53,8 @@ int sleep(unsigned long long time) { sched_yield(); } return 0; +} + +int pipe(void* p) { + return syscall(SYS_pipe2, p); } \ No newline at end of file diff --git a/user/src/pipetest.c b/user/src/pipetest.c new file mode 100644 index 0000000..dac6d81 --- /dev/null +++ b/user/src/pipetest.c @@ -0,0 +1,43 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +char STR[] = "hello pipe!"; + +int main() { + // create pipe + uint64 pipe_fd[2]; + int ret = pipe((void*)&pipe_fd); + assert(ret == 0, -2); + printf("[parent] read end = %p, write end = %p\n", pipe_fd[0], pipe_fd[1]); + if (fork() == 0) { + // child process, read from parent + // close write_end + close(pipe_fd[1]); + puts("[child] close write end"); + char buffer[32 + 1]; + int len_read = read(pipe_fd[0], buffer, 32); + puts("[chile] read over"); + // assert(len_read < 32); + buffer[len_read] = 0; + assert(strncmp(buffer, STR, strlen(STR)) == 0, -3); + puts("Read OK, child process exited!"); + return 0; + } else { + // parent process, write to child + // close read end + close(pipe_fd[0]); + printf("[parent] close read end\n"); + assert(write(pipe_fd[1], STR, strlen(STR)) == strlen(STR), -3); + printf("[parent] write over\n"); + // close write end + close(pipe_fd[1]); + int exit_code = 0; + wait(-1, &exit_code); + assert(exit_code == 0, -2); + puts("pipetest passed!"); + } + return 0; +} + diff --git a/user/src/user_shell.c b/user/src/user_shell.c index 678df6e..f023091 100644 --- a/user/src/user_shell.c +++ b/user/src/user_shell.c @@ -2,12 +2,14 @@ #include <stdlib.h> #include <unistd.h> + const unsigned char LF = 0x0a; const unsigned char CR = 0x0d; const unsigned char DL = 0x7f; const unsigned char BS = 0x08; char line[100] = {}; + int top = 0; void push(char c) { @@ -68,6 +70,7 @@ int main() { default: putchar(c); push(c); + break; } } return 0; -- GitLab