/* two ways to say what a system call is */ #define SYSCALL(x) void x(struct Ureg *ureg) typedef void(*Syscall)(struct Ureg*); /* macros for use within system calls */ #define ARG1 ((ureg)->bx) #define ARG2 ((ureg)->cx) #define ARG3 ((ureg)->dx) #define ARG4 ((ureg)->si) #define ARG5 ((ureg)->di) #define ARG6 ((ureg)->bp) #define RETURN(X) { ureg->ax = (ulong) (X); return; } /* ioctls */ #define IOCTL(x) int x(int fd, uint cmd, ulong arg) typedef struct Ioctl Ioctl; struct Ioctl { uint num; int (*f)(int, uint, ulong); }; typedef struct Ioctlname Ioctlname; struct Ioctlname { uint num; char *name; }; /* a mechanically generated list of names. */ extern char *syscallname[]; extern Ioctlname ioctlname[]; /* * provided by systab.c, which is mechanically * generated from systab */ extern Syscall syscalltab[]; extern Ioctl ioctltab[]; enum { PAGE_SIZE = 4096, PAGE_MASK = ~(PAGE_SIZE-1), }; #define TRUNC_PAGE(x) \ ((x) & PAGE_MASK) #define ROUND_PAGE(x) \ (((x) & (PAGE_SIZE-1)) ? (TRUNC_PAGE(x) + PAGE_SIZE) : (x)) /* an assembly hack */ void jumpstack(ulong addr, ulong *stack); void jumpureg(struct Ureg *ureg); void callsignal(int sig, void *handler); /* atomic inc/dec */ void _xinc(long *); long _xdec(long *); /* proc */ void set9stack(void *); int do9stack(int (*fn)(void *), void *); int createxproc(void (*fn)(void *), void *arg, int flags, int stacksize); /* load.c, elf loading */ typedef struct ElfEx ElfEx; struct ElfEx { ulong ientry; // interpreter ulong ibase; ulong entry; ulong base; ulong phdr; ulong phnum; ulong phent; }; int loadelf(char *file, ElfEx *ex); /* * contains argv[] not including the emulated program * arguments. used in execve() syscall to restart the emulator * with another program. */ extern char **emuargv; enum { SIGQUEUESIZE = 256, }; typedef struct Sigqueue Sigqueue; struct Sigqueue { struct { int sig; void *info; } e[SIGQUEUESIZE]; int rp; int wp; }; typedef struct Sigstate Sigstate; struct Sigstate { long level; /* signal actions */ struct { void *handler; ulong flags; uvlong blocked; } action[63]; /* for normal signals only */ void *info[31]; ulong pending; /* for realtime signals only */ Sigqueue rtsq; /* all blocked signals */ uvlong blocked; }; typedef struct Thread Thread; struct Thread { union { int tgid; /* threadgroupid */ int pid; }; int tid; /* threadid */ int ptid; /* parent threadid */ int uid; int gid; int umask; int exitsig; int *cleartidaddr; /* see set_tid_address() */ Sigstate ss; }; extern Thread *threadp; /* debugging */ #define DPRINT if(!debug) {} else print extern int debug; /* error.c translate from plan9 errors to linux ones */ int stringerr(char *); int mkerror(void); /* signal.c translate from plan9 waitmsg to linux signal numbers */ int stringsig(char *); char *sigstring(int sig); void sigprocess(Sigstate *ss); uvlong sigpending(Sigstate *ss); void sigdisable(Sigstate *ss); void sigenable(Sigstate *ss); int signote(Sigstate *ss, char *msg); void sigclearall(Sigstate *ss); int _kill(int pid, int sig); /* sysfile.c linux versions of close/read/write */ int _close(int fd); int _read(int fd, void *data, int len); int _write(int fd, void *data, int len); /* mmap.c */ void mmapinit(void); void mmapexit(void); void *mmap(void *addr, int len, int prot, int flags, int fd, int offset); int munmap(void *addr, int len); void *allocstack(int); int msync(void *addr); /* epoll.c */ typedef struct epoll_event epoll_event; struct epoll_event { ulong events; uvlong data; }; int epoll_create(int size); int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); int epoll_wait(int epfd, epoll_event *events, int maxevents, int timeout); /* notify epoll - callback used in buffd */ void epollevent(int fd, ulong setevents, ulong resetevents); /* buffd.c */ void buffd(int fd); void shutdownbuffd(int fd, int how); void pollbuffd(int fd); int buffdionread(int fd); int readbuffd(int fd, void *data, int len, int noblock); int peekbuffd(int fd, void *data, int len, int noblock); int writebuffd(int fd, void *data, int len, int noblock); /* util.c, filedescriptor tags */ enum { TAG_ALL = 0, TAG_READDIR = 1, TAG_BUFFD = 2, TAG_EPOLL = 3, TAG_FDFLAGS = 4, TAG_SOCK = 5, }; void *openfdtag(int fd, int tag, int create); void closefdtag(void *tag); void **fdtagp(void *tag); int fdtagfd(void *tag); void atdestroyfdtag(void *tag, void (*destroy)(void *tag)); void atforkfdtag(void *tag, void (*fork)(void *tag)); void destroyfdtag(void *tag); void forkfdtag(void *tag); void unlinkfdtag(void *tag); void forkallfdtags(void); /* util.c converting from plan9 /env to char** and back */ char **readenv(char *buf, int nbuf); void writeenv(char **);