diff options
| author | Frans Kaashoek <kaashoek@mit.edu> | 2019-07-02 14:19:31 -0400 | 
|---|---|---|
| committer | Frans Kaashoek <kaashoek@mit.edu> | 2019-07-02 14:19:31 -0400 | 
| commit | 1e4d7065d6582fd57d251dfe405afbbe68a55309 (patch) | |
| tree | f5ba795c113d04f43fd49744d04519aeef3df4ef | |
| parent | 84c759fc02c7843b64a1bafc843cd80fe3c9d7ee (diff) | |
| parent | f59c1bf1d82da4b445c1cff10c228ea55fa035d4 (diff) | |
| download | xv6-labs-1e4d7065d6582fd57d251dfe405afbbe68a55309.tar.gz xv6-labs-1e4d7065d6582fd57d251dfe405afbbe68a55309.tar.bz2 xv6-labs-1e4d7065d6582fd57d251dfe405afbbe68a55309.zip | |
Merge branch 'riscv' into riscv-proc
| -rw-r--r-- | Makefile | 1 | ||||
| -rw-r--r-- | kernel/defs.h | 4 | ||||
| -rw-r--r-- | kernel/kernelvec.S | 2 | ||||
| -rw-r--r-- | kernel/proc.c | 44 | ||||
| -rw-r--r-- | kernel/syscall.c | 46 | ||||
| -rw-r--r-- | kernel/sysfile.c | 26 | ||||
| -rw-r--r-- | kernel/sysproc.c | 16 | ||||
| -rw-r--r-- | kernel/trap.c | 27 | ||||
| -rw-r--r-- | kernel/vm.c | 32 | ||||
| -rwxr-xr-x | runoff | 5 | ||||
| -rw-r--r-- | runoff.list | 98 | ||||
| -rw-r--r-- | user/cow.c | 196 | ||||
| -rw-r--r-- | user/usertests.c | 13 | 
13 files changed, 376 insertions, 134 deletions
| @@ -128,6 +128,7 @@ UPROGS=\  	$U/_usertests\  	$U/_wc\  	$U/_zombie\ +	$U/_cow\  fs.img: mkfs/mkfs README $(UPROGS)  	mkfs/mkfs fs.img README $(UPROGS) diff --git a/kernel/defs.h b/kernel/defs.h index 1b397fe..bd89af0 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -185,9 +185,9 @@ pagetable_t     uvmcreate(void);  void            uvminit(pagetable_t, uchar *, uint);  uint64          uvmalloc(pagetable_t, uint64, uint64);  uint64          uvmdealloc(pagetable_t, uint64, uint64); -void            uvmcopy(pagetable_t, pagetable_t, uint64); +int             uvmcopy(pagetable_t, pagetable_t, uint64);  void            uvmfree(pagetable_t, uint64); -void            mappages(pagetable_t, uint64, uint64, uint64, int); +int             mappages(pagetable_t, uint64, uint64, uint64, int);  void            unmappages(pagetable_t, uint64, uint64, int);  uint64          walkaddr(pagetable_t, uint64);  int             copyout(pagetable_t, uint64, char *, uint64); diff --git a/kernel/kernelvec.S b/kernel/kernelvec.S index 4f52688..e9b0ced 100644 --- a/kernel/kernelvec.S +++ b/kernel/kernelvec.S @@ -47,7 +47,7 @@ kernelvec:          ld ra, 0(sp)          ld sp, 8(sp)          ld gp, 16(sp) -        ld tp, 24(sp) +        // not this, in case we moved CPUs: ld tp, 24(sp)          ld t0, 32(sp)          ld t1, 40(sp)          ld t2, 48(sp) diff --git a/kernel/proc.c b/kernel/proc.c index c12d97e..8ea09b5 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -111,6 +111,30 @@ found:    return p;  } +// free a proc structure and the data hanging from it, +// including user pages. +// the proc lock must be held. +static void +freeproc(struct proc *p) +{ +  if(p->kstack) +    kfree(p->kstack); +  p->kstack = 0; +  if(p->tf) +    kfree((void*)p->tf); +  p->tf = 0; +  if(p->pagetable) +    proc_freepagetable(p->pagetable, p->sz); +  p->pagetable = 0; +  p->sz = 0; +  p->pid = 0; +  p->parent = 0; +  p->name[0] = 0; +  p->chan = 0; +  p->killed = 0; +  p->state = UNUSED; +} +  // Create a page table for a given process,  // with no users pages, but with trampoline pages.  // Called both when creating a process, and @@ -147,7 +171,8 @@ proc_freepagetable(pagetable_t pagetable, uint64 sz)  {    unmappages(pagetable, TRAMPOLINE, PGSIZE, 0);    unmappages(pagetable, TRAMPOLINE-PGSIZE, PGSIZE, 0); -  uvmfree(pagetable, sz); +  if(sz > 0) +    uvmfree(pagetable, sz);  }  // a user program that calls exec("/init") @@ -226,7 +251,10 @@ fork(void)    }    // Copy user memory from parent to child. -  uvmcopy(p->pagetable, np->pagetable, p->sz); +  if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){ +    freeproc(np); +    return -1; +  }    np->sz = p->sz;    np->parent = p; @@ -342,17 +370,7 @@ wait(void)        if(np->state == ZOMBIE){          // Found one.          pid = np->pid; -        kfree(np->kstack); -        np->kstack = 0; -        kfree((void*)np->tf); -        np->tf = 0; -        proc_freepagetable(np->pagetable, np->sz); -        np->pagetable = 0; -        np->pid = 0; -        np->parent = 0; -        np->name[0] = 0; -        np->killed = 0; -        np->state = UNUSED; +        freeproc(np);          release(&np->lock);          release(&p->lock);          return pid; diff --git a/kernel/syscall.c b/kernel/syscall.c index 8e9d51c..a054da2 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -117,29 +117,29 @@ argstr(int n, char *buf, int max)    return fetchstr(addr, buf, max);  } -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); - -static int (*syscalls[])(void) = { +extern uint64 sys_chdir(void); +extern uint64 sys_close(void); +extern uint64 sys_dup(void); +extern uint64 sys_exec(void); +extern uint64 sys_exit(void); +extern uint64 sys_fork(void); +extern uint64 sys_fstat(void); +extern uint64 sys_getpid(void); +extern uint64 sys_kill(void); +extern uint64 sys_link(void); +extern uint64 sys_mkdir(void); +extern uint64 sys_mknod(void); +extern uint64 sys_open(void); +extern uint64 sys_pipe(void); +extern uint64 sys_read(void); +extern uint64 sys_sbrk(void); +extern uint64 sys_sleep(void); +extern uint64 sys_unlink(void); +extern uint64 sys_wait(void); +extern uint64 sys_write(void); +extern uint64 sys_uptime(void); + +static uint64 (*syscalls[])(void) = {  [SYS_fork]    sys_fork,  [SYS_exit]    sys_exit,  [SYS_wait]    sys_wait, diff --git a/kernel/sysfile.c b/kernel/sysfile.c index 33f37f2..533e097 100644 --- a/kernel/sysfile.c +++ b/kernel/sysfile.c @@ -52,7 +52,7 @@ fdalloc(struct file *f)    return -1;  } -int +uint64  sys_dup(void)  {    struct file *f; @@ -66,7 +66,7 @@ sys_dup(void)    return fd;  } -int +uint64  sys_read(void)  {    struct file *f; @@ -78,7 +78,7 @@ sys_read(void)    return fileread(f, p, n);  } -int +uint64  sys_write(void)  {    struct file *f; @@ -91,7 +91,7 @@ sys_write(void)    return filewrite(f, p, n);  } -int +uint64  sys_close(void)  {    int fd; @@ -104,7 +104,7 @@ sys_close(void)    return 0;  } -int +uint64  sys_fstat(void)  {    struct file *f; @@ -116,7 +116,7 @@ sys_fstat(void)  }  // Create the path new as a link to the same inode as old. -int +uint64  sys_link(void)  {    char name[DIRSIZ], new[MAXPATH], old[MAXPATH]; @@ -182,7 +182,7 @@ isdirempty(struct inode *dp)  }  //PAGEBREAK! -int +uint64  sys_unlink(void)  {    struct inode *ip, *dp; @@ -284,7 +284,7 @@ create(char *path, short type, short major, short minor)    return ip;  } -int +uint64  sys_open(void)  {    char path[MAXPATH]; @@ -347,7 +347,7 @@ sys_open(void)    return fd;  } -int +uint64  sys_mkdir(void)  {    char path[MAXPATH]; @@ -363,7 +363,7 @@ sys_mkdir(void)    return 0;  } -int +uint64  sys_mknod(void)  {    struct inode *ip; @@ -383,7 +383,7 @@ sys_mknod(void)    return 0;  } -int +uint64  sys_chdir(void)  {    char path[MAXPATH]; @@ -408,7 +408,7 @@ sys_chdir(void)    return 0;  } -int +uint64  sys_exec(void)  {    char path[MAXPATH], *argv[MAXARG]; @@ -446,7 +446,7 @@ sys_exec(void)    return ret;  } -int +uint64  sys_pipe(void)  {    uint64 fdarray; // user pointer to array of two integers diff --git a/kernel/sysproc.c b/kernel/sysproc.c index 65dde26..face81a 100644 --- a/kernel/sysproc.c +++ b/kernel/sysproc.c @@ -7,32 +7,32 @@  #include "spinlock.h"  #include "proc.h" -int +uint64  sys_exit(void)  {    exit();    return 0;  // not reached  } -int +uint64  sys_getpid(void)  {    return myproc()->pid;  } -int +uint64  sys_fork(void)  {    return fork();  } -int +uint64  sys_wait(void)  {    return wait();  } -int +uint64  sys_sbrk(void)  {    int addr; @@ -46,7 +46,7 @@ sys_sbrk(void)    return addr;  } -int +uint64  sys_sleep(void)  {    int n; @@ -67,7 +67,7 @@ sys_sleep(void)    return 0;  } -int +uint64  sys_kill(void)  {    int pid; @@ -79,7 +79,7 @@ sys_kill(void)  // return how many clock tick interrupts have occurred  // since start. -int +uint64  sys_uptime(void)  {    uint xticks; diff --git a/kernel/trap.c b/kernel/trap.c index 6c0d04b..018b7db 100644 --- a/kernel/trap.c +++ b/kernel/trap.c @@ -37,7 +37,7 @@ void  usertrap(void)  {    int which_dev = 0; -   +    if((r_sstatus() & SSTATUS_SPP) != 0)      panic("usertrap: not from user mode"); @@ -49,8 +49,6 @@ usertrap(void)    // save user program counter.    p->tf->epc = r_sepc(); - -  intr_on();    if(r_scause() == 8){      // system call @@ -59,11 +57,15 @@ usertrap(void)      // but we want to return to the next instruction.      p->tf->epc += 4; +    // an interrupt will change sstatus &c registers, +    // so don't enable until done with those registers. +    intr_on(); +      syscall();    } else if((which_dev = devintr()) != 0){      // ok    } else { -    printf("usertrap(): unexpected scause 0x%p pid=%d\n", r_scause(), p->pid); +    printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid);      printf("            sepc=%p stval=%p\n", r_sepc(), r_stval());      p->killed = 1;    } @@ -121,12 +123,14 @@ usertrapret(void)    ((void (*)(uint64,uint64))TRAMPOLINE)(TRAMPOLINE - PGSIZE, satp);  } -// interrupts and exceptions from kernel code go here, +// interrupts and exceptions from kernel code go here via kernelvec,  // on whatever the current kernel stack is.  // must be 4-byte aligned to fit in stvec.  void   kerneltrap()  { +  int which_dev = 0; +  uint64 sepc = r_sepc();    uint64 sstatus = r_sstatus();    uint64 scause = r_scause(); @@ -135,11 +139,20 @@ kerneltrap()    if(intr_get() != 0)      panic("kerneltrap: interrupts enabled"); -  if(devintr() == 0){ -    printf("scause 0x%p\n", scause); +  if((which_dev = devintr()) == 0){ +    printf("scause %p\n", scause);      printf("sepc=%p stval=%p\n", r_sepc(), r_stval());      panic("kerneltrap");    } + +  // give up the CPU if this is a timer interrupt. +  if(which_dev == 2 && myproc() != 0 && myproc()->state == RUNNING) +    yield(); + +  // the yield() may have caused some traps to occur, +  // so restore trap registers for use by kernelvec.S's sepc instruction. +  w_sepc(sepc); +  w_sstatus(sstatus);  }  // check if it's an external interrupt or software interrupt, diff --git a/kernel/vm.c b/kernel/vm.c index 580669f..bdb53c2 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -97,8 +97,8 @@ walk(pagetable_t pagetable, uint64 va, int alloc)  }  // Look up a virtual address, return the physical address, -// Can only be used to look up user pages.  // or 0 if not mapped. +// Can only be used to look up user pages.  uint64  walkaddr(pagetable_t pagetable, uint64 va)  { @@ -119,8 +119,9 @@ walkaddr(pagetable_t pagetable, uint64 va)  // Create PTEs for virtual addresses starting at va that refer to  // physical addresses starting at pa. va and size might not -// be page-aligned. -void +// be page-aligned. Returns 0 on success, -1 if walk() couldn't +// allocate a needed page-table page. +int  mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm)  {    uint64 a, last; @@ -130,7 +131,7 @@ mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm)    last = PGROUNDDOWN(va + size - 1);    for(;;){      if((pte = walk(pagetable, a, 1)) == 0) -      panic("mappages: walk"); +      return -1;      if(*pte & PTE_V)        panic("remap");      *pte = PA2PTE(pa) | perm | PTE_V; @@ -139,6 +140,7 @@ mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm)      a += PGSIZE;      pa += PGSIZE;    } +  return 0;  }  // Remove mappings from a page table. The mappings in @@ -222,7 +224,11 @@ uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz)        return 0;      }      memset(mem, 0, PGSIZE); -    mappages(pagetable, a, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U); +    if(mappages(pagetable, a, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U) != 0){ +      kfree(mem); +      uvmdealloc(pagetable, a, oldsz); +      return 0; +    }    }    return newsz;  } @@ -273,7 +279,9 @@ uvmfree(pagetable_t pagetable, uint64 sz)  // its memory into a child's page table.  // Copies both the page table and the  // physical memory. -void +// returns 0 on success, -1 on failure. +// frees any allocated pages on failure. +int  uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)  {    pte_t *pte; @@ -289,10 +297,18 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)      pa = PTE2PA(*pte);      flags = PTE_FLAGS(*pte);      if((mem = kalloc()) == 0) -      panic("uvmcopy: kalloc failed"); +      goto err;      memmove(mem, (char*)pa, PGSIZE); -    mappages(new, i, PGSIZE, (uint64)mem, flags); +    if(mappages(new, i, PGSIZE, (uint64)mem, flags) != 0){ +      kfree(mem); +      goto err; +    }    } +  return 0; + + err: +  unmappages(new, 0, i, 1); +  return -1;  }  // Copy from kernel to user. @@ -12,7 +12,10 @@ pad()  # create formatted (numbered) files  mkdir -p fmt -rm -f fmt/* +mkdir -p fmt/kernel +mkdir -p fmt/user +rm -f fmt/kernel/* +rm -f fmt/user/*  cp README fmt  echo > fmt/blank  files=`grep -v '^#' runoff.list | awk '{print $1}'` diff --git a/runoff.list b/runoff.list index 9fdc9e0..6e6af18 100644 --- a/runoff.list +++ b/runoff.list @@ -1,76 +1,64 @@  # basic headers -types.h -param.h -memlayout.h -defs.h -x86.h -asm.h -mmu.h -elf.h -date.h +kernel/types.h +kernel/param.h +kernel/memlayout.h +kernel/defs.h +kernel/riscv.h +kernel/elf.h +kernel/date.h  # entering xv6 -entry.S -entryother.S -main.c +kernel/entry.S +kernel/main.c  # locks -spinlock.h -spinlock.c +kernel/spinlock.h +kernel/spinlock.c  # processes -vm.c -proc.h -proc.c -swtch.S -kalloc.c +kernel/vm.c +kernel/proc.h +kernel/proc.c +kernel/swtch.S +kernel/kalloc.c  # system calls -traps.h -vectors.pl -trapasm.S -trap.c -syscall.h -syscall.c -sysproc.c +user/usys.pl +kernel/trap.c +kernel/syscall.h +kernel/syscall.c +kernel/sysproc.c  # file system -buf.h -sleeplock.h -fcntl.h -stat.h -fs.h -file.h -ide.c -bio.c -sleeplock.c -log.c -fs.c -file.c -sysfile.c -exec.c +kernel/buf.h +kernel/sleeplock.h +kernel/fcntl.h +kernel/stat.h +kernel/fs.h +kernel/file.h +kernel/virtio_disk.c +kernel/bio.c +kernel/sleeplock.c +kernel/log.c +kernel/fs.c +kernel/file.c +kernel/sysfile.c +kernel/exec.c  # pipes -pipe.c +kernel/pipe.c  # string operations -string.c +kernel/string.c  # low-level hardware -mp.h -mp.c -lapic.c -ioapic.c -kbd.h -kbd.c -console.c -uart.c +kernel/uart.c  # user-level -initcode.S -usys.S -init.c -sh.c +user/initcode.S +user/usys.S +user/init.c +user/sh.c  # link -kernel.ld +kernel/kernel.ld diff --git a/user/cow.c b/user/cow.c new file mode 100644 index 0000000..45efc98 --- /dev/null +++ b/user/cow.c @@ -0,0 +1,196 @@ +// +// tests for copy-on-write fork() assignment. +// + +#include "kernel/types.h" +#include "kernel/memlayout.h" +#include "user/user.h" + +// allocate more than half of physical memory, +// then fork. this will fail in the default +// kernel, which does not support copy-on-write. +void +simpletest() +{ +  uint64 phys_size = PHYSTOP - KERNBASE; +  int sz = (phys_size / 3) * 2; + +  printf(1, "simple: "); +   +  char *p = sbrk(sz); +  if(p == (char*)0xffffffffffffffffL){ +    printf(1, "sbrk(%d) failed\n", sz); +    exit(); +  } + +  for(char *q = p; q < p + sz; q += 4096){ +    *(int*)q = getpid(); +  } + +  int pid = fork(); +  if(pid < 0){ +    printf(1, "fork() failed\n"); +    exit(); +  } + +  if(pid == 0) +    exit(); + +  wait(); + +  if(sbrk(-sz) == (char*)0xffffffffffffffffL){ +    printf(1, "sbrk(-%d) failed\n", sz); +    exit(); +  } + +  printf(1, "ok\n"); +} + +// three processes all write COW memory. +// this causes more than half of physical memory +// to be allocated, so it also checks whether +// copied pages are freed. +void +threetest() +{ +  uint64 phys_size = PHYSTOP - KERNBASE; +  int sz = phys_size / 4; +  int pid1, pid2; + +  printf(1, "three: "); +   +  char *p = sbrk(sz); +  if(p == (char*)0xffffffffffffffffL){ +    printf(1, "sbrk(%d) failed\n", sz); +    exit(); +  } + +  pid1 = fork(); +  if(pid1 < 0){ +    printf(1, "fork failed\n"); +    exit(); +  } +  if(pid1 == 0){ +    pid2 = fork(); +    if(pid2 < 0){ +      printf(1, "fork failed"); +      exit(); +    } +    if(pid2 == 0){ +      for(char *q = p; q < p + (sz/5)*4; q += 4096){ +        *(int*)q = getpid(); +      } +      for(char *q = p; q < p + (sz/5)*4; q += 4096){ +        if(*(int*)q != getpid()){ +          printf(1, "wrong content\n"); +          exit(); +        } +      } +      exit(); +    } +    for(char *q = p; q < p + (sz/2); q += 4096){ +      *(int*)q = 9999; +    } +    exit(); +  } + +  for(char *q = p; q < p + sz; q += 4096){ +    *(int*)q = getpid(); +  } + +  wait(); + +  sleep(1); + +  for(char *q = p; q < p + sz; q += 4096){ +    if(*(int*)q != getpid()){ +      printf(1, "wrong content\n"); +      exit(); +    } +  } + +  if(sbrk(-sz) == (char*)0xffffffffffffffffL){ +    printf(1, "sbrk(-%d) failed\n", sz); +    exit(); +  } + +  printf(1, "ok\n"); +} + +char junk1[4096]; +int fds[2]; +char junk2[4096]; +char buf[4096]; +char junk3[4096]; + +// test whether copyout() simulates COW faults. +void +filetest() +{ +  int parent = getpid(); +   +  printf(1, "file test: "); +   +  buf[0] = 99; + +  for(int i = 0; i < 4; i++){ +    if(pipe(fds) != 0){ +      printf(1, "pipe() failed\n"); +      exit(); +    } +    int pid = fork(); +    if(pid < 0){ +      printf(1, "fork failed\n"); +      exit(); +    } +    if(pid == 0){ +      sleep(1); +      if(read(fds[0], buf, sizeof(i)) != sizeof(i)){ +        printf(1, "read failed\n"); +        kill(parent); +        exit(); +      } +      sleep(1); +      int j = *(int*)buf; +      if(j != i){ +        printf(1, "read the wrong value\n"); +        kill(parent); +        exit(); +      } +      exit(); +    } +    if(write(fds[1], &i, sizeof(i)) != sizeof(i)){ +      printf(1, "write failed\n"); +      exit(); +    } +  } + +  for(int i = 0; i < 4; i++) +    wait(); + +  if(buf[0] != 99){ +    printf(1, "child overwrote parent\n"); +    exit(); +  } + +  printf(1, "ok\n"); +} + +int +main(int argc, char *argv[]) +{ +  simpletest(); + +  // check that the first simpletest() freed the physical memory. +  simpletest(); + +  threetest(); +  threetest(); +  threetest(); + +  filetest(); + +  printf(1, "ALL COW TESTS PASSED\n"); + +  exit(); +} diff --git a/user/usertests.c b/user/usertests.c index beca8f9..ef70bfb 100644 --- a/user/usertests.c +++ b/user/usertests.c @@ -1438,6 +1438,13 @@ sbrktest(void)    printf(stdout, "sbrk test\n");    oldbrk = sbrk(0); +  // does sbrk() return the expected failure value? +  a = sbrk(1024*1024*1024); +  if(a != (char*)0xffffffffffffffffL){ +    printf(stdout, "sbrk(<toomuch>) returned %p\n", a); +    exit(); +  } +    // can one sbrk() less than a page?    a = sbrk(0);    for(i = 0; i < 5000; i++){ @@ -1466,7 +1473,7 @@ sbrktest(void)    // can one grow address space to something big?    a = sbrk(0); -  amt = (BIG) - (uint64)a; +  amt = BIG - (uint64)a;    p = sbrk(amt);    if (p != a) {      printf(stdout, "sbrk test failed to grow big address space; enough phys mem?\n"); @@ -1478,7 +1485,7 @@ sbrktest(void)    // can one de-allocate?    a = sbrk(0);    c = sbrk(-4096); -  if(c == (char*)0xffffffff){ +  if(c == (char*)0xffffffffffffffffL){      printf(stdout, "sbrk could not deallocate\n");      exit();    } @@ -1551,7 +1558,7 @@ sbrktest(void)      kill(pids[i]);      wait();    } -  if(c == (char*)0xffffffff){ +  if(c == (char*)0xffffffffffffffffL){      printf(stdout, "failed sbrk leaked memory\n");      exit();    } | 
