Date: Fri, 15 Jul 2005 08:29:01 +0100
authorSam Lantinga <slouken@libsdl.org>
Thu, 21 Jul 2005 06:19:18 +0000
changeset 10991ccbb2b7d905
parent 1098 2911ff0a32bb
child 1100 76459577e620
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.
src/thread/riscos/SDL_syssem.c
     1.1 --- a/src/thread/riscos/SDL_syssem.c	Wed Jul 20 17:47:18 2005 +0000
     1.2 +++ b/src/thread/riscos/SDL_syssem.c	Thu Jul 21 06:19:18 2005 +0000
     1.3 @@ -20,14 +20,13 @@
     1.4      slouken@libsdl.org
     1.5  */
     1.6  
     1.7 -/* RISC OS doesn't have semiphores so use code based on generic implementation */
     1.8 +/* RISC OS semiphores based on linux code */
     1.9  
    1.10  #ifdef SAVE_RCSID
    1.11  static char rcsid =
    1.12   "@(#) $Id$";
    1.13  #endif
    1.14  
    1.15 -/* An implementation of semaphores using mutexes and condition variables */
    1.16  
    1.17  #include <stdlib.h>
    1.18  
    1.19 @@ -81,51 +80,40 @@
    1.20  
    1.21  #else
    1.22  
    1.23 -struct SDL_semaphore
    1.24 -{
    1.25 -	Uint32 count;
    1.26 -	Uint32 waiters_count;
    1.27 -	SDL_mutex *count_lock;
    1.28 -	SDL_cond *count_nonzero;
    1.29 +
    1.30 +#include <stdio.h>
    1.31 +#include <stdlib.h>
    1.32 +#include <unistd.h>			/* For getpid() */
    1.33 +#include <pthread.h>
    1.34 +#include <semaphore.h>
    1.35 +
    1.36 +struct SDL_semaphore {
    1.37 +	sem_t *sem;
    1.38 +	sem_t sem_data;
    1.39  };
    1.40  
    1.41 +/* Create a semaphore, initialized with value */
    1.42  SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
    1.43  {
    1.44 -	SDL_sem *sem;
    1.45 -
    1.46 -	sem = (SDL_sem *)malloc(sizeof(*sem));
    1.47 -	if ( ! sem ) {
    1.48 +	SDL_sem *sem = (SDL_sem *) malloc(sizeof(SDL_sem));
    1.49 +	if ( sem ) {
    1.50 +		if ( sem_init(&sem->sem_data, 0, initial_value) < 0 ) {
    1.51 +			SDL_SetError("sem_init() failed");
    1.52 +			free(sem);
    1.53 +			sem = NULL;
    1.54 +		} else {
    1.55 +			sem->sem = &sem->sem_data;
    1.56 +		}
    1.57 +	} else {
    1.58  		SDL_OutOfMemory();
    1.59 -		return(0);
    1.60  	}
    1.61 -	sem->count = initial_value;
    1.62 -	sem->waiters_count = 0;
    1.63 -
    1.64 -	sem->count_lock = SDL_CreateMutex();
    1.65 -	sem->count_nonzero = SDL_CreateCond();
    1.66 -	if ( ! sem->count_lock || ! sem->count_nonzero ) {
    1.67 -		SDL_DestroySemaphore(sem);
    1.68 -		return(0);
    1.69 -	}
    1.70 -
    1.71 -	return(sem);
    1.72 +	return sem;
    1.73  }
    1.74  
    1.75 -/* WARNING:
    1.76 -   You cannot call this function when another thread is using the semaphore.
    1.77 -*/
    1.78  void SDL_DestroySemaphore(SDL_sem *sem)
    1.79  {
    1.80  	if ( sem ) {
    1.81 -		sem->count = 0xFFFFFFFF;
    1.82 -		while ( sem->waiters_count > 0) {
    1.83 -			SDL_CondSignal(sem->count_nonzero);
    1.84 -			SDL_Delay(10);
    1.85 -		}
    1.86 -		SDL_DestroyCond(sem->count_nonzero);
    1.87 -		SDL_mutexP(sem->count_lock);
    1.88 -		SDL_mutexV(sem->count_lock);
    1.89 -		SDL_DestroyMutex(sem->count_lock);
    1.90 +		sem_destroy(sem->sem);
    1.91  		free(sem);
    1.92  	}
    1.93  }
    1.94 @@ -138,15 +126,26 @@
    1.95  		SDL_SetError("Passed a NULL semaphore");
    1.96  		return -1;
    1.97  	}
    1.98 -
    1.99  	retval = SDL_MUTEX_TIMEDOUT;
   1.100 -	SDL_LockMutex(sem->count_lock);
   1.101 -	if ( sem->count > 0 ) {
   1.102 -		--sem->count;
   1.103 +	if ( sem_trywait(sem->sem) == 0 ) {
   1.104  		retval = 0;
   1.105  	}
   1.106 -	SDL_UnlockMutex(sem->count_lock);
   1.107 +	return retval;
   1.108 +}
   1.109  
   1.110 +int SDL_SemWait(SDL_sem *sem)
   1.111 +{
   1.112 +	int retval;
   1.113 +
   1.114 +	if ( ! sem ) {
   1.115 +		SDL_SetError("Passed a NULL semaphore");
   1.116 +		return -1;
   1.117 +	}
   1.118 +
   1.119 +	retval = sem_wait(sem->sem);
   1.120 +	if ( retval < 0 ) {
   1.121 +		SDL_SetError("sem_wait() failed");
   1.122 +	}
   1.123  	return retval;
   1.124  }
   1.125  
   1.126 @@ -159,58 +158,53 @@
   1.127  		return -1;
   1.128  	}
   1.129  
   1.130 -	/* A timeout of 0 is an easy case */
   1.131 +	/* Try the easy cases first */
   1.132  	if ( timeout == 0 ) {
   1.133  		return SDL_SemTryWait(sem);
   1.134  	}
   1.135 +	if ( timeout == SDL_MUTEX_MAXWAIT ) {
   1.136 +		return SDL_SemWait(sem);
   1.137 +	}
   1.138  
   1.139 -	SDL_LockMutex(sem->count_lock);
   1.140 -	++sem->waiters_count;
   1.141 -	retval = 0;
   1.142 -	while ( (sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT) ) {
   1.143 -		retval = SDL_CondWaitTimeout(sem->count_nonzero,
   1.144 -		                             sem->count_lock, timeout);
   1.145 -	}
   1.146 -	--sem->waiters_count;
   1.147 -	--sem->count;
   1.148 -	SDL_UnlockMutex(sem->count_lock);
   1.149 +	/* Ack!  We have to busy wait... */
   1.150 +	timeout += SDL_GetTicks();
   1.151 +	do {
   1.152 +		retval = SDL_SemTryWait(sem);
   1.153 +		if ( retval == 0 ) {
   1.154 +			break;
   1.155 +		}
   1.156 +		SDL_Delay(1);
   1.157 +	} while ( SDL_GetTicks() < timeout );
   1.158  
   1.159  	return retval;
   1.160  }
   1.161  
   1.162 -int SDL_SemWait(SDL_sem *sem)
   1.163 -{
   1.164 -	return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
   1.165 -}
   1.166 -
   1.167  Uint32 SDL_SemValue(SDL_sem *sem)
   1.168  {
   1.169 -	Uint32 value;
   1.170 -	
   1.171 -	value = 0;
   1.172 +	int ret = 0;
   1.173  	if ( sem ) {
   1.174 -		SDL_LockMutex(sem->count_lock);
   1.175 -		value = sem->count;
   1.176 -		SDL_UnlockMutex(sem->count_lock);
   1.177 +		sem_getvalue(sem->sem, &ret);
   1.178 +		if ( ret < 0 ) {
   1.179 +			ret = 0;
   1.180 +		}
   1.181  	}
   1.182 -	return value;
   1.183 +	return (Uint32)ret;
   1.184  }
   1.185  
   1.186  int SDL_SemPost(SDL_sem *sem)
   1.187  {
   1.188 +	int retval;
   1.189 +
   1.190  	if ( ! sem ) {
   1.191  		SDL_SetError("Passed a NULL semaphore");
   1.192  		return -1;
   1.193  	}
   1.194  
   1.195 -	SDL_LockMutex(sem->count_lock);
   1.196 -	if ( sem->waiters_count > 0 ) {
   1.197 -		SDL_CondSignal(sem->count_nonzero);
   1.198 +	retval = sem_post(sem->sem);
   1.199 +	if ( retval < 0 ) {
   1.200 +		SDL_SetError("sem_post() failed");
   1.201  	}
   1.202 -	++sem->count;
   1.203 -	SDL_UnlockMutex(sem->count_lock);
   1.204 -
   1.205 -	return 0;
   1.206 +	return retval;
   1.207  }
   1.208  
   1.209  #endif /* DISABLE_THREADS */