Commit b58487d8 authored by Sam Lantinga's avatar Sam Lantinga

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
parent 71a8858b
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
*/ */
#include "SDL_config.h" #include "SDL_config.h"
#include <errno.h>
#include <pthread.h> #include <pthread.h>
#include <semaphore.h> #include <semaphore.h>
...@@ -102,6 +103,8 @@ int ...@@ -102,6 +103,8 @@ int
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout) SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
{ {
int retval; int retval;
struct timeval now;
struct timespec ts_timeout;
if (!sem) { if (!sem) {
SDL_SetError("Passed a NULL semaphore"); SDL_SetError("Passed a NULL semaphore");
...@@ -116,16 +119,34 @@ SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout) ...@@ -116,16 +119,34 @@ SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
return SDL_SemWait(sem); return SDL_SemWait(sem);
} }
/* Ack! We have to busy wait... */ /* Setup the timeout. sem_timedwait doesn't wait for
/* FIXME: Use sem_timedwait()? */ * a lapse of time, but until we reach a certain time.
timeout += SDL_GetTicks(); * 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 { do {
retval = SDL_SemTryWait(sem); retval = sem_timedwait(&sem->sem, &ts_timeout);
if (retval == 0) { } while (retval < 0 && errno == EINTR);
break;
} if (retval < 0) {
SDL_Delay(1); SDL_SetError("sem_timedwait() failed");
} while (SDL_GetTicks() < timeout); }
return retval; return retval;
} }
......
...@@ -39,6 +39,29 @@ killed(int sig) ...@@ -39,6 +39,29 @@ killed(int sig)
alive = 0; 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 int
main(int argc, char **argv) main(int argc, char **argv)
{ {
...@@ -81,6 +104,9 @@ main(int argc, char **argv) ...@@ -81,6 +104,9 @@ main(int argc, char **argv)
printf("Finished waiting for threads\n"); printf("Finished waiting for threads\n");
SDL_DestroySemaphore(sem); SDL_DestroySemaphore(sem);
TestWaitTimeout();
SDL_Quit(); SDL_Quit();
return (0); return (0);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment