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#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 35struct SDL_semaphore { 36 HMTX id; 37 HEV changed; 38 Uint32 value; 39}; 40 41 42/* Create a semaphore */ 43DECLSPEC 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 */ 70DECLSPEC 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 82DECLSPEC 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 158DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem *sem) 159{ 160 return SDL_SemWaitTimeout(sem, 0); 161} 162 163DECLSPEC 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 */ 169DECLSPEC 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 178DECLSPEC 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