Convert ticks to 64-bit, added nanosecond precision to the API

Fixes https://github.com/libsdl-org/SDL/issues/5512
Fixes https://github.com/libsdl-org/SDL/issues/6731
This commit is contained in:
Sam Lantinga
2022-12-02 01:17:17 -08:00
parent 764b899a13
commit 8121bbd083
96 changed files with 938 additions and 1243 deletions

View File

@@ -91,7 +91,7 @@ int SDL_CondBroadcast(SDL_cond *cond)
return retval;
}
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
int SDL_CondWaitTimeoutNS(SDL_cond *cond, SDL_mutex *mutex, Sint64 timeoutNS)
{
int retval;
#ifndef HAVE_CLOCK_GETTIME
@@ -103,18 +103,25 @@ int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
return SDL_InvalidParamError("cond");
}
if (timeoutNS < 0) {
if (pthread_cond_wait(&cond->cond, &mutex->id) != 0) {
return SDL_SetError("pthread_cond_wait() failed");
}
return 0;
}
#ifdef HAVE_CLOCK_GETTIME
clock_gettime(CLOCK_REALTIME, &abstime);
abstime.tv_nsec += (ms % 1000) * 1000000;
abstime.tv_sec += ms / 1000;
abstime.tv_sec += (timeoutNS / SDL_NS_PER_SECOND);
abstime.tv_nsec += (timeoutNS % SDL_NS_PER_SECOND);
#else
gettimeofday(&delta, NULL);
abstime.tv_sec = delta.tv_sec + (ms / 1000);
abstime.tv_nsec = (long)(delta.tv_usec + (ms % 1000) * 1000) * 1000;
abstime.tv_sec = delta.tv_sec + (timeoutNS / SDL_NS_PER_SECOND);
abstime.tv_nsec = SDL_US_TO_NS(delta.tv_usec) + (timeoutNS % SDL_NS_PER_SECOND);
#endif
if (abstime.tv_nsec > 1000000000) {
while (abstime.tv_nsec > 1000000000) {
abstime.tv_sec += 1;
abstime.tv_nsec -= 1000000000;
}
@@ -136,17 +143,4 @@ tryagain:
return retval;
}
/* Wait on the condition variable, unlocking the provided mutex.
The mutex must be locked before entering this function!
*/
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
{
if (cond == NULL) {
return SDL_InvalidParamError("cond");
} else if (pthread_cond_wait(&cond->cond, &mutex->id) != 0) {
return SDL_SetError("pthread_cond_wait() failed");
}
return 0;
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -63,39 +63,7 @@ void SDL_DestroySemaphore(SDL_sem *sem)
}
}
int SDL_SemTryWait(SDL_sem *sem)
{
int retval;
if (sem == NULL) {
return SDL_InvalidParamError("sem");
}
retval = SDL_MUTEX_TIMEDOUT;
if (sem_trywait(&sem->sem) == 0) {
retval = 0;
}
return retval;
}
int SDL_SemWait(SDL_sem *sem)
{
int retval;
if (sem == NULL) {
return SDL_InvalidParamError("sem");
}
do {
retval = sem_wait(&sem->sem);
} while (retval < 0 && errno == EINTR);
if (retval < 0) {
retval = SDL_SetError("sem_wait() failed");
}
return retval;
}
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
int SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS)
{
int retval;
#ifdef HAVE_SEM_TIMEDWAIT
@@ -104,7 +72,7 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
#endif
struct timespec ts_timeout;
#else
Uint32 end;
Uint64 end;
#endif
if (sem == NULL) {
@@ -112,11 +80,22 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
}
/* Try the easy cases first */
if (timeout == 0) {
return SDL_SemTryWait(sem);
if (timeoutNS == 0) {
retval = SDL_MUTEX_TIMEDOUT;
if (sem_trywait(&sem->sem) == 0) {
retval = 0;
}
return retval;
}
if (timeout == SDL_MUTEX_MAXWAIT) {
return SDL_SemWait(sem);
if (timeoutNS < 0) {
do {
retval = sem_wait(&sem->sem);
} while (retval < 0 && errno == EINTR);
if (retval < 0) {
retval = SDL_SetError("sem_wait() failed");
}
return retval;
}
#ifdef HAVE_SEM_TIMEDWAIT
@@ -128,18 +107,18 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
clock_gettime(CLOCK_REALTIME, &ts_timeout);
/* Add our timeout to current time */
ts_timeout.tv_nsec += (timeout % 1000) * 1000000;
ts_timeout.tv_sec += timeout / 1000;
ts_timeout.tv_sec += (timeoutNS / SDL_NS_PER_SECOND);
ts_timeout.tv_nsec += (timeoutNS % SDL_NS_PER_SECOND);
#else
gettimeofday(&now, NULL);
/* Add our timeout to current time */
ts_timeout.tv_sec = now.tv_sec + (timeout / 1000);
ts_timeout.tv_nsec = (now.tv_usec + (timeout % 1000) * 1000) * 1000;
ts_timeout.tv_sec = now.tv_sec + (timeoutNS / SDL_NS_PER_SECOND);
ts_timeout.tv_nsec = SDL_US_TO_NS(now.tv_usec) + (timeoutNS % SDL_NS_PER_SECOND);
#endif
/* Wrap the second if needed */
if (ts_timeout.tv_nsec > 1000000000) {
while (ts_timeout.tv_nsec > 1000000000) {
ts_timeout.tv_sec += 1;
ts_timeout.tv_nsec -= 1000000000;
}
@@ -157,12 +136,13 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
}
}
#else
end = SDL_GetTicks() + timeout;
while ((retval = SDL_SemTryWait(sem)) == SDL_MUTEX_TIMEDOUT) {
if (SDL_TICKS_PASSED(SDL_GetTicks(), end)) {
end = SDL_GetTicksNS() + timeoutNS;
while (sem_trywait(&sem->sem) != 0) {
if (SDL_GetTicksNS() >= end) {
retval = SDL_MUTEX_TIMEDOUT;
break;
}
SDL_Delay(1);
SDL_DelayNS(100);
}
#endif /* HAVE_SEM_TIMEDWAIT */