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

问题描述 投票: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 += 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 timeout pthreads mutex semaphore
1个回答
3
投票

可能只是一个错字。

    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
是一个有符号整数,因此在异常情况下可能需要更多的工作来处理有符号/无符号数学的混合。

© www.soinside.com 2019 - 2024. All rights reserved.