syscalls.c
来自「kaffe Java 解释器语言,源码,Java的子集系统,开放源代码」· C语言 代码 · 共 926 行 · 第 1/2 页
C
926 行
* Threaded socket accept. */intjthreadedAccept(int fd, struct sockaddr* addr, int* len, int timeout, int* out){ /* absolute time at which time out is reached */#if defined(SO_RCVTIMEO) int ret; struct timeval old_tv; struct timeval new_tv; int old_tv_sz = sizeof (old_tv); getsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, &old_tv, &old_tv_sz); new_tv.tv_sec = 0; /* Guessed according to the former behaviour of jthreadedAccept * Even if it is wrong */ if (timeout == NOTIMEOUT) new_tv.tv_usec = 0; else new_tv.tv_usec = timeout*1000; ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &new_tv, sizeof(new_tv)); if (!ret) { ret = accept (fd, addr, len); setsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, &old_tv, sizeof (old_tv)); if( ret < 0 ) { switch( errno ) { case EAGAIN: errno = ETIMEDOUT; break; } } } SET_RETURN_OUT(ret, out, ret) return ret;#else int r=-1, ret; ret = waitForTimeout(fd,timeout); if (ret > 0) { r = accept(fd,addr,len); SET_RETURN_OUT(r, out, r) return (r); } else { errno = ETIMEDOUT; r = -1; } SET_RETURN_OUT(r, out, r) return (r);#endif}/* * Threaded read with timeout */intjthreadedTimedRead(int fd, void* buf, size_t len, int timeout, ssize_t *out){ ssize_t r = -1; /* absolute time at which timeout is reached */ int ret; ret = waitForTimeout(fd,timeout); if (ret > 0) { r = read(fd, buf, len); } SET_RETURN_OUT(r, out, r) return (r);}/* * Threaded write with timeout */intjthreadedTimedWrite(int fd, const void* buf, size_t len, int timeout, ssize_t *out){ ssize_t r = -1; /* absolute time at which timeout is reached */ int ret; ret = waitForWritable(fd,timeout); if (ret > 0) { r = write(fd, buf, len); } SET_RETURN_OUT(r, out, r) return (r);}/* * Threaded read with no time out */intjthreadedRead(int fd, void* buf, size_t len, ssize_t *out){ ssize_t r = -1; r = read(fd, buf, len); SET_RETURN_OUT(r, out, r); return (r);}/* * Threaded write */intjthreadedWrite(int fd, const void* buf, size_t len, ssize_t *out){ ssize_t r = 1; const void* ptr; ptr = buf; while (len > 0 && r > 0) { r = (ssize_t)write(fd, ptr, len); if (r >= 0) { ptr += r; len -= r; r = ptr - buf; continue; } if (errno == EINTR) { /* ignore */ r = 1; continue; } if (!(errno == EWOULDBLOCK || errno == EAGAIN)) { /* real error */ break; } r = 1; } SET_RETURN_OUT(r, out, r) return (r); }/* * Threaded recvfrom */int jthreadedRecvfrom(int fd, void* buf, size_t len, int flags, struct sockaddr* from, int* fromlen, int timeout, ssize_t *out){ int r; jlong deadline = 0; SET_DEADLINE(deadline, timeout) for (;;) { r = recvfrom(fd, buf, len, flags, from, fromlen); if (r >= 0 || !(errno == EWOULDBLOCK || errno == EINTR || errno == EAGAIN)) { break; } IGNORE_EINTR(r) BREAK_IF_LATE(deadline, timeout) } SET_RETURN_OUT(r, out, r) return (r);}/* helper function for forkexec, close fd[0..n-1] */static voidclose_fds(int fd[], int n){ int i = 0; while (i < n) { close(fd[i++]); }}int jthreadedForkExec(char **argv, char **arge, int ioes[4], int *outpid, const char *dir){/* these defines are indices in ioes */#define IN_IN 0#define IN_OUT 1#define OUT_IN 2#define OUT_OUT 3#define ERR_IN 4#define ERR_OUT 5#define SYNC_IN 6#define SYNC_OUT 7 int fds[8]; int nfd; /* number of fds in `fds' that are valid */ sigset_t nsig; char b[1]; int pid, i, err; /* * we need execve() and fork() for this to work. Don't bother if * we don't have them. */#if !defined(HAVE_EXECVE) && !defined(HAVE_EXECVP) unimp("neither execve() nor execvp() provided");#endif#if !defined(HAVE_FORK) unimp("fork() not provided");#endif /* Create the pipes to communicate with the child */ /* Make sure fds get closed if we can't create all pipes */ for (nfd = 0; nfd < 8; nfd += 2) { int e; err = pipe(fds + nfd); e = errno; if (err == -1) { close_fds(fds, nfd); return (e); } } /* * We must avoid that the child dies because of SIGVTALRM or * other signals. We disable interrupts before forking and then * reenable signals in the child after we cleaned up. */ sigfillset(&nsig); sigprocmask(SIG_BLOCK, &nsig, 0); pid = fork(); switch (pid) { case 0: /* Child */ /* set all signals back to their default state */ for (i = 0; i < NSIG; i++) { clearSignal(i); } /* now reenable interrupts */ sigprocmask(SIG_UNBLOCK, &nsig, 0); /* set stdin, stdout, and stderr up from the pipes */ dup2(fds[IN_IN], 0); dup2(fds[OUT_OUT], 1); dup2(fds[ERR_OUT], 2); /* What is sync about anyhow? Well my current guess is that * the parent writes a single byte to it when it's ready to * proceed. So here I wait until I get it before doing * anything. */ /* note that this is a blocking read */ read(fds[SYNC_IN], b, sizeof(b)); /* now close all pipe fds */ close_fds(fds, 8); /* change working directory */#if defined(HAVE_CHDIR) (void)chdir(dir);#endif /* * If no environment was given and we have execvp, we use it. * If an environment was given, we use execve. * This is roughly was the linux jdk seems to do. */ /* execute program */#if defined(HAVE_EXECVP) if (arge == NULL) execvp(argv[0], argv); else#endif execve(argv[0], argv, arge); break; case -1: /* Error */ err = errno; /* Close all pipe fds */ close_fds(fds, 8); sigprocmask(SIG_UNBLOCK, &nsig, 0); return (err); default: /* Parent */ /* close the fds we won't need */ close(fds[IN_IN]); close(fds[OUT_OUT]); close(fds[ERR_OUT]); close(fds[SYNC_IN]); /* copy and fix up the fds we do need */ ioes[0] = fds[IN_OUT]; ioes[1] = fds[OUT_IN]; ioes[2] = fds[ERR_IN]; ioes[3] = fds[SYNC_OUT]; sigprocmask(SIG_UNBLOCK, &nsig, 0); *outpid = pid; return (0); } exit(-1); /* NEVER REACHED */ }/* * Wait for a child process. */intjthreadedWaitpid(int wpid, int* status, int options, int *outpid){#if defined(HAVE_WAITPID) int npid; npid = waitpid(wpid, status, options); if (npid > 0) { *outpid = npid; return (0); } else { return (-1); }#else return (-1);#endif}intjthreadedMmap(void **memory, size_t *size, int mode, int fd, off_t *offset){#if defined(HAVE_MMAP) size_t pages_sz; off_t pages_offset; int sysmode, sysflags; int rc = 0; pages_sz = (*size)/getpagesize(); *size = (pages_sz+1)*getpagesize(); pages_offset = (*offset)/getpagesize(); *offset = pages_offset*getpagesize(); switch (mode) { case KAFFE_MMAP_READ: sysflags = MAP_SHARED; sysmode = PROT_READ; break; case KAFFE_MMAP_WRITE: sysflags = MAP_SHARED; sysmode = PROT_WRITE | PROT_READ; break; case KAFFE_MMAP_PRIVATE: sysflags = MAP_PRIVATE; sysmode = PROT_WRITE | PROT_READ; break; default: return -EINVAL; } *memory = mmap(*memory, *size, sysmode, sysflags, fd, *offset); return (rc);#else return (ENOTSUP);#endif}static intjthreadedMunmap(void *memory, size_t size){#if defined(HAVE_MMAP) int rc = 0; if (munmap(memory, size) < 0) { rc = errno; } return (rc);#else return (ENOTSUP);#endif}static intjthreadedMsync(void *memory, size_t size){#if defined(HAVE_MMAP) int rc = 0; memory = (void *)(((size_t)memory/getpagesize()) * getpagesize()); size += getpagesize(); /* TODO: Try not to freeze the entire VM. */ if (msync(memory, size, MS_SYNC | MS_INVALIDATE) < 0) { rc = errno; } return rc;#else return (ENOTSUP);#endif}int jthreadedPipeCreate(int *read_fd, int *write_fd){ int pairs[2]; assert(read_fd != NULL); assert(write_fd != NULL); if (pipe(pairs) < 0) return errno; *read_fd = pairs[0]; *write_fd = pairs[1]; return 0;}/* * The syscall interface as provided by the internal jthread system. */SystemCallInterface Kaffe_SystemCallInterface = { jthreadedOpen, jthreadedRead, jthreadedWrite, jthreadedLSeek, jthreadedClose, jthreadedFStat, jthreadedStat, jthreadedFTruncate, jthreadedFSync, jthreadedMkdir, jthreadedRmdir, jthreadedRename, jthreadedRemove, jthreadedSocket, jthreadedConnect, jthreadedBind, jthreadedListen, jthreadedAccept, jthreadedTimedRead, jthreadedRecvfrom, jthreadedWrite, jthreadedSendto, jthreadedSetSockOpt, jthreadedGetSockOpt, jthreadedGetSockName, jthreadedGetPeerName, jthreadedClose, jthreadedGetHostByName, jthreadedGetHostByAddr, jthreadedSelect, jthreadedForkExec, jthreadedWaitpid, jthreadedKill, jthreadedMmap, jthreadedMunmap, jthreadedMsync, jthreadedPipeCreate, jthreadedTimedRead, jthreadedTimedWrite};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?