示例#1
0
static DWORD adjust_timeout_win32(DWORD timeout, uint64_t start)
{
    if (timeout == INFINITE)
        return INFINITE;

    uint64_t now = ty_millis();

    if (now > start + timeout)
        return 0;
    return (DWORD)(start + timeout - now);
}
示例#2
0
int ty_poll(const ty_descriptor_set *set, int timeout)
{
    assert(set);
    assert(set->count);
    assert(set->count <= 64);

    fd_set fds;
    uint64_t start;
    struct timeval tv;
    int r;

    FD_ZERO(&fds);
    for (unsigned int i = 0; i < set->count; i++)
        FD_SET(set->desc[i], &fds);

    start = ty_millis();
restart:
    if (timeout >= 0) {
        tv.tv_sec = timeout / 1000;
        tv.tv_usec = (timeout % 1000) * 1000;
    }

    r = select(FD_SETSIZE, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
    if (r < 0) {
        switch (errno) {
        case EINTR:
            timeout = ty_adjust_timeout(timeout, start);
            goto restart;
        case ENOMEM:
            return ty_error(TY_ERROR_MEMORY, NULL);
        }
        return ty_error(TY_ERROR_SYSTEM, "poll() failed: %s", strerror(errno));
    }
    if (!r)
        return 0;

    for (unsigned int i = 0; i < set->count; i++) {
        if (FD_ISSET(set->desc[i], &fds))
            return set->id[i];
    }

    assert(false);
    __builtin_unreachable();
}
示例#3
0
// Not sure if the fallback code is correct or not, let's hope so for now
static BOOL WINAPI SleepConditionVariableCS_fallback(CONDITION_VARIABLE *cv,
                                                     CRITICAL_SECTION *mutex, DWORD timeout)
{
    ty_cond *cond = (ty_cond *)cv;
    uint64_t start;
    bool signaled;
    DWORD wret;

    while (true) {
        EnterCriticalSection((CRITICAL_SECTION *)&cond->xp.mutex);
        if (!cond->xp.wakeup)
            break;
        LeaveCriticalSection((CRITICAL_SECTION *)&cond->xp.mutex);
    }

    cond->xp.waiting++;

    LeaveCriticalSection((CRITICAL_SECTION *)&cond->xp.mutex);
    LeaveCriticalSection(mutex);

    start = ty_millis();
restart:
    wret = WaitForSingleObject(cond->xp.ev, adjust_timeout_win32(timeout, start));
    assert(wret == WAIT_OBJECT_0 || wret == WAIT_TIMEOUT);

    EnterCriticalSection((CRITICAL_SECTION *)&cond->xp.mutex);

    if (cond->xp.wakeup) {
        if (!--cond->xp.wakeup)
            ResetEvent(cond->xp.ev);
        signaled = true;
    } else if (wret == WAIT_TIMEOUT) {
        signaled = false;
    } else {
        LeaveCriticalSection((CRITICAL_SECTION *)&cond->xp.mutex);
        goto restart;
    }
    cond->xp.waiting--;

    LeaveCriticalSection((CRITICAL_SECTION *)&cond->xp.mutex);

    EnterCriticalSection(mutex);
    return signaled;
}
示例#4
0
int ty_poll(const ty_descriptor_set *set, int timeout)
{
    assert(set);
    assert(set->count);
    assert(set->count <= 64);

    struct pollfd pfd[64];
    uint64_t start;
    int r;

    for (unsigned int i = 0; i < set->count; i++) {
        pfd[i].events = POLLIN;
        pfd[i].fd = set->desc[i];
    }

    if (timeout < 0)
        timeout = -1;

    start = ty_millis();
restart:
    r = poll(pfd, (nfds_t)set->count, ty_adjust_timeout(timeout, start));
    if (r < 0) {
        switch (errno) {
        case EINTR:
            goto restart;
        case ENOMEM:
            return ty_error(TY_ERROR_MEMORY, NULL);
        }
        return ty_error(TY_ERROR_SYSTEM, "poll() failed: %s", strerror(errno));
    }
    if (!r)
        return 0;

    for (unsigned int i = 0; i < set->count; i++) {
        if (pfd[i].revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL))
            return set->id[i];
    }

    assert(false);
    __builtin_unreachable();
}