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@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 */
SDL_CreateSemaphore(Uint32 initial_value)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 */
SDL_DestroySemaphore(SDL_sem * sem)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
SDL_SemWaitTimeout(SDL_sem * sem,Uint32 timeout)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 --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 ++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 --sem->count; /* restore */
160 SDL_SetError("ReleaseSemaphore() failed");
161 return -1;
162 }
163 return 0;
164 }
165