Skip to content

Commit

Permalink
Colin Leroy 2011-01-26 04:24:20 PST
Browse files Browse the repository at this point in the history
the pthread implementation of SDL_SemWaitTimeout() uses busy waiting, while
pthread's sem_timedwait() does work. Attached are patches that make use of it
  • Loading branch information
slouken committed Jan 27, 2011
1 parent 23e1008 commit f50fcad
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 10 deletions.
39 changes: 29 additions & 10 deletions src/thread/pthread/SDL_syssem.c
Expand Up @@ -97,6 +97,8 @@ int SDL_SemWait(SDL_sem *sem)
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
{
int retval;
struct timeval now;
struct timespec ts_timeout;

if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore");
Expand All @@ -111,16 +113,33 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
return SDL_SemWait(sem);
}

/* Ack! We have to busy wait... */
/* FIXME: Use sem_timedwait()? */
timeout += SDL_GetTicks();
do {
retval = SDL_SemTryWait(sem);
if ( retval == 0 ) {
break;
}
SDL_Delay(1);
} while ( SDL_GetTicks() < timeout );
/* 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 = sem_timedwait(&sem->sem, &ts_timeout);
while (retval == -1 && errno == EINTR);

if (retval == -1)
SDL_SetError(strerror(errno));

return retval;
}
Expand Down
25 changes: 25 additions & 0 deletions test/testsem.c
Expand Up @@ -33,6 +33,28 @@ static void killed(int sig)
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)
{
SDL_Thread *threads[NUM_THREADS];
Expand Down Expand Up @@ -73,6 +95,9 @@ int main(int argc, char **argv)
printf("Finished waiting for threads\n");

SDL_DestroySemaphore(sem);

TestWaitTimeout();

SDL_Quit();
return(0);
}

0 comments on commit f50fcad

Please sign in to comment.