#undef Lock #undef lock #undef unlock #undef Ref #undef incref #undef decref #undef canlock #undef QLock #undef qlock #undef qunlock #undef canqlock #undef RWLock #undef runlock #undef wunlock #undef rlock #undef wlock #undef canrlock #undef canwlock #undef open #undef read #undef write #undef remove #undef wstat #undef sysname #undef Waitmsg #undef postnote #undef nsec typedef struct Alarms Alarms; typedef struct Block Block; typedef struct Chan Chan; typedef struct Cmdbuf Cmdbuf; typedef struct Cmdtab Cmdtab; typedef struct Cname Cname; typedef struct Dev Dev; typedef struct Dirtab Dirtab; typedef struct Egrp Egrp; typedef struct Eiaport Eiaport; typedef struct Evalue Evalue; typedef struct Fgrp Fgrp; typedef struct DevConf DevConf; typedef struct Image Image; typedef struct Label Label; typedef struct List List; typedef struct Lock Lock; typedef struct Log Log; typedef struct Logflag Logflag; typedef struct Mntcache Mntcache; typedef struct Mount Mount; typedef struct Mntrpc Mntrpc; typedef struct Mntwalk Mntwalk; typedef struct Mnt Mnt; typedef struct Mhead Mhead; typedef struct Note Note; typedef struct Page Page; typedef struct Pgrps Pgrps; typedef struct PhysUart PhysUart; typedef struct Pgrp Pgrp; typedef struct Physseg Physseg; typedef struct Proc Proc; typedef struct Procalloc Procalloc; typedef struct Pte Pte; typedef struct QLock QLock; typedef struct Queue Queue; typedef struct Ref Ref; typedef struct Rendez Rendez; typedef struct Rgrp Rgrp; typedef struct RWlock RWlock; typedef struct Systab Systab; typedef struct Talarm Talarm; typedef struct Uart Uart; typedef struct Waitq Waitq; typedef struct Walkqid Walkqid; typedef struct Waitmsg Waitmsg; typedef int Devgen(Chan*, char*, Dirtab*, int, int, Dir*); typedef long Syscall(ulong*); enum { KNAMELEN = 28, MAXPROC = 4096, HZ = 1000, /* not really, but it will do */ }; struct Lock { ulong key; /* semaphore (non-zero = locked) */ ulong sr; ulong pc; Proc *p; ushort isilock; }; struct Ref { Lock lk; long ref; }; struct Rendez { Lock lk; Proc *p; }; struct QLock { Lock use; /* to access Qlock structure */ Proc *head; /* next process waiting for object */ Proc *tail; /* last process waiting for object */ int locked; /* flag */ }; struct RWlock { Lock use; Proc *head; /* list of waiting processes */ Proc *tail; ulong wpc; /* pc of writer */ Proc *wproc; /* writing proc */ int readers; /* number of readers */ int writer; /* number of writers */ }; struct Talarm { Lock lk; Proc *list; }; struct Alarms { QLock lk; Proc *head; }; /* * Access types in namec & channel flags */ enum { Aaccess, /* as in stat, wstat */ Abind, /* for left-hand-side of bind */ Atodir, /* as in chdir */ Aopen, /* for i/o */ Amount, /* to be mounted or mounted upon */ Acreate, /* is to be created */ Aremove, /* will be removed by caller */ COPEN = 0x0001, /* for i/o */ CMSG = 0x0002, /* the message channel for a mount */ /*rsc CCREATE = 0x0004, /* permits creation if c->mnt */ CCEXEC = 0x0008, /* close on exec */ CFREE = 0x0010, /* not in use */ CRCLOSE = 0x0020, /* remove on close */ CCACHE = 0x0080, /* client cache */ }; enum { BINTR = (1<<0), BFREE = (1<<1), }; struct Block { Block* next; Block* list; uchar* rp; /* first unconsumed byte */ uchar* wp; /* first empty byte */ uchar* lim; /* 1 past the end of the buffer */ uchar* base; /* start of the buffer */ void (*free)(Block*); ulong flag; }; #define BLEN(s) ((s)->wp - (s)->rp) #define BALLOC(s) ((s)->lim - (s)->base) struct Chan { Ref ref; Lock lk; Chan* next; /* allocation */ Chan* link; vlong offset; /* in file */ ushort type; ulong dev; ushort mode; /* read/write */ ushort flag; Qid qid; int fid; /* for devmnt */ ulong iounit; /* chunk size for i/o; 0==default */ Mhead* umh; /* mount point that derived Chan; used in unionread */ Chan* umc; /* channel in union; held for union read */ QLock umqlock; /* serialize unionreads */ int uri; /* union read index */ int dri; /* devdirread index */ ulong mountid; Mnt *mux; /* Mnt for clients using me for messages */ void* aux; Qid pgrpid; /* for #p/notepg */ ulong mid; /* for ns in devproc */ Chan* mchan; /* channel to mounted server */ Qid mqid; /* qid of root of mount point */ Cname *name; }; struct Cname { Ref ref; int alen; /* allocated length */ int len; /* strlen(s) */ char *s; }; struct Dev { int dc; char* name; void (*reset)(void); Chan* (*attach)(char*); Walkqid* (*walk)(Chan*, Chan*, char**, int); int (*stat)(Chan*, uchar*, int); Chan* (*open)(Chan*, int); void (*create)(Chan*, char*, int, ulong); void (*close)(Chan*); long (*read)(Chan*, void*, long, vlong); Block* (*bread)(Chan*, long, ulong); long (*write)(Chan*, void*, long, vlong); long (*bwrite)(Chan*, Block*, ulong); void (*remove)(Chan*); int (*wstat)(Chan*, uchar*, int); }; struct Dirtab { char name[KNAMELEN]; Qid qid; vlong length; long perm; }; struct Label { pm_jmp_buf jb; }; enum { NSMAX = 1000, NSLOG = 7, NSCACHE = (1<ref; channels on this mount point incref(c->mchan) == Mnt.c */ Chan *c; /* Channel to file service */ Proc *rip; /* Reader in progress */ Mntrpc *queue; /* Queue of pending requests on this channel */ ulong id; /* Multiplexer id for channel check */ Mnt *list; /* Free list */ int flags; /* cache */ int msize; /* data + IOHDRSZ */ char *version; /* 9P version */ Queue *q; /* input queue */ }; enum { NUser, /* note provided externally */ NExit, /* deliver note quietly */ NDebug, /* print debug message */ }; struct Note { char msg[ERRMAX]; int flag; /* whether system posted it */ }; enum { RENDLOG = 5, RENDHASH = 1<rendhash[(s)&((1<mnthash[(qid).path&((1< variadic */ }; struct Systab { Syscall *fn; char *fmt; char *psstate; }; #define DEVDOTDOT -1 extern Dev* devtab[]; extern Dev devaudio; extern Dev devcons; extern Dev devdraw; extern Dev devdup; extern Dev deveia; extern Dev devenv; extern Dev devfs; extern Dev devip; extern Dev devmnt; extern Dev devmouse; extern Dev devpipe; extern Dev devproc; extern Dev devroot; extern Dev devsrv; extern Dev devssl; extern Mach *machp0; extern Procalloc procalloc; extern Systab systab[Nsyscall]; extern char Enoerror[]; /* no error */ extern char Emount[]; /* inconsistent mount */ extern char Eunmount[]; /* not mounted */ extern char Eunion[]; /* not in union */ extern char Emountrpc[]; /* mount rpc error */ extern char Eshutdown[]; /* device shut down */ extern char Enocreate[]; /* mounted directory forbids creation */ extern char Enonexist[]; /* file does not exist */ extern char Eexist[]; /* file already exists */ extern char Ebadsharp[]; /* unknown device in # filename */ extern char Enotdir[]; /* not a directory */ extern char Eisdir[]; /* file is a directory */ extern char Ebadchar[]; /* bad character in file name */ extern char Efilename[]; /* file name syntax */ extern char Eperm[]; /* permission denied */ extern char Ebadusefd[]; /* inappropriate use of fd */ extern char Ebadarg[]; /* bad arg in system call */ extern char Einuse[]; /* device or object already in use */ extern char Eio[]; /* i/o error */ extern char Etoobig[]; /* read or write too large */ extern char Etoosmall[]; /* read or write too small */ extern char Enoport[]; /* network port not available */ extern char Ehungup[]; /* i/o on hungup channel */ extern char Ebadctl[]; /* bad process or channel control request */ extern char Enodev[]; /* no free devices */ extern char Eprocdied[]; /* process exited */ extern char Enochild[]; /* no living children */ extern char Eioload[]; /* i/o error in demand load */ extern char Enovmem[]; /* virtual memory allocation failed */ extern char Ebadfd[]; /* fd out of range or not open */ extern char Enofd[]; /* no free file descriptors */ extern char Eisstream[]; /* seek on a stream */ extern char Ebadexec[]; /* exec header invalid */ extern char Etimedout[]; /* connection timed out */ extern char Econrefused[]; /* connection refused */ extern char Econinuse[]; /* connection in use */ extern char Eintr[]; /* interrupted */ extern char Enomem[]; /* kernel allocate failed */ extern char Enoswap[]; /* swap space full */ extern char Esoverlap[]; /* segments overlap */ extern char Emouseset[]; /* mouse type already set */ extern char Eshort[]; /* i/o count too small */ extern char Egreg[]; /* ken has left the building */ extern char Ebadspec[]; /* bad attach specifier */ extern char Enoreg[]; /* process has no saved registers */ extern char Enoattach[]; /* mount/attach disallowed */ extern char Eshortstat[]; /* stat buffer too small */ extern char Ebadstat[]; /* malformed stat buffer */ extern char Enegoff[]; /* negative i/o offset */ extern char Ecmdargs[]; /* wrong #args in control message */ #define M getmach() #define up (M->_up)