# HG changeset patch # User kono # Date 1559553164 -32400 # Node ID 214d21c891c7ad209e46e89b440e4e8bc3624f6b # Parent fadfd62d6b142ff2c6ebfb30ad58ff76cca46123 rename to cbc __ncode is not handled as interfaces diff -r fadfd62d6b14 -r 214d21c891c7 src/CMakeLists.txt --- a/src/CMakeLists.txt Tue May 28 22:27:01 2019 +0900 +++ b/src/CMakeLists.txt Mon Jun 03 18:12:44 2019 +0900 @@ -80,8 +80,8 @@ TARGET kernel SOURCES - lib/string.c arm.c asm.S bio.c buddy.c console.cbc exec.c file.c fs.c log.c main.c memide.c pipe.c proc.c spinlock.c - start.c swtch.S syscall.c sysfile.c sysproc.c trap_asm.S trap.c vm.c device/picirq.c device/timer.c device/uart.c + lib/string.c arm.c asm.S bio.c buddy.c console.cbc exec.c file.cbc fs.c log.c main.c memide.c pipe.cbc proc.cbc spinlock.cbc + start.c swtch.S syscall.cbc sysfile.cbc sysproc.c trap_asm.S trap.c vm.c device/picirq.c device/timer.c device/uart.c entry-osx.S ) diff -r fadfd62d6b14 -r 214d21c891c7 src/console.cbc --- a/src/console.cbc Tue May 28 22:27:01 2019 +0900 +++ b/src/console.cbc Mon Jun 03 18:12:44 2019 +0900 @@ -15,8 +15,10 @@ #include "../context.h" -__code cbc_consoleread1 (); -__code cbc_consoleread2 (); +#define __ncode __code + +__ncode cbc_consoleread1 (); +__ncode cbc_consoleread2 (); static void consputc (int); @@ -124,7 +126,7 @@ } } -__code cbc_panic (char *s) +__ncode cbc_panic (char *s) { cli(); @@ -236,10 +238,10 @@ release(&input.lock); } -__code cbc_consoleread2 () +__ncode cbc_consoleread2() { struct inode *ip = proc->cbc_arg.cbc_console_arg.ip; - __code(*next)(int ret) = proc->cbc_arg.cbc_console_arg.next; + __code (*next)(int ret) = proc->cbc_arg.cbc_console_arg.next; if (input.r == input.w) { if (proc->killed) { release(&input.lock); @@ -251,14 +253,14 @@ goto cbc_consoleread1(); } -__code cbc_consoleread1 () +__ncode cbc_consoleread1() { int cont = 1; int n = proc->cbc_arg.cbc_console_arg.n; int target = proc->cbc_arg.cbc_console_arg.target; char* dst = proc->cbc_arg.cbc_console_arg.dst; struct inode *ip = proc->cbc_arg.cbc_console_arg.ip; - __code(*next)(int ret) = proc->cbc_arg.cbc_console_arg.next; + __code (*next)(int ret) = proc->cbc_arg.cbc_console_arg.next; int c = input.buf[input.r++ % INPUT_BUF]; @@ -295,7 +297,7 @@ goto next(target - n); } -__code cbc_consoleread (struct inode *ip, char *dst, int n, __code(*next)(int ret)) +__ncode cbc_consoleread(struct inode *ip, char *dst, int n, __code(*next)(int ret)) { uint target; diff -r fadfd62d6b14 -r 214d21c891c7 src/context.h --- a/src/context.h Tue May 28 22:27:01 2019 +0900 +++ b/src/context.h Mon Jun 03 18:12:44 2019 +0900 @@ -1,8 +1,8 @@ /* Context definition for llrb example */ -#ifdef CONTEXT_H -#define CONTEXT_H -#include -#include +// #ifdef CBC_CONTEXT_H does not work well +#define CBC_CONTEXT_H +// #include +// #include #ifdef USE_CUDAWorker #include #include @@ -10,65 +10,65 @@ #include "helper_cuda.h" #endif -#include "use_context_numbers.h" +// #include "use_context_numbers.h" #define ALLOCATE_SIZE 20000000 #define NEW(type) (type*)(calloc(1, sizeof(type))) #define NEWN(n, type) (type*)(calloc(n, sizeof(type))) -#define ALLOC_DATA(context, dseg) ({\ - Meta* meta = (Meta*)context->heap;\ +#define ALLOC_DATA(cbc_context, dseg) ({\ + Meta* meta = (Meta*)cbc_context->heap;\ meta->type = D_##dseg;\ meta->size = sizeof(dseg);\ meta->len = 1;\ - context->heap += sizeof(Meta);\ - context->data[D_##dseg] = context->heap; context->heap += sizeof(dseg); (dseg *)context->data[D_##dseg]; }) + cbc_context->heap += sizeof(Meta);\ + cbc_context->data[D_##dseg] = cbc_context->heap; cbc_context->heap += sizeof(dseg); (dseg *)cbc_context->data[D_##dseg]; }) -#define ALLOC_DATA_TYPE(context, dseg, t) ({\ - Meta* meta = (Meta*)context->heap;\ +#define ALLOC_DATA_TYPE(cbc_context, dseg, t) ({\ + Meta* meta = (Meta*)cbc_context->heap;\ meta->type = D_##t;\ meta->size = sizeof(t);\ meta->len = 1;\ - context->heap += sizeof(Meta);\ - context->data[D_##dseg] = context->heap; context->heap += sizeof(t); (t *)context->data[D_##dseg]; }) + cbc_context->heap += sizeof(Meta);\ + cbc_context->data[D_##dseg] = cbc_context->heap; cbc_context->heap += sizeof(t); (t *)cbc_context->data[D_##dseg]; }) -#define ALLOCATE(context, t) ({ \ - Meta* meta = (Meta*)context->heap;\ - context->heap += sizeof(Meta);\ - union Data* data = context->heap; \ - context->heap += sizeof(t); \ +#define ALLOCATE(cbc_context, t) ({ \ + Meta* meta = (Meta*)cbc_context->heap;\ + cbc_context->heap += sizeof(Meta);\ + union Data* data = cbc_context->heap; \ + cbc_context->heap += sizeof(t); \ meta->type = D_##t; \ meta->size = sizeof(t); \ meta->len = 1;\ data; }) -#define ALLOCATE_ARRAY(context, t, length) ({ \ - Meta* meta = (Meta*)context->heap;\ - context->heap += sizeof(Meta);\ - union Data* data = context->heap; \ - context->heap += sizeof(t)*length; \ +#define ALLOCATE_ARRAY(cbc_context, t, length) ({ \ + Meta* meta = (Meta*)cbc_context->heap;\ + cbc_context->heap += sizeof(Meta);\ + union Data* data = cbc_context->heap; \ + cbc_context->heap += sizeof(t)*length; \ meta->type = D_##t; \ meta->size = sizeof(t)*length; \ meta->len = length; \ data; }) -#define ALLOCATE_PTR_ARRAY(context, dseg, length) ({\ - Meta* meta = (Meta*)context->heap;\ - context->heap += sizeof(Meta);\ - union Data* data = context->heap; \ - context->heap += sizeof(dseg *)*length; \ +#define ALLOCATE_PTR_ARRAY(cbc_context, dseg, length) ({\ + Meta* meta = (Meta*)cbc_context->heap;\ + cbc_context->heap += sizeof(Meta);\ + union Data* data = cbc_context->heap; \ + cbc_context->heap += sizeof(dseg *)*length; \ meta->type = D_##dseg; \ meta->size = sizeof(dseg *)*length; \ meta->len = length; \ data; }) -#define ALLOCATE_DATA_GEAR(context, t) ({ \ - union Data* data = ALLOCATE(context, t); \ +#define ALLOCATE_DATA_GEAR(cbc_context, t) ({ \ + union Data* data = ALLOCATE(cbc_context, t); \ Meta* meta = GET_META(data); \ - meta->wait = createSynchronizedQueue(context); \ + meta->wait = createSynchronizedQueue(cbc_context); \ data; }) -#define ALLOC(context, t) (&ALLOCATE(context, t)->t) +#define ALLOC(cbc_context, t) (&ALLOCATE(cbc_context, t)->t) #define GET_META(dseg) ((Meta*)(((void*)dseg) - sizeof(Meta))) #define GET_TYPE(dseg) (GET_META(dseg)->type) @@ -76,11 +76,11 @@ #define GET_LEN(dseg) (GET_META(dseg)->len) #define GET_WAIT_LIST(dseg) (GET_META(dseg)->wait) -#define Gearef(context, t) (&(context)->data[D_##t]->t) +#define Gearef(cbc_context, t) (&(cbc_context)->data[D_##t]->t) -// (SingleLinkedStack *)context->data[D_Stack]->Stack.stack->Stack.stack +// (SingleLinkedStack *)cbc_context->data[D_Stack]->Stack.stack->Stack.stack -#define GearImpl(context, intf, name) (Gearef(context, intf)->name->intf.name) +#define GearImpl(cbc_context, intf, name) (Gearef(cbc_context, intf)->name->intf.name) #include "c/enumCode.h" @@ -151,7 +151,7 @@ } LoopCounter; struct TaskManager { union Data* taskManager; - enum Code spawn; // start NEW context on the worker + enum Code spawn; // start NEW cbc_context on the worker enum Code spawnTasks; // start NEW tasks on the worker enum Code shutdown; enum Code incrementTaskCount; @@ -169,7 +169,7 @@ int sendCPUWorkerIndex; int sendGPUWorkerIndex; int taskCount; - pthread_mutex_t mutex; + // pthread_mutex_t mutex; struct Queue* activeQueue; struct Worker** workers; struct Element* taskList; @@ -185,22 +185,22 @@ enum Code shutdown; enum Code next; struct Queue* tasks; - pthread_t thread; + // pthread_t thread; struct TaskManager* taskManager; struct Context* task; } Worker; struct CPUWorker { - pthread_mutex_t mutex; - pthread_cond_t cond; - struct Context* context; + // pthread_mutex_t mutex; + // pthread_cond_t cond; + struct Context* cbc_context; int id; int loopCounter; } CPUWorker; #ifdef USE_CUDAWorker struct CUDAWorker { CUdevice device; - CUcontext cuCtx; - struct Context* context; + CUcbc_context cuCtx; + struct Context* cbc_context; int id; int loopCounter; int deviceNum; @@ -439,7 +439,7 @@ struct Atomic* atomic; struct Context* lockContext; } SpinLock; - /* CbCxv6 context*/ + /* CbCxv6 cbc_context*/ struct Inode { uint dev; // Device number uint inum; // Inode number @@ -482,7 +482,7 @@ char name[DIRSIZ]; } Dirent; // --- fs.h -}; // union Data end this is necessary for context generator +}; // union Data end this is necessary for cbc_context generator typedef union Data Data; @@ -490,11 +490,11 @@ #include "c/extern.h" -extern __code start_code(struct Context* context); -extern __code exit_code(struct Context* context); -extern __code meta(struct Context* context, enum Code next); -//extern __code par_meta(struct Context* context, enum Code spawns, enum Code next); -extern __code parGotoMeta(struct Context* context, enum Code next); -extern void initContext(struct Context* context); +extern __code start_code(struct Context* cbc_context); +extern __code exit_code(struct Context* cbc_context); +extern __code meta(struct Context* cbc_context, enum Code next); +//extern __code par_meta(struct Context* cbc_context, enum Code spawns, enum Code next); +extern __code parGotoMeta(struct Context* cbc_context, enum Code next); +extern void initContext(struct Context* cbc_context); -#endif +// #endif diff -r fadfd62d6b14 -r 214d21c891c7 src/file.c --- a/src/file.c Tue May 28 22:27:01 2019 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,222 +0,0 @@ -// -// File descriptors -// - -#include "types.h" -#include "defs.h" -#include "param.h" -#include "fs.h" -#include "file.h" -#include "spinlock.h" -#include "proc.h" - -struct devsw devsw[NDEV]; -struct cbc_devsw cbc_devsw[NDEV]; - -struct { - struct spinlock lock; - struct file file[NFILE]; -} ftable; - -void fileinit (void) -{ - initlock(&ftable.lock, "ftable"); -} - -// Allocate a file structure. -struct file* filealloc (void) -{ - struct file *f; - - acquire(&ftable.lock); - - for (f = ftable.file; f < ftable.file + NFILE; f++) { - if (f->ref == 0) { - f->ref = 1; - release(&ftable.lock); - return f; - } - } - - release(&ftable.lock); - return 0; -} - -// Increment ref count for file f. -struct file* filedup (struct file *f) -{ - acquire(&ftable.lock); - - if (f->ref < 1) { - panic("filedup"); - } - - f->ref++; - release(&ftable.lock); - return f; -} - -// Close file f. (Decrement ref count, close when reaches 0.) -void fileclose (struct file *f) -{ - struct file ff; - - acquire(&ftable.lock); - - if (f->ref < 1) { - panic("fileclose"); - } - - if (--f->ref > 0) { - release(&ftable.lock); - return; - } - - ff = *f; - f->ref = 0; - f->type = FD_NONE; - release(&ftable.lock); - - if (ff.type == FD_PIPE) { - pipeclose(ff.pipe, ff.writable); - - } else if (ff.type == FD_INODE) { - begin_trans(); - iput(ff.ip); - commit_trans(); - } -} - -// Get metadata about file f. -int filestat (struct file *f, struct stat *st) -{ - if (f->type == FD_INODE) { - ilock(f->ip); - stati(f->ip, st); - iunlock(f->ip); - - return 0; - } - - return -1; -} - -__code cbc_fileread1 (int r) -{ - struct file *f = proc->cbc_arg.cbc_console_arg.f; - __code (*next)(int ret) = cbc_ret; - if (r > 0) - f->off += r; - iunlock(f->ip); - goto next(r); -} - -__code cbc_fileread (struct file *f, char *addr, int n, __code (*next)(int ret)) -{ - if (f->readable == 0) { - goto next(-1); - } - - if (f->type == FD_PIPE) { - goto cbc_piperead(f->pipe, addr, n, next); - goto next(-1); - } - - if (f->type == FD_INODE) { - ilock(f->ip); - proc->cbc_arg.cbc_console_arg.f = f; - goto cbc_readi(f->ip, addr, f->off, n, cbc_fileread1); - } - - goto cbc_panic("fileread"); -} - -// Read from file f. -int fileread (struct file *f, char *addr, int n) -{ - int r; - - if (f->readable == 0) { - return -1; - } - - if (f->type == FD_PIPE) { - return piperead(f->pipe, addr, n); - } - - if (f->type == FD_INODE) { - ilock(f->ip); - - if ((r = readi(f->ip, addr, f->off, n)) > 0) { - f->off += r; - } - - iunlock(f->ip); - - return r; - } - - panic("fileread"); -} - -//PAGEBREAK! -// Write to file f. -int filewrite (struct file *f, char *addr, int n) -{ - int r; - int i; - int max; - int n1; - - if (f->writable == 0) { - return -1; - } - - if (f->type == FD_PIPE) { - return pipewrite(f->pipe, addr, n); - } - - if (f->type == FD_INODE) { - // write a few blocks at a time to avoid exceeding - // the maximum log transaction size, including - // i-node, indirect block, allocation blocks, - // and 2 blocks of slop for non-aligned writes. - // this really belongs lower down, since writei() - // might be writing a device like the console. - max = ((LOGSIZE - 1 - 1 - 2) / 2) * 512; - i = 0; - - while (i < n) { - n1 = n - i; - - if (n1 > max) { - n1 = max; - } - - begin_trans(); - ilock(f->ip); - - if ((r = writei(f->ip, addr + i, f->off, n1)) > 0) { - f->off += r; - } - - iunlock(f->ip); - commit_trans(); - - if (r < 0) { - break; - } - - if (r != n1) { - panic("short filewrite"); - } - - i += r; - } - - return i == n ? n : -1; - } - - panic("filewrite"); -} - diff -r fadfd62d6b14 -r 214d21c891c7 src/file.cbc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/file.cbc Mon Jun 03 18:12:44 2019 +0900 @@ -0,0 +1,224 @@ +// +// File descriptors +// + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "fs.h" +#include "file.h" +#include "spinlock.h" +#include "proc.h" + +#define __ncode __code +# +struct devsw devsw[NDEV]; +struct cbc_devsw cbc_devsw[NDEV]; + +struct { + struct spinlock lock; + struct file file[NFILE]; +} ftable; + +void fileinit (void) +{ + initlock(&ftable.lock, "ftable"); +} + +// Allocate a file structure. +struct file* filealloc (void) +{ + struct file *f; + + acquire(&ftable.lock); + + for (f = ftable.file; f < ftable.file + NFILE; f++) { + if (f->ref == 0) { + f->ref = 1; + release(&ftable.lock); + return f; + } + } + + release(&ftable.lock); + return 0; +} + +// Increment ref count for file f. +struct file* filedup (struct file *f) +{ + acquire(&ftable.lock); + + if (f->ref < 1) { + panic("filedup"); + } + + f->ref++; + release(&ftable.lock); + return f; +} + +// Close file f. (Decrement ref count, close when reaches 0.) +void fileclose (struct file *f) +{ + struct file ff; + + acquire(&ftable.lock); + + if (f->ref < 1) { + panic("fileclose"); + } + + if (--f->ref > 0) { + release(&ftable.lock); + return; + } + + ff = *f; + f->ref = 0; + f->type = FD_NONE; + release(&ftable.lock); + + if (ff.type == FD_PIPE) { + pipeclose(ff.pipe, ff.writable); + + } else if (ff.type == FD_INODE) { + begin_trans(); + iput(ff.ip); + commit_trans(); + } +} + +// Get metadata about file f. +int filestat (struct file *f, struct stat *st) +{ + if (f->type == FD_INODE) { + ilock(f->ip); + stati(f->ip, st); + iunlock(f->ip); + + return 0; + } + + return -1; +} + +__ncode cbc_fileread1 (int r) +{ + struct file *f = proc->cbc_arg.cbc_console_arg.f; + __code (*next)(int ret) = cbc_ret; + if (r > 0) + f->off += r; + iunlock(f->ip); + goto next(r); +} + +__ncode cbc_fileread (struct file *f, char *addr, int n, __code (*next)(int ret)) +{ + if (f->readable == 0) { + goto next(-1); + } + + if (f->type == FD_PIPE) { + goto cbc_piperead(f->pipe, addr, n, next); + goto next(-1); + } + + if (f->type == FD_INODE) { + ilock(f->ip); + proc->cbc_arg.cbc_console_arg.f = f; + goto cbc_readi(f->ip, addr, f->off, n, cbc_fileread1); + } + + goto cbc_panic("fileread"); +} + +// Read from file f. +int fileread (struct file *f, char *addr, int n) +{ + int r; + + if (f->readable == 0) { + return -1; + } + + if (f->type == FD_PIPE) { + return piperead(f->pipe, addr, n); + } + + if (f->type == FD_INODE) { + ilock(f->ip); + + if ((r = readi(f->ip, addr, f->off, n)) > 0) { + f->off += r; + } + + iunlock(f->ip); + + return r; + } + + panic("fileread"); +} + +//PAGEBREAK! +// Write to file f. +int filewrite (struct file *f, char *addr, int n) +{ + int r; + int i; + int max; + int n1; + + if (f->writable == 0) { + return -1; + } + + if (f->type == FD_PIPE) { + return pipewrite(f->pipe, addr, n); + } + + if (f->type == FD_INODE) { + // write a few blocks at a time to avoid exceeding + // the maximum log transaction size, including + // i-node, indirect block, allocation blocks, + // and 2 blocks of slop for non-aligned writes. + // this really belongs lower down, since writei() + // might be writing a device like the console. + max = ((LOGSIZE - 1 - 1 - 2) / 2) * 512; + i = 0; + + while (i < n) { + n1 = n - i; + + if (n1 > max) { + n1 = max; + } + + begin_trans(); + ilock(f->ip); + + if ((r = writei(f->ip, addr + i, f->off, n1)) > 0) { + f->off += r; + } + + iunlock(f->ip); + commit_trans(); + + if (r < 0) { + break; + } + + if (r != n1) { + panic("short filewrite"); + } + + i += r; + } + + return i == n ? n : -1; + } + + panic("filewrite"); +} + diff -r fadfd62d6b14 -r 214d21c891c7 src/gearsTools/generate_context.pl --- a/src/gearsTools/generate_context.pl Tue May 28 22:27:01 2019 +0900 +++ b/src/gearsTools/generate_context.pl Mon Jun 03 18:12:44 2019 +0900 @@ -9,7 +9,7 @@ # CodeGear # # get stub information from # *.c -# __code taskManager_stub(struct Context* context) { +# __code taskManager_stub(struct Context* cbc_context) { # # generate CodeGear indexn in context.h # C_taskManager, @@ -18,7 +18,7 @@ # extern __code taskManager_stub(struct Context*); # # generate CodeGear stub reference in $name-context.h for each module -# context->code[C_taskManager] = taskManager_stub; +# cbc_context->code[C_taskManager] = taskManager_stub; # # DataGear # @@ -85,7 +85,7 @@ my ($filename) = @_; open my $fd,"<",$filename or die("can't open $filename $!"); while (<$fd>) { - if (/^__code (\w+)_stub\(struct *Context *\* *context\)/) { + if (/^__code (\w+)_stub\(struct *Context *\* *cbc_context\)/) { $codeGear{$1} = $filename; } elsif (/^(\w+)(\*)+ *create(\w+)\(([^]]*)\)/) { my $interface = $1; @@ -138,7 +138,7 @@ my $code_init = ''; for my $code ( sort keys %mCodeGear ) { - $code_init .= " context->code[C_${code}] = ${code}_stub;\n"; + $code_init .= " cbc_context->code[C_${code}] = ${code}_stub;\n"; } my $data_num = keys(%dataGear); @@ -150,18 +150,18 @@ #include "../context.h" -void initContext(struct Context* context) { - context->heapLimit = sizeof(union Data)*ALLOCATE_SIZE; - context->code = (__code(**) (struct Context*)) NEWN(ALLOCATE_SIZE, void*); - context->data = NEWN(ALLOCATE_SIZE, union Data*); - context->heapStart = NEWN(context->heapLimit, char); - context->heap = context->heapStart; - // context->codeNum = Exit; +void initContext(struct Context* cbc_context) { + cbc_context->heapLimit = sizeof(union Data)*ALLOCATE_SIZE; + cbc_context->code = (__code(**) (struct Context*)) NEWN(ALLOCATE_SIZE, void*); + cbc_context->data = NEWN(ALLOCATE_SIZE, union Data*); + cbc_context->heapStart = NEWN(cbc_context->heapLimit, char); + cbc_context->heap = cbc_context->heapStart; + // cbc_context->codeNum = Exit; $code_init #include "dataGearInit.c" - context->dataNum = $data_num; + cbc_context->dataNum = $data_num; } EOFEOF @@ -169,34 +169,34 @@ print $fd $context_c; my $meta_call = <<"EOFEOF"; -__code meta(struct Context* context, enum Code next) { +__code meta(struct Context* cbc_context, enum Code next) { // printf("meta %d\\n",next); - goto (context->code[next])(context); + goto (cbc_context->code[next])(cbc_context); } -__code parGotoMeta(struct Context* context, enum Code next) { - context->task = NULL; - context->taskList = NULL; - goto (context->code[Gearef(context, TaskManager)->taskManager->TaskManager.spawnTasks])(context); +__code parGotoMeta(struct Context* cbc_context, enum Code next) { + cbc_context->task = NULL; + cbc_context->taskList = NULL; + goto (cbc_context->code[Gearef(context, TaskManager)->taskManager->TaskManager.spawnTasks])(cbc_context); } -__code start_code(struct Context* context) { - goto meta(context, context->next); +__code start_code(struct Context* cbc_context) { + goto meta(context, cbc_context->next); } -__code start_code_stub(struct Context* context) { - goto start_code(context); +__code start_code_stub(struct Context* cbc_context) { + goto start_code(cbc_context); } -__code exit_code(struct Context* context) { - free(context->code); - free(context->data); - free(context->heapStart); +__code exit_code(struct Context* cbc_context) { + free(cbc_context->code); + free(cbc_context->data); + free(cbc_context->heapStart); goto exit(0); } -__code exit_code_stub(struct Context* context) { - goto exit_code(context); +__code exit_code_stub(struct Context* cbc_context) { + goto exit_code(cbc_context); } // end context_c @@ -221,7 +221,7 @@ open my $fd,">","$ddir/dataGearInit.c" or die("can't open $ddir/dataGearInit.c $!"); for my $data ( sort keys %dataGear ) { - print $fd " ALLOC_DATA(context, ${data});\n"; + print $fd " ALLOC_DATA(cbc_context, ${data});\n"; } } diff -r fadfd62d6b14 -r 214d21c891c7 src/gearsTools/generate_stub.pl --- a/src/gearsTools/generate_stub.pl Tue May 28 22:27:01 2019 +0900 +++ b/src/gearsTools/generate_stub.pl Mon Jun 03 18:12:44 2019 +0900 @@ -68,10 +68,10 @@ # # generated meta level code # -# Gearef(context, Stack)->stack = (union Data*)nodeStack; -# Gearef(context, Stack)->data = (union Data*)node; -# Gearef(context, Stack)->next = C_stackTest3; -# goto meta(context, nodeStack->push); +# Gearef(cbc_context, Stack)->stack = (union Data*)nodeStack; +# Gearef(cbc_context, Stack)->data = (union Data*)node; +# Gearef(cbc_context, Stack)->next = C_stackTest3; +# goto meta(cbc_context, nodeStack->push); sub getDataGear { my ($filename) = @_; @@ -222,7 +222,7 @@ sub generateStub { my($fd,$prevCodeGearName,$dataGearName) = @_; - print $fd "__code ", $prevCodeGearName ,"_stub(struct Context* context) {\n"; + print $fd "__code ", $prevCodeGearName ,"_stub(struct Context* cbc_context) {\n"; print $fd $dataGearName; print $fd "\n} \n\n"; return 1; @@ -239,7 +239,7 @@ push @{$dataGearVarType{$codeGearName}}, $typeName; if ($typeName eq $implementation) { # get implementation - $dataGearName{$codeGearName} .= "\t$typeName* $varName = ($typeName*)GearImpl(context, $interface, $varName);\n"; + $dataGearName{$codeGearName} .= "\t$typeName* $varName = ($typeName*)GearImpl(cbc_context, $interface, $varName);\n"; } else { # interface var for my $ivar (keys %{$var{$interface}}) { @@ -247,11 +247,11 @@ if ($varName eq $ivar) { if ($typeName eq $var{$interface}->{$ivar}) { if ($output) { - $dataGearName{$codeGearName} .= "\t$typeName$ptrType* O_$varName = &Gearef(context, $interface)->$varName;\n"; + $dataGearName{$codeGearName} .= "\t$typeName$ptrType* O_$varName = &Gearef(cbc_context, $interface)->$varName;\n"; $outputVar{$codeGearName} .= "\t$typeName$ptrType $varName = *O_$varName;\n"; return 1; } - $dataGearName{$codeGearName} .= "\t$typeName$ptrType $varName = Gearef(context, $interface)->$varName;\n"; + $dataGearName{$codeGearName} .= "\t$typeName$ptrType $varName = Gearef(cbc_context, $interface)->$varName;\n"; return 1; } } @@ -261,7 +261,7 @@ for my $cName (keys %{$code{$interface}}) { if ($varName eq $cName) { # continuation field - $dataGearName{$codeGearName} .= "\tenum Code $varName = Gearef(context, $interface)->$varName;\n"; + $dataGearName{$codeGearName} .= "\tenum Code $varName = Gearef(cbc_context, $interface)->$varName;\n"; return 1; } } @@ -273,11 +273,11 @@ my ($type, $count) = split(/\s/, $codeGear{$codeGearName}->{"var"}->{$var}); if ($typeName eq $type) { if ($output) { - $dataGearName{$codeGearName} .= "\t$typeName$ptrType* O_$varName = ($typeName $ptrType*)&context->data[context->odg + $count];\n"; + $dataGearName{$codeGearName} .= "\t$typeName$ptrType* O_$varName = ($typeName $ptrType*)&cbc_context->data[cbc_context->odg + $count];\n"; $outputVar{$codeGearName} .= "\t$typeName$ptrType $varName = *O_$varName;\n"; return 1; } - $dataGearName{$codeGearName} .= "\t$typeName$ptrType $varName = &context->data[context->idg + $count]->$typeName;\n"; + $dataGearName{$codeGearName} .= "\t$typeName$ptrType $varName = &cbc_context->data[cbc_context->idg + $count]->$typeName;\n"; return 1; } } @@ -287,7 +287,7 @@ for my $cName (keys %{$codeGear{$codeGearName}->{"code"}}) { if ($varName eq $cName) { # continuation field - $dataGearName{$codeGearName} .= "\tenum Code $varName = context->next;\n"; + $dataGearName{$codeGearName} .= "\tenum Code $varName = cbc_context->next;\n"; return 1; } } @@ -295,10 +295,10 @@ # par goto continuation # global or local variable case if ($typeName eq "Code") { - $dataGearName{$codeGearName} .= "\tenum $typeName$ptrType $varName = Gearef(context, $interface)->$varName;\n"; + $dataGearName{$codeGearName} .= "\tenum $typeName$ptrType $varName = Gearef(cbc_context, $interface)->$varName;\n"; return 1; } - $dataGearName{$codeGearName} .= "\t$typeName$ptrType $varName = Gearef(context, $typeName);\n"; + $dataGearName{$codeGearName} .= "\t$typeName$ptrType $varName = Gearef(cbc_context, $typeName);\n"; return 1; } } @@ -332,9 +332,11 @@ my $inStub = 0; my $hasParGoto = 0; my $inMain = 0 ; + my $inCode = 0 ; my %stub; my $codeGearName; my %localVarType; + my %localCode; while (<$in>) { if (! $inTypedef && ! $inStub && ! $inMain) { @@ -346,7 +348,13 @@ my $interfaceHeader = $1; # #interface not write next unless ($interfaceHeader =~ /context.h/); + } elsif (/^\s\s*_\_code (\w+)\((.*)\)(.*)/) { + $localCode{$1} = 1; + } elsif (/^\s\s*_\_code *\(\s*\*\s*(\w+)\)\((.*)\)(.*)/) { + $localCode{$1} = 1; } elsif (/^\_\_code (\w+)\((.*)\)(.*)/) { + $inCode = 1; + %localCode = {}; %localVarType = {}; $codeGearName = $1; my $args = $2; @@ -376,12 +384,12 @@ $dataGearVar{$codeGearName} = []; $outputVar{$codeGearName} = ""; $outputArgs{$codeGearName} = {}; - my $newArgs = "struct Context *context,"; - if ($args=~/^struct Context\s*\*\s*context/) { + my $newArgs = "struct Context *cbc_context,"; + if ($args=~/^struct Context\s*\*\s*cbc_context/) { $newArgs = ""; } if (!$args){ - $newArgs = "struct Context *context"; + $newArgs = "struct Context *cbc_context"; } while($args) { if ($args =~ s/(^\s*,\s*)//) { @@ -427,7 +435,7 @@ } } # generate goto statement from stub to the CodeGear in the buffer - $dataGearName{$codeGearName} .= "\tgoto $codeGearName(context"; + $dataGearName{$codeGearName} .= "\tgoto $codeGearName(cbc_context"; for my $arg ( @{$dataGearVar{$codeGearName}}) { $dataGearName{$codeGearName} .= ", $arg"; } @@ -440,6 +448,9 @@ print $fd $outputVar{$codeGearName}; } next; + } elsif (! $inCode) { + print $fd $_; + next; } elsif (/^(.*)goto (\w+)\-\>(\w+)\((.*)\);/) { # handling goto statement # convert it to the meta call form with two arugments, that is context and enum Code @@ -449,6 +460,10 @@ my $tmpArgs = $4; $tmpArgs =~ s/\(.*\)/\(\)/; my @args = split(/,/,$tmpArgs); + if (! defined $dataGearVarType{$codeGearName}) { + print $fd $_ ; + next ; + } my @types = @{$dataGearVarType{$codeGearName}}; my $ntype; my $ftype; @@ -463,7 +478,7 @@ $ntype = $localVarType{$next}; $ftype = lcfirst($ntype); } - print $fd "\tGearef(context, $ntype)->$ftype = (union Data*) $next;\n"; + print $fd "\tGearef(cbc_context, $ntype)->$ftype = (union Data*) $next;\n"; # Put interface argument my $prot = $code{$ntype}->{$method}; my $i = 1; @@ -478,19 +493,19 @@ $arg =~ s/^(\s)*(\w+)/$2/; if ($pType =~ s/\_\_code$//) { if ($arg =~ /(\w+)\(.*\)/) { - print $fd "\tGearef(context, $ntype)->$pName = $1;\n"; + print $fd "\tGearef(cbc_context, $ntype)->$pName = $1;\n"; } else { - print $fd "\tGearef(context, $ntype)->$pName = C_$arg;\n"; + print $fd "\tGearef(cbc_context, $ntype)->$pName = C_$arg;\n"; } } elsif ($pType =~ /Data\**$/){ - print $fd "\tGearef(context, $ntype)->$pName = (union $pType) $arg;\n"; + print $fd "\tGearef(cbc_context, $ntype)->$pName = (union $pType) $arg;\n"; } else { - print $fd "\tGearef(context, $ntype)->$pName = $arg;\n"; + print $fd "\tGearef(cbc_context, $ntype)->$pName = $arg;\n"; } $i++; } - print $fd "${prev}context->before = C_$codeGearName;\n"; - print $fd "${prev}goto meta(context, $next->$method);\n"; + # print $fd "${prev}cbc_context->before = C_$codeGearName;\n"; + print $fd "${prev}goto meta(cbc_context, $next->$method);\n"; next; } elsif(/^(.*)par goto (\w+)\((.*)\);/) { # handling par goto statement @@ -515,41 +530,41 @@ print $fd "${prev}struct Element* element;\n"; } my $initTask = << "EOFEOF"; - ${prev}context->task = NEW(struct Context); - ${prev}initContext(context->task); - ${prev}context->task->next = C_$codeGearName; - ${prev}context->task->idgCount = $inputCount; - ${prev}context->task->idg = context->task->dataNum; - ${prev}context->task->maxIdg = context->task->idg + $inputCount; - ${prev}context->task->odg = context->task->maxIdg; - ${prev}context->task->maxOdg = context->task->odg + $outputCount; + ${prev}cbc_context->task = NEW(struct Context); + ${prev}initContext(cbc_context->task); + ${prev}cbc_context->task->next = C_$codeGearName; + ${prev}cbc_context->task->idgCount = $inputCount; + ${prev}cbc_context->task->idg = cbc_context->task->dataNum; + ${prev}cbc_context->task->maxIdg = cbc_context->task->idg + $inputCount; + ${prev}cbc_context->task->odg = cbc_context->task->maxIdg; + ${prev}cbc_context->task->maxOdg = cbc_context->task->odg + $outputCount; EOFEOF print $fd $initTask; if (@iterateCounts) { - print $fd "${prev}context->task->iterate = 0;\n"; + print $fd "${prev}cbc_context->task->iterate = 0;\n"; my $len = @iterateCounts; if ($len == 1) { - print $fd "${prev}context->task->iterator = createMultiDimIterator(context, $iterateCounts[0], 1, 1);\n"; + print $fd "${prev}cbc_context->task->iterator = createMultiDimIterator(cbc_context, $iterateCounts[0], 1, 1);\n"; } elsif ($len == 2) { - print $fd "${prev}context->task->iterator = createMultiDimIterator(context, $iterateCounts[0], $iterateCounts[1], 1);\n"; + print $fd "${prev}cbc_context->task->iterator = createMultiDimIterator(cbc_context, $iterateCounts[0], $iterateCounts[1], 1);\n"; } elsif ($len == 3) { - print $fd "${prev}context->task->iterator = createMultiDimIterator(context, $iterateCounts[0], $iterateCounts[1], $iterateCounts[2]);\n"; + print $fd "${prev}cbc_context->task->iterator = createMultiDimIterator(cbc_context, $iterateCounts[0], $iterateCounts[1], $iterateCounts[2]);\n"; } } for my $dataGear (@dataGears) { - print $fd "${prev}GET_META($dataGear)->wait = createSynchronizedQueue(context);\n"; + print $fd "${prev}GET_META($dataGear)->wait = createSynchronizedQueue(cbc_context);\n"; } for my $i (0..$inputCount-1) { - print $fd "${prev}context->task->data[context->task->idg+$i] = (union Data*)@dataGears[$i];\n"; + print $fd "${prev}cbc_context->task->data[cbc_context->task->idg+$i] = (union Data*)@dataGears[$i];\n"; } for my $i (0..$outputCount-1) { - print $fd "${prev}context->task->data[context->task->odg+$i] = (union Data*)@dataGears[$inputCount+$i];\n"; + print $fd "${prev}cbc_context->task->data[cbc_context->task->odg+$i] = (union Data*)@dataGears[$inputCount+$i];\n"; } my $putTask = << "EOFEOF"; - ${prev}element = &ALLOCATE(context, Element)->Element; - ${prev}element->data = (union Data*)context->task; - ${prev}element->next = context->taskList; - ${prev}context->taskList = element; + ${prev}element = &ALLOCATE(cbc_context, Element)->Element; + ${prev}element->data = (union Data*)cbc_context->task; + ${prev}element->next = cbc_context->taskList; + ${prev}cbc_context->taskList = element; EOFEOF print $fd $putTask; next; @@ -560,6 +575,9 @@ my $next = $2; my @args = split(/,/, $3); my $v = 0; + if (defined $localCode{$next}) { + print $fd $_; next; + } for my $n ( @{$dataGearVar{$codeGearName}} ) { # continuation arguments $v = 1 if ( $n eq $next); @@ -572,37 +590,37 @@ print $fd "\t*O_$arg = $v;\n"; } if ($hasParGoto) { - print $fd "${prev}Gearef(context, TaskManager)->taskList = context->taskList;\n"; - print $fd "${prev}Gearef(context, TaskManager)->next1 = C_$next;\n"; - print $fd "${prev}goto meta(context, C_$next);\n"; + print $fd "${prev}Gearef(cbc_context, TaskManager)->taskList = cbc_context->taskList;\n"; + print $fd "${prev}Gearef(cbc_context, TaskManager)->next1 = C_$next;\n"; + print $fd "${prev}goto meta(cbc_context, C_$next);\n"; } else { - print $fd "${prev}context->before = C_$codeGearName;\n"; - print $fd "${prev}goto meta(context, $next);\n"; + # print $fd "${prev}cbc_context->before = C_$codeGearName;\n"; + print $fd "${prev}goto meta(cbc_context, $next);\n"; } next; } if ($hasParGoto) { - print $fd "${prev}Gearef(context, TaskManager)->taskList = context->taskList;\n"; - print $fd "${prev}Gearef(context, TaskManager)->next1 = C_$next;\n"; - print $fd "${prev}goto parGotoMeta(context, C_$next);\n"; + print $fd "${prev}Gearef(cbc_context, TaskManager)->taskList = cbc_context->taskList;\n"; + print $fd "${prev}Gearef(cbc_context, TaskManager)->next1 = C_$next;\n"; + print $fd "${prev}goto parGotoMeta(cbc_context, C_$next);\n"; next; } elsif ($next eq "meta") { print $fd $_; next; } else { - print $fd "${prev}context->before = C_$codeGearName;\n"; - print $fd "${prev}goto meta(context, C_$next);\n"; + # print $fd "${prev}cbc_context->before = C_$codeGearName;\n"; + print $fd "${prev}goto meta(cbc_context, C_$next);\n"; next; } } elsif(/^.*(struct|union)?\s(\w+)\*\s(\w+)\s?[=;]/) { my $type = $2; my $varName = $3; $localVarType{$varName} = $type; - s/new\s+(\w+)\(\)/\&ALLOCATE(context, \1)->\1/g; # replacing new + s/new\s+(\w+)\(\)/\&ALLOCATE(cbc_context, \1)->\1/g; # replacing new } elsif(/^}/) { $hasParGoto = 0; } else { - s/new\s+(\w+)\(\)/\&ALLOCATE(context, \1)->\1/g; # replacing new + s/new\s+(\w+)\(\)/\&ALLOCATE(cbc_context, \1)->\1/g; # replacing new } # gather type name and type } elsif ($inMain) { @@ -614,7 +632,7 @@ my $next = $2; print $fd "${prev}struct Context* main_context = NEW(struct Context);\n"; print $fd "${prev}initContext(main_context);\n"; - print $fd "${prev}main_context->next = C_$next;\n"; + print $fd "${prev}main_cbc_context->next = C_$next;\n"; print $fd "${prev}goto start_code(main_context);\n"; next; } @@ -623,6 +641,7 @@ $inStub = 0; $inTypedef = 0; $inMain = 0; + $inCode = 0; } print $fd $_; } diff -r fadfd62d6b14 -r 214d21c891c7 src/pipe.c --- a/src/pipe.c Tue May 28 22:27:01 2019 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,199 +0,0 @@ -#include "types.h" -#include "defs.h" -#include "param.h" -#include "mmu.h" -#include "proc.h" -#include "fs.h" -#include "file.h" -#include "spinlock.h" - -#define PIPESIZE 512 - -struct pipe { - struct spinlock lock; - 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 -}; - -int pipealloc(struct file **f0, struct file **f1) -{ - struct pipe *p; - - p = 0; - *f0 = *f1 = 0; - - if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0) { - goto bad; - } - - if((p = kmalloc (get_order(sizeof(*p)))) == 0) { - goto bad; - } - - p->readopen = 1; - p->writeopen = 1; - p->nwrite = 0; - p->nread = 0; - - initlock(&p->lock, "pipe"); - - (*f0)->type = FD_PIPE; - (*f0)->readable = 1; - (*f0)->writable = 0; - (*f0)->pipe = p; - (*f1)->type = FD_PIPE; - (*f1)->readable = 0; - (*f1)->writable = 1; - (*f1)->pipe = p; - - return 0; - - //PAGEBREAK: 20 - bad: - if(p) { - kfree (p, get_order(sizeof*p)); - } - - if(*f0) { - fileclose(*f0); - } - - if(*f1) { - fileclose(*f1); - } - - return -1; -} - -void pipeclose(struct pipe *p, int writable) -{ - acquire(&p->lock); - - if(writable){ - p->writeopen = 0; - wakeup(&p->nread); - - } else { - p->readopen = 0; - wakeup(&p->nwrite); - } - - if(p->readopen == 0 && p->writeopen == 0){ - release(&p->lock); - kfree (p, get_order(sizeof(*p))); - - } else { - release(&p->lock); - } -} - -//PAGEBREAK: 40 -int pipewrite(struct pipe *p, char *addr, int n) -{ - int i; - - acquire(&p->lock); - - for(i = 0; i < n; i++){ - while(p->nwrite == p->nread + PIPESIZE){ //DOC: pipewrite-full - if(p->readopen == 0 /*|| proc->killed*/){ - release(&p->lock); - return -1; - } - - wakeup(&p->nread); - sleep(&p->nwrite, &p->lock); //DOC: pipewrite-sleep - } - - p->data[p->nwrite++ % PIPESIZE] = addr[i]; - } - - wakeup(&p->nread); //DOC: pipewrite-wakeup1 - release(&p->lock); - return n; -} - -__code cbc_piperead3(){ - struct pipe *p = proc->cbc_arg.cbc_console_arg.p; - int i = proc->cbc_arg.cbc_console_arg.i; - __code(*next)(int ret) = proc->cbc_arg.cbc_console_arg.next; - release(&p->lock); - - goto next(i); -} - -__code cbc_piperead2(){ - int i = proc->cbc_arg.cbc_console_arg.i; - int n = proc->cbc_arg.cbc_console_arg.n; - struct pipe *p = proc->cbc_arg.cbc_console_arg.p; - char *addr = proc->cbc_arg.cbc_console_arg.addr; - if (i < n && !(p->nread == p->nwrite)) { - addr[i] = p->data[p->nread++ % PIPESIZE]; - i ++; - proc->cbc_arg.cbc_console_arg.i = i; - proc->cbc_arg.cbc_console_arg.p = p; - proc->cbc_arg.cbc_console_arg.addr = addr; - goto cbc_piperead2(); - } - proc->cbc_arg.cbc_console_arg.p = p; - goto cbc_wakeup(&p->nwrite, cbc_piperead3); //DOC: piperead-wakeup -} - -__code cbc_piperead1(){ - struct pipe *p = proc->cbc_arg.cbc_console_arg.p; - __code(*next)(int ret) = proc->cbc_arg.cbc_console_arg.next; - if (p->nread == p->nwrite && p->writeopen){ - if(proc->killed){ - release(&p->lock); - goto next(-1); - } - proc->cbc_arg.cbc_console_arg.p = p; - goto cbc_sleep(&p->nread, &p->lock, cbc_piperead1); - } - int i = 0; - proc->cbc_arg.cbc_console_arg.i = i; - proc->cbc_arg.cbc_console_arg.p = p; - goto cbc_piperead2(); -} - -__code cbc_piperead(struct pipe *p, char *addr, int n, __code (*next)(int ret)) -{ - acquire(&p->lock); - proc->cbc_arg.cbc_console_arg.n = n; - proc->cbc_arg.cbc_console_arg.p = p; - proc->cbc_arg.cbc_console_arg.addr = addr; - proc->cbc_arg.cbc_console_arg.next = next; - goto cbc_piperead1(); -} - -int piperead(struct pipe *p, char *addr, int n) -{ - int i; - - acquire(&p->lock); - - while(p->nread == p->nwrite && p->writeopen){ //DOC: pipe-empty - if(proc->killed){ - release(&p->lock); - return -1; - } - - sleep(&p->nread, &p->lock); //DOC: piperead-sleep*/ - } - - for(i = 0; i < n; i++){ //DOC: piperead-copy - if(p->nread == p->nwrite) { - break; - } - - addr[i] = p->data[p->nread++ % PIPESIZE]; - } - - wakeup(&p->nwrite); //DOC: piperead-wakeup - release(&p->lock); - - return i; -} diff -r fadfd62d6b14 -r 214d21c891c7 src/pipe.cbc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pipe.cbc Mon Jun 03 18:12:44 2019 +0900 @@ -0,0 +1,201 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "mmu.h" +#include "proc.h" +#include "fs.h" +#include "file.h" +#include "spinlock.h" + +#define PIPESIZE 512 + +#define __ncode __code +# +struct pipe { + struct spinlock lock; + 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 +}; + +int pipealloc(struct file **f0, struct file **f1) +{ + struct pipe *p; + + p = 0; + *f0 = *f1 = 0; + + if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0) { + goto bad; + } + + if((p = kmalloc (get_order(sizeof(*p)))) == 0) { + goto bad; + } + + p->readopen = 1; + p->writeopen = 1; + p->nwrite = 0; + p->nread = 0; + + initlock(&p->lock, "pipe"); + + (*f0)->type = FD_PIPE; + (*f0)->readable = 1; + (*f0)->writable = 0; + (*f0)->pipe = p; + (*f1)->type = FD_PIPE; + (*f1)->readable = 0; + (*f1)->writable = 1; + (*f1)->pipe = p; + + return 0; + + //PAGEBREAK: 20 + bad: + if(p) { + kfree (p, get_order(sizeof*p)); + } + + if(*f0) { + fileclose(*f0); + } + + if(*f1) { + fileclose(*f1); + } + + return -1; +} + +void pipeclose(struct pipe *p, int writable) +{ + acquire(&p->lock); + + if(writable){ + p->writeopen = 0; + wakeup(&p->nread); + + } else { + p->readopen = 0; + wakeup(&p->nwrite); + } + + if(p->readopen == 0 && p->writeopen == 0){ + release(&p->lock); + kfree (p, get_order(sizeof(*p))); + + } else { + release(&p->lock); + } +} + +//PAGEBREAK: 40 +int pipewrite(struct pipe *p, char *addr, int n) +{ + int i; + + acquire(&p->lock); + + for(i = 0; i < n; i++){ + while(p->nwrite == p->nread + PIPESIZE){ //DOC: pipewrite-full + if(p->readopen == 0 /*|| proc->killed*/){ + release(&p->lock); + return -1; + } + + wakeup(&p->nread); + sleep(&p->nwrite, &p->lock); //DOC: pipewrite-sleep + } + + p->data[p->nwrite++ % PIPESIZE] = addr[i]; + } + + wakeup(&p->nread); //DOC: pipewrite-wakeup1 + release(&p->lock); + return n; +} + +__ncode cbc_piperead3(){ + struct pipe *p = proc->cbc_arg.cbc_console_arg.p; + int i = proc->cbc_arg.cbc_console_arg.i; + __code(*next)(int ret) = proc->cbc_arg.cbc_console_arg.next; + release(&p->lock); + + goto next(i); +} + +__ncode cbc_piperead2(){ + int i = proc->cbc_arg.cbc_console_arg.i; + int n = proc->cbc_arg.cbc_console_arg.n; + struct pipe *p = proc->cbc_arg.cbc_console_arg.p; + char *addr = proc->cbc_arg.cbc_console_arg.addr; + if (i < n && !(p->nread == p->nwrite)) { + addr[i] = p->data[p->nread++ % PIPESIZE]; + i ++; + proc->cbc_arg.cbc_console_arg.i = i; + proc->cbc_arg.cbc_console_arg.p = p; + proc->cbc_arg.cbc_console_arg.addr = addr; + goto cbc_piperead2(); + } + proc->cbc_arg.cbc_console_arg.p = p; + goto cbc_wakeup(&p->nwrite, cbc_piperead3); //DOC: piperead-wakeup +} + +__ncode cbc_piperead1(){ + struct pipe *p = proc->cbc_arg.cbc_console_arg.p; + __code(*next)(int ret) = proc->cbc_arg.cbc_console_arg.next; + if (p->nread == p->nwrite && p->writeopen){ + if(proc->killed){ + release(&p->lock); + goto next(-1); + } + proc->cbc_arg.cbc_console_arg.p = p; + goto cbc_sleep(&p->nread, &p->lock, cbc_piperead1); + } + int i = 0; + proc->cbc_arg.cbc_console_arg.i = i; + proc->cbc_arg.cbc_console_arg.p = p; + goto cbc_piperead2(); +} + +__ncode cbc_piperead(struct pipe *p, char *addr, int n, __code (*next)(int ret)) +{ + acquire(&p->lock); + proc->cbc_arg.cbc_console_arg.n = n; + proc->cbc_arg.cbc_console_arg.p = p; + proc->cbc_arg.cbc_console_arg.addr = addr; + proc->cbc_arg.cbc_console_arg.next = next; + goto cbc_piperead1(); +} + +int piperead(struct pipe *p, char *addr, int n) +{ + int i; + + acquire(&p->lock); + + while(p->nread == p->nwrite && p->writeopen){ //DOC: pipe-empty + if(proc->killed){ + release(&p->lock); + return -1; + } + + sleep(&p->nread, &p->lock); //DOC: piperead-sleep*/ + } + + for(i = 0; i < n; i++){ //DOC: piperead-copy + if(p->nread == p->nwrite) { + break; + } + + addr[i] = p->data[p->nread++ % PIPESIZE]; + } + + wakeup(&p->nwrite); //DOC: piperead-wakeup + release(&p->lock); + + return i; +} diff -r fadfd62d6b14 -r 214d21c891c7 src/proc.c --- a/src/proc.c Tue May 28 22:27:01 2019 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,620 +0,0 @@ -#include "types.h" -#include "defs.h" -#include "param.h" -#include "memlayout.h" -#include "mmu.h" -#include "arm.h" -#include "proc.h" -#include "spinlock.h" - -// -// Process initialization: -// process initialize is somewhat tricky. -// 1. We need to fake the kernel stack of a new process as if the process -// has been interrupt (a trapframe on the stack), this would allow us -// to "return" to the correct user instruction. -// 2. We also need to fake the kernel execution for this new process. When -// swtch switches to this (new) process, it will switch to its stack, -// and reload registers with the saved context. We use forkret as the -// return address (in lr register). (In x86, it will be the return address -// pushed on the stack by the process.) -// -// The design of context switch in xv6 is interesting: after initialization, -// each CPU executes in the scheduler() function. The context switch is not -// between two processes, but instead, between the scheduler. Think of scheduler -// as the idle process. -// -struct { - struct spinlock lock; - struct proc proc[NPROC]; -} ptable; - -static struct proc *initproc; -struct proc *proc; - -int nextpid = 1; -extern void forkret(void); -extern void trapret(void); - -static void wakeup1(void *chan); - -void pinit(void) -{ - initlock(&ptable.lock, "ptable"); -} - -//PAGEBREAK: 32 -// Look in the process table for an UNUSED proc. -// If found, change state to EMBRYO and initialize -// state required to run in the kernel. -// Otherwise return 0. -static struct proc* allocproc(void) -{ - struct proc *p; - char *sp; - - acquire(&ptable.lock); - - for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) { - if(p->state == UNUSED) { - goto found; - } - - } - - release(&ptable.lock); - return 0; - - found: - p->state = EMBRYO; - p->pid = nextpid++; - release(&ptable.lock); - - // Allocate kernel stack. - if((p->kstack = alloc_page ()) == 0){ - p->state = UNUSED; - return 0; - } - - sp = p->kstack + KSTACKSIZE; - - // Leave room for trap frame. - sp -= sizeof (*p->tf); - p->tf = (struct trapframe*)sp; - - // Set up new context to start executing at forkret, - // which returns to trapret. - sp -= 4; - *(uint*)sp = (uint)trapret; - - sp -= 4; - *(uint*)sp = (uint)p->kstack + KSTACKSIZE; - - sp -= sizeof (*p->context); - p->context = (struct context*)sp; - memset(p->context, 0, sizeof(*p->context)); - - // skip the push {fp, lr} instruction in the prologue of forkret. - // This is different from x86, in which the harderware pushes return - // address before executing the callee. In ARM, return address is - // loaded into the lr register, and push to the stack by the callee - // (if and when necessary). We need to skip that instruction and let - // it use our implementation. - p->context->lr = (uint)forkret+4; - - return p; -} - -void error_init () -{ - panic ("failed to craft first process\n"); -} - - -//PAGEBREAK: 32 -// hand-craft the first user process. We link initcode.S into the kernel -// as a binary, the linker will generate __binary_initcode_start/_size -void userinit(void) -{ - struct proc *p; - extern char _binary_initcode_start[], _binary_initcode_size[]; - - p = allocproc(); - initproc = p; - - if((p->pgdir = kpt_alloc()) == NULL) { - panic("userinit: out of memory?"); - } - - inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); - - p->sz = PTE_SZ; - - // craft the trapframe as if - memset(p->tf, 0, sizeof(*p->tf)); - - p->tf->r14_svc = (uint)error_init; - p->tf->spsr = spsr_usr (); - p->tf->sp_usr = PTE_SZ; // set the user stack - p->tf->lr_usr = 0; - - // set the user pc. The actual pc loaded into r15_usr is in - // p->tf, the trapframe. - p->tf->pc = 0; // beginning of initcode.S - - safestrcpy(p->name, "initcode", sizeof(p->name)); - p->cwd = namei("/"); - - p->state = RUNNABLE; -} - -// Grow current process's memory by n bytes. -// Return 0 on success, -1 on failure. -int growproc(int n) -{ - uint sz; - - sz = proc->sz; - - if(n > 0){ - if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0) { - return -1; - } - - } else if(n < 0){ - if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0) { - return -1; - } - } - - proc->sz = sz; - switchuvm(proc); - - return 0; -} - -// Create a new process copying p as the parent. -// Sets up stack to return as if from system call. -// Caller must set state of returned proc to RUNNABLE. -int fork(void) -{ - int i, pid; - struct proc *np; - - // Allocate process. - if((np = allocproc()) == 0) { - return -1; - } - - // Copy process state from p. - if((np->pgdir = copyuvm(proc->pgdir, proc->sz)) == 0){ - free_page(np->kstack); - np->kstack = 0; - np->state = UNUSED; - return -1; - } - - np->sz = proc->sz; - np->parent = proc; - // *np->tf = *proc->tf; // This generate memcpy4 which is not in libgcc.a - memmove(np->tf, proc->tf, sizeof(*np->tf)); - - // Clear r0 so that fork returns 0 in the child. - np->tf->r0 = 0; - - for(i = 0; i < NOFILE; i++) { - if(proc->ofile[i]) { - np->ofile[i] = filedup(proc->ofile[i]); - } - } - - np->cwd = idup(proc->cwd); - - pid = np->pid; - np->state = RUNNABLE; - safestrcpy(np->name, proc->name, sizeof(proc->name)); - - return pid; -} - -// Exit the current process. Does not return. -// An exited process remains in the zombie state -// until its parent calls wait() to find out it exited. -void exit(void) -{ - struct proc *p; - int fd; - - if(proc == initproc) { - panic("init exiting"); - } - - // Close all open files. - for(fd = 0; fd < NOFILE; fd++){ - if(proc->ofile[fd]){ - fileclose(proc->ofile[fd]); - proc->ofile[fd] = 0; - } - } - - iput(proc->cwd); - proc->cwd = 0; - - acquire(&ptable.lock); - - // Parent might be sleeping in wait(). - wakeup1(proc->parent); - - // Pass abandoned children to init. - for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ - if(p->parent == proc){ - p->parent = initproc; - - if(p->state == ZOMBIE) { - wakeup1(initproc); - } - } - } - - // Jump into the scheduler, never to return. - proc->state = ZOMBIE; - sched(); - - panic("zombie exit"); -} - -// Wait for a child process to exit and return its pid. -// Return -1 if this process has no children. -int wait(void) -{ - struct proc *p; - int havekids, pid; - - acquire(&ptable.lock); - - for(;;){ - // Scan through table looking for zombie children. - havekids = 0; - - for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ - if(p->parent != proc) { - continue; - } - - havekids = 1; - - if(p->state == ZOMBIE){ - // Found one. - pid = p->pid; - free_page(p->kstack); - p->kstack = 0; - freevm(p->pgdir); - p->state = UNUSED; - p->pid = 0; - p->parent = 0; - p->name[0] = 0; - p->killed = 0; - release(&ptable.lock); - - return pid; - } - } - - // No point waiting if we don't have any children. - if(!havekids || proc->killed){ - release(&ptable.lock); - return -1; - } - - // Wait for children to exit. (See wakeup1 call in proc_exit.) - sleep(proc, &ptable.lock); //DOC: wait-sleep - } -} - -//PAGEBREAK: 42 -// Per-CPU process scheduler. -// Each CPU calls scheduler() after setting itself up. -// Scheduler never returns. It loops, doing: -// - choose a process to run -// - swtch to start running that process -// - eventually that process transfers control -// via swtch back to the scheduler. -void scheduler(void) -{ - struct proc *p; - - for(;;){ - // Enable interrupts on this processor. - sti(); - - // Loop over process table looking for process to run. - acquire(&ptable.lock); - - for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ - if(p->state != RUNNABLE) { - continue; - } - - // Switch to chosen process. It is the process's job - // to release ptable.lock and then reacquire it - // before jumping back to us. - proc = p; - switchuvm(p); - - p->state = RUNNING; - - swtch(&cpu->scheduler, proc->context); - // Process is done running for now. - // It should have changed its p->state before coming back. - proc = 0; - } - - release(&ptable.lock); - } -} - -__code cbc_sched(__code(*next)()) -{ - int intena; - - if(!holding(&ptable.lock)) { - panic("sched ptable.lock"); - } - - if(cpu->ncli != 1) { - panic("sched locks"); - } - - if(proc->state == RUNNING) { - panic("sched running"); - } - - if(int_enabled ()) { - panic("sched interruptible"); - } - - intena = cpu->intena; - swtch(&proc->context, cpu->scheduler); - cpu->intena = intena; - - goto next(); -} - - -// Enter scheduler. Must hold only ptable.lock -// and have changed proc->state. -void sched(void) -{ - int intena; - - //show_callstk ("sched"); - - if(!holding(&ptable.lock)) { - panic("sched ptable.lock"); - } - - if(cpu->ncli != 1) { - panic("sched locks"); - } - - if(proc->state == RUNNING) { - panic("sched running"); - } - - if(int_enabled ()) { - panic("sched interruptible"); - } - - intena = cpu->intena; - swtch(&proc->context, cpu->scheduler); - cpu->intena = intena; -} - -// Give up the CPU for one scheduling round. -void yield(void) -{ - acquire(&ptable.lock); //DOC: yieldlock - proc->state = RUNNABLE; - sched(); - release(&ptable.lock); -} - -// A fork child's very first scheduling by scheduler() -// will swtch here. "Return" to user space. -void forkret(void) -{ - static int first = 1; - - // Still holding ptable.lock from scheduler. - release(&ptable.lock); - - if (first) { - // Some initialization functions must be run in the context - // of a regular process (e.g., they call sleep), and thus cannot - // be run from main(). - first = 0; - initlog(); - } - - // Return to "caller", actually trapret (see allocproc). -} - -__code cbc_sleep1() -{ - struct spinlock *lk = proc->lk; - // Tidy up. - proc->chan = 0; - - // Reacquire original lock. - if(lk != &ptable.lock){ //DOC: sleeplock2 - release(&ptable.lock); - acquire(lk); - } - goto proc->cbc_next(); -} - -__code cbc_sleep(void *chan, struct spinlock *lk, __code(*next1)()) -{ - //show_callstk("sleep"); - - if(proc == 0) { - panic("sleep"); - } - - if(lk == 0) { - panic("sleep without lk"); - } - - if(lk != &ptable.lock){ //DOC: sleeplock0 - acquire(&ptable.lock); //DOC: sleeplock1 - release(lk); - } - proc->chan = chan; - proc->state = SLEEPING; - proc->lk = lk; - proc->cbc_next = next1; - - goto cbc_sched(cbc_sleep1); -} - -// Atomically release lock and sleep on chan. -// Reacquires lock when awakened. -void sleep(void *chan, struct spinlock *lk) -{ - //show_callstk("sleep"); - - if(proc == 0) { - panic("sleep"); - } - - if(lk == 0) { - panic("sleep without lk"); - } - - // Must acquire ptable.lock in order to change p->state and then call - // sched. Once we hold ptable.lock, we can be guaranteed that we won't - // miss any wakeup (wakeup runs with ptable.lock locked), so it's okay - // to release lk. - if(lk != &ptable.lock){ //DOC: sleeplock0 - acquire(&ptable.lock); //DOC: sleeplock1 - release(lk); - } - - // Go to sleep. - proc->chan = chan; - proc->state = SLEEPING; - sched(); - - // Tidy up. - proc->chan = 0; - - // Reacquire original lock. - if(lk != &ptable.lock){ //DOC: sleeplock2 - release(&ptable.lock); - acquire(lk); - } -} - -//PAGEBREAK! -// Wake up all processes sleeping on chan. The ptable lock must be held. -static void wakeup1(void *chan) -{ - struct proc *p; - - for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) { - if(p->state == SLEEPING && p->chan == chan) { - p->state = RUNNABLE; - } - } -} - -__code cbc_wakeup1(void *chan) -{ - struct proc *p; - - for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) { - if(p->state == SLEEPING && p->chan == chan) { - p->state = RUNNABLE; - } - } - - release(&ptable.lock); - goto proc->cbc_next(); -} - -__code cbc_wakeup(void *chan, __code(*next1)()) -{ - acquire(&ptable.lock); - proc->cbc_next = next1; - cbc_wakeup1(chan); -} - -// Wake up all processes sleeping on chan. -void wakeup(void *chan) -{ - acquire(&ptable.lock); - wakeup1(chan); - release(&ptable.lock); -} - -// Kill the process with the given pid. Process won't exit until it returns -// to user space (see trap in trap.c). -int kill(int pid) -{ - struct proc *p; - - acquire(&ptable.lock); - - for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ - if(p->pid == pid){ - p->killed = 1; - - // Wake process from sleep if necessary. - if(p->state == SLEEPING) { - p->state = RUNNABLE; - } - - release(&ptable.lock); - return 0; - } - } - - release(&ptable.lock); - return -1; -} - -//PAGEBREAK: 36 -// Print a process listing to console. For debugging. Runs when user -// types ^P on console. No lock to avoid wedging a stuck machine further. -void procdump(void) -{ - static char *states[] = { - [UNUSED] ="unused", - [EMBRYO] ="embryo", - [SLEEPING] ="sleep ", - [RUNNABLE] ="runble", - [RUNNING] ="run ", - [ZOMBIE] ="zombie" - }; - - struct proc *p; - char *state; - - for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ - if(p->state == UNUSED) { - continue; - } - - if(p->state >= 0 && p->state < NELEM(states) && states[p->state]) { - state = states[p->state]; - } else { - state = "???"; - } - - cprintf("%d %s %d:%s %d\n", p->pid, state, p->pid, p->name, p->parent->pid); - } - - show_callstk("procdump: \n"); -} - - diff -r fadfd62d6b14 -r 214d21c891c7 src/proc.cbc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/proc.cbc Mon Jun 03 18:12:44 2019 +0900 @@ -0,0 +1,622 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "arm.h" +#include "proc.h" +#include "spinlock.h" + +#define __ncode __code + +// +// Process initialization: +// process initialize is somewhat tricky. +// 1. We need to fake the kernel stack of a new process as if the process +// has been interrupt (a trapframe on the stack), this would allow us +// to "return" to the correct user instruction. +// 2. We also need to fake the kernel execution for this new process. When +// swtch switches to this (new) process, it will switch to its stack, +// and reload registers with the saved context. We use forkret as the +// return address (in lr register). (In x86, it will be the return address +// pushed on the stack by the process.) +// +// The design of context switch in xv6 is interesting: after initialization, +// each CPU executes in the scheduler() function. The context switch is not +// between two processes, but instead, between the scheduler. Think of scheduler +// as the idle process. +// +struct { + struct spinlock lock; + struct proc proc[NPROC]; +} ptable; + +static struct proc *initproc; +struct proc *proc; + +int nextpid = 1; +extern void forkret(void); +extern void trapret(void); + +static void wakeup1(void *chan); + +void pinit(void) +{ + initlock(&ptable.lock, "ptable"); +} + +//PAGEBREAK: 32 +// Look in the process table for an UNUSED proc. +// If found, change state to EMBRYO and initialize +// state required to run in the kernel. +// Otherwise return 0. +static struct proc* allocproc(void) +{ + struct proc *p; + char *sp; + + acquire(&ptable.lock); + + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) { + if(p->state == UNUSED) { + goto found; + } + + } + + release(&ptable.lock); + return 0; + + found: + p->state = EMBRYO; + p->pid = nextpid++; + release(&ptable.lock); + + // Allocate kernel stack. + if((p->kstack = alloc_page ()) == 0){ + p->state = UNUSED; + return 0; + } + + sp = p->kstack + KSTACKSIZE; + + // Leave room for trap frame. + sp -= sizeof (*p->tf); + p->tf = (struct trapframe*)sp; + + // Set up new context to start executing at forkret, + // which returns to trapret. + sp -= 4; + *(uint*)sp = (uint)trapret; + + sp -= 4; + *(uint*)sp = (uint)p->kstack + KSTACKSIZE; + + sp -= sizeof (*p->context); + p->context = (struct context*)sp; + memset(p->context, 0, sizeof(*p->context)); + + // skip the push {fp, lr} instruction in the prologue of forkret. + // This is different from x86, in which the harderware pushes return + // address before executing the callee. In ARM, return address is + // loaded into the lr register, and push to the stack by the callee + // (if and when necessary). We need to skip that instruction and let + // it use our implementation. + p->context->lr = (uint)forkret+4; + + return p; +} + +void error_init () +{ + panic ("failed to craft first process\n"); +} + + +//PAGEBREAK: 32 +// hand-craft the first user process. We link initcode.S into the kernel +// as a binary, the linker will generate __binary_initcode_start/_size +void userinit(void) +{ + struct proc *p; + extern char _binary_initcode_start[], _binary_initcode_size[]; + + p = allocproc(); + initproc = p; + + if((p->pgdir = kpt_alloc()) == NULL) { + panic("userinit: out of memory?"); + } + + inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size); + + p->sz = PTE_SZ; + + // craft the trapframe as if + memset(p->tf, 0, sizeof(*p->tf)); + + p->tf->r14_svc = (uint)error_init; + p->tf->spsr = spsr_usr (); + p->tf->sp_usr = PTE_SZ; // set the user stack + p->tf->lr_usr = 0; + + // set the user pc. The actual pc loaded into r15_usr is in + // p->tf, the trapframe. + p->tf->pc = 0; // beginning of initcode.S + + safestrcpy(p->name, "initcode", sizeof(p->name)); + p->cwd = namei("/"); + + p->state = RUNNABLE; +} + +// Grow current process's memory by n bytes. +// Return 0 on success, -1 on failure. +int growproc(int n) +{ + uint sz; + + sz = proc->sz; + + if(n > 0){ + if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0) { + return -1; + } + + } else if(n < 0){ + if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0) { + return -1; + } + } + + proc->sz = sz; + switchuvm(proc); + + return 0; +} + +// Create a new process copying p as the parent. +// Sets up stack to return as if from system call. +// Caller must set state of returned proc to RUNNABLE. +int fork(void) +{ + int i, pid; + struct proc *np; + + // Allocate process. + if((np = allocproc()) == 0) { + return -1; + } + + // Copy process state from p. + if((np->pgdir = copyuvm(proc->pgdir, proc->sz)) == 0){ + free_page(np->kstack); + np->kstack = 0; + np->state = UNUSED; + return -1; + } + + np->sz = proc->sz; + np->parent = proc; + // *np->tf = *proc->tf; // This generate memcpy4 which is not in libgcc.a + memmove(np->tf, proc->tf, sizeof(*np->tf)); + + // Clear r0 so that fork returns 0 in the child. + np->tf->r0 = 0; + + for(i = 0; i < NOFILE; i++) { + if(proc->ofile[i]) { + np->ofile[i] = filedup(proc->ofile[i]); + } + } + + np->cwd = idup(proc->cwd); + + pid = np->pid; + np->state = RUNNABLE; + safestrcpy(np->name, proc->name, sizeof(proc->name)); + + return pid; +} + +// Exit the current process. Does not return. +// An exited process remains in the zombie state +// until its parent calls wait() to find out it exited. +void exit(void) +{ + struct proc *p; + int fd; + + if(proc == initproc) { + panic("init exiting"); + } + + // Close all open files. + for(fd = 0; fd < NOFILE; fd++){ + if(proc->ofile[fd]){ + fileclose(proc->ofile[fd]); + proc->ofile[fd] = 0; + } + } + + iput(proc->cwd); + proc->cwd = 0; + + acquire(&ptable.lock); + + // Parent might be sleeping in wait(). + wakeup1(proc->parent); + + // Pass abandoned children to init. + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->parent == proc){ + p->parent = initproc; + + if(p->state == ZOMBIE) { + wakeup1(initproc); + } + } + } + + // Jump into the scheduler, never to return. + proc->state = ZOMBIE; + sched(); + + panic("zombie exit"); +} + +// Wait for a child process to exit and return its pid. +// Return -1 if this process has no children. +int wait(void) +{ + struct proc *p; + int havekids, pid; + + acquire(&ptable.lock); + + for(;;){ + // Scan through table looking for zombie children. + havekids = 0; + + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->parent != proc) { + continue; + } + + havekids = 1; + + if(p->state == ZOMBIE){ + // Found one. + pid = p->pid; + free_page(p->kstack); + p->kstack = 0; + freevm(p->pgdir); + p->state = UNUSED; + p->pid = 0; + p->parent = 0; + p->name[0] = 0; + p->killed = 0; + release(&ptable.lock); + + return pid; + } + } + + // No point waiting if we don't have any children. + if(!havekids || proc->killed){ + release(&ptable.lock); + return -1; + } + + // Wait for children to exit. (See wakeup1 call in proc_exit.) + sleep(proc, &ptable.lock); //DOC: wait-sleep + } +} + +//PAGEBREAK: 42 +// Per-CPU process scheduler. +// Each CPU calls scheduler() after setting itself up. +// Scheduler never returns. It loops, doing: +// - choose a process to run +// - swtch to start running that process +// - eventually that process transfers control +// via swtch back to the scheduler. +void scheduler(void) +{ + struct proc *p; + + for(;;){ + // Enable interrupts on this processor. + sti(); + + // Loop over process table looking for process to run. + acquire(&ptable.lock); + + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->state != RUNNABLE) { + continue; + } + + // Switch to chosen process. It is the process's job + // to release ptable.lock and then reacquire it + // before jumping back to us. + proc = p; + switchuvm(p); + + p->state = RUNNING; + + swtch(&cpu->scheduler, proc->context); + // Process is done running for now. + // It should have changed its p->state before coming back. + proc = 0; + } + + release(&ptable.lock); + } +} + +__ncode cbc_sched(__code(*next)()) +{ + int intena; + + if(!holding(&ptable.lock)) { + panic("sched ptable.lock"); + } + + if(cpu->ncli != 1) { + panic("sched locks"); + } + + if(proc->state == RUNNING) { + panic("sched running"); + } + + if(int_enabled ()) { + panic("sched interruptible"); + } + + intena = cpu->intena; + swtch(&proc->context, cpu->scheduler); + cpu->intena = intena; + + goto next(); +} + + +// Enter scheduler. Must hold only ptable.lock +// and have changed proc->state. +void sched(void) +{ + int intena; + + //show_callstk ("sched"); + + if(!holding(&ptable.lock)) { + panic("sched ptable.lock"); + } + + if(cpu->ncli != 1) { + panic("sched locks"); + } + + if(proc->state == RUNNING) { + panic("sched running"); + } + + if(int_enabled ()) { + panic("sched interruptible"); + } + + intena = cpu->intena; + swtch(&proc->context, cpu->scheduler); + cpu->intena = intena; +} + +// Give up the CPU for one scheduling round. +void yield(void) +{ + acquire(&ptable.lock); //DOC: yieldlock + proc->state = RUNNABLE; + sched(); + release(&ptable.lock); +} + +// A fork child's very first scheduling by scheduler() +// will swtch here. "Return" to user space. +void forkret(void) +{ + static int first = 1; + + // Still holding ptable.lock from scheduler. + release(&ptable.lock); + + if (first) { + // Some initialization functions must be run in the context + // of a regular process (e.g., they call sleep), and thus cannot + // be run from main(). + first = 0; + initlog(); + } + + // Return to "caller", actually trapret (see allocproc). +} + +__ncode cbc_sleep1() +{ + struct spinlock *lk = proc->lk; + // Tidy up. + proc->chan = 0; + + // Reacquire original lock. + if(lk != &ptable.lock){ //DOC: sleeplock2 + release(&ptable.lock); + acquire(lk); + } + goto proc->cbc_next(); +} + +__ncode cbc_sleep(void *chan, struct spinlock *lk, __code(*next1)()) +{ + //show_callstk("sleep"); + + if(proc == 0) { + panic("sleep"); + } + + if(lk == 0) { + panic("sleep without lk"); + } + + if(lk != &ptable.lock){ //DOC: sleeplock0 + acquire(&ptable.lock); //DOC: sleeplock1 + release(lk); + } + proc->chan = chan; + proc->state = SLEEPING; + proc->lk = lk; + proc->cbc_next = next1; + + goto cbc_sched(cbc_sleep1); +} + +// Atomically release lock and sleep on chan. +// Reacquires lock when awakened. +void sleep(void *chan, struct spinlock *lk) +{ + //show_callstk("sleep"); + + if(proc == 0) { + panic("sleep"); + } + + if(lk == 0) { + panic("sleep without lk"); + } + + // Must acquire ptable.lock in order to change p->state and then call + // sched. Once we hold ptable.lock, we can be guaranteed that we won't + // miss any wakeup (wakeup runs with ptable.lock locked), so it's okay + // to release lk. + if(lk != &ptable.lock){ //DOC: sleeplock0 + acquire(&ptable.lock); //DOC: sleeplock1 + release(lk); + } + + // Go to sleep. + proc->chan = chan; + proc->state = SLEEPING; + sched(); + + // Tidy up. + proc->chan = 0; + + // Reacquire original lock. + if(lk != &ptable.lock){ //DOC: sleeplock2 + release(&ptable.lock); + acquire(lk); + } +} + +//PAGEBREAK! +// Wake up all processes sleeping on chan. The ptable lock must be held. +static void wakeup1(void *chan) +{ + struct proc *p; + + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) { + if(p->state == SLEEPING && p->chan == chan) { + p->state = RUNNABLE; + } + } +} + +__ncode cbc_wakeup1(void *chan) +{ + struct proc *p; + + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) { + if(p->state == SLEEPING && p->chan == chan) { + p->state = RUNNABLE; + } + } + + release(&ptable.lock); + goto proc->cbc_next(); +} + +__ncode cbc_wakeup(void *chan, __code(*next1)()) +{ + acquire(&ptable.lock); + proc->cbc_next = next1; + cbc_wakeup1(chan); +} + +// Wake up all processes sleeping on chan. +void wakeup(void *chan) +{ + acquire(&ptable.lock); + wakeup1(chan); + release(&ptable.lock); +} + +// Kill the process with the given pid. Process won't exit until it returns +// to user space (see trap in trap.c). +int kill(int pid) +{ + struct proc *p; + + acquire(&ptable.lock); + + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->pid == pid){ + p->killed = 1; + + // Wake process from sleep if necessary. + if(p->state == SLEEPING) { + p->state = RUNNABLE; + } + + release(&ptable.lock); + return 0; + } + } + + release(&ptable.lock); + return -1; +} + +//PAGEBREAK: 36 +// Print a process listing to console. For debugging. Runs when user +// types ^P on console. No lock to avoid wedging a stuck machine further. +void procdump(void) +{ + static char *states[] = { + [UNUSED] ="unused", + [EMBRYO] ="embryo", + [SLEEPING] ="sleep ", + [RUNNABLE] ="runble", + [RUNNING] ="run ", + [ZOMBIE] ="zombie" + }; + + struct proc *p; + char *state; + + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ + if(p->state == UNUSED) { + continue; + } + + if(p->state >= 0 && p->state < NELEM(states) && states[p->state]) { + state = states[p->state]; + } else { + state = "???"; + } + + cprintf("%d %s %d:%s %d\n", p->pid, state, p->pid, p->name, p->parent->pid); + } + + show_callstk("procdump: \n"); +} + + diff -r fadfd62d6b14 -r 214d21c891c7 src/spinlock.c --- a/src/spinlock.c Tue May 28 22:27:01 2019 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -// Mutual exclusion spin locks. - -#include "types.h" -#include "defs.h" -#include "param.h" -#include "arm.h" -#include "memlayout.h" -#include "mmu.h" -#include "proc.h" -#include "spinlock.h" - -void initlock(struct spinlock *lk, char *name) -{ - lk->name = name; - lk->locked = 0; - lk->cpu = 0; -} - -// For single CPU systems, there is no need for spinlock. -// Add the support when multi-processor is supported. - - -// Acquire the lock. -// Loops (spins) until the lock is acquired. -// Holding a lock for a long time may cause -// other CPUs to waste time spinning to acquire it. -void acquire(struct spinlock *lk) -{ - pushcli(); // disable interrupts to avoid deadlock. - lk->locked = 1; // set the lock status to make the kernel happy - -#if 0 - if(holding(lk)) - panic("acquire"); - - // The xchg is atomic. - // It also serializes, so that reads after acquire are not - // reordered before it. - while(xchg(&lk->locked, 1) != 0) - ; - - // Record info about lock acquisition for debugging. - lk->cpu = cpu; - getcallerpcs(get_fp(), lk->pcs); - -#endif -} - -/* -void cbc_acquire(struct spinlock *lk, __code (*next)(int ret)) -{ - pushcli(); // disable interrupts to avoid deadlock. - lk->locked = 1; // set the lock status to make the kernel happy - -#if 0 - if(holding(lk)) - panic("acquire"); - - // The xchg is atomic. - // It also serializes, so that reads after acquire are not - // reordered before it. - while(xchg(&lk->locked, 1) != 0) - ; - - // Record info about lock acquisition for debugging. - lk->cpu = cpu; - getcallerpcs(get_fp(), lk->pcs); - -#endif - goto next(); -} -*/ - -/* -// Release the lock. -void cbc_release(struct spinlock *lk, __code (*next)(int ret)) -{ -#if 0 - if(!holding(lk)) - panic("release"); - - lk->pcs[0] = 0; - lk->cpu = 0; - - // The xchg serializes, so that reads before release are - // not reordered after it. The 1996 PentiumPro manual (Volume 3, - // 7.2) says reads can be carried out speculatively and in - // any order, which implies we need to serialize here. - // But the 2007 Intel 64 Architecture Memory Ordering White - // Paper says that Intel 64 and IA-32 will not move a load - // after a store. So lock->locked = 0 would work here. - // The xchg being asm volatile ensures gcc emits it after - // the above assignments (and after the critical section). - xchg(&lk->locked, 0); -#endif - - lk->locked = 0; // set the lock state to keep the kernel happy - popcli(); - goto next(); -} -*/ - -void release(struct spinlock *lk) -{ -#if 0 - if(!holding(lk)) - panic("release"); - - lk->pcs[0] = 0; - lk->cpu = 0; - - // The xchg serializes, so that reads before release are - // not reordered after it. The 1996 PentiumPro manual (Volume 3, - // 7.2) says reads can be carried out speculatively and in - // any order, which implies we need to serialize here. - // But the 2007 Intel 64 Architecture Memory Ordering White - // Paper says that Intel 64 and IA-32 will not move a load - // after a store. So lock->locked = 0 would work here. - // The xchg being asm volatile ensures gcc emits it after - // the above assignments (and after the critical section). - xchg(&lk->locked, 0); -#endif - - lk->locked = 0; // set the lock state to keep the kernel happy - popcli(); -} - - -// Check whether this cpu is holding the lock. -int holding(struct spinlock *lock) -{ - return lock->locked; // && lock->cpu == cpus; -} - diff -r fadfd62d6b14 -r 214d21c891c7 src/spinlock.cbc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/spinlock.cbc Mon Jun 03 18:12:44 2019 +0900 @@ -0,0 +1,136 @@ +// Mutual exclusion spin locks. + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "arm.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "spinlock.h" + +#define __ncode __code +# +void initlock(struct spinlock *lk, char *name) +{ + lk->name = name; + lk->locked = 0; + lk->cpu = 0; +} + +// For single CPU systems, there is no need for spinlock. +// Add the support when multi-processor is supported. + + +// Acquire the lock. +// Loops (spins) until the lock is acquired. +// Holding a lock for a long time may cause +// other CPUs to waste time spinning to acquire it. +void acquire(struct spinlock *lk) +{ + pushcli(); // disable interrupts to avoid deadlock. + lk->locked = 1; // set the lock status to make the kernel happy + +#if 0 + if(holding(lk)) + panic("acquire"); + + // The xchg is atomic. + // It also serializes, so that reads after acquire are not + // reordered before it. + while(xchg(&lk->locked, 1) != 0) + ; + + // Record info about lock acquisition for debugging. + lk->cpu = cpu; + getcallerpcs(get_fp(), lk->pcs); + +#endif +} + +/* +void cbc_acquire(struct spinlock *lk, __code (*next)(int ret)) +{ + pushcli(); // disable interrupts to avoid deadlock. + lk->locked = 1; // set the lock status to make the kernel happy + +#if 0 + if(holding(lk)) + panic("acquire"); + + // The xchg is atomic. + // It also serializes, so that reads after acquire are not + // reordered before it. + while(xchg(&lk->locked, 1) != 0) + ; + + // Record info about lock acquisition for debugging. + lk->cpu = cpu; + getcallerpcs(get_fp(), lk->pcs); + +#endif + goto next(); +} +*/ + +/* +// Release the lock. +void cbc_release(struct spinlock *lk, __code (*next)(int ret)) +{ +#if 0 + if(!holding(lk)) + panic("release"); + + lk->pcs[0] = 0; + lk->cpu = 0; + + // The xchg serializes, so that reads before release are + // not reordered after it. The 1996 PentiumPro manual (Volume 3, + // 7.2) says reads can be carried out speculatively and in + // any order, which implies we need to serialize here. + // But the 2007 Intel 64 Architecture Memory Ordering White + // Paper says that Intel 64 and IA-32 will not move a load + // after a store. So lock->locked = 0 would work here. + // The xchg being asm volatile ensures gcc emits it after + // the above assignments (and after the critical section). + xchg(&lk->locked, 0); +#endif + + lk->locked = 0; // set the lock state to keep the kernel happy + popcli(); + goto next(); +} +*/ + +void release(struct spinlock *lk) +{ +#if 0 + if(!holding(lk)) + panic("release"); + + lk->pcs[0] = 0; + lk->cpu = 0; + + // The xchg serializes, so that reads before release are + // not reordered after it. The 1996 PentiumPro manual (Volume 3, + // 7.2) says reads can be carried out speculatively and in + // any order, which implies we need to serialize here. + // But the 2007 Intel 64 Architecture Memory Ordering White + // Paper says that Intel 64 and IA-32 will not move a load + // after a store. So lock->locked = 0 would work here. + // The xchg being asm volatile ensures gcc emits it after + // the above assignments (and after the critical section). + xchg(&lk->locked, 0); +#endif + + lk->locked = 0; // set the lock state to keep the kernel happy + popcli(); +} + + +// Check whether this cpu is holding the lock. +int holding(struct spinlock *lock) +{ + return lock->locked; // && lock->cpu == cpus; +} + diff -r fadfd62d6b14 -r 214d21c891c7 src/syscall.c --- a/src/syscall.c Tue May 28 22:27:01 2019 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,190 +0,0 @@ -#include "types.h" -#include "defs.h" -#include "param.h" -#include "memlayout.h" -#include "mmu.h" -#include "proc.h" -#include "arm.h" -#include "syscall.h" - -// User code makes a system call with INT T_SYSCALL. System call number -// in r0. Arguments on the stack, from the user call to the C library -// system call function. The saved user sp points to the first argument. - -// Fetch the int at addr from the current process. -int fetchint(uint addr, int *ip) -{ - if(addr >= proc->sz || addr+4 > proc->sz) { - return -1; - } - - *ip = *(int*)(addr); - return 0; -} - -// Fetch the nul-terminated string at addr from the current process. -// Doesn't actually copy the string - just sets *pp to point at it. -// Returns length of string, not including nul. -int fetchstr(uint addr, char **pp) -{ - char *s, *ep; - - if(addr >= proc->sz) { - return -1; - } - - *pp = (char*)addr; - ep = (char*)proc->sz; - - for(s = *pp; s < ep; s++) { - if(*s == 0) { - return s - *pp; - } - } - - return -1; -} - -// Fetch the nth (starting from 0) 32-bit system call argument. -// In our ABI, r0 contains system call index, r1-r4 contain parameters. -// now we support system calls with at most 4 parameters. -int argint(int n, int *ip) -{ - if (n > 3) { - panic ("too many system call parameters\n"); - } - - *ip = *(&proc->tf->r1 + n); - - return 0; -} - -// Fetch the nth word-sized system call argument as a pointer -// to a block of memory of size n bytes. Check that the pointer -// lies within the process address space. -int argptr(int n, char **pp, int size) -{ - int i; - - if(argint(n, &i) < 0) { - return -1; - } - - if((uint)i >= proc->sz || (uint)i+size > proc->sz) { - return -1; - } - - *pp = (char*)i; - return 0; -} - -// Fetch the nth word-sized system call argument as a string pointer. -// Check that the pointer is valid and the string is nul-terminated. -// (There is no shared writable memory, so the string can't change -// between this check and being used by the kernel.) -int argstr(int n, char **pp) -{ - int addr; - - if(argint(n, &addr) < 0) { - return -1; - } - - return fetchstr(addr, pp); -} - -extern int sys_chdir(void); -extern int sys_close(void); -extern int sys_dup(void); -extern int sys_exec(void); -extern int sys_exit(void); -extern int sys_fork(void); -extern int sys_fstat(void); -extern int sys_getpid(void); -extern int sys_kill(void); -extern int sys_link(void); -extern int sys_mkdir(void); -extern int sys_mknod(void); -extern int sys_open(void); -extern int sys_pipe(void); -extern int sys_read(void); -extern int sys_sbrk(void); -extern int sys_sleep(void); -extern int sys_unlink(void); -extern int sys_wait(void); -extern int sys_write(void); -extern int sys_uptime(void); - -extern __code cbc_read(__code(*)(int)); - -static int (*syscalls[])(void) = { - [SYS_fork] =sys_fork, - [SYS_exit] =sys_exit, - [SYS_wait] =sys_wait, - [SYS_pipe] =sys_pipe, - [SYS_read] =sys_read, - [SYS_kill] =sys_kill, - [SYS_exec] =sys_exec, - [SYS_fstat] =sys_fstat, - [SYS_chdir] =sys_chdir, - [SYS_dup] =sys_dup, - [SYS_getpid] =sys_getpid, - [SYS_sbrk] =sys_sbrk, - [SYS_sleep] =sys_sleep, - [SYS_uptime] =sys_uptime, - [SYS_open] =sys_open, - [SYS_write] =sys_write, - [SYS_mknod] =sys_mknod, - [SYS_unlink] =sys_unlink, - [SYS_link] =sys_link, - [SYS_mkdir] =sys_mkdir, - [SYS_close] =sys_close, -}; - -static __code (*cbccodes[])(__code (*)(int)) = { - [SYS_cbc_read] = cbc_read, -}; - -__code cbc_trap_return(){ - return; -} - -__code cbc_ret(int ret){ - int num = proc->cbc_arg.cbc_console_arg.num; - if (num != SYS_exec) { - proc->tf->r0 = ret; - } - goto cbc_trap_return(); -} - -void syscall(void) -{ - int num; - int ret; - - num = proc->tf->r0; - - if (num == 5) - num = 22; - //cprintf ("syscall(%d) from %s(%d)\n", num, proc->name, proc->pid); - - if((num >= NELEM(syscalls)) && (num <= NELEM(cbccodes)) && cbccodes[num]) { - proc->cbc_arg.cbc_console_arg.num = num; - goto (cbccodes[num])(cbc_ret); - } - - - if((num > 0) && (num < NELEM(syscalls)) && syscalls[num]) { - ret = syscalls[num](); - - // in ARM, parameters to main (argc, argv) are passed in r0 and r1 - // do not set the return value if it is SYS_exec (the user program - // anyway does not expect us to return anything). - if (num != SYS_exec) { - proc->tf->r0 = ret; - } - } else { - cprintf("%d %s: unknown sys call %d\n", proc->pid, proc->name, num); - proc->tf->r0 = -1; - } -} diff -r fadfd62d6b14 -r 214d21c891c7 src/syscall.cbc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/syscall.cbc Mon Jun 03 18:12:44 2019 +0900 @@ -0,0 +1,192 @@ +#include "types.h" +#include "defs.h" +#include "param.h" +#include "memlayout.h" +#include "mmu.h" +#include "proc.h" +#include "arm.h" +#include "syscall.h" + +#define __ncode __code +# +// User code makes a system call with INT T_SYSCALL. System call number +// in r0. Arguments on the stack, from the user call to the C library +// system call function. The saved user sp points to the first argument. + +// Fetch the int at addr from the current process. +int fetchint(uint addr, int *ip) +{ + if(addr >= proc->sz || addr+4 > proc->sz) { + return -1; + } + + *ip = *(int*)(addr); + return 0; +} + +// Fetch the nul-terminated string at addr from the current process. +// Doesn't actually copy the string - just sets *pp to point at it. +// Returns length of string, not including nul. +int fetchstr(uint addr, char **pp) +{ + char *s, *ep; + + if(addr >= proc->sz) { + return -1; + } + + *pp = (char*)addr; + ep = (char*)proc->sz; + + for(s = *pp; s < ep; s++) { + if(*s == 0) { + return s - *pp; + } + } + + return -1; +} + +// Fetch the nth (starting from 0) 32-bit system call argument. +// In our ABI, r0 contains system call index, r1-r4 contain parameters. +// now we support system calls with at most 4 parameters. +int argint(int n, int *ip) +{ + if (n > 3) { + panic ("too many system call parameters\n"); + } + + *ip = *(&proc->tf->r1 + n); + + return 0; +} + +// Fetch the nth word-sized system call argument as a pointer +// to a block of memory of size n bytes. Check that the pointer +// lies within the process address space. +int argptr(int n, char **pp, int size) +{ + int i; + + if(argint(n, &i) < 0) { + return -1; + } + + if((uint)i >= proc->sz || (uint)i+size > proc->sz) { + return -1; + } + + *pp = (char*)i; + return 0; +} + +// Fetch the nth word-sized system call argument as a string pointer. +// Check that the pointer is valid and the string is nul-terminated. +// (There is no shared writable memory, so the string can't change +// between this check and being used by the kernel.) +int argstr(int n, char **pp) +{ + int addr; + + if(argint(n, &addr) < 0) { + return -1; + } + + return fetchstr(addr, pp); +} + +extern int sys_chdir(void); +extern int sys_close(void); +extern int sys_dup(void); +extern int sys_exec(void); +extern int sys_exit(void); +extern int sys_fork(void); +extern int sys_fstat(void); +extern int sys_getpid(void); +extern int sys_kill(void); +extern int sys_link(void); +extern int sys_mkdir(void); +extern int sys_mknod(void); +extern int sys_open(void); +extern int sys_pipe(void); +extern int sys_read(void); +extern int sys_sbrk(void); +extern int sys_sleep(void); +extern int sys_unlink(void); +extern int sys_wait(void); +extern int sys_write(void); +extern int sys_uptime(void); + +extern __code cbc_read(__code(*)(int)); + +static int (*syscalls[])(void) = { + [SYS_fork] =sys_fork, + [SYS_exit] =sys_exit, + [SYS_wait] =sys_wait, + [SYS_pipe] =sys_pipe, + [SYS_read] =sys_read, + [SYS_kill] =sys_kill, + [SYS_exec] =sys_exec, + [SYS_fstat] =sys_fstat, + [SYS_chdir] =sys_chdir, + [SYS_dup] =sys_dup, + [SYS_getpid] =sys_getpid, + [SYS_sbrk] =sys_sbrk, + [SYS_sleep] =sys_sleep, + [SYS_uptime] =sys_uptime, + [SYS_open] =sys_open, + [SYS_write] =sys_write, + [SYS_mknod] =sys_mknod, + [SYS_unlink] =sys_unlink, + [SYS_link] =sys_link, + [SYS_mkdir] =sys_mkdir, + [SYS_close] =sys_close, +}; + +static __code (*cbccodes[])(__code (*)(int)) = { + [SYS_cbc_read] = cbc_read, +}; + +__ncode cbc_trap_return(){ + return; +} + +__ncode cbc_ret(int ret){ + int num = proc->cbc_arg.cbc_console_arg.num; + if (num != SYS_exec) { + proc->tf->r0 = ret; + } + goto cbc_trap_return(); +} + +void syscall(void) +{ + int num; + int ret; + + num = proc->tf->r0; + + if (num == 5) + num = 22; + //cprintf ("syscall(%d) from %s(%d)\n", num, proc->name, proc->pid); + + if((num >= NELEM(syscalls)) && (num <= NELEM(cbccodes)) && cbccodes[num]) { + proc->cbc_arg.cbc_console_arg.num = num; + goto (cbccodes[num])(cbc_ret); + } + + + if((num > 0) && (num < NELEM(syscalls)) && syscalls[num]) { + ret = syscalls[num](); + + // in ARM, parameters to main (argc, argv) are passed in r0 and r1 + // do not set the return value if it is SYS_exec (the user program + // anyway does not expect us to return anything). + if (num != SYS_exec) { + proc->tf->r0 = ret; + } + } else { + cprintf("%d %s: unknown sys call %d\n", proc->pid, proc->name, num); + proc->tf->r0 = -1; + } +} diff -r fadfd62d6b14 -r 214d21c891c7 src/sysfile.c --- a/src/sysfile.c Tue May 28 22:27:01 2019 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,518 +0,0 @@ -// -// File-system system calls. -// Mostly argument checking, since we don't trust -// user code, and calls into file.c and fs.c. -// - -#include "types.h" -#include "defs.h" -#include "param.h" -#include "stat.h" -#include "mmu.h" -#include "proc.h" -#include "fs.h" -#include "file.h" -#include "fcntl.h" - -// Fetch the nth word-sized system call argument as a file descriptor -// and return both the descriptor and the corresponding struct file. -static int argfd(int n, int *pfd, struct file **pf) -{ - int fd; - struct file *f; - - if(argint(n, &fd) < 0) { - return -1; - } - - if(fd < 0 || fd >= NOFILE || (f=proc->ofile[fd]) == 0) { - return -1; - } - - if(pfd) { - *pfd = fd; - } - - if(pf) { - *pf = f; - } - - return 0; -} - -// Allocate a file descriptor for the given file. -// Takes over file reference from caller on success. -static int fdalloc(struct file *f) -{ - int fd; - - for(fd = 0; fd < NOFILE; fd++){ - if(proc->ofile[fd] == 0){ - proc->ofile[fd] = f; - return fd; - } - } - - return -1; -} - -int sys_dup(void) -{ - struct file *f; - int fd; - - if(argfd(0, 0, &f) < 0) { - return -1; - } - - if((fd=fdalloc(f)) < 0) { - return -1; - } - - filedup(f); - - return fd; -} - -__code cbc_read(__code (*next)(int ret)){ - struct file *f; - int n; - char *p; - - if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) { - goto next(-1); - } - goto cbc_fileread(f, p, n, next); -} - -int sys_read(void) -{ - struct file *f; - int n; - char *p; - - if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) { - return -1; - } - - return fileread(f, p, n); -} - -int sys_write(void) -{ - struct file *f; - int n; - char *p; - - if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) { - return -1; - } - - return filewrite(f, p, n); -} - -int sys_close(void) -{ - int fd; - struct file *f; - - if(argfd(0, &fd, &f) < 0) { - return -1; - } - - proc->ofile[fd] = 0; - fileclose(f); - - return 0; -} - -int sys_fstat(void) -{ - struct file *f; - struct stat *st; - - if(argfd(0, 0, &f) < 0 || argptr(1, (void*)&st, sizeof(*st)) < 0) { - return -1; - } - - return filestat(f, st); -} - -// Create the path new as a link to the same inode as old. -int sys_link(void) -{ - char name[DIRSIZ], *new, *old; - struct inode *dp, *ip; - - if(argstr(0, &old) < 0 || argstr(1, &new) < 0) { - return -1; - } - - if((ip = namei(old)) == 0) { - return -1; - } - - begin_trans(); - - ilock(ip); - - if(ip->type == T_DIR){ - iunlockput(ip); - commit_trans(); - return -1; - } - - ip->nlink++; - iupdate(ip); - iunlock(ip); - - if((dp = nameiparent(new, name)) == 0) { - goto bad; - } - - ilock(dp); - - if(dp->dev != ip->dev || dirlink(dp, name, ip->inum) < 0){ - iunlockput(dp); - goto bad; - } - - iunlockput(dp); - iput(ip); - - commit_trans(); - - return 0; - - bad: - ilock(ip); - ip->nlink--; - iupdate(ip); - iunlockput(ip); - commit_trans(); - return -1; -} - -// Is the directory dp empty except for "." and ".." ? -static int isdirempty(struct inode *dp) -{ - int off; - struct dirent de; - - for(off=2*sizeof(de); offsize; off+=sizeof(de)){ - if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) { - panic("isdirempty: readi"); - } - - if(de.inum != 0) { - return 0; - } - } - return 1; -} - -//PAGEBREAK! -int sys_unlink(void) -{ - struct inode *ip, *dp; - struct dirent de; - char name[DIRSIZ], *path; - uint off; - - if(argstr(0, &path) < 0) { - return -1; - } - - if((dp = nameiparent(path, name)) == 0) { - return -1; - } - - begin_trans(); - - ilock(dp); - - // Cannot unlink "." or "..". - if(namecmp(name, ".") == 0 || namecmp(name, "..") == 0) { - goto bad; - } - - if((ip = dirlookup(dp, name, &off)) == 0) { - goto bad; - } - - ilock(ip); - - if(ip->nlink < 1) { - panic("unlink: nlink < 1"); - } - - if(ip->type == T_DIR && !isdirempty(ip)){ - iunlockput(ip); - goto bad; - } - - memset(&de, 0, sizeof(de)); - - if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) { - panic("unlink: writei"); - } - - if(ip->type == T_DIR){ - dp->nlink--; - iupdate(dp); - } - - iunlockput(dp); - - ip->nlink--; - iupdate(ip); - iunlockput(ip); - - commit_trans(); - - return 0; - - bad: - iunlockput(dp); - commit_trans(); - return -1; -} - -static struct inode* create(char *path, short type, short major, short minor) -{ - uint off; - struct inode *ip, *dp; - char name[DIRSIZ]; - - if((dp = nameiparent(path, name)) == 0) { - return 0; - } - - ilock(dp); - - if((ip = dirlookup(dp, name, &off)) != 0){ - iunlockput(dp); - ilock(ip); - - if(type == T_FILE && ip->type == T_FILE) { - return ip; - } - - iunlockput(ip); - - return 0; - } - - if((ip = ialloc(dp->dev, type)) == 0) { - panic("create: ialloc"); - } - - ilock(ip); - ip->major = major; - ip->minor = minor; - ip->nlink = 1; - iupdate(ip); - - if(type == T_DIR){ // Create . and .. entries. - dp->nlink++; // for ".." - iupdate(dp); - - // No ip->nlink++ for ".": avoid cyclic ref count. - if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0) { - panic("create dots"); - } - } - - if(dirlink(dp, name, ip->inum) < 0) { - panic("create: dirlink"); - } - - iunlockput(dp); - - return ip; -} - -int sys_open(void) -{ - char *path; - int fd, omode; - struct file *f; - struct inode *ip; - - if(argstr(0, &path) < 0 || argint(1, &omode) < 0) { - return -1; - } - - if(omode & O_CREATE){ - begin_trans(); - ip = create(path, T_FILE, 0, 0); - commit_trans(); - - if(ip == 0) { - return -1; - } - - } else { - if((ip = namei(path)) == 0) { - return -1; - } - - ilock(ip); - - if(ip->type == T_DIR && omode != O_RDONLY){ - iunlockput(ip); - return -1; - } - } - - if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){ - if(f) { - fileclose(f); - } - - iunlockput(ip); - return -1; - } - - iunlock(ip); - - f->type = FD_INODE; - f->ip = ip; - f->off = 0; - f->readable = !(omode & O_WRONLY); - f->writable = (omode & O_WRONLY) || (omode & O_RDWR); - - return fd; -} - -int sys_mkdir(void) -{ - char *path; - struct inode *ip; - - begin_trans(); - - if(argstr(0, &path) < 0 || (ip = create(path, T_DIR, 0, 0)) == 0){ - commit_trans(); - return -1; - } - - iunlockput(ip); - commit_trans(); - - return 0; -} - -int sys_mknod(void) -{ - struct inode *ip; - char *path; - int len; - int major, minor; - - begin_trans(); - - if((len=argstr(0, &path)) < 0 || - argint(1, &major) < 0 || argint(2, &minor) < 0 || - (ip = create(path, T_DEV, major, minor)) == 0){ - - commit_trans(); - return -1; - } - - iunlockput(ip); - commit_trans(); - - return 0; -} - -int sys_chdir(void) -{ - char *path; - struct inode *ip; - - if(argstr(0, &path) < 0 || (ip = namei(path)) == 0) { - return -1; - } - - ilock(ip); - - if(ip->type != T_DIR){ - iunlockput(ip); - return -1; - } - - iunlock(ip); - - iput(proc->cwd); - proc->cwd = ip; - - return 0; -} - -int sys_exec(void) -{ - char *path, *argv[MAXARG]; - int i; - uint uargv, uarg; - - if(argstr(0, &path) < 0 || argint(1, (int*)&uargv) < 0){ - return -1; - } - - memset(argv, 0, sizeof(argv)); - - for(i=0;; i++){ - if(i >= NELEM(argv)) { - return -1; - } - - if(fetchint(uargv+4*i, (int*)&uarg) < 0) { - return -1; - } - - if(uarg == 0){ - argv[i] = 0; - break; - } - - if(fetchstr(uarg, &argv[i]) < 0) { - return -1; - } - } - - return exec(path, argv); -} - -int sys_pipe(void) -{ - int *fd; - struct file *rf, *wf; - int fd0, fd1; - - if(argptr(0, (void*)&fd, 2*sizeof(fd[0])) < 0) { - return -1; - } - - if(pipealloc(&rf, &wf) < 0) { - return -1; - } - - fd0 = -1; - - if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){ - if(fd0 >= 0) { - proc->ofile[fd0] = 0; - } - - fileclose(rf); - fileclose(wf); - - return -1; - } - - fd[0] = fd0; - fd[1] = fd1; - - return 0; -} diff -r fadfd62d6b14 -r 214d21c891c7 src/sysfile.cbc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sysfile.cbc Mon Jun 03 18:12:44 2019 +0900 @@ -0,0 +1,520 @@ +// +// File-system system calls. +// Mostly argument checking, since we don't trust +// user code, and calls into file.c and fs.c. +// + +#include "types.h" +#include "defs.h" +#include "param.h" +#include "stat.h" +#include "mmu.h" +#include "proc.h" +#include "fs.h" +#include "file.h" +#include "fcntl.h" + +#define __ncode __code + +// Fetch the nth word-sized system call argument as a file descriptor +// and return both the descriptor and the corresponding struct file. +static int argfd(int n, int *pfd, struct file **pf) +{ + int fd; + struct file *f; + + if(argint(n, &fd) < 0) { + return -1; + } + + if(fd < 0 || fd >= NOFILE || (f=proc->ofile[fd]) == 0) { + return -1; + } + + if(pfd) { + *pfd = fd; + } + + if(pf) { + *pf = f; + } + + return 0; +} + +// Allocate a file descriptor for the given file. +// Takes over file reference from caller on success. +static int fdalloc(struct file *f) +{ + int fd; + + for(fd = 0; fd < NOFILE; fd++){ + if(proc->ofile[fd] == 0){ + proc->ofile[fd] = f; + return fd; + } + } + + return -1; +} + +int sys_dup(void) +{ + struct file *f; + int fd; + + if(argfd(0, 0, &f) < 0) { + return -1; + } + + if((fd=fdalloc(f)) < 0) { + return -1; + } + + filedup(f); + + return fd; +} + +__ncode cbc_read(__code (*next)(int ret)){ + struct file *f; + int n; + char *p; + + if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) { + goto next(-1); + } + goto cbc_fileread(f, p, n, next); +} + +int sys_read(void) +{ + struct file *f; + int n; + char *p; + + if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) { + return -1; + } + + return fileread(f, p, n); +} + +int sys_write(void) +{ + struct file *f; + int n; + char *p; + + if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) { + return -1; + } + + return filewrite(f, p, n); +} + +int sys_close(void) +{ + int fd; + struct file *f; + + if(argfd(0, &fd, &f) < 0) { + return -1; + } + + proc->ofile[fd] = 0; + fileclose(f); + + return 0; +} + +int sys_fstat(void) +{ + struct file *f; + struct stat *st; + + if(argfd(0, 0, &f) < 0 || argptr(1, (void*)&st, sizeof(*st)) < 0) { + return -1; + } + + return filestat(f, st); +} + +// Create the path new as a link to the same inode as old. +int sys_link(void) +{ + char name[DIRSIZ], *new, *old; + struct inode *dp, *ip; + + if(argstr(0, &old) < 0 || argstr(1, &new) < 0) { + return -1; + } + + if((ip = namei(old)) == 0) { + return -1; + } + + begin_trans(); + + ilock(ip); + + if(ip->type == T_DIR){ + iunlockput(ip); + commit_trans(); + return -1; + } + + ip->nlink++; + iupdate(ip); + iunlock(ip); + + if((dp = nameiparent(new, name)) == 0) { + goto bad; + } + + ilock(dp); + + if(dp->dev != ip->dev || dirlink(dp, name, ip->inum) < 0){ + iunlockput(dp); + goto bad; + } + + iunlockput(dp); + iput(ip); + + commit_trans(); + + return 0; + + bad: + ilock(ip); + ip->nlink--; + iupdate(ip); + iunlockput(ip); + commit_trans(); + return -1; +} + +// Is the directory dp empty except for "." and ".." ? +static int isdirempty(struct inode *dp) +{ + int off; + struct dirent de; + + for(off=2*sizeof(de); offsize; off+=sizeof(de)){ + if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) { + panic("isdirempty: readi"); + } + + if(de.inum != 0) { + return 0; + } + } + return 1; +} + +//PAGEBREAK! +int sys_unlink(void) +{ + struct inode *ip, *dp; + struct dirent de; + char name[DIRSIZ], *path; + uint off; + + if(argstr(0, &path) < 0) { + return -1; + } + + if((dp = nameiparent(path, name)) == 0) { + return -1; + } + + begin_trans(); + + ilock(dp); + + // Cannot unlink "." or "..". + if(namecmp(name, ".") == 0 || namecmp(name, "..") == 0) { + goto bad; + } + + if((ip = dirlookup(dp, name, &off)) == 0) { + goto bad; + } + + ilock(ip); + + if(ip->nlink < 1) { + panic("unlink: nlink < 1"); + } + + if(ip->type == T_DIR && !isdirempty(ip)){ + iunlockput(ip); + goto bad; + } + + memset(&de, 0, sizeof(de)); + + if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) { + panic("unlink: writei"); + } + + if(ip->type == T_DIR){ + dp->nlink--; + iupdate(dp); + } + + iunlockput(dp); + + ip->nlink--; + iupdate(ip); + iunlockput(ip); + + commit_trans(); + + return 0; + + bad: + iunlockput(dp); + commit_trans(); + return -1; +} + +static struct inode* create(char *path, short type, short major, short minor) +{ + uint off; + struct inode *ip, *dp; + char name[DIRSIZ]; + + if((dp = nameiparent(path, name)) == 0) { + return 0; + } + + ilock(dp); + + if((ip = dirlookup(dp, name, &off)) != 0){ + iunlockput(dp); + ilock(ip); + + if(type == T_FILE && ip->type == T_FILE) { + return ip; + } + + iunlockput(ip); + + return 0; + } + + if((ip = ialloc(dp->dev, type)) == 0) { + panic("create: ialloc"); + } + + ilock(ip); + ip->major = major; + ip->minor = minor; + ip->nlink = 1; + iupdate(ip); + + if(type == T_DIR){ // Create . and .. entries. + dp->nlink++; // for ".." + iupdate(dp); + + // No ip->nlink++ for ".": avoid cyclic ref count. + if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0) { + panic("create dots"); + } + } + + if(dirlink(dp, name, ip->inum) < 0) { + panic("create: dirlink"); + } + + iunlockput(dp); + + return ip; +} + +int sys_open(void) +{ + char *path; + int fd, omode; + struct file *f; + struct inode *ip; + + if(argstr(0, &path) < 0 || argint(1, &omode) < 0) { + return -1; + } + + if(omode & O_CREATE){ + begin_trans(); + ip = create(path, T_FILE, 0, 0); + commit_trans(); + + if(ip == 0) { + return -1; + } + + } else { + if((ip = namei(path)) == 0) { + return -1; + } + + ilock(ip); + + if(ip->type == T_DIR && omode != O_RDONLY){ + iunlockput(ip); + return -1; + } + } + + if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){ + if(f) { + fileclose(f); + } + + iunlockput(ip); + return -1; + } + + iunlock(ip); + + f->type = FD_INODE; + f->ip = ip; + f->off = 0; + f->readable = !(omode & O_WRONLY); + f->writable = (omode & O_WRONLY) || (omode & O_RDWR); + + return fd; +} + +int sys_mkdir(void) +{ + char *path; + struct inode *ip; + + begin_trans(); + + if(argstr(0, &path) < 0 || (ip = create(path, T_DIR, 0, 0)) == 0){ + commit_trans(); + return -1; + } + + iunlockput(ip); + commit_trans(); + + return 0; +} + +int sys_mknod(void) +{ + struct inode *ip; + char *path; + int len; + int major, minor; + + begin_trans(); + + if((len=argstr(0, &path)) < 0 || + argint(1, &major) < 0 || argint(2, &minor) < 0 || + (ip = create(path, T_DEV, major, minor)) == 0){ + + commit_trans(); + return -1; + } + + iunlockput(ip); + commit_trans(); + + return 0; +} + +int sys_chdir(void) +{ + char *path; + struct inode *ip; + + if(argstr(0, &path) < 0 || (ip = namei(path)) == 0) { + return -1; + } + + ilock(ip); + + if(ip->type != T_DIR){ + iunlockput(ip); + return -1; + } + + iunlock(ip); + + iput(proc->cwd); + proc->cwd = ip; + + return 0; +} + +int sys_exec(void) +{ + char *path, *argv[MAXARG]; + int i; + uint uargv, uarg; + + if(argstr(0, &path) < 0 || argint(1, (int*)&uargv) < 0){ + return -1; + } + + memset(argv, 0, sizeof(argv)); + + for(i=0;; i++){ + if(i >= NELEM(argv)) { + return -1; + } + + if(fetchint(uargv+4*i, (int*)&uarg) < 0) { + return -1; + } + + if(uarg == 0){ + argv[i] = 0; + break; + } + + if(fetchstr(uarg, &argv[i]) < 0) { + return -1; + } + } + + return exec(path, argv); +} + +int sys_pipe(void) +{ + int *fd; + struct file *rf, *wf; + int fd0, fd1; + + if(argptr(0, (void*)&fd, 2*sizeof(fd[0])) < 0) { + return -1; + } + + if(pipealloc(&rf, &wf) < 0) { + return -1; + } + + fd0 = -1; + + if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){ + if(fd0 >= 0) { + proc->ofile[fd0] = 0; + } + + fileclose(rf); + fileclose(wf); + + return -1; + } + + fd[0] = fd0; + fd[1] = fd1; + + return 0; +}