Ejemplo n.º 1
0
/*
 * __wt_cond_wait_signal --
 *	Wait on a mutex, optionally timing out.  If we get it
 *	before the time out period expires, let the caller know.
 */
int
__wt_cond_wait_signal(
    WT_SESSION_IMPL *session, WT_CONDVAR *cond, uint64_t usecs, bool *signalled)
{
	struct timespec ts;
	WT_DECL_RET;
	bool locked;

	locked = false;

	/* Fast path if already signalled. */
	*signalled = true;
	if (__wt_atomic_addi32(&cond->waiters, 1) == 0)
		return (0);

	/*
	 * !!!
	 * This function MUST handle a NULL session handle.
	 */
	if (session != NULL) {
		WT_RET(__wt_verbose(session, WT_VERB_MUTEX,
		    "wait %s cond (%p)", cond->name, cond));
		WT_STAT_FAST_CONN_INCR(session, cond_wait);
	}

	WT_ERR(pthread_mutex_lock(&cond->mtx));
	locked = true;

	if (usecs > 0) {
		WT_ERR(__wt_epoch(session, &ts));
		ts.tv_sec += (time_t)
		    (((uint64_t)ts.tv_nsec + 1000 * usecs) / WT_BILLION);
		ts.tv_nsec = (long)
		    (((uint64_t)ts.tv_nsec + 1000 * usecs) % WT_BILLION);
		ret = pthread_cond_timedwait(&cond->cond, &cond->mtx, &ts);
	} else
		ret = pthread_cond_wait(&cond->cond, &cond->mtx);

	/*
	 * Check pthread_cond_wait() return for EINTR, ETIME and
	 * ETIMEDOUT, some systems return these errors.
	 */
	if (ret == EINTR ||
#ifdef ETIME
	    ret == ETIME ||
#endif
	    ret == ETIMEDOUT) {
		*signalled = false;
		ret = 0;
	}

	(void)__wt_atomic_subi32(&cond->waiters, 1);

err:	if (locked)
		WT_TRET(pthread_mutex_unlock(&cond->mtx));
	if (ret == 0)
		return (0);
	WT_RET_MSG(session, ret, "pthread_cond_wait");
}
Ejemplo n.º 2
0
/*
 * __wt_cond_wait_signal --
 *	Wait on a mutex, optionally timing out.  If we get it before the time
 * out period expires, let the caller know.
 */
void
__wt_cond_wait_signal(WT_SESSION_IMPL *session, WT_CONDVAR *cond,
    uint64_t usecs, bool (*run_func)(WT_SESSION_IMPL *), bool *signalled)
{
	BOOL sleepret;
	DWORD milliseconds, windows_error;
	bool locked;
	uint64_t milliseconds64;

	locked = false;

	/* Fast path if already signalled. */
	*signalled = true;
	if (__wt_atomic_addi32(&cond->waiters, 1) == 0)
		return;

	__wt_verbose(session, WT_VERB_MUTEX, "wait %s", cond->name);
	WT_STAT_CONN_INCR(session, cond_wait);

	EnterCriticalSection(&cond->mtx);
	locked = true;

	/*
	 * It's possible to race with threads waking us up. That's not a problem
	 * if there are multiple wakeups because the next wakeup will get us, or
	 * if we're only pausing for a short period. It's a problem if there's
	 * only a single wakeup, our waker is likely waiting for us to exit.
	 * After acquiring the mutex (so we're guaranteed to be awakened by any
	 * future wakeup call), optionally check if we're OK to keep running.
	 * This won't ensure our caller won't just loop and call us again, but
	 * at least it's not our fault.
	 *
	 * Assert we're not waiting longer than a second if not checking the
	 * run status.
	 */
	WT_ASSERT(session, run_func != NULL || usecs <= WT_MILLION);

	if (run_func != NULL && !run_func(session))
		goto skipping;

	if (usecs > 0) {
		milliseconds64 = usecs / WT_THOUSAND;

		/*
		 * Check for 32-bit unsigned integer overflow
		 * INFINITE is max unsigned int on Windows
		 */
		if (milliseconds64 >= INFINITE)
			milliseconds64 = INFINITE - 1;
		milliseconds = (DWORD)milliseconds64;

		/*
		 * 0 would mean the CV sleep becomes a TryCV which we do not
		 * want
		 */
		if (milliseconds == 0)
			milliseconds = 1;

		sleepret = SleepConditionVariableCS(
		    &cond->cond, &cond->mtx, milliseconds);
	} else
		sleepret = SleepConditionVariableCS(
		    &cond->cond, &cond->mtx, INFINITE);

	/*
	 * SleepConditionVariableCS returns non-zero on success, 0 on timeout
	 * or failure.
	 */
	if (sleepret == 0) {
		windows_error = __wt_getlasterror();
		if (windows_error == ERROR_TIMEOUT) {
skipping:		*signalled = false;
			sleepret = 1;
		}
	}

	(void)__wt_atomic_subi32(&cond->waiters, 1);

	if (locked)
		LeaveCriticalSection(&cond->mtx);

	if (sleepret != 0)
		return;

	__wt_err(session,
	    __wt_map_windows_error(windows_error),
	    "SleepConditionVariableCS: %s: %s",
	    cond->name, __wt_formatmessage(session, windows_error));
	WT_PANIC_MSG(session, __wt_map_windows_error(windows_error),
	    "SleepConditionVariableCS: %s", cond->name);
}
Ejemplo n.º 3
0
/*
 * __wt_cond_wait_signal --
 *	Wait on a mutex, optionally timing out.  If we get it
 *	before the time out period expires, let the caller know.
 */
int
__wt_cond_wait_signal(
    WT_SESSION_IMPL *session, WT_CONDVAR *cond, uint64_t usecs, bool *signalled)
{
    BOOL sleepret;
    DWORD milliseconds, windows_error;
    bool locked;
    uint64_t milliseconds64;

    locked = false;

    /* Fast path if already signalled. */
    *signalled = true;
    if (__wt_atomic_addi32(&cond->waiters, 1) == 0)
        return (0);

    /*
     * !!!
     * This function MUST handle a NULL session handle.
     */
    if (session != NULL) {
        WT_RET(__wt_verbose(session, WT_VERB_MUTEX,
                            "wait %s cond (%p)", cond->name, cond));
        WT_STAT_FAST_CONN_INCR(session, cond_wait);
    }

    EnterCriticalSection(&cond->mtx);
    locked = true;

    if (usecs > 0) {
        milliseconds64 = usecs / 1000;

        /*
         * Check for 32-bit unsigned integer overflow
         * INFINITE is max unsigned int on Windows
         */
        if (milliseconds64 >= INFINITE)
            milliseconds64 = INFINITE - 1;
        milliseconds = (DWORD)milliseconds64;

        /*
         * 0 would mean the CV sleep becomes a TryCV which we do not
         * want
         */
        if (milliseconds == 0)
            milliseconds = 1;

        sleepret = SleepConditionVariableCS(
                       &cond->cond, &cond->mtx, milliseconds);
    } else
        sleepret = SleepConditionVariableCS(
                       &cond->cond, &cond->mtx, INFINITE);

    /*
     * SleepConditionVariableCS returns non-zero on success, 0 on timeout
     * or failure.
     */
    if (sleepret == 0) {
        windows_error = __wt_getlasterror();
        if (windows_error == ERROR_TIMEOUT) {
            *signalled = false;
            sleepret = 1;
        }
    }

    (void)__wt_atomic_subi32(&cond->waiters, 1);

    if (locked)
        LeaveCriticalSection(&cond->mtx);

    if (sleepret != 0)
        return (0);

    __wt_errx(session, "SleepConditionVariableCS: %s",
              __wt_formatmessage(session, windows_error));
    return (__wt_map_windows_error(windows_error));
}
Ejemplo n.º 4
0
/*
 * __wt_cond_wait_signal --
 *	Wait on a mutex, optionally timing out.  If we get it
 *	before the time out period expires, let the caller know.
 */
int
__wt_cond_wait_signal(
    WT_SESSION_IMPL *session, WT_CONDVAR *cond, uint64_t usecs, bool *signalled)
{
	DWORD err, milliseconds;
	WT_DECL_RET;
	uint64_t milliseconds64;
	bool locked;

	locked = false;

	/* Fast path if already signalled. */
	*signalled = true;
	if (__wt_atomic_addi32(&cond->waiters, 1) == 0)
		return (0);

	/*
	 * !!!
	 * This function MUST handle a NULL session handle.
	 */
	if (session != NULL) {
		WT_RET(__wt_verbose(session, WT_VERB_MUTEX,
			"wait %s cond (%p)", cond->name, cond));
		WT_STAT_FAST_CONN_INCR(session, cond_wait);
	}

	EnterCriticalSection(&cond->mtx);
	locked = true;

	if (usecs > 0) {
		milliseconds64 = usecs / 1000;

		/*
		 * Check for 32-bit unsigned integer overflow
		 * INFINITE is max unsigned int on Windows
		 */
		if (milliseconds64 >= INFINITE)
			milliseconds64 = INFINITE - 1;
		milliseconds = (DWORD)milliseconds64;

		/*
		 * 0 would mean the CV sleep becomes a TryCV which we do not
		 * want
		 */
		if (milliseconds == 0)
			milliseconds = 1;

		ret = SleepConditionVariableCS(
		    &cond->cond, &cond->mtx, milliseconds);
	} else
		ret = SleepConditionVariableCS(
		    &cond->cond, &cond->mtx, INFINITE);

	/*
	 * SleepConditionVariableCS returns non-zero on success, 0 on timeout
	 * or failure. Check for timeout, else convert to a WiredTiger error
	 * value and fail.
	 */
	if (ret == 0) {
		if ((err = GetLastError()) == ERROR_TIMEOUT)
			*signalled = false;
		else
			ret = __wt_errno();
	} else
		ret = 0;

	(void)__wt_atomic_subi32(&cond->waiters, 1);

	if (locked)
		LeaveCriticalSection(&cond->mtx);

	if (ret == 0)
		return (0);
	WT_RET_MSG(session, ret, "SleepConditionVariableCS");
}