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 /* Semaphore functions using the OS/2 API */ 25 26 #define INCL_DOS 27 #define INCL_DOSERRORS 28 #define INCL_DOSSEMAPHORES 29 #include <os2.h> 30 31 #include "SDL_thread.h" 32 #include "SDL_timer.h" 33 34 35 struct SDL_semaphore { 36 HMTX id; 37 HEV changed; 38 Uint32 value; 39 }; 40 41 42 /* Create a semaphore */ 43 DECLSPEC SDL_sem * SDLCALL SDL_CreateSemaphore(Uint32 initial_value) 44 { 45 SDL_sem *sem; 46 ULONG ulrc; 47 48 /* Allocate sem memory */ 49 sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); 50 if ( sem ) { 51 /* Create the mutex semaphore */ 52 ulrc = DosCreateMutexSem(NULL,&(sem->id),0,TRUE); 53 if ( ulrc ) { 54 SDL_SetError("Couldn't create semaphore"); 55 SDL_free(sem); 56 sem = NULL; 57 } else 58 { 59 DosCreateEventSem(NULL, &(sem->changed), 0, FALSE); 60 sem->value = initial_value; 61 DosReleaseMutexSem(sem->id); 62 } 63 } else { 64 SDL_OutOfMemory(); 65 } 66 return(sem); 67 } 68 69 /* Free the semaphore */ 70 DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem *sem) 71 { 72 if ( sem ) { 73 if ( sem->id ) { 74 DosCloseEventSem(sem->changed); 75 DosCloseMutexSem(sem->id); 76 sem->id = 0; 77 } 78 SDL_free(sem); 79 } 80 } 81 82 DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) 83 { 84 ULONG ulrc; 85 86 if ( ! sem ) { 87 SDL_SetError("Passed a NULL sem"); 88 return -1; 89 } 90 91 if ( timeout == SDL_MUTEX_MAXWAIT ) { 92 while (1) { 93 ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT); 94 if (ulrc) { 95 /* if error waiting mutex */ 96 SDL_SetError("DosRequestMutexSem() failed"); 97 return -1; 98 } else if (sem->value) { 99 sem->value--; 100 DosReleaseMutexSem(sem->id); 101 return 0; 102 } else { 103 ULONG ulPostCount; 104 DosResetEventSem(sem->changed, &ulPostCount); 105 DosReleaseMutexSem(sem->id); 106 /* continue waiting until somebody posts the semaphore */ 107 DosWaitEventSem(sem->changed, SEM_INDEFINITE_WAIT); 108 } 109 } 110 } else 111 if ( timeout == 0 ) 112 { 113 ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT); 114 if (ulrc==NO_ERROR) 115 { 116 if (sem->value) 117 { 118 sem->value--; 119 DosReleaseMutexSem(sem->id); 120 return 0; 121 } else 122 { 123 DosReleaseMutexSem(sem->id); 124 return SDL_MUTEX_TIMEDOUT; 125 } 126 } else 127 { 128 SDL_SetError("DosRequestMutexSem() failed"); 129 return -1; 130 } 131 } else { 132 ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT); 133 if (ulrc) { 134 /* if error waiting mutex */ 135 SDL_SetError("DosRequestMutexSem() failed"); 136 return -1; 137 } else 138 if (sem->value) { 139 sem->value--; 140 DosReleaseMutexSem(sem->id); 141 return 0; 142 } else { 143 ULONG ulPostCount; 144 DosResetEventSem(sem->changed, &ulPostCount); 145 DosReleaseMutexSem(sem->id); 146 /* continue waiting until somebody posts the semaphore */ 147 ulrc = DosWaitEventSem(sem->changed, timeout); 148 if (ulrc==NO_ERROR) 149 return 0; 150 else 151 return SDL_MUTEX_TIMEDOUT; 152 } 153 } 154 /* never reached */ 155 return -1; 156 } 157 158 DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem *sem) 159 { 160 return SDL_SemWaitTimeout(sem, 0); 161 } 162 163 DECLSPEC int SDLCALL SDL_SemWait(SDL_sem *sem) 164 { 165 return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); 166 } 167 168 /* Returns the current count of the semaphore */ 169 DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem *sem) 170 { 171 if ( ! sem ) { 172 SDL_SetError("Passed a NULL sem"); 173 return 0; 174 } 175 return sem->value; 176 } 177 178 DECLSPEC int SDLCALL SDL_SemPost(SDL_sem *sem) 179 { 180 if ( ! sem ) { 181 SDL_SetError("Passed a NULL sem"); 182 return -1; 183 } 184 if ( DosRequestMutexSem(sem->id,SEM_INDEFINITE_WAIT) ) { 185 SDL_SetError("DosRequestMutexSem() failed"); 186 return -1; 187 } 188 sem->value++; 189 DosPostEventSem(sem->changed); 190 DosReleaseMutexSem(sem->id); 191 return 0; 192 } 193