1/* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 Sam Lantinga 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 19 Sam Lantinga 20 slouken@libsdl.org 21*/ 22 23#include <errno.h> 24 25#include "SDL_config.h" 26 27/* RISC OS semiphores based on linux code */ 28 29 30#include "SDL_timer.h" 31#include "SDL_thread.h" 32#include "SDL_systhread_c.h" 33 34#if !SDL_THREADS_DISABLED 35 36SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) 37{ 38 SDL_SetError("SDL not configured with thread support"); 39 return (SDL_sem *)0; 40} 41 42void SDL_DestroySemaphore(SDL_sem *sem) 43{ 44 return; 45} 46 47int SDL_SemTryWait(SDL_sem *sem) 48{ 49 SDL_SetError("SDL not configured with thread support"); 50 return -1; 51} 52 53int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) 54{ 55 SDL_SetError("SDL not configured with thread support"); 56 return -1; 57} 58 59int SDL_SemWait(SDL_sem *sem) 60{ 61 SDL_SetError("SDL not configured with thread support"); 62 return -1; 63} 64 65Uint32 SDL_SemValue(SDL_sem *sem) 66{ 67 return 0; 68} 69 70int SDL_SemPost(SDL_sem *sem) 71{ 72 SDL_SetError("SDL not configured with thread support"); 73 return -1; 74} 75 76#else 77 78 79#include <unistd.h> /* For getpid() */ 80#include <pthread.h> 81#include <semaphore.h> 82 83struct SDL_semaphore { 84 sem_t *sem; 85 sem_t sem_data; 86}; 87 88/* Create a semaphore, initialized with value */ 89SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) 90{ 91 SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem)); 92 if ( sem ) { 93 if ( sem_init(&sem->sem_data, 0, initial_value) < 0 ) { 94 SDL_SetError("sem_init() failed"); 95 SDL_free(sem); 96 sem = NULL; 97 } else { 98 sem->sem = &sem->sem_data; 99 } 100 } else { 101 SDL_OutOfMemory(); 102 } 103 return sem; 104} 105 106void SDL_DestroySemaphore(SDL_sem *sem) 107{ 108 if ( sem ) { 109 sem_destroy(sem->sem); 110 SDL_free(sem); 111 } 112} 113 114int SDL_SemTryWait(SDL_sem *sem) 115{ 116 int retval; 117 118 if ( ! sem ) { 119 SDL_SetError("Passed a NULL semaphore"); 120 return -1; 121 } 122 retval = SDL_MUTEX_TIMEDOUT; 123 if ( sem_trywait(sem->sem) == 0 ) { 124 retval = 0; 125 } 126 return retval; 127} 128 129int SDL_SemWait(SDL_sem *sem) 130{ 131 int retval; 132 133 if ( ! sem ) { 134 SDL_SetError("Passed a NULL semaphore"); 135 return -1; 136 } 137 138 while ( ((retval = sem_wait(sem->sem)) == -1) && (errno == EINTR) ) {} 139 if ( retval < 0 ) { 140 SDL_SetError("sem_wait() failed"); 141 } 142 return retval; 143} 144 145int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) 146{ 147 int retval; 148 149 if ( ! sem ) { 150 SDL_SetError("Passed a NULL semaphore"); 151 return -1; 152 } 153 154 /* Try the easy cases first */ 155 if ( timeout == 0 ) { 156 return SDL_SemTryWait(sem); 157 } 158 if ( timeout == SDL_MUTEX_MAXWAIT ) { 159 return SDL_SemWait(sem); 160 } 161 162 /* Ack! We have to busy wait... */ 163 timeout += SDL_GetTicks(); 164 do { 165 retval = SDL_SemTryWait(sem); 166 if ( retval == 0 ) { 167 break; 168 } 169 SDL_Delay(1); 170 } while ( SDL_GetTicks() < timeout ); 171 172 return retval; 173} 174 175Uint32 SDL_SemValue(SDL_sem *sem) 176{ 177 int ret = 0; 178 if ( sem ) { 179 sem_getvalue(sem->sem, &ret); 180 if ( ret < 0 ) { 181 ret = 0; 182 } 183 } 184 return (Uint32)ret; 185} 186 187int SDL_SemPost(SDL_sem *sem) 188{ 189 int retval; 190 191 if ( ! sem ) { 192 SDL_SetError("Passed a NULL semaphore"); 193 return -1; 194 } 195 196 retval = sem_post(sem->sem); 197 if ( retval < 0 ) { 198 SDL_SetError("sem_post() failed"); 199 } 200 return retval; 201} 202 203#endif /* !SDL_THREADS_DISABLED */ 204