📄 syscalls.c
字号:
} break; } else if (r == -1 && errno == EINPROGRESS) { inProgress = 1; } IGNORE_EINTR(r) BREAK_IF_LATE(deadline, timeout) } SET_RETURN(r) return (r);}/* * Threaded socket accept. */static intjthreadedAccept(int fd, struct sockaddr* addr, socklen_t* len, int timeout, int* out){ /* absolute time at which time out is reached */ int r=-1, ret; ret = waitForRW(fd,timeout); /* If result is 0, we had a timeout. * If it's not, let's try to accept. */ 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);}/* * Threaded read with timeout */static 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 */static 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 */static 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 */static 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 = (void *)((uintp)ptr + r); len -= r; r = (uintp)ptr - (uintp)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 */static int jthreadedRecvfrom(int fd, void* buf, size_t len, int flags, struct sockaddr* from, socklen_t* fromlen, int timeout, ssize_t *out){ int r = 0; jlong deadline = 0; int poll_timeout; int blocking = jthread_is_blocking(fd); jthread_set_blocking(fd, 0); SET_DEADLINE(deadline, timeout) for (;;) { if (timeout != NOTIMEOUT) { poll_timeout = deadline - currentTime(); if (poll_timeout > 0) waitForTimeout(fd, poll_timeout); } else { waitForTimeout(fd, NOTIMEOUT); } BREAK_IF_LATE(deadline, timeout) r = recvfrom(fd, buf, len, flags, from, fromlen); if (r >= 0 || !(errno == EWOULDBLOCK || errno == EINTR || errno == EAGAIN)) { break; } } jthread_set_blocking(fd, blocking); 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++]); }}static 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, osig; 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, &osig); 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, NULL); /* 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, &osig, NULL); 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, &osig, NULL); *outpid = pid; return (0); } exit(-1); /* NEVER REACHED */ }/* * Wait for a child process. */static intjthreadedWaitpid(int wpid, int* status, int options, int *outpid){#if defined(HAVE_WAITPID) int npid; sigset_t sigdata; KaffePThread_setBlockingCall(&sigdata); npid = waitpid(wpid, status, options); KaffePThread_clearBlockingCall(&sigdata); if (npid > 0) { *outpid = npid; return (0); } else { return (-1); }#else return (-1);#endif}static 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}static intjthreadedPipeCreate(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, jthreadedSocketShutdown, jthreadedGetHostByName, jthreadedGetHostByAddr, jthreadedSelect, jthreadedForkExec, jthreadedWaitpid, jthreadedKill, jthreadedMmap, jthreadedMunmap, jthreadedMsync, jthreadedPipeCreate, jthreadedTimedRead, jthreadedTimedWrite};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -