Mercurial > sdl-ios-xcode
changeset 5108:d547877e355e
Colin Leroy 2011-01-26 04:24:20 PST
the pthread implementation of SDL_SemWaitTimeout() uses busy waiting, while
pthread's sem_timedwait() does work. Attached are patches that make use of it
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 27 Jan 2011 00:34:12 -0800 |
parents | 5fe0330b0fd6 |
children | 30da7089dcb4 |
files | src/thread/pthread/SDL_syssem.c test/testsem.c |
diffstat | 2 files changed, 56 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/src/thread/pthread/SDL_syssem.c Thu Jan 27 00:19:46 2011 -0800 +++ b/src/thread/pthread/SDL_syssem.c Thu Jan 27 00:34:12 2011 -0800 @@ -21,6 +21,7 @@ */ #include "SDL_config.h" +#include <errno.h> #include <pthread.h> #include <semaphore.h> @@ -102,6 +103,8 @@ SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout) { int retval; + struct timeval now; + struct timespec ts_timeout; if (!sem) { SDL_SetError("Passed a NULL semaphore"); @@ -116,16 +119,34 @@ return SDL_SemWait(sem); } - /* Ack! We have to busy wait... */ - /* FIXME: Use sem_timedwait()? */ - timeout += SDL_GetTicks(); + /* Setup the timeout. sem_timedwait doesn't wait for + * a lapse of time, but until we reach a certain time. + * This time is now plus the timeout. + */ + gettimeofday(&now, NULL); + + /* Add our timeout to current time */ + now.tv_usec += (timeout % 1000) * 1000; + now.tv_sec += timeout / 1000; + + /* Wrap the second if needed */ + if ( now.tv_usec >= 1000000 ) { + now.tv_usec -= 1000000; + now.tv_sec ++; + } + + /* Convert to timespec */ + ts_timeout.tv_sec = now.tv_sec; + ts_timeout.tv_nsec = now.tv_usec * 1000; + + /* Wait. */ do { - retval = SDL_SemTryWait(sem); - if (retval == 0) { - break; - } - SDL_Delay(1); - } while (SDL_GetTicks() < timeout); + retval = sem_timedwait(&sem->sem, &ts_timeout); + } while (retval < 0 && errno == EINTR); + + if (retval < 0) { + SDL_SetError("sem_timedwait() failed"); + } return retval; }
--- a/test/testsem.c Thu Jan 27 00:19:46 2011 -0800 +++ b/test/testsem.c Thu Jan 27 00:34:12 2011 -0800 @@ -39,6 +39,29 @@ alive = 0; } +static void +TestWaitTimeout(void) +{ + Uint32 start_ticks; + Uint32 end_ticks; + Uint32 duration; + + sem = SDL_CreateSemaphore(0); + printf("Waiting 2 seconds on semaphore\n"); + + start_ticks = SDL_GetTicks(); + SDL_SemWaitTimeout(sem, 2000); + end_ticks = SDL_GetTicks(); + + duration = end_ticks - start_ticks; + + /* Accept a little offset in the effective wait */ + if (duration > 1900 && duration < 2050) + printf("Wait done.\n"); + else + fprintf(stderr, "Wait took %d milliseconds\n", duration); +} + int main(int argc, char **argv) { @@ -81,6 +104,9 @@ printf("Finished waiting for threads\n"); SDL_DestroySemaphore(sem); + + TestWaitTimeout(); + SDL_Quit(); return (0); }