예제 #1
0
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 (&current, 0, sizeof (TIMESPEC));
#else
		gettimeofday (&current, 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;
}
예제 #2
0
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;
    }

}