有时我的二进制信号量无法等待正确的时间

问题描述 投票:0回答:1

有时等待的时间不够长。我可能错过了一些简单的东西 - 但我找不到它。为什么等待函数有时会过早返回

#define SEMAPHORE_MAXWAIT   -1
#define SEMAPHORE_NOWAIT    0

// Type your code here, or load an example.
typedef struct binary_semaphore {
    pthread_mutex_t mutex;
    pthread_cond_t condvar;
    bool variable;
}binary_semaphore_t;


static struct timespec *timespec_addms(struct timespec *ts, unsigned ms)
{
    uint64_t nsec;
    if(ts)
    {
        ts -> tv_sec += ms / 1000;
        nsec = ts -> tv_nsec + (ms % 1000) * 1000000ULL;
        ts -> tv_sec += ms / 1000000000ULL;
        ts -> tv_nsec = ms % 1000000000ULL;
    }
    return ts;
}

static int mutex_lockwait(pthread_mutex_t *mutex, unsigned wait)
{
    int result = 0;
    int line;
    struct timespec timeOut;

    if(mutex)
    {
        if(result = clock_gettime(CLOCK_REALTIME, &timeOut))
        {
            line = __LINE__;
            goto exit_cleanup;
        }

        timespec_addms(&timeOut, wait);

        switch(wait)
        {
            case SEMAPHORE_NOWAIT:
                result = pthread_mutex_trylock(mutex);
                line = __LINE__;
                break;
            case SEMAPHORE_MAXWAIT:
                result = pthread_mutex_lock(mutex);
                line = __LINE__;
                break;
            default:
                result = pthread_mutex_timedlock(mutex, &timeOut);
                line = __LINE__;
                break;
        }
    }
    else result = EFAULT;

    exit_cleanup:
    if(result)
    {
        if(result != EBUSY)
        {
            printError("[MUTEX]", line, __FUNCTION__);
        }
    }
    return result;
}


static int64_t timespec_diff(const struct timespec *t1, const struct timespec *t2)
{
    int64_t nanodiff = -1;
    //t1 has to be later than t2
    if(t1 -> tv_sec >= t2 -> tv_sec)
    {
        nanodiff = (t1 -> tv_sec - t2 -> tv_sec) * 1000000000ULL;
        if(t1 -> tv_nsec > t2 -> tv_nsec)
        {
            nanodiff += t1 -> tv_nsec - t2 -> tv_nsec;
        }
        else
        {
            if(!nanodiff)
            {
                nanodiff = -1;
            }
            else
            {
                nanodiff -= 1000000000ULL + (t1 -> tv_nsec - t2 -> tv_sec);

            }
        }
    }
    return nanodiff;
}

static struct timespec nanoToTimespec(int64_t nanosec)
{
    return (struct timespec){.tv_sec = nanosec / 1000000000ULL, .tv_nsec = nanosec % 1000000000ULL};
}

int binarySemaphoreWait(struct binary_semaphore *p, unsigned wait)
{
    int result= -1;

    struct timespec ts, ts1;
    
    if(!p) goto function_return;

    if((result = clock_gettime(CLOCK_REALTIME, &ts))) goto function_return;

    if((result = mutex_lockwait(&p -> mutex, wait))) goto function_return;
    while (!p->variable)
    {
        if((result = clock_gettime(CLOCK_REALTIME, &ts1))) goto cleanup_exit;
        int64_t nanodiff = timespec_diff(&ts1, &ts);
        if(nanodiff > 0 && (nanodiff / 1000000ULL) < wait)
        {
            timespec_addms(&ts, wait - nanodiff / 1000000ULL);
            pthread_cond_timedwait(&p->condvar, &p->mutex, &ts);
        }
    }
    p->variable = false;

    cleanup_exit:
    pthread_mutex_unlock(&p->mutex);
    function_return:
    return result;
}


int binarySemaphorePost(struct binary_semaphore *p)
{
    int result =  -1;
    
    if(!p) goto cleanup_exit;
    
    result = mutex_lockwait(&p -> mutex, SEMAPHORE_MAXWAIT);

    if(result) goto cleanup_exit;
    if (p->variable)
    {
        result = EAGAIN;
        goto cleanup_exit;
    }

    p->variable = true;

    if((result = pthread_cond_signal(&p->condvar))) goto cleanup_exit;
    if((result = pthread_mutex_unlock(&p->mutex))) goto cleanup_exit;

    cleanup_exit:
    return result;
}
c timeout pthreads mutex semaphore
1个回答
0
投票

而不是

    ts -> tv_sec += ms / 1000;
    nsec = ts -> tv_nsec + (ms % 1000) * 1000000ULL; // nsec never used.
    ts -> tv_sec += ms / 1000000000ULL;
    ts -> tv_nsec = ms % 1000000000ULL;

我怀疑你想要

    uint64_t delta = ms * 1000000LL + ts->tv_nsec;
    ts->tv_nsec = delta % 1000000000;
    ts->tv_sec += delta / 1000000000;
© www.soinside.com 2019 - 2024. All rights reserved.