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 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 --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