SDL-1.2.14
[sdl_omap.git] / src / thread / os2 / SDL_syssem.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 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
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 }