📄 syscallwrap.c
字号:
/* Pull together the functions to wrap IO system calls to * avoid blocking user-level threads */#include <signal.h>#include <sys/time.h>#include <sys/types.h>#include <unistd.h>#include <assert.h>#include <scout_thread.h>#include <scout_fifo.h>#include <scout_synch.h>void defineHandler(int sig, void (*handler)());/* Structures used by the thread that wakes up * threads sleeping on IO. We can't do the fdescSignal * from inside an interrupt handler, so we devote a thread * to the task. */static Thread wakeupThread;static struct FIFO wakeupFIFO;#define SYSCALLWRAP_WAIT 1#define SYSCALLWRAP_IO 2struct wakeupEl { struct FIFOEl el; int type; int fd;};/* The thread that wakes up other threads sleeping on IO */static void syscallWrapWakeupThread(int foo) { struct wakeupEl *el; int done = 0; while (!done) { /* Remove elements from the queue and signal them */ while ((el = fifoRemove(&wakeupFIFO)) != 0) { if (el->type == SYSCALLWRAP_IO) { if (el->fd == -1) fdescAnySignal(); else fdescSignal(el->fd); } else if (el->type == SYSCALLWRAP_WAIT) { waitSignal(); } el->type = 0; } /* We have to be very careful here so that we don't miss * any wakeup events, and so we don't get woken up multiple * times. */ synchAtomicSequence( if (fifoIsEmpty(&wakeupFIFO)) { done = 1; wakeupThread = tSelf; }); } threadSuspendWithContinuation();}static voidaddWakeupElement(int type, int fd) { extern void GC_scout_no_yields(); extern void GC_scout_allow_yields(); extern void *GC_malloc(int count); struct wakeupEl *el; /* Scout threads doesn't want preemption in signal handlers. * The java finalizer code makes sure that if we get there * through finalization, we don't break anything. */ GC_scout_no_yields(); el = (void *)GC_malloc(sizeof(struct wakeupEl)); GC_scout_allow_yields(); el->type = type; el->fd = fd; fifoAppendUnsafe(&wakeupFIFO, (FIFOEl)el); }static voidscheduleWakeupThread(){ if (wakeupThread) { Thread t = wakeupThread; wakeupThread = 0; fifoAppendUnsafe(&threadFixedPrioScheduler.async_q, t); }}static void waitSignalHandler(int sig){ addWakeupElement(SYSCALLWRAP_WAIT, -1); scheduleWakeupThread();}long syscallWrapIOPending = 0;voidsyscallWrapIOCheck() { fd_set read, write, except; struct timeval timeout; int res; int i; int maxFD; if (syscallWrapIOPending == 0) return; /* Find which file desciptors have I/O available */ FD_ZERO(&read); FD_ZERO(&write); FD_ZERO(&except); maxFD = fdescMaxOpen(); for (i = 0; i <= maxFD; i++) { if (fdescIsOpen(i)) { FD_SET(i, &read); FD_SET(i, &write); FD_SET(i, &except); } } timeout.tv_sec = 0; timeout.tv_usec = 0; res = __real_select(FD_SETSIZE, &read, &write, &except, &timeout); /* signal each potentially ready file descriptor */ for (i = 0; (i <= maxFD) && (res > 0); i++) { if (FD_ISSET(i, &read) || FD_ISSET(i, &write) || FD_ISSET(i, &except)) { addWakeupElement(SYSCALLWRAP_IO, i); res--; } } /* If we found any ready desriptors, wakeup the thread that * actually calls fdescSignal. */ if (i > 0) { /* -1 signifies the select descriptor */ addWakeupElement(SYSCALLWRAP_IO, -1); scheduleWakeupThread(); } return;}static void ioSignalHandler(int sig) { syscallWrapIOCheck(); }void syscallWrapInit() { struct ThreadOptions opt; fdescInit(); waitInit(); fifoInit(&wakeupFIFO); /* Create the thread that does the IO wakeups */ opt.arg.l = 0; opt.scheduler = 0; opt.priority.i = THREAD_PRIO_STD; opt.name = "Syscall wakeup thread"; wakeupThread = threadCreate((ThreadFunc)syscallWrapWakeupThread, &opt); /* Now define the SIGIO and SIGCHLD signal handler, and setup is finished */ defineHandler(SIGIO, ioSignalHandler); defineHandler(SIGCHLD, waitSignalHandler);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -