Beispiel #1
0
static ETHR_INLINE int
wait__(ethr_event *e, int spincount)
{
    unsigned sc = spincount;
    int res;
    ethr_sint32_t val;
    int until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS;

    if (spincount < 0)
	ETHR_FATAL_ERROR__(EINVAL);

    while (1) {
	while (1) {
	    val = ethr_atomic32_read(&e->futex);
	    if (val == ETHR_EVENT_ON__)
		return 0;
	    if (sc == 0)
		break;
	    sc--;
	    ETHR_SPIN_BODY;
	    if (--until_yield == 0) {
		until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS;
		res = ETHR_YIELD();
		if (res != 0)
		    ETHR_FATAL_ERROR__(res);
	    }
	}

	if (val != ETHR_EVENT_OFF_WAITER__) {
	    val = ethr_atomic32_cmpxchg(&e->futex,
					ETHR_EVENT_OFF_WAITER__,
					ETHR_EVENT_OFF__);

	    if (val == ETHR_EVENT_ON__)
		return 0;
	    ETHR_ASSERT(val == ETHR_EVENT_OFF__);
	}

	res = ETHR_FUTEX__(&e->futex,
			   ETHR_FUTEX_WAIT__,
			   ETHR_EVENT_OFF_WAITER__);
	if (res == EINTR)
	    break;
	if (res != 0 && res != EWOULDBLOCK)
	    ETHR_FATAL_ERROR__(res);
    }

    return res;
}
Beispiel #2
0
static ETHR_INLINE int
wait__(ethr_event *e, int spincount, ethr_sint64_t timeout)
{
    unsigned sc = spincount;
    int res;
    ethr_sint32_t val;
    int until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS;
    ethr_sint64_t time = 0; /* SHUT UP annoying faulty warning... */
    struct timespec ts, *tsp;
#ifdef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME
    ethr_sint64_t start = 0; /* SHUT UP annoying faulty warning... */
#endif

    if (spincount < 0)
        ETHR_FATAL_ERROR__(EINVAL);

    if (timeout < 0) {
        tsp = NULL;
    }
    else {
#ifdef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME
        start = ethr_get_monotonic_time();
#endif
        tsp = &ts;
        time = timeout;
        if (spincount == 0) {
            val = ethr_atomic32_read(&e->futex);
            if (val == ETHR_EVENT_ON__)
                goto return_event_on;
            goto set_timeout;
        }
    }

    while (1) {
        while (1) {
            val = ethr_atomic32_read(&e->futex);
            if (val == ETHR_EVENT_ON__)
                goto return_event_on;
            if (sc == 0)
                break;
            sc--;
            ETHR_SPIN_BODY;
            if (--until_yield == 0) {
                until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS;
                res = ETHR_YIELD();
                if (res != 0)
                    ETHR_FATAL_ERROR__(res);
            }
        }

        if (timeout >= 0) {
#ifdef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME
            time = timeout - (ethr_get_monotonic_time() - start);
#endif
set_timeout:
            if (time <= 0) {
                val = ethr_atomic32_read(&e->futex);
                if (val == ETHR_EVENT_ON__)
                    goto return_event_on;
                return ETIMEDOUT;
            }
            ts.tv_sec = time / (1000*1000*1000);
            ts.tv_nsec = time % (1000*1000*1000);
        }

        if (val != ETHR_EVENT_OFF_WAITER__) {
            val = ethr_atomic32_cmpxchg(&e->futex,
                                        ETHR_EVENT_OFF_WAITER__,
                                        ETHR_EVENT_OFF__);

            if (val == ETHR_EVENT_ON__)
                goto return_event_on;
            ETHR_ASSERT(val == ETHR_EVENT_OFF__);
        }

        res = ETHR_FUTEX__(&e->futex,
                           ETHR_FUTEX_WAIT__,
                           ETHR_EVENT_OFF_WAITER__,
                           tsp);
        switch (res) {
        case EINTR:
        case ETIMEDOUT:
            return res;
        case 0:
        case EWOULDBLOCK:
            break;
        default:
            ETHR_FATAL_ERROR__(res);
        }
    }

return_event_on:

    ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore);

    return 0;

}