changeset 52:214d21c891c7

rename to cbc __ncode is not handled as interfaces
author kono
date Mon, 03 Jun 2019 18:12:44 +0900
parents fadfd62d6b14
children 435bfab09924
files src/CMakeLists.txt src/console.cbc src/context.h src/file.c src/file.cbc src/gearsTools/generate_context.pl src/gearsTools/generate_stub.pl src/pipe.c src/pipe.cbc src/proc.c src/proc.cbc src/spinlock.c src/spinlock.cbc src/syscall.c src/syscall.cbc src/sysfile.c src/sysfile.cbc
diffstat 17 files changed, 2064 insertions(+), 2031 deletions(-) [+]
line wrap: on
line diff
--- 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 
 )
 
--- 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;
 
--- 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 <stdlib.h>
-#include <pthread.h>
+// #ifdef CBC_CONTEXT_H  does not work well
+#define CBC_CONTEXT_H
+// #include <stdlib.h>
+// #include <pthread.h>
 #ifdef USE_CUDAWorker
 #include <cuda.h>
 #include <driver_types.h>
@@ -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
--- 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");
-}
-
--- /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");
+}
+
--- 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";
 }
 }
 
--- 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 $_;
     }
--- 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;
-}
--- /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;
+}
--- 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");
-}
-
-
--- /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");
+}
+
+
--- 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;
-}
-
--- /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;
+}
+
--- 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;
-    }
-}
--- /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;
+    }
+}
--- 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); off<dp->size; 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;
-}
--- /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); off<dp->size; 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;
+}