kernel: introduce devself
Devself provides to each process access to its own structures. So far it contains four files: - pid - ppid - pipes used to implement pipe(2) - segments used to implement segattach, segdetach and segfree
This commit is contained in:
parent
f52a185030
commit
c6de6b66e9
@ -36,13 +36,8 @@ main(void)
|
|||||||
exits("FAIL");
|
exits("FAIL");
|
||||||
}
|
}
|
||||||
rfork(RFNOMNT|RFCNAMEG);
|
rfork(RFNOMNT|RFCNAMEG);
|
||||||
if(getpid() != -1){
|
if(getpid() != pid){
|
||||||
print("FAIL: rfork(RFNOMNT|RFCNAMEG)); getpid() != -1\n");
|
print("FAIL: rfork(RFNOMNT|RFCNAMEG)); getpid() != getmainpid()\n");
|
||||||
exits("FAIL");
|
|
||||||
}
|
|
||||||
rerrstr(err, ERRMAX);
|
|
||||||
if(strcmp("getpid: cannot open neither #c/pid nor /dev/pid", err)){
|
|
||||||
print("FAIL: rfork(RFNOMNT|RFCNAMEG)); getpid() set errstr '%s'\n", err);
|
|
||||||
exits("FAIL");
|
exits("FAIL");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,13 +38,8 @@ main(void)
|
|||||||
exits("FAIL");
|
exits("FAIL");
|
||||||
}
|
}
|
||||||
rfork(RFNOMNT|RFCNAMEG);
|
rfork(RFNOMNT|RFCNAMEG);
|
||||||
if(getppid() != -1){
|
if(getppid() != ppid){
|
||||||
print("FAIL: rfork(RFNOMNT|RFCNAMEG)); getppid() != -1\n");
|
print("FAIL: rfork(RFNOMNT|RFCNAMEG)); getppid() != getmainpid()\n");
|
||||||
exits("FAIL");
|
|
||||||
}
|
|
||||||
rerrstr(err, ERRMAX);
|
|
||||||
if(strcmp("getppid: cannot open neither #c/ppid nor /dev/ppid", err)){
|
|
||||||
print("FAIL: rfork(RFNOMNT|RFCNAMEG)); getppid() set errstr '%s'\n", err);
|
|
||||||
exits("FAIL");
|
exits("FAIL");
|
||||||
}
|
}
|
||||||
exits(nil);
|
exits(nil);
|
||||||
|
@ -396,6 +396,7 @@ extern char* mktemp(char*);
|
|||||||
extern double modf(double, double*);
|
extern double modf(double, double*);
|
||||||
extern void notejmp(void*, jmp_buf, int);
|
extern void notejmp(void*, jmp_buf, int);
|
||||||
extern void perror(const char*);
|
extern void perror(const char*);
|
||||||
|
extern int pipe(int pipes[2]);
|
||||||
extern int postnote(int, int, const char *);
|
extern int postnote(int, int, const char *);
|
||||||
extern double pow10(int);
|
extern double pow10(int);
|
||||||
extern int putenv(const char*, const char*);
|
extern int putenv(const char*, const char*);
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
"root",
|
"root",
|
||||||
"rtc",
|
"rtc",
|
||||||
"sd",
|
"sd",
|
||||||
|
"self",
|
||||||
"shr",
|
"shr",
|
||||||
"srv",
|
"srv",
|
||||||
"ssl",
|
"ssl",
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
"proc",
|
"proc",
|
||||||
"root",
|
"root",
|
||||||
"sd",
|
"sd",
|
||||||
|
"self",
|
||||||
"shr",
|
"shr",
|
||||||
"srv",
|
"srv",
|
||||||
"uart"
|
"uart"
|
||||||
|
@ -1291,9 +1291,10 @@ namec(char *aname, int amode, int omode, int perm)
|
|||||||
* noattach is sandboxing.
|
* noattach is sandboxing.
|
||||||
*
|
*
|
||||||
* the OK exceptions are:
|
* the OK exceptions are:
|
||||||
* | it only gives access to pipes you create
|
* | current process's pipes
|
||||||
* d this process's file descriptors
|
* 0 current process's kernel infos
|
||||||
* e this process's environment
|
* d current process's file descriptors
|
||||||
|
* e current process's environment
|
||||||
* NOTE: Plan9 also allows
|
* NOTE: Plan9 also allows
|
||||||
* c time and pid, but also cons and consctl
|
* c time and pid, but also cons and consctl
|
||||||
* p control of your own processes (and unfortunately
|
* p control of your own processes (and unfortunately
|
||||||
@ -1303,7 +1304,7 @@ namec(char *aname, int amode, int omode, int perm)
|
|||||||
* Who actually need them can bind #c and #p somewhere
|
* Who actually need them can bind #c and #p somewhere
|
||||||
* before rfork(RFNOMNT)
|
* before rfork(RFNOMNT)
|
||||||
*/
|
*/
|
||||||
if(up->pgrp->noattach && utfrune("|de", r)==nil)
|
if(up->pgrp->noattach && utfrune("|0de", r)==nil)
|
||||||
error(Enoattach);
|
error(Enoattach);
|
||||||
dev = devtabget(r, 1); //XDYNX
|
dev = devtabget(r, 1); //XDYNX
|
||||||
if(dev == nil)
|
if(dev == nil)
|
||||||
|
@ -680,8 +680,6 @@ enum{
|
|||||||
Qnull,
|
Qnull,
|
||||||
Qosversion,
|
Qosversion,
|
||||||
Qpgrpid,
|
Qpgrpid,
|
||||||
Qpid,
|
|
||||||
Qppid,
|
|
||||||
Qrandom,
|
Qrandom,
|
||||||
Qreboot,
|
Qreboot,
|
||||||
Qswap,
|
Qswap,
|
||||||
@ -713,8 +711,6 @@ static Dirtab consdir[]={
|
|||||||
"null", {Qnull}, 0, 0666,
|
"null", {Qnull}, 0, 0666,
|
||||||
"osversion", {Qosversion}, 0, 0444,
|
"osversion", {Qosversion}, 0, 0444,
|
||||||
"pgrpid", {Qpgrpid}, NUMSIZE, 0444,
|
"pgrpid", {Qpgrpid}, NUMSIZE, 0444,
|
||||||
"pid", {Qpid}, NUMSIZE, 0444,
|
|
||||||
"ppid", {Qppid}, NUMSIZE, 0444,
|
|
||||||
"random", {Qrandom}, 0, 0444,
|
"random", {Qrandom}, 0, 0444,
|
||||||
"reboot", {Qreboot}, 0, 0664,
|
"reboot", {Qreboot}, 0, 0664,
|
||||||
"swap", {Qswap}, 0, 0664,
|
"swap", {Qswap}, 0, 0664,
|
||||||
@ -944,12 +940,6 @@ consread(Chan *c, void *buf, long n, int64_t off)
|
|||||||
case Qpgrpid:
|
case Qpgrpid:
|
||||||
return readnum(offset, buf, n, up->pgrp->pgrpid, NUMSIZE);
|
return readnum(offset, buf, n, up->pgrp->pgrpid, NUMSIZE);
|
||||||
|
|
||||||
case Qpid:
|
|
||||||
return readnum(offset, buf, n, up->pid, NUMSIZE);
|
|
||||||
|
|
||||||
case Qppid:
|
|
||||||
return readnum(offset, buf, n, up->parentpid, NUMSIZE);
|
|
||||||
|
|
||||||
case Qtime:
|
case Qtime:
|
||||||
return readtime(offset, buf, n);
|
return readtime(offset, buf, n);
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ dupgen(Chan *c, char * _1, Dirtab* _2, int _3, int s, Dir *dp)
|
|||||||
{
|
{
|
||||||
Fgrp *fgrp = up->fgrp;
|
Fgrp *fgrp = up->fgrp;
|
||||||
Chan *f;
|
Chan *f;
|
||||||
static int perm[] = { 0400, 0200, 0600, 0 };
|
static int perm[] = { 0, 0400, 0200, 0600, 0 };
|
||||||
int p;
|
int p;
|
||||||
Qid q;
|
Qid q;
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ dupgen(Chan *c, char * _1, Dirtab* _2, int _3, int s, Dir *dp)
|
|||||||
p = 0400;
|
p = 0400;
|
||||||
sprint(up->genbuf, "%dctl", s/2);
|
sprint(up->genbuf, "%dctl", s/2);
|
||||||
}else{
|
}else{
|
||||||
p = perm[f->mode&3];
|
p = perm[f->mode&7];
|
||||||
sprint(up->genbuf, "%d", s/2);
|
sprint(up->genbuf, "%d", s/2);
|
||||||
}
|
}
|
||||||
mkqid(&q, s+1, 0, QTFILE);
|
mkqid(&q, s+1, 0, QTFILE);
|
||||||
|
@ -1,3 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Jehanne.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015-2016 Giacomo Tesio <giacomo@tesio.it>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
#include "u.h"
|
#include "u.h"
|
||||||
#include "../port/lib.h"
|
#include "../port/lib.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
@ -51,11 +68,6 @@ enum
|
|||||||
CMwaitstop,
|
CMwaitstop,
|
||||||
CMwired,
|
CMwired,
|
||||||
CMtrace,
|
CMtrace,
|
||||||
|
|
||||||
/* segments */
|
|
||||||
CMsegattach,
|
|
||||||
CMsegdetach,
|
|
||||||
CMsegfree,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum{
|
enum{
|
||||||
@ -83,7 +95,7 @@ Dirtab procdir[] =
|
|||||||
"ns", {Qns}, 0, 0444,
|
"ns", {Qns}, 0, 0444,
|
||||||
"proc", {Qproc}, 0, 0400,
|
"proc", {Qproc}, 0, 0400,
|
||||||
"regs", {Qregs}, sizeof(Ureg), 0000,
|
"regs", {Qregs}, sizeof(Ureg), 0000,
|
||||||
"segment", {Qsegment}, 0, 0644,
|
"segment", {Qsegment}, 0, 0444,
|
||||||
"status", {Qstatus}, STATSIZE, 0444,
|
"status", {Qstatus}, STATSIZE, 0444,
|
||||||
"text", {Qtext}, 0, 0000,
|
"text", {Qtext}, 0, 0000,
|
||||||
"wait", {Qwait}, 0, 0400,
|
"wait", {Qwait}, 0, 0400,
|
||||||
@ -108,9 +120,6 @@ Cmdtab proccmd[] = {
|
|||||||
CMwaitstop, "waitstop", 1,
|
CMwaitstop, "waitstop", 1,
|
||||||
CMwired, "wired", 2,
|
CMwired, "wired", 2,
|
||||||
CMtrace, "trace", 0,
|
CMtrace, "trace", 0,
|
||||||
CMsegattach, "attach", 5,
|
|
||||||
CMsegdetach, "detach", 2,
|
|
||||||
CMsegfree, "free", 3,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -366,7 +375,6 @@ procopen(Chan *c, unsigned long omode)
|
|||||||
|
|
||||||
case Qsegment:
|
case Qsegment:
|
||||||
if(omode != OREAD && omode != OSTAT)
|
if(omode != OREAD && omode != OSTAT)
|
||||||
if(omode != OWRITE || up->pid != pid)
|
|
||||||
error(Eperm);
|
error(Eperm);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1092,137 +1100,6 @@ mntscan(Mntwalk *mw, Proc *p)
|
|||||||
runlock(&pg->ns);
|
runlock(&pg->ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uintptr_t
|
|
||||||
segattach(Proc* p, int attr, const char* name, uintptr_t va, usize len)
|
|
||||||
{
|
|
||||||
unsigned int sno, tmp;
|
|
||||||
ProcSegment *s;
|
|
||||||
uintptr_t pa, size;
|
|
||||||
|
|
||||||
|
|
||||||
if((va != 0 && va < UTZERO) || iskaddr(va))
|
|
||||||
error("virtual address below text or in kernel");
|
|
||||||
|
|
||||||
vmemchr((void *)name, 0, ~0);
|
|
||||||
|
|
||||||
for(sno = 0; sno < NSEG; sno++)
|
|
||||||
if(p->seg[sno] == nil && sno != ESEG)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if(sno == NSEG)
|
|
||||||
error("too many segments in process");
|
|
||||||
|
|
||||||
len = ROUNDUP(va+len, PGSZ) - ROUNDDN(va, PGSZ);
|
|
||||||
va = ROUNDDN(va, PGSZ);
|
|
||||||
|
|
||||||
if(rawmem_find((char**)&name, &pa, &tmp, &size)){
|
|
||||||
s = 0;
|
|
||||||
wlock(&p->seglock);
|
|
||||||
if(pa){
|
|
||||||
if(!segment_physical(&s, attr&SegPermissionMask, attr&SegFlagMask, va, pa))
|
|
||||||
goto SegAttachEbadarg;
|
|
||||||
} else if(size != -1){
|
|
||||||
if(!segment_global(&s, attr&SegPermissionMask, va, (char*)name))
|
|
||||||
goto SegAttachEbadarg;
|
|
||||||
} else {
|
|
||||||
if(!segment_virtual(&s, tmp&SegmentTypesMask, attr&SegPermissionMask&~SgExecute, attr&SegFlagMask, va, va+len))
|
|
||||||
goto SegAttachEbadarg;
|
|
||||||
}
|
|
||||||
for(tmp = 0; tmp < NSEG; tmp++){
|
|
||||||
if(p->seg[tmp])
|
|
||||||
if((p->seg[tmp]->base > s->base && p->seg[tmp]->base < s->top)
|
|
||||||
|| (p->seg[tmp]->top > s->base && p->seg[tmp]->top < s->top)){
|
|
||||||
goto SegAttachEsoverlap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
up->seg[sno] = s;
|
|
||||||
wunlock(&p->seglock);
|
|
||||||
return s->base;
|
|
||||||
}
|
|
||||||
error("segment not found");
|
|
||||||
SegAttachEbadarg:
|
|
||||||
wunlock(&p->seglock);
|
|
||||||
error(Ebadarg);
|
|
||||||
SegAttachEsoverlap:
|
|
||||||
wunlock(&p->seglock);
|
|
||||||
segment_release(&s);
|
|
||||||
error(Esoverlap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uintptr_t
|
|
||||||
segdetach(Proc* p, uintptr_t va)
|
|
||||||
{
|
|
||||||
if(!proc_segment_detach(p, va))
|
|
||||||
error(Ebadarg);
|
|
||||||
|
|
||||||
mmuflush();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uintptr_t
|
|
||||||
segfree(Proc* p, uintptr_t va, unsigned long len)
|
|
||||||
{
|
|
||||||
ProcSegment *s;
|
|
||||||
uintptr_t from, to;
|
|
||||||
|
|
||||||
from = PTR2UINT(va);
|
|
||||||
to = ROUNDDN(from + len, PGSZ);
|
|
||||||
|
|
||||||
s = proc_segment(p, from);
|
|
||||||
if(s == nil || to < from || to > s->top)
|
|
||||||
error(Ebadarg);
|
|
||||||
|
|
||||||
from = ROUNDUP(from, PGSZ);
|
|
||||||
if(from == to)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
segment_free_pages(s, from, to);
|
|
||||||
mmuflush();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long
|
|
||||||
procsegctl(Proc *p, char *va, int n)
|
|
||||||
{
|
|
||||||
Cmdbuf *cb;
|
|
||||||
Cmdtab *ct;
|
|
||||||
int attr;
|
|
||||||
const char *class;
|
|
||||||
uintptr_t vareq;
|
|
||||||
unsigned long len;
|
|
||||||
long result;
|
|
||||||
|
|
||||||
cb = parsecmd(va, n);
|
|
||||||
if(waserror()){
|
|
||||||
free(cb);
|
|
||||||
nexterror();
|
|
||||||
}
|
|
||||||
|
|
||||||
ct = lookupcmd(cb, proccmd, nelem(proccmd));
|
|
||||||
switch(ct->index){
|
|
||||||
default:
|
|
||||||
error(Ebadctl);
|
|
||||||
return -1;
|
|
||||||
case CMsegattach:
|
|
||||||
attr = strtoul(cb->f[1], 0, 0);
|
|
||||||
vareq = strtoull(cb->f[2], 0, 0);
|
|
||||||
len = strtoull(cb->f[3], 0, 0);
|
|
||||||
class = cb->f[4];
|
|
||||||
result = segattach(p, attr, class, vareq, len);
|
|
||||||
break;
|
|
||||||
case CMsegdetach:
|
|
||||||
vareq = strtoull(cb->f[1], 0, 0);
|
|
||||||
result = segdetach(p, vareq);
|
|
||||||
break;
|
|
||||||
case CMsegfree:
|
|
||||||
vareq = strtoull(cb->f[1], 0, 0);
|
|
||||||
len = strtoull(cb->f[2], 0, 0);
|
|
||||||
result = segfree(p, vareq, len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
poperror();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static long
|
static long
|
||||||
procwrite(Chan *c, void *va, long n, int64_t off)
|
procwrite(Chan *c, void *va, long n, int64_t off)
|
||||||
@ -1300,10 +1177,6 @@ procwrite(Chan *c, void *va, long n, int64_t off)
|
|||||||
n = fpudevprocio(p, va, n, offset, 1);
|
n = fpudevprocio(p, va, n, offset, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qsegment:
|
|
||||||
n = procsegctl(p, va, n);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Qctl:
|
case Qctl:
|
||||||
procctlreq(p, va, n);
|
procctlreq(p, va, n);
|
||||||
break;
|
break;
|
||||||
|
387
sys/src/kern/port/devself.c
Normal file
387
sys/src/kern/port/devself.c
Normal file
@ -0,0 +1,387 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Jehanne.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Giacomo Tesio <giacomo@tesio.it>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#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)
|
||||||
|
|
||||||
|
/* devself provides to each process access to its own structures
|
||||||
|
* (pid, ppid, segments...).
|
||||||
|
*/
|
||||||
|
typedef enum SelfNodes
|
||||||
|
{
|
||||||
|
Qdir,
|
||||||
|
|
||||||
|
/* Process control */
|
||||||
|
Qpid,
|
||||||
|
Qppid,
|
||||||
|
Qsegments,
|
||||||
|
Qpipes,
|
||||||
|
} SelfNodes;
|
||||||
|
|
||||||
|
typedef enum SegmentsCmd
|
||||||
|
{
|
||||||
|
CMsegattach,
|
||||||
|
CMsegdetach,
|
||||||
|
CMsegfree,
|
||||||
|
} SegmentsCmd;
|
||||||
|
|
||||||
|
static
|
||||||
|
Cmdtab proccmd[] = {
|
||||||
|
CMsegattach, "attach", 5,
|
||||||
|
CMsegdetach, "detach", 2,
|
||||||
|
CMsegfree, "free", 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union PipeSet
|
||||||
|
{
|
||||||
|
long merged;
|
||||||
|
int fd[2];
|
||||||
|
} PipeSet;
|
||||||
|
|
||||||
|
static Dirtab selfdir[]={
|
||||||
|
".", {Qdir, 0, QTDIR}, 0, DMDIR|0777,
|
||||||
|
"pid", {Qpid}, 0, 0,
|
||||||
|
"ppid", {Qppid}, 0, 0,
|
||||||
|
"segments", {Qsegments}, 0, 0644,
|
||||||
|
"pipes", {Qpipes}, 0, 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static Chan*
|
||||||
|
selfattach(Chan *c, Chan *ac, char *spec, int flags)
|
||||||
|
{
|
||||||
|
return devattach('0', spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Walkqid*
|
||||||
|
selfwalk(Chan *c, Chan *nc, char **name, int nname)
|
||||||
|
{
|
||||||
|
return devwalk(c, nc, name, nname, selfdir, nelem(selfdir), devgen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
selfstat(Chan *c, uint8_t *dp, long n)
|
||||||
|
{
|
||||||
|
return devstat(c, dp, n, selfdir, nelem(selfdir), devgen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Chan*
|
||||||
|
selfopen(Chan *c, unsigned long omode)
|
||||||
|
{
|
||||||
|
c->aux = nil;
|
||||||
|
c = devopen(c, omode, selfdir, nelem(selfdir), devgen);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
selfread(Chan *c, void *va, long n, int64_t off)
|
||||||
|
{
|
||||||
|
int64_t offset;
|
||||||
|
ProcSegment *sg;
|
||||||
|
int i, j;
|
||||||
|
char statbuf[NSEG*STATSIZE];
|
||||||
|
|
||||||
|
offset = off;
|
||||||
|
switch(QID(c->qid)){
|
||||||
|
case Qsegments:
|
||||||
|
rlock(&up->seglock);
|
||||||
|
j = 0;
|
||||||
|
for(i = 0; i < NSEG; i++) {
|
||||||
|
sg = up->seg[i];
|
||||||
|
if(sg == 0)
|
||||||
|
continue;
|
||||||
|
j += sprint(statbuf+j, "%-6s %c%c %p %p %4d\n",
|
||||||
|
segment_name(sg),
|
||||||
|
!(sg->type&SgWrite) ? 'R' : ' ',
|
||||||
|
(sg->type&SgExecute) ? 'x' : ' ',
|
||||||
|
' ', // sg->profile ? 'P' : ' ', // here was profiling
|
||||||
|
sg->base, sg->top, sg->r.ref);
|
||||||
|
}
|
||||||
|
runlock(&up->seglock);
|
||||||
|
if(offset >= j)
|
||||||
|
return 0;
|
||||||
|
if(offset+n > j)
|
||||||
|
n = j-offset;
|
||||||
|
if(n == 0 && offset == 0)
|
||||||
|
exhausted("segments");
|
||||||
|
memmove(va, &statbuf[offset], n);
|
||||||
|
return n;
|
||||||
|
default:
|
||||||
|
error(Egreg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uintptr_t
|
||||||
|
segattach(Proc* p, int attr, const char* name, uintptr_t va, usize len)
|
||||||
|
{
|
||||||
|
unsigned int sno, tmp;
|
||||||
|
ProcSegment *s;
|
||||||
|
uintptr_t pa, size;
|
||||||
|
|
||||||
|
|
||||||
|
if((va != 0 && va < UTZERO) || iskaddr(va))
|
||||||
|
error("virtual address below text or in kernel");
|
||||||
|
|
||||||
|
vmemchr((void *)name, 0, ~0);
|
||||||
|
|
||||||
|
for(sno = 0; sno < NSEG; sno++)
|
||||||
|
if(p->seg[sno] == nil && sno != ESEG)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(sno == NSEG)
|
||||||
|
error("too many segments in process");
|
||||||
|
|
||||||
|
len = ROUNDUP(va+len, PGSZ) - ROUNDDN(va, PGSZ);
|
||||||
|
va = ROUNDDN(va, PGSZ);
|
||||||
|
|
||||||
|
if(rawmem_find((char**)&name, &pa, &tmp, &size)){
|
||||||
|
s = 0;
|
||||||
|
wlock(&p->seglock);
|
||||||
|
if(pa){
|
||||||
|
if(!segment_physical(&s, attr&SegPermissionMask, attr&SegFlagMask, va, pa))
|
||||||
|
goto SegAttachEbadarg;
|
||||||
|
} else if(size != -1){
|
||||||
|
if(!segment_global(&s, attr&SegPermissionMask, va, (char*)name))
|
||||||
|
goto SegAttachEbadarg;
|
||||||
|
} else {
|
||||||
|
if(!segment_virtual(&s, tmp&SegmentTypesMask, attr&SegPermissionMask&~SgExecute, attr&SegFlagMask, va, va+len))
|
||||||
|
goto SegAttachEbadarg;
|
||||||
|
}
|
||||||
|
for(tmp = 0; tmp < NSEG; tmp++){
|
||||||
|
if(p->seg[tmp])
|
||||||
|
if((p->seg[tmp]->base > s->base && p->seg[tmp]->base < s->top)
|
||||||
|
|| (p->seg[tmp]->top > s->base && p->seg[tmp]->top < s->top)){
|
||||||
|
goto SegAttachEsoverlap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
up->seg[sno] = s;
|
||||||
|
wunlock(&p->seglock);
|
||||||
|
return s->base;
|
||||||
|
}
|
||||||
|
error("segment not found");
|
||||||
|
SegAttachEbadarg:
|
||||||
|
wunlock(&p->seglock);
|
||||||
|
error(Ebadarg);
|
||||||
|
SegAttachEsoverlap:
|
||||||
|
wunlock(&p->seglock);
|
||||||
|
segment_release(&s);
|
||||||
|
error(Esoverlap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uintptr_t
|
||||||
|
segdetach(Proc* p, uintptr_t va)
|
||||||
|
{
|
||||||
|
if(!proc_segment_detach(p, va))
|
||||||
|
error(Ebadarg);
|
||||||
|
|
||||||
|
mmuflush();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uintptr_t
|
||||||
|
segfree(Proc* p, uintptr_t va, unsigned long len)
|
||||||
|
{
|
||||||
|
ProcSegment *s;
|
||||||
|
uintptr_t from, to;
|
||||||
|
|
||||||
|
from = PTR2UINT(va);
|
||||||
|
to = ROUNDDN(from + len, PGSZ);
|
||||||
|
|
||||||
|
s = proc_segment(p, from);
|
||||||
|
if(s == nil || to < from || to > s->top)
|
||||||
|
error(Ebadarg);
|
||||||
|
|
||||||
|
from = ROUNDUP(from, PGSZ);
|
||||||
|
if(from == to)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
segment_free_pages(s, from, to);
|
||||||
|
mmuflush();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
procsegctl(Proc *p, char *va, int n)
|
||||||
|
{
|
||||||
|
Cmdbuf *cb;
|
||||||
|
Cmdtab *ct;
|
||||||
|
int attr;
|
||||||
|
const char *class;
|
||||||
|
uintptr_t vareq;
|
||||||
|
unsigned long len;
|
||||||
|
long result;
|
||||||
|
|
||||||
|
cb = parsecmd(va, n);
|
||||||
|
if(waserror()){
|
||||||
|
free(cb);
|
||||||
|
nexterror();
|
||||||
|
}
|
||||||
|
|
||||||
|
ct = lookupcmd(cb, proccmd, nelem(proccmd));
|
||||||
|
switch(ct->index){
|
||||||
|
default:
|
||||||
|
error(Ebadctl);
|
||||||
|
return -1;
|
||||||
|
case CMsegattach:
|
||||||
|
attr = strtoul(cb->f[1], 0, 0);
|
||||||
|
vareq = strtoull(cb->f[2], 0, 0);
|
||||||
|
len = strtoull(cb->f[3], 0, 0);
|
||||||
|
class = cb->f[4];
|
||||||
|
result = segattach(p, attr, class, vareq, len);
|
||||||
|
break;
|
||||||
|
case CMsegdetach:
|
||||||
|
vareq = strtoull(cb->f[1], 0, 0);
|
||||||
|
result = segdetach(p, vareq);
|
||||||
|
break;
|
||||||
|
case CMsegfree:
|
||||||
|
vareq = strtoull(cb->f[1], 0, 0);
|
||||||
|
len = strtoull(cb->f[2], 0, 0);
|
||||||
|
result = segfree(p, vareq, len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
poperror();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
selfwrite(Chan *c, void *va, long n, int64_t off)
|
||||||
|
{
|
||||||
|
switch(QID(c->qid)){
|
||||||
|
default:
|
||||||
|
error(Egreg);
|
||||||
|
case Qsegments:
|
||||||
|
n = procsegctl(up, va, n);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
newfd2(int fd[2], Chan *c[2])
|
||||||
|
{
|
||||||
|
extern int findfreefd(Fgrp *f, int start);
|
||||||
|
extern void unlockfgrp(Fgrp *f);
|
||||||
|
Fgrp *f;
|
||||||
|
|
||||||
|
f = up->fgrp;
|
||||||
|
lock(&f->l);
|
||||||
|
fd[0] = findfreefd(f, 0);
|
||||||
|
if(fd[0] < 0){
|
||||||
|
unlockfgrp(f);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fd[1] = findfreefd(f, fd[0]+1);
|
||||||
|
if(fd[1] < 0){
|
||||||
|
unlockfgrp(f);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(fd[1] > f->maxfd)
|
||||||
|
f->maxfd = fd[1];
|
||||||
|
f->fd[fd[0]] = c[0];
|
||||||
|
f->fd[fd[1]] = c[1];
|
||||||
|
unlockfgrp(f);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long
|
||||||
|
newpipe(void)
|
||||||
|
{
|
||||||
|
PipeSet pipe;
|
||||||
|
Chan *c[2];
|
||||||
|
static char *datastr[] = {"data", "data1"};
|
||||||
|
|
||||||
|
c[0] = namec("#|", Atodir, 0, 0);
|
||||||
|
c[1] = nil;
|
||||||
|
pipe.fd[0] = -1;
|
||||||
|
pipe.fd[1] = -1;
|
||||||
|
|
||||||
|
if(waserror()){
|
||||||
|
cclose(c[0]);
|
||||||
|
if(c[1])
|
||||||
|
cclose(c[1]);
|
||||||
|
nexterror();
|
||||||
|
}
|
||||||
|
c[1] = cclone(c[0]);
|
||||||
|
if(walk(&c[0], datastr+0, 1, 1, nil) < 0)
|
||||||
|
error(Egreg);
|
||||||
|
if(walk(&c[1], datastr+1, 1, 1, nil) < 0)
|
||||||
|
error(Egreg);
|
||||||
|
c[0] = c[0]->dev->open(c[0], ORDWR);
|
||||||
|
c[1] = c[1]->dev->open(c[1], ORDWR);
|
||||||
|
if(newfd2(pipe.fd, c) < 0)
|
||||||
|
error(Enofd);
|
||||||
|
poperror();
|
||||||
|
|
||||||
|
return pipe.merged;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
selfremove(Chan* c)
|
||||||
|
{
|
||||||
|
long pipeset;
|
||||||
|
switch((uint32_t)c->qid.path){
|
||||||
|
case Qsegments:
|
||||||
|
error(Eperm);
|
||||||
|
break;
|
||||||
|
case Qpid:
|
||||||
|
errorl("got pid", up->pid);
|
||||||
|
break;
|
||||||
|
case Qppid:
|
||||||
|
errorl("got parent pid", up->parentpid);
|
||||||
|
break;
|
||||||
|
case Qpipes:
|
||||||
|
pipeset = newpipe();
|
||||||
|
errorl("got new pipes", pipeset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
selfclose(Chan *c)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Dev selfdevtab = {
|
||||||
|
'0',
|
||||||
|
"self",
|
||||||
|
|
||||||
|
devreset,
|
||||||
|
devinit,
|
||||||
|
devshutdown,
|
||||||
|
selfattach,
|
||||||
|
selfwalk,
|
||||||
|
selfstat,
|
||||||
|
selfopen,
|
||||||
|
devcreate,
|
||||||
|
selfclose,
|
||||||
|
selfread,
|
||||||
|
devbread,
|
||||||
|
selfwrite,
|
||||||
|
devbwrite,
|
||||||
|
selfremove,
|
||||||
|
devwstat,
|
||||||
|
};
|
@ -23,6 +23,7 @@
|
|||||||
"../port/chan.c",
|
"../port/chan.c",
|
||||||
"../port/debug.c",
|
"../port/debug.c",
|
||||||
"../port/dev.c",
|
"../port/dev.c",
|
||||||
|
"../port/dev9p.c",
|
||||||
"../port/devbridge.c",
|
"../port/devbridge.c",
|
||||||
"../port/devcap.c",
|
"../port/devcap.c",
|
||||||
"../port/devcons.c",
|
"../port/devcons.c",
|
||||||
@ -30,12 +31,12 @@
|
|||||||
"../port/devenv.c",
|
"../port/devenv.c",
|
||||||
"../port/devfs.c",
|
"../port/devfs.c",
|
||||||
"../port/devkprof.c",
|
"../port/devkprof.c",
|
||||||
"../port/dev9p.c",
|
|
||||||
"../port/devpci.c",
|
"../port/devpci.c",
|
||||||
"../port/devpipe.c",
|
"../port/devpipe.c",
|
||||||
"../port/devproc.c",
|
"../port/devproc.c",
|
||||||
"../port/devroot.c",
|
"../port/devroot.c",
|
||||||
"../port/devsd.c",
|
"../port/devsd.c",
|
||||||
|
"../port/devself.c",
|
||||||
"../port/devshr.c",
|
"../port/devshr.c",
|
||||||
"../port/devsrv.c",
|
"../port/devsrv.c",
|
||||||
"../port/devssl.c",
|
"../port/devssl.c",
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
* The sys*() routines needn't poperror() as they return directly to syscall().
|
* The sys*() routines needn't poperror() as they return directly to syscall().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
void
|
||||||
unlockfgrp(Fgrp *f)
|
unlockfgrp(Fgrp *f)
|
||||||
{
|
{
|
||||||
int ex;
|
int ex;
|
||||||
@ -74,7 +74,7 @@ growfd(Fgrp *f, int fd) /* fd is always >= 0 */
|
|||||||
/*
|
/*
|
||||||
* this assumes that the fgrp is locked
|
* this assumes that the fgrp is locked
|
||||||
*/
|
*/
|
||||||
static int
|
int
|
||||||
findfreefd(Fgrp *f, int start)
|
findfreefd(Fgrp *f, int start)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
@ -107,32 +107,6 @@ newfd(Chan *c)
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
newfd2(int fd[2], Chan *c[2])
|
|
||||||
{
|
|
||||||
Fgrp *f;
|
|
||||||
|
|
||||||
f = up->fgrp;
|
|
||||||
lock(&f->l);
|
|
||||||
fd[0] = findfreefd(f, 0);
|
|
||||||
if(fd[0] < 0){
|
|
||||||
unlockfgrp(f);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
fd[1] = findfreefd(f, fd[0]+1);
|
|
||||||
if(fd[1] < 0){
|
|
||||||
unlockfgrp(f);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(fd[1] > f->maxfd)
|
|
||||||
f->maxfd = fd[1];
|
|
||||||
f->fd[fd[0]] = c[0];
|
|
||||||
f->fd[fd[1]] = c[1];
|
|
||||||
unlockfgrp(f);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Chan*
|
Chan*
|
||||||
fdtochan(int fd, unsigned long mode, int chkmnt, int iref)
|
fdtochan(int fd, unsigned long mode, int chkmnt, int iref)
|
||||||
{
|
{
|
||||||
@ -205,44 +179,6 @@ sysfd2path(int fd, char* buf, int nbuf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
syspipe(int* a)
|
|
||||||
{
|
|
||||||
int fd[2];
|
|
||||||
Chan *c[2];
|
|
||||||
static char *datastr[] = {"data", "data1"};
|
|
||||||
|
|
||||||
a = validaddr(a, sizeof(fd), 1);
|
|
||||||
evenaddr(PTR2UINT(a));
|
|
||||||
|
|
||||||
c[0] = namec("#|", Atodir, 0, 0);
|
|
||||||
c[1] = nil;
|
|
||||||
fd[0] = -1;
|
|
||||||
fd[1] = -1;
|
|
||||||
|
|
||||||
if(waserror()){
|
|
||||||
cclose(c[0]);
|
|
||||||
if(c[1])
|
|
||||||
cclose(c[1]);
|
|
||||||
nexterror();
|
|
||||||
}
|
|
||||||
c[1] = cclone(c[0]);
|
|
||||||
if(walk(&c[0], datastr+0, 1, 1, nil) < 0)
|
|
||||||
error(Egreg);
|
|
||||||
if(walk(&c[1], datastr+1, 1, 1, nil) < 0)
|
|
||||||
error(Egreg);
|
|
||||||
c[0] = c[0]->dev->open(c[0], ORDWR);
|
|
||||||
c[1] = c[1]->dev->open(c[1], ORDWR);
|
|
||||||
if(newfd2(fd, c) < 0)
|
|
||||||
error(Enofd);
|
|
||||||
poperror();
|
|
||||||
|
|
||||||
a[0] = fd[0];
|
|
||||||
a[1] = fd[1];
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
sysdup(int ofd, int nfd)
|
sysdup(int ofd, int nfd)
|
||||||
{
|
{
|
||||||
|
@ -22,20 +22,7 @@
|
|||||||
int
|
int
|
||||||
getpid(void)
|
getpid(void)
|
||||||
{
|
{
|
||||||
char buf[20];
|
|
||||||
int pid;
|
int pid;
|
||||||
|
pid = (int)remove("#0/pid");
|
||||||
pid = open("#c/pid", OREAD);
|
return pid;
|
||||||
if(pid < 0){
|
|
||||||
// probably rfork(RFNOMNT)
|
|
||||||
pid = open("/dev/pid", OREAD);
|
|
||||||
if(pid < 0){
|
|
||||||
werrstr("getpid: cannot open neither #c/pid nor /dev/pid");
|
|
||||||
return -1; // probably rfork(RFNOMNT|RFCNAMEG)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
assert(read(pid, buf, sizeof(buf)) > 0);
|
|
||||||
close(pid);
|
|
||||||
return atol(buf);
|
|
||||||
}
|
}
|
||||||
|
@ -22,20 +22,7 @@
|
|||||||
int
|
int
|
||||||
getppid(void)
|
getppid(void)
|
||||||
{
|
{
|
||||||
char buf[20];
|
int pid;
|
||||||
int ppid;
|
pid = (int)remove("#0/ppid");
|
||||||
|
return pid;
|
||||||
ppid = open("#c/ppid", OREAD);
|
|
||||||
if(ppid < 0){
|
|
||||||
// probably rfork(RFNOMNT)
|
|
||||||
ppid = open("/dev/ppid", OREAD);
|
|
||||||
if(ppid < 0){
|
|
||||||
werrstr("getppid: cannot open neither #c/ppid nor /dev/ppid");
|
|
||||||
return -1; // probably rfork(RFNOMNT|RFCNAMEG)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
assert(read(ppid, buf, sizeof(buf)) > 0);
|
|
||||||
close(ppid);
|
|
||||||
return atol(buf);
|
|
||||||
}
|
}
|
||||||
|
37
sys/src/lib/c/9sys/pipe.c
Normal file
37
sys/src/lib/c/9sys/pipe.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Jehanne.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015-2017 Giacomo Tesio <giacomo@tesio.it>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
|
||||||
|
typedef union PipeSet
|
||||||
|
{
|
||||||
|
long merged;
|
||||||
|
int fd[2];
|
||||||
|
} PipeSet;
|
||||||
|
|
||||||
|
int
|
||||||
|
pipe(int pipes[2])
|
||||||
|
{
|
||||||
|
PipeSet pset;
|
||||||
|
pset.merged = remove("#0/pipes");
|
||||||
|
if(pset.merged == -1)
|
||||||
|
return -1;
|
||||||
|
pipes[0] = pset.fd[0];
|
||||||
|
pipes[1] = pset.fd[1];
|
||||||
|
return 0;
|
||||||
|
}
|
@ -18,21 +18,6 @@
|
|||||||
#include <u.h>
|
#include <u.h>
|
||||||
#include <libc.h>
|
#include <libc.h>
|
||||||
|
|
||||||
static int
|
|
||||||
opensegment(int pid)
|
|
||||||
{
|
|
||||||
char file[128];
|
|
||||||
int32_t f;
|
|
||||||
|
|
||||||
sprint(file, "#p/%d/segment", pid);
|
|
||||||
f = open(file, OWRITE);
|
|
||||||
if(f < 0){
|
|
||||||
sprint(file, "/proc/%d/segment", pid);
|
|
||||||
f = open(file, OWRITE);
|
|
||||||
}
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void*
|
void*
|
||||||
segattach(int attr, const char *class, void *va, unsigned long len)
|
segattach(int attr, const char *class, void *va, unsigned long len)
|
||||||
{
|
{
|
||||||
@ -40,8 +25,7 @@ segattach(int attr, const char *class, void *va, unsigned long len)
|
|||||||
long tmp;
|
long tmp;
|
||||||
char msg[256];
|
char msg[256];
|
||||||
|
|
||||||
tmp = getpid();
|
fd = open("#0/segments", OWRITE);
|
||||||
fd = opensegment(tmp);
|
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
return (void*)-1;
|
return (void*)-1;
|
||||||
|
|
||||||
@ -57,8 +41,7 @@ segdetach(void *addr)
|
|||||||
int fd, tmp;
|
int fd, tmp;
|
||||||
char msg[256];
|
char msg[256];
|
||||||
|
|
||||||
tmp = getpid();
|
fd = open("#0/segments", OWRITE);
|
||||||
fd = opensegment(tmp);
|
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -74,8 +57,7 @@ segfree(void *addr, unsigned long len)
|
|||||||
int fd, tmp;
|
int fd, tmp;
|
||||||
char msg[256];
|
char msg[256];
|
||||||
|
|
||||||
tmp = getpid();
|
fd = open("#0/segments", OWRITE);
|
||||||
fd = opensegment(tmp);
|
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
"9sys/getwd.c",
|
"9sys/getwd.c",
|
||||||
"9sys/iounit.c",
|
"9sys/iounit.c",
|
||||||
"9sys/nulldir.c",
|
"9sys/nulldir.c",
|
||||||
|
"9sys/pipe.c",
|
||||||
"9sys/postnote.c",
|
"9sys/postnote.c",
|
||||||
"9sys/privalloc.c",
|
"9sys/privalloc.c",
|
||||||
"9sys/pushssl.c",
|
"9sys/pushssl.c",
|
||||||
|
@ -251,16 +251,6 @@
|
|||||||
"long"
|
"long"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Args": [
|
|
||||||
"int*"
|
|
||||||
],
|
|
||||||
"Id": 21,
|
|
||||||
"Name": "pipe",
|
|
||||||
"Ret": [
|
|
||||||
"int"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Args": [
|
"Args": [
|
||||||
"int",
|
"int",
|
||||||
@ -268,7 +258,7 @@
|
|||||||
"int",
|
"int",
|
||||||
"long"
|
"long"
|
||||||
],
|
],
|
||||||
"Id": 22,
|
"Id": 21,
|
||||||
"Name": "pread",
|
"Name": "pread",
|
||||||
"Ret": [
|
"Ret": [
|
||||||
"long"
|
"long"
|
||||||
@ -281,7 +271,7 @@
|
|||||||
"int",
|
"int",
|
||||||
"long"
|
"long"
|
||||||
],
|
],
|
||||||
"Id": 23,
|
"Id": 22,
|
||||||
"Name": "pwrite",
|
"Name": "pwrite",
|
||||||
"Ret": [
|
"Ret": [
|
||||||
"long"
|
"long"
|
||||||
@ -291,7 +281,7 @@
|
|||||||
"Args": [
|
"Args": [
|
||||||
"const char*"
|
"const char*"
|
||||||
],
|
],
|
||||||
"Id": 24,
|
"Id": 23,
|
||||||
"Name": "remove",
|
"Name": "remove",
|
||||||
"Ret": [
|
"Ret": [
|
||||||
"long"
|
"long"
|
||||||
@ -302,7 +292,7 @@
|
|||||||
"const void*",
|
"const void*",
|
||||||
"void*"
|
"void*"
|
||||||
],
|
],
|
||||||
"Id": 25,
|
"Id": 24,
|
||||||
"Name": "rendezvous",
|
"Name": "rendezvous",
|
||||||
"Ret": [
|
"Ret": [
|
||||||
"void*"
|
"void*"
|
||||||
@ -312,7 +302,7 @@
|
|||||||
"Args": [
|
"Args": [
|
||||||
"uint32_t"
|
"uint32_t"
|
||||||
],
|
],
|
||||||
"Id": 26,
|
"Id": 25,
|
||||||
"Name": "rfork",
|
"Name": "rfork",
|
||||||
"Ret": [
|
"Ret": [
|
||||||
"int"
|
"int"
|
||||||
@ -324,7 +314,7 @@
|
|||||||
"long",
|
"long",
|
||||||
"int"
|
"int"
|
||||||
],
|
],
|
||||||
"Id": 27,
|
"Id": 26,
|
||||||
"Name": "seek",
|
"Name": "seek",
|
||||||
"Ret": [
|
"Ret": [
|
||||||
"long"
|
"long"
|
||||||
@ -335,7 +325,7 @@
|
|||||||
"int*",
|
"int*",
|
||||||
"int"
|
"int"
|
||||||
],
|
],
|
||||||
"Id": 28,
|
"Id": 27,
|
||||||
"Name": "semacquire",
|
"Name": "semacquire",
|
||||||
"Ret": [
|
"Ret": [
|
||||||
"int"
|
"int"
|
||||||
@ -346,7 +336,7 @@
|
|||||||
"int*",
|
"int*",
|
||||||
"int"
|
"int"
|
||||||
],
|
],
|
||||||
"Id": 29,
|
"Id": 28,
|
||||||
"Name": "semrelease",
|
"Name": "semrelease",
|
||||||
"Ret": [
|
"Ret": [
|
||||||
"int"
|
"int"
|
||||||
@ -357,7 +347,7 @@
|
|||||||
"int*",
|
"int*",
|
||||||
"uint64_t"
|
"uint64_t"
|
||||||
],
|
],
|
||||||
"Id": 30,
|
"Id": 29,
|
||||||
"Name": "tsemacquire",
|
"Name": "tsemacquire",
|
||||||
"Ret": [
|
"Ret": [
|
||||||
"int"
|
"int"
|
||||||
@ -368,7 +358,7 @@
|
|||||||
"const char*",
|
"const char*",
|
||||||
"const char*"
|
"const char*"
|
||||||
],
|
],
|
||||||
"Id": 31,
|
"Id": 30,
|
||||||
"Name": "unmount",
|
"Name": "unmount",
|
||||||
"Ret": [
|
"Ret": [
|
||||||
"int"
|
"int"
|
||||||
@ -378,7 +368,7 @@
|
|||||||
"Args": [
|
"Args": [
|
||||||
"unsigned long"
|
"unsigned long"
|
||||||
],
|
],
|
||||||
"Id": 32,
|
"Id": 31,
|
||||||
"Name": "alarm",
|
"Name": "alarm",
|
||||||
"Ret": [
|
"Ret": [
|
||||||
"long"
|
"long"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user