有时等待的时间不够长。我可能错过了一些简单的东西 - 但我找不到它。为什么等待函数有时会过早返回
#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;
}
可能只是一个错字。
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
是一个有符号整数,因此在异常情况下可能需要更多的工作来处理有符号/无符号数学的混合。