有时我的二进制信号量不会等待正确的时间

Sometimes my binary semaphore does not wait the correct time

提问人:0___________ 提问时间:11/4/2023 最后编辑:Costantino Grana0___________ 更新时间:11/4/2023 访问量:50

问:

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

#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 += nsec / 1000000000ULL;
        ts -> tv_nsec = nsec % 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_nsec);

            }
        }
    }
    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 超时 pthreads 互斥信号

评论

2赞 chux - Reinstate Monica 11/4/2023
为什么。因为随后没有使用?nsec = ts -> tv_nsec + (ms % 1000) * 1000000ULL;nsec
0赞 0___________ 11/4/2023
@chux-ReinstateMonica 好地方 - 迟到了,我写了nsecms

答:

4赞 chux - Reinstate Monica 11/4/2023 #1

可能只是一个错别字。

    ts -> tv_sec += ms / 1000;
    nsec = ts -> tv_nsec + (ms % 1000) * 1000000ULL; // nsec never used.
    ts -> tv_sec += ms / 1000000000ULL;  // Did you want nsec and not ms?
    ts -> tv_nsec = ms % 1000000000ULL;  // Did you want nsec and not ms?

请注意,这是一个有符号整数,因此在异常情况下可能需要做更多的工作来处理有符号/无符号数学的混合。ts->tv_nsec

评论

0赞 0___________ 11/4/2023
确实是愚蠢的错误。