int mono_sem_timedwait (MonoSemType *sem, guint32 timeout_ms, gboolean alertable) { TIMESPEC ts, copy; struct timeval t; int res = 0; #if defined(__OpenBSD__) int timeout; #endif #ifndef USE_MACH_SEMA if (timeout_ms == 0) return sem_trywait (sem); #endif if (timeout_ms == (guint32) 0xFFFFFFFF) return mono_sem_wait (sem, alertable); #ifdef USE_MACH_SEMA memset (&t, 0, sizeof (TIMESPEC)); #else gettimeofday (&t, NULL); #endif ts.tv_sec = timeout_ms / 1000 + t.tv_sec; ts.tv_nsec = (timeout_ms % 1000) * 1000000 + t.tv_usec * 1000; while (ts.tv_nsec > NSEC_PER_SEC) { ts.tv_nsec -= NSEC_PER_SEC; ts.tv_sec++; } #if defined(__OpenBSD__) timeout = ts.tv_sec; while (timeout) { if ((res = WAIT_BLOCK (sem)) == 0) return res; if (alertable) return -1; usleep (ts.tv_nsec / 1000); timeout--; } #else copy = ts; while ((res = WAIT_BLOCK (sem, &ts)) == -1 && errno == EINTR) { struct timeval current; if (alertable) return -1; #ifdef USE_MACH_SEMA memset (¤t, 0, sizeof (TIMESPEC)); #else gettimeofday (¤t, NULL); #endif ts = copy; ts.tv_sec -= (current.tv_sec - t.tv_sec); ts.tv_nsec -= (current.tv_usec - t.tv_usec) * 1000; if (ts.tv_nsec < 0) { if (ts.tv_sec <= 0) { ts.tv_nsec = 0; } else { ts.tv_sec--; ts.tv_nsec += NSEC_PER_SEC; } } if (ts.tv_sec < 0) { ts.tv_sec = 0; ts.tv_nsec = 0; } } #endif /* OSX might return > 0 for error */ if (res != 0) res = -1; return res; }
static int rwait_(int tid, LS_WAIT_T *status, int options, struct rusage *ru) { int rpid; struct lslibNiosWaitReq req; struct lslibNiosHdr hdr; fd_set rmask; struct timeval timeout; sigset_t newMask, oldMask; int cc; if (tid < 0) { lserrno = LSE_BAD_ARGS; return -1; } if (!nios_ok_) { lserrno = LSE_NORCHILD; return -1; } blockALL_SIGS_(&newMask, &oldMask); Start: FD_ZERO(&rmask); FD_SET(cli_nios_fd[0], &rmask); timeout.tv_sec = NIOS_TIMEOUT; timeout.tv_usec = 0; SET_LSLIB_NIOS_HDR(req.hdr, LIB_NIOS_RWAIT, sizeof(req.r)); req.r.options = options; req.r.tid = tid; if (b_write_fix(cli_nios_fd[0], (char *) &req, sizeof(req)) != sizeof(req)) { lserrno = LSE_MSG_SYS; sigprocmask(SIG_SETMASK, &oldMask, NULL); return -1; } cc = select(cli_nios_fd[0] + 1, &rmask, 0, 0, &timeout); if (cc <= 0) { if (cc < 0) lserrno = LSE_SELECT_SYS; else lserrno = LSE_TIME_OUT; sigprocmask(SIG_SETMASK, &oldMask, NULL); return -1; } if (b_read_fix(cli_nios_fd[0], (char *) &hdr, sizeof(hdr)) == -1) { lserrno = LSE_MSG_SYS; sigprocmask(SIG_SETMASK, &oldMask, NULL); return -1; } if (WAIT_BLOCK(options) && hdr.opCode == NONB_RETRY) { restartRWait(oldMask); if(!isPamBlockWait){ goto Start; } } switch (hdr.opCode) { case CHILD_FAIL: lserrno = LSE_NORCHILD; sigprocmask(SIG_SETMASK, &oldMask, NULL); return -1; case NONB_RETRY: sigprocmask(SIG_SETMASK, &oldMask, NULL); return 0; case CHILD_OK: rpid = readWaitReply(status, ru); sigprocmask(SIG_SETMASK, &oldMask, NULL); return (rpid); default: lserrno = LSE_PROTOC_NIOS; sigprocmask(SIG_SETMASK, &oldMask, NULL); return -1; } }