1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2006 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 (at) libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 #include <pthread.h> 25 #include <semaphore.h> 26 #include <errno.h> 27 28 #include "SDL_thread.h" 29 #include "SDL_timer.h" 30 31 /* Wrapper around POSIX 1003.1b semaphores */ 32 33 #ifdef __MACOSX__ 34 /* Mac OS X doesn't support sem_getvalue() as of version 10.4 */ 35 #include "../generic/SDL_syssem.c" 36 #else 37 38 struct SDL_semaphore { 39 sem_t sem; 40 }; 41 42 /* Create a semaphore, initialized with value */ 43 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) 44 { 45 SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem)); 46 if ( sem ) { 47 if ( sem_init(&sem->sem, 0, initial_value) < 0 ) { 48 SDL_SetError("sem_init() failed"); 49 SDL_free(sem); 50 sem = NULL; 51 } 52 } else { 53 SDL_OutOfMemory(); 54 } 55 return sem; 56 } 57 58 void SDL_DestroySemaphore(SDL_sem *sem) 59 { 60 if ( sem ) { 61 sem_destroy(&sem->sem); 62 SDL_free(sem); 63 } 64 } 65 66 int SDL_SemTryWait(SDL_sem *sem) 67 { 68 int retval; 69 70 if ( ! sem ) { 71 SDL_SetError("Passed a NULL semaphore"); 72 return -1; 73 } 74 retval = SDL_MUTEX_TIMEDOUT; 75 if ( sem_trywait(&sem->sem) == 0 ) { 76 retval = 0; 77 } 78 return retval; 79 } 80 81 int SDL_SemWait(SDL_sem *sem) 82 { 83 int retval; 84 85 if ( ! sem ) { 86 SDL_SetError("Passed a NULL semaphore"); 87 return -1; 88 } 89 90 while ( ((retval = sem_wait(&sem->sem)) == -1) && (errno == EINTR) ) {} 91 if ( retval < 0 ) { 92 SDL_SetError("sem_wait() failed"); 93 } 94 return retval; 95 } 96 97 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) 98 { 99 int retval; 100 101 if ( ! sem ) { 102 SDL_SetError("Passed a NULL semaphore"); 103 return -1; 104 } 105 106 /* Try the easy cases first */ 107 if ( timeout == 0 ) { 108 return SDL_SemTryWait(sem); 109 } 110 if ( timeout == SDL_MUTEX_MAXWAIT ) { 111 return SDL_SemWait(sem); 112 } 113 114 /* Ack! We have to busy wait... */ 115 /* FIXME: Use sem_timedwait()? */ 116 timeout += SDL_GetTicks(); 117 do { 118 retval = SDL_SemTryWait(sem); 119 if ( retval == 0 ) { 120 break; 121 } 122 SDL_Delay(1); 123 } while ( SDL_GetTicks() < timeout ); 124 125 return retval; 126 } 127 128 Uint32 SDL_SemValue(SDL_sem *sem) 129 { 130 int ret = 0; 131 if ( sem ) { 132 sem_getvalue(&sem->sem, &ret); 133 if ( ret < 0 ) { 134 ret = 0; 135 } 136 } 137 return (Uint32)ret; 138 } 139 140 int SDL_SemPost(SDL_sem *sem) 141 { 142 int retval; 143 144 if ( ! sem ) { 145 SDL_SetError("Passed a NULL semaphore"); 146 return -1; 147 } 148 149 retval = sem_post(&sem->sem); 150 if ( retval < 0 ) { 151 SDL_SetError("sem_post() failed"); 152 } 153 return retval; 154 } 155 156 #endif /* __MACOSX__ */ 157