Commit 82d3a5b3 authored by Sam Lantinga's avatar Sam Lantinga

Date: Fri, 15 Jul 2005 08:29:01 +0100

From: "alan buckley"
Subject: SDL Improved semiphore implementation for RISC OS (version 2)

I've attached a new version of the patch for the RISC OS
semaphore processing (in a zip file) that updates it to use
the improved semaphores support in UnixLiib.

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401100
parent 94e33418
...@@ -20,14 +20,13 @@ ...@@ -20,14 +20,13 @@
slouken@libsdl.org slouken@libsdl.org
*/ */
/* RISC OS doesn't have semiphores so use code based on generic implementation */ /* RISC OS semiphores based on linux code */
#ifdef SAVE_RCSID #ifdef SAVE_RCSID
static char rcsid = static char rcsid =
"@(#) $Id$"; "@(#) $Id$";
#endif #endif
/* An implementation of semaphores using mutexes and condition variables */
#include <stdlib.h> #include <stdlib.h>
...@@ -81,51 +80,40 @@ int SDL_SemPost(SDL_sem *sem) ...@@ -81,51 +80,40 @@ int SDL_SemPost(SDL_sem *sem)
#else #else
struct SDL_semaphore
{ #include <stdio.h>
Uint32 count; #include <stdlib.h>
Uint32 waiters_count; #include <unistd.h> /* For getpid() */
SDL_mutex *count_lock; #include <pthread.h>
SDL_cond *count_nonzero; #include <semaphore.h>
struct SDL_semaphore {
sem_t *sem;
sem_t sem_data;
}; };
/* Create a semaphore, initialized with value */
SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
{ {
SDL_sem *sem; SDL_sem *sem = (SDL_sem *) malloc(sizeof(SDL_sem));
if ( sem ) {
sem = (SDL_sem *)malloc(sizeof(*sem)); if ( sem_init(&sem->sem_data, 0, initial_value) < 0 ) {
if ( ! sem ) { SDL_SetError("sem_init() failed");
free(sem);
sem = NULL;
} else {
sem->sem = &sem->sem_data;
}
} else {
SDL_OutOfMemory(); SDL_OutOfMemory();
return(0);
} }
sem->count = initial_value; return sem;
sem->waiters_count = 0;
sem->count_lock = SDL_CreateMutex();
sem->count_nonzero = SDL_CreateCond();
if ( ! sem->count_lock || ! sem->count_nonzero ) {
SDL_DestroySemaphore(sem);
return(0);
}
return(sem);
} }
/* WARNING:
You cannot call this function when another thread is using the semaphore.
*/
void SDL_DestroySemaphore(SDL_sem *sem) void SDL_DestroySemaphore(SDL_sem *sem)
{ {
if ( sem ) { if ( sem ) {
sem->count = 0xFFFFFFFF; sem_destroy(sem->sem);
while ( sem->waiters_count > 0) {
SDL_CondSignal(sem->count_nonzero);
SDL_Delay(10);
}
SDL_DestroyCond(sem->count_nonzero);
SDL_mutexP(sem->count_lock);
SDL_mutexV(sem->count_lock);
SDL_DestroyMutex(sem->count_lock);
free(sem); free(sem);
} }
} }
...@@ -138,15 +126,26 @@ int SDL_SemTryWait(SDL_sem *sem) ...@@ -138,15 +126,26 @@ int SDL_SemTryWait(SDL_sem *sem)
SDL_SetError("Passed a NULL semaphore"); SDL_SetError("Passed a NULL semaphore");
return -1; return -1;
} }
retval = SDL_MUTEX_TIMEDOUT; retval = SDL_MUTEX_TIMEDOUT;
SDL_LockMutex(sem->count_lock); if ( sem_trywait(sem->sem) == 0 ) {
if ( sem->count > 0 ) {
--sem->count;
retval = 0; retval = 0;
} }
SDL_UnlockMutex(sem->count_lock); return retval;
}
int SDL_SemWait(SDL_sem *sem)
{
int retval;
if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore");
return -1;
}
retval = sem_wait(sem->sem);
if ( retval < 0 ) {
SDL_SetError("sem_wait() failed");
}
return retval; return retval;
} }
...@@ -159,58 +158,53 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) ...@@ -159,58 +158,53 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
return -1; return -1;
} }
/* A timeout of 0 is an easy case */ /* Try the easy cases first */
if ( timeout == 0 ) { if ( timeout == 0 ) {
return SDL_SemTryWait(sem); return SDL_SemTryWait(sem);
} }
if ( timeout == SDL_MUTEX_MAXWAIT ) {
SDL_LockMutex(sem->count_lock); return SDL_SemWait(sem);
++sem->waiters_count;
retval = 0;
while ( (sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT) ) {
retval = SDL_CondWaitTimeout(sem->count_nonzero,
sem->count_lock, timeout);
} }
--sem->waiters_count;
--sem->count;
SDL_UnlockMutex(sem->count_lock);
return retval; /* Ack! We have to busy wait... */
} timeout += SDL_GetTicks();
do {
retval = SDL_SemTryWait(sem);
if ( retval == 0 ) {
break;
}
SDL_Delay(1);
} while ( SDL_GetTicks() < timeout );
int SDL_SemWait(SDL_sem *sem) return retval;
{
return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
} }
Uint32 SDL_SemValue(SDL_sem *sem) Uint32 SDL_SemValue(SDL_sem *sem)
{ {
Uint32 value; int ret = 0;
value = 0;
if ( sem ) { if ( sem ) {
SDL_LockMutex(sem->count_lock); sem_getvalue(sem->sem, &ret);
value = sem->count; if ( ret < 0 ) {
SDL_UnlockMutex(sem->count_lock); ret = 0;
}
} }
return value; return (Uint32)ret;
} }
int SDL_SemPost(SDL_sem *sem) int SDL_SemPost(SDL_sem *sem)
{ {
int retval;
if ( ! sem ) { if ( ! sem ) {
SDL_SetError("Passed a NULL semaphore"); SDL_SetError("Passed a NULL semaphore");
return -1; return -1;
} }
SDL_LockMutex(sem->count_lock); retval = sem_post(sem->sem);
if ( sem->waiters_count > 0 ) { if ( retval < 0 ) {
SDL_CondSignal(sem->count_nonzero); SDL_SetError("sem_post() failed");
} }
++sem->count; return retval;
SDL_UnlockMutex(sem->count_lock);
return 0;
} }
#endif /* DISABLE_THREADS */ #endif /* DISABLE_THREADS */
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