diff --git a/qa/kern/brk.c b/qa/kern/brk.c new file mode 100644 index 0000000..4fa24aa --- /dev/null +++ b/qa/kern/brk.c @@ -0,0 +1,46 @@ +/* + * This file is part of Jehanne. + * + * Copyright (C) 2016 Giacomo Tesio + * + * Jehanne is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * Jehanne is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jehanne. If not, see . + */ +#include +#include + +void +main(void) +{ + long b, b1; + + b = create("#0/brk", -1, 16*1024*1024); + if(b >= 0){ + print("FAIL: create returned fd %d.\n", b); + exits("FAIL"); + } + if(b == -1){ + print("FAIL: create: %r.\n"); + exits("FAIL"); + } + b1 = brk((void*)b + 16*1024*1024); + if(b1 == -1){ + print("FAIL: brk: %r.\n"); + exits("FAIL"); + } + if(b >= b1){ + print("FAIL: b >= b1.\n"); + exits("FAIL"); + } + print("PASS\n"); + exits("PASS"); +} diff --git a/qa/kern/build.json b/qa/kern/build.json index be3b549..e43402e 100644 --- a/qa/kern/build.json +++ b/qa/kern/build.json @@ -11,6 +11,7 @@ "alarm.c", "args.c", "awake.c", + "brk.c", "execl.c", "float.c", "fork.c", diff --git a/sys/src/kern/port/chan.c b/sys/src/kern/port/chan.c index 9640734..fec6cf2 100644 --- a/sys/src/kern/port/chan.c +++ b/sys/src/kern/port/chan.c @@ -1214,7 +1214,7 @@ nameerror(char *name, char *err) * correct name so they can rewrite the stat info. */ Chan* -namec(char *aname, int amode, int omode, int perm) +namec(char *aname, int amode, long omode, long perm) { int len, n, nomount; Chan *c, *cnew; @@ -1479,6 +1479,7 @@ namec(char *aname, int amode, int omode, int perm) */ e.nelems++; e.nerror++; + if(omode >=0) /* a negative omode means this is a message for the server */ if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) == 0) error(Eexist); diff --git a/sys/src/kern/port/devself.c b/sys/src/kern/port/devself.c index 605bcfa..c18c07f 100644 --- a/sys/src/kern/port/devself.c +++ b/sys/src/kern/port/devself.c @@ -15,12 +15,12 @@ * You should have received a copy of the GNU General Public License * along with Jehanne. If not, see . */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" #define QID(q) ((((uint32_t)(q).path)&0x0000001F)>>0) #define STATSIZE (2*KNAMELEN+NUMSIZE+9*NUMSIZE + 1) @@ -33,6 +33,7 @@ typedef enum SelfNodes Qdir, /* Process control */ + Qbrk, Qpid, Qppid, Qpgrpid, @@ -63,6 +64,7 @@ typedef union PipeSet static Dirtab selfdir[]={ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0777, + "brk", {Qbrk}, 0, 0, "pid", {Qpid}, 0, 0, "ppid", {Qppid}, 0, 0, "pgrpid", {Qpgrpid}, 0, 0, @@ -117,6 +119,84 @@ selfattach(Chan *c, Chan *ac, char *spec, int flags) return devattach('0', spec); } +static uintptr_t +grow_bss(uintptr_t addr) +{ + ProcSegment *s, *ns; + uintptr_t newtop; + long newsize; + int i; + + s = up->seg[BSEG]; + if(s == nil) + panic("grow_bss: no bss segment"); + + if(addr == 0) + return s->top; + + qlock(&s->ql); + if(waserror()){ + qunlock(&s->ql); + nexterror(); + } + + DBG("grow_bss addr %#p base %#p top %#p\n", + addr, s->base, s->top); + /* We may start with the bss overlapping the data */ + if(addr < s->base) { + if(up->seg[DSEG] == 0 || addr < up->seg[DSEG]->base) + error(Enovmem); + addr = s->base; + } + + newtop = ROUNDUP(addr, PGSZ); + newsize = (newtop - s->table->base)/PGSZ; + + + DBG("grow_bss addr %#p newtop %#p newsize %ld\n", addr, newtop, newsize); + + if(newtop < s->top) { + /* for simplicity we only allow the bss to grow, + * memory will be freed on process exit + */ + panic("grow_bss: shrinking bss"); + } + + rlock(&up->seglock); + for(i = 0; i < NSEG; i++) { + ns = up->seg[i]; + if(ns == 0 || ns == s) + continue; + if(newtop >= ns->base && newtop < ns->top){ + runlock(&up->seglock); + error(Esoverlap); + } + } + runlock(&up->seglock); + + if(!umem_available(newtop - s->top)) + error(Enovmem); + + if(!segment_grow(s, newtop)) + error(Enovmem); + + poperror(); + qunlock(&s->ql); + + return s->top; +} + +static Chan* +selfcreate(Chan* c, char* name, unsigned long omode, unsigned long perm) +{ + long e; + if(strcmp(name, "brk") == 0){ + e = (long)grow_bss(perm); + errorl("brk set", ~e); + } + error(Eperm); +} + static Walkqid* selfwalk(Chan *c, Chan *nc, char **name, int nname) { @@ -483,7 +563,7 @@ Dev selfdevtab = { selfwalk, selfstat, selfopen, - devcreate, + selfcreate, selfclose, selfread, devbread, diff --git a/sys/src/kern/port/include.json b/sys/src/kern/port/include.json index b6b19bf..ef17130 100644 --- a/sys/src/kern/port/include.json +++ b/sys/src/kern/port/include.json @@ -73,7 +73,6 @@ "../port/syscallfmt.c", "../port/sysfile.c", "../port/sysproc.c", - "../port/sysseg.c", "../port/tod.c", "../port/uidgid.c", "../port/usbehci.c" diff --git a/sys/src/kern/port/portfns.h b/sys/src/kern/port/portfns.h index 3537f52..ad8cf0d 100644 --- a/sys/src/kern/port/portfns.h +++ b/sys/src/kern/port/portfns.h @@ -214,7 +214,7 @@ int mregfmt(Fmt*); uint64_t ms2fastticks(uint32_t); void mul64fract(uint64_t*, uint64_t, uint64_t); void muxclose(Mnt*); -Chan* namec(char*, int, int, int); +Chan* namec(char*, int, long, long); void nameerror(char*, char*); Chan* newchan(void); int newfd(Chan*); diff --git a/sys/src/kern/port/sysfile.c b/sys/src/kern/port/sysfile.c index 05e6951..62c4bcb 100644 --- a/sys/src/kern/port/sysfile.c +++ b/sys/src/kern/port/sysfile.c @@ -1025,12 +1025,13 @@ sysunmount(char* name, char* old) } int -syscreate(char* aname, uint32_t omode, uint32_t perm) +syscreate(char* aname, long omode, long perm) { int fd; Chan *c; - openmode(omode); /* error check only; OEXCL okay here */ + if(omode >= 0) + openmode(omode); /* error check only */ c = nil; if(waserror()) { if(c != nil) diff --git a/sys/src/kern/port/sysseg.c b/sys/src/kern/port/sysseg.c deleted file mode 100644 index 1ecb921..0000000 --- a/sys/src/kern/port/sysseg.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This file is part of Jehanne. - * - * Copyright (C) 2015-2016 Giacomo Tesio - * - * Jehanne is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2 of the License. - * - * Jehanne is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Jehanne. If not, see . - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -uintptr_t -grow_bss(uintptr_t addr) -{ - ProcSegment *s, *ns; - uintptr_t newtop; - long newsize; - int i; - - s = up->seg[BSEG]; - if(s == nil) - panic("grow_bss: no bss segment"); - - if(addr == 0) - return s->top; - - qlock(&s->ql); - if(waserror()){ - qunlock(&s->ql); - nexterror(); - } - - DBG("grow_bss addr %#p base %#p top %#p\n", - addr, s->base, s->top); - /* We may start with the bss overlapping the data */ - if(addr < s->base) { - if(up->seg[DSEG] == 0 || addr < up->seg[DSEG]->base) - error(Enovmem); - addr = s->base; - } - - newtop = ROUNDUP(addr, PGSZ); - newsize = (newtop - s->table->base)/PGSZ; - - - DBG("grow_bss addr %#p newtop %#p newsize %ld\n", addr, newtop, newsize); - - if(newtop < s->top) { - /* for simplicity we only allow the bss to grow, - * memory will be freed on process exit - */ - panic("grow_bss: shrinking bss"); - } - - rlock(&up->seglock); - for(i = 0; i < NSEG; i++) { - ns = up->seg[i]; - if(ns == 0 || ns == s) - continue; - if(newtop >= ns->base && newtop < ns->top){ - runlock(&up->seglock); - error(Esoverlap); - } - } - runlock(&up->seglock); - - if(!umem_available(newtop - s->top)) - error(Enovmem); - - if(!segment_grow(s, newtop)) - error(Enovmem); - - poperror(); - qunlock(&s->ql); - - return s->top; -} - -uintptr_t -sysbrk_(void* addrp) -{ - uintptr_t addr; - addr = PTR2UINT(addrp); - - /* NOTE: this assumes that a bss segment ALWAYS exists. - * Thus we always add one on sysexec (see sysproc.c). - */ - grow_bss(addr); - - return 0; -} diff --git a/sys/src/lib/c/9sys/sbrk.c b/sys/src/lib/c/9sys/sbrk.c index 8b873e0..b42a77e 100644 --- a/sys/src/lib/c/9sys/sbrk.c +++ b/sys/src/lib/c/9sys/sbrk.c @@ -18,13 +18,15 @@ enum Round = 7 }; +#define brk_(p) ((uintptr_t)~create("#0/brk", -1, p)) + int brk(void *p) { uintptr_t bl; bl = ((uintptr_t)p + Round) & ~Round; - if(brk_((void*)bl) < 0) + if(brk_(bl) < 0) return -1; bloc = (char*)bl; return 0; @@ -36,7 +38,7 @@ sbrk(uint32_t n) uintptr_t bl; bl = ((uintptr_t)bloc + Round) & ~Round; - if(brk_((void*)(bl+n)) < 0) + if(brk_(bl+n) < 0) return (void*)-1; bloc = (char*)bl + n; return (void*)bl; diff --git a/sys/src/sysconf.json b/sys/src/sysconf.json index ab80fe9..a3922ce 100644 --- a/sys/src/sysconf.json +++ b/sys/src/sysconf.json @@ -53,21 +53,11 @@ "int" ] }, - { - "Args": [ - "const void*" - ], - "Id": 3, - "Name": "brk_", - "Ret": [ - "uintptr_t" - ] - }, { "Args": [ "int" ], - "Id": 4, + "Id": 3, "Name": "close", "Ret": [ "long" @@ -76,10 +66,10 @@ { "Args": [ "const char*", - "uint32_t", - "uint32_t" + "long", + "long" ], - "Id": 5, + "Id": 4, "Name": "create", "Ret": [ "long" @@ -90,7 +80,7 @@ "int32_t", "int32_t" ], - "Id": 6, + "Id": 5, "Name": "dup", "Ret": [ "int32_t" @@ -101,7 +91,7 @@ "char*", "int" ], - "Id": 7, + "Id": 6, "Name": "errstr", "Ret": [ "int" @@ -112,7 +102,7 @@ "const char*", "const char**" ], - "Id": 8, + "Id": 7, "Name": "exec", "Ret": [ "uintptr_t" @@ -122,7 +112,7 @@ "Args": [ "const char*" ], - "Id": 9, + "Id": 8, "Name": "_exits", "Ret": [ "int" @@ -133,7 +123,7 @@ "int", "const char*" ], - "Id": 10, + "Id": 9, "Name": "fauth", "Ret": [ "int" @@ -145,7 +135,7 @@ "const char*", "uint32_t" ], - "Id": 11, + "Id": 10, "Name": "fd2path", "Ret": [ "int32_t" @@ -157,7 +147,7 @@ "uint8_t*", "int" ], - "Id": 12, + "Id": 11, "Name": "fstat", "Ret": [ "long" @@ -170,7 +160,7 @@ "const char*", "int" ], - "Id": 13, + "Id": 12, "Name": "fversion", "Ret": [ "int" @@ -182,7 +172,7 @@ "const uint8_t*", "uint32_t" ], - "Id": 14, + "Id": 13, "Name": "fwstat", "Ret": [ "long" @@ -197,7 +187,7 @@ "const char*", "int" ], - "Id": 15, + "Id": 14, "Name": "mount", "Ret": [ "int" @@ -207,7 +197,7 @@ "Args": [ "int" ], - "Id": 16, + "Id": 15, "Name": "noted", "Ret": [ "int" @@ -217,14 +207,14 @@ "Args": [ "const void*" ], - "Id": 17, + "Id": 16, "Name": "notify", "Ret": [ "int" ] }, { - "Id": 18, + "Id": 17, "Name": "nsec", "Ret": [ "long" @@ -235,7 +225,7 @@ "const char*", "uint32_t" ], - "Id": 19, + "Id": 18, "Name": "open", "Ret": [ "long" @@ -248,7 +238,7 @@ "long", "long" ], - "Id": 20, + "Id": 19, "Name": "pread", "Ret": [ "long" @@ -261,7 +251,7 @@ "long", "long" ], - "Id": 21, + "Id": 20, "Name": "pwrite", "Ret": [ "long" @@ -271,7 +261,7 @@ "Args": [ "const char*" ], - "Id": 22, + "Id": 21, "Name": "remove", "Ret": [ "long" @@ -282,7 +272,7 @@ "const void*", "void*" ], - "Id": 23, + "Id": 22, "Name": "rendezvous", "Ret": [ "void*" @@ -292,7 +282,7 @@ "Args": [ "uint32_t" ], - "Id": 24, + "Id": 23, "Name": "rfork", "Ret": [ "int" @@ -304,7 +294,7 @@ "long", "int" ], - "Id": 25, + "Id": 24, "Name": "seek", "Ret": [ "long" @@ -315,7 +305,7 @@ "int*", "int" ], - "Id": 26, + "Id": 25, "Name": "semacquire", "Ret": [ "int" @@ -326,7 +316,7 @@ "int*", "int" ], - "Id": 27, + "Id": 26, "Name": "semrelease", "Ret": [ "int" @@ -337,7 +327,7 @@ "int*", "uint64_t" ], - "Id": 28, + "Id": 27, "Name": "tsemacquire", "Ret": [ "int" @@ -348,7 +338,7 @@ "const char*", "const char*" ], - "Id": 29, + "Id": 28, "Name": "unmount", "Ret": [ "int" @@ -358,7 +348,7 @@ "Args": [ "unsigned long" ], - "Id": 30, + "Id": 29, "Name": "alarm", "Ret": [ "long"