SDL-1.2.14
[sdl_omap.git] / src / thread / win32 / 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 Win32 API */
25
26 #define WIN32_LEAN_AND_MEAN
27 #include <windows.h>
28
29 #include "SDL_thread.h"
30 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
31 #include "win_ce_semaphore.h"
32 #endif
33
34
35 struct SDL_semaphore {
36 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
37         SYNCHHANDLE id;
38 #else
39         HANDLE id;
40 #endif
41         Uint32 volatile count;
42 };
43
44
45 /* Create a semaphore */
46 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
47 {
48         SDL_sem *sem;
49
50         /* Allocate sem memory */
51         sem = (SDL_sem *)SDL_malloc(sizeof(*sem));
52         if ( sem ) {
53                 /* Create the semaphore, with max value 32K */
54 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
55                 sem->id = CreateSemaphoreCE(NULL, initial_value, 32*1024, NULL);
56 #else
57                 sem->id = CreateSemaphore(NULL, initial_value, 32*1024, NULL);
58 #endif
59                 sem->count = initial_value;
60                 if ( ! sem->id ) {
61                         SDL_SetError("Couldn't create semaphore");
62                         SDL_free(sem);
63                         sem = NULL;
64                 }
65         } else {
66                 SDL_OutOfMemory();
67         }
68         return(sem);
69 }
70
71 /* Free the semaphore */
72 void SDL_DestroySemaphore(SDL_sem *sem)
73 {
74         if ( sem ) {
75                 if ( sem->id ) {
76 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
77                         CloseSynchHandle(sem->id);
78 #else
79                         CloseHandle(sem->id);
80 #endif
81                         sem->id = 0;
82                 }
83                 SDL_free(sem);
84         }
85 }
86
87 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
88 {
89         int retval;
90         DWORD dwMilliseconds;
91
92         if ( ! sem ) {
93                 SDL_SetError("Passed a NULL sem");
94                 return -1;
95         }
96
97         if ( timeout == SDL_MUTEX_MAXWAIT ) {
98                 dwMilliseconds = INFINITE;
99         } else {
100                 dwMilliseconds = (DWORD)timeout;
101         }
102 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
103         switch (WaitForSemaphoreCE(sem->id, dwMilliseconds)) {
104 #else
105         switch (WaitForSingleObject(sem->id, dwMilliseconds)) {
106 #endif
107             case WAIT_OBJECT_0:
108                 InterlockedDecrement(&sem->count);
109                 retval = 0;
110                 break;
111             case WAIT_TIMEOUT:
112                 retval = SDL_MUTEX_TIMEDOUT;
113                 break;
114             default:
115                 SDL_SetError("WaitForSingleObject() failed");
116                 retval = -1;
117                 break;
118         }
119         return retval;
120 }
121
122 int SDL_SemTryWait(SDL_sem *sem)
123 {
124         return SDL_SemWaitTimeout(sem, 0);
125 }
126
127 int SDL_SemWait(SDL_sem *sem)
128 {
129         return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
130 }
131
132 /* Returns the current count of the semaphore */
133 Uint32 SDL_SemValue(SDL_sem *sem)
134 {
135         if ( ! sem ) {
136                 SDL_SetError("Passed a NULL sem");
137                 return 0;
138         }
139         return sem->count;
140 }
141
142 int SDL_SemPost(SDL_sem *sem)
143 {
144         if ( ! sem ) {
145                 SDL_SetError("Passed a NULL sem");
146                 return -1;
147         }
148         /* Increase the counter in the first place, because
149          * after a successful release the semaphore may
150          * immediately get destroyed by another thread which
151          * is waiting for this semaphore.
152          */
153         InterlockedIncrement(&sem->count);
154 #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
155         if ( ReleaseSemaphoreCE(sem->id, 1, NULL) == FALSE ) {
156 #else
157         if ( ReleaseSemaphore(sem->id, 1, NULL) == FALSE ) {
158 #endif
159                 InterlockedDecrement(&sem->count);      /* restore */
160                 SDL_SetError("ReleaseSemaphore() failed");
161                 return -1;
162         }
163         return 0;
164 }