diff options
author | Franklin Wei <git@fwei.tk> | 2017-01-21 15:18:31 -0500 |
---|---|---|
committer | Franklin Wei <git@fwei.tk> | 2017-12-23 21:01:26 -0500 |
commit | a855d6202536ff28e5aae4f22a0f31d8f5b325d0 (patch) | |
tree | 8c75f224dd64ed360505afa8843d016b0d75000b /apps/plugins/sdl/src/thread | |
parent | 01c6dcf6c7b9bb1ad2fa0450f99bacc5f3d3e04b (diff) | |
download | rockbox-a855d6202536ff28e5aae4f22a0f31d8f5b325d0.tar.gz rockbox-a855d6202536ff28e5aae4f22a0f31d8f5b325d0.zip |
Port of Duke Nukem 3D
This ports Fabien Sanglard's Chocolate Duke to run on a version of SDL
for Rockbox.
Change-Id: I8f2c4c78af19de10c1633ed7bb7a997b43256dd9
Diffstat (limited to 'apps/plugins/sdl/src/thread')
62 files changed, 6679 insertions, 0 deletions
diff --git a/apps/plugins/sdl/src/thread/SDL_systhread.h b/apps/plugins/sdl/src/thread/SDL_systhread.h new file mode 100644 index 0000000000..a59ac50386 --- /dev/null +++ b/apps/plugins/sdl/src/thread/SDL_systhread.h | |||
@@ -0,0 +1,52 @@ | |||
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 | /* These are functions that need to be implemented by a port of SDL */ | ||
25 | |||
26 | #ifndef _SDL_systhread_h | ||
27 | #define _SDL_systhread_h | ||
28 | |||
29 | #include "SDL_thread.h" | ||
30 | |||
31 | /* This function creates a thread, passing args to SDL_RunThread(), | ||
32 | saves a system-dependent thread id in thread->id, and returns 0 | ||
33 | on success. | ||
34 | */ | ||
35 | #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD | ||
36 | extern int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread); | ||
37 | #else | ||
38 | extern int SDL_SYS_CreateThread(SDL_Thread *thread, void *args); | ||
39 | #endif | ||
40 | |||
41 | /* This function does any necessary setup in the child thread */ | ||
42 | extern void SDL_SYS_SetupThread(void); | ||
43 | |||
44 | /* This function waits for the thread to finish and frees any data | ||
45 | allocated by SDL_SYS_CreateThread() | ||
46 | */ | ||
47 | extern void SDL_SYS_WaitThread(SDL_Thread *thread); | ||
48 | |||
49 | /* This function kills the thread and returns */ | ||
50 | extern void SDL_SYS_KillThread(SDL_Thread *thread); | ||
51 | |||
52 | #endif /* _SDL_systhread_h */ | ||
diff --git a/apps/plugins/sdl/src/thread/SDL_thread.c b/apps/plugins/sdl/src/thread/SDL_thread.c new file mode 100644 index 0000000000..250371dd89 --- /dev/null +++ b/apps/plugins/sdl/src/thread/SDL_thread.c | |||
@@ -0,0 +1,300 @@ | |||
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 | /* System independent thread management routines for SDL */ | ||
25 | |||
26 | #include "SDL_mutex.h" | ||
27 | #include "SDL_thread.h" | ||
28 | #include "SDL_thread_c.h" | ||
29 | #include "SDL_systhread.h" | ||
30 | |||
31 | #define ARRAY_CHUNKSIZE 32 | ||
32 | /* The array of threads currently active in the application | ||
33 | (except the main thread) | ||
34 | The manipulation of an array here is safer than using a linked list. | ||
35 | */ | ||
36 | static int SDL_maxthreads = 0; | ||
37 | static int SDL_numthreads = 0; | ||
38 | static SDL_Thread **SDL_Threads = NULL; | ||
39 | static SDL_mutex *thread_lock = NULL; | ||
40 | |||
41 | int SDL_ThreadsInit(void) | ||
42 | { | ||
43 | int retval; | ||
44 | |||
45 | retval = 0; | ||
46 | thread_lock = SDL_CreateMutex(); | ||
47 | if ( thread_lock == NULL ) { | ||
48 | retval = -1; | ||
49 | } | ||
50 | return(retval); | ||
51 | } | ||
52 | |||
53 | /* This should never be called... | ||
54 | If this is called by SDL_Quit(), we don't know whether or not we should | ||
55 | clean up threads here. If any threads are still running after this call, | ||
56 | they will no longer have access to any per-thread data. | ||
57 | */ | ||
58 | void SDL_ThreadsQuit(void) | ||
59 | { | ||
60 | SDL_mutex *mutex; | ||
61 | |||
62 | mutex = thread_lock; | ||
63 | thread_lock = NULL; | ||
64 | if ( mutex != NULL ) { | ||
65 | SDL_DestroyMutex(mutex); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | /* Routines for manipulating the thread list */ | ||
70 | static void SDL_AddThread(SDL_Thread *thread) | ||
71 | { | ||
72 | /* WARNING: | ||
73 | If the very first threads are created simultaneously, then | ||
74 | there could be a race condition causing memory corruption. | ||
75 | In practice, this isn't a problem because by definition there | ||
76 | is only one thread running the first time this is called. | ||
77 | */ | ||
78 | if ( !thread_lock ) { | ||
79 | if ( SDL_ThreadsInit() < 0 ) { | ||
80 | return; | ||
81 | } | ||
82 | } | ||
83 | SDL_mutexP(thread_lock); | ||
84 | |||
85 | /* Expand the list of threads, if necessary */ | ||
86 | #ifdef DEBUG_THREADS | ||
87 | printf("Adding thread (%d already - %d max)\n", | ||
88 | SDL_numthreads, SDL_maxthreads); | ||
89 | #endif | ||
90 | if ( SDL_numthreads == SDL_maxthreads ) { | ||
91 | SDL_Thread **threads; | ||
92 | threads = (SDL_Thread **)SDL_realloc(SDL_Threads, | ||
93 | (SDL_maxthreads+ARRAY_CHUNKSIZE)*(sizeof *threads)); | ||
94 | if ( threads == NULL ) { | ||
95 | SDL_OutOfMemory(); | ||
96 | goto done; | ||
97 | } | ||
98 | SDL_maxthreads += ARRAY_CHUNKSIZE; | ||
99 | SDL_Threads = threads; | ||
100 | } | ||
101 | SDL_Threads[SDL_numthreads++] = thread; | ||
102 | done: | ||
103 | SDL_mutexV(thread_lock); | ||
104 | } | ||
105 | |||
106 | static void SDL_DelThread(SDL_Thread *thread) | ||
107 | { | ||
108 | int i; | ||
109 | |||
110 | if ( !thread_lock ) { | ||
111 | return; | ||
112 | } | ||
113 | SDL_mutexP(thread_lock); | ||
114 | for ( i=0; i<SDL_numthreads; ++i ) { | ||
115 | if ( thread == SDL_Threads[i] ) { | ||
116 | break; | ||
117 | } | ||
118 | } | ||
119 | if ( i < SDL_numthreads ) { | ||
120 | if ( --SDL_numthreads > 0 ) { | ||
121 | while ( i < SDL_numthreads ) { | ||
122 | SDL_Threads[i] = SDL_Threads[i+1]; | ||
123 | ++i; | ||
124 | } | ||
125 | } else { | ||
126 | SDL_maxthreads = 0; | ||
127 | SDL_free(SDL_Threads); | ||
128 | SDL_Threads = NULL; | ||
129 | } | ||
130 | #ifdef DEBUG_THREADS | ||
131 | printf("Deleting thread (%d left - %d max)\n", | ||
132 | SDL_numthreads, SDL_maxthreads); | ||
133 | #endif | ||
134 | } | ||
135 | SDL_mutexV(thread_lock); | ||
136 | |||
137 | #if 0 /* There could be memory corruption if another thread is starting */ | ||
138 | if ( SDL_Threads == NULL ) { | ||
139 | SDL_ThreadsQuit(); | ||
140 | } | ||
141 | #endif | ||
142 | } | ||
143 | |||
144 | /* The default (non-thread-safe) global error variable */ | ||
145 | static SDL_error SDL_global_error; | ||
146 | |||
147 | /* Routine to get the thread-specific error variable */ | ||
148 | SDL_error *SDL_GetErrBuf(void) | ||
149 | { | ||
150 | SDL_error *errbuf; | ||
151 | |||
152 | errbuf = &SDL_global_error; | ||
153 | if ( SDL_Threads ) { | ||
154 | int i; | ||
155 | Uint32 this_thread; | ||
156 | |||
157 | this_thread = SDL_ThreadID(); | ||
158 | SDL_mutexP(thread_lock); | ||
159 | for ( i=0; i<SDL_numthreads; ++i ) { | ||
160 | if ( this_thread == SDL_Threads[i]->threadid ) { | ||
161 | errbuf = &SDL_Threads[i]->errbuf; | ||
162 | break; | ||
163 | } | ||
164 | } | ||
165 | SDL_mutexV(thread_lock); | ||
166 | } | ||
167 | return(errbuf); | ||
168 | } | ||
169 | |||
170 | |||
171 | /* Arguments and callback to setup and run the user thread function */ | ||
172 | typedef struct { | ||
173 | int (SDLCALL *func)(void *); | ||
174 | void *data; | ||
175 | SDL_Thread *info; | ||
176 | SDL_sem *wait; | ||
177 | } thread_args; | ||
178 | |||
179 | void SDL_RunThread(void *data) | ||
180 | { | ||
181 | thread_args *args; | ||
182 | int (SDLCALL *userfunc)(void *); | ||
183 | void *userdata; | ||
184 | int *statusloc; | ||
185 | |||
186 | /* Perform any system-dependent setup | ||
187 | - this function cannot fail, and cannot use SDL_SetError() | ||
188 | */ | ||
189 | SDL_SYS_SetupThread(); | ||
190 | |||
191 | /* Get the thread id */ | ||
192 | args = (thread_args *)data; | ||
193 | args->info->threadid = SDL_ThreadID(); | ||
194 | |||
195 | /* Figure out what function to run */ | ||
196 | userfunc = args->func; | ||
197 | userdata = args->data; | ||
198 | statusloc = &args->info->status; | ||
199 | |||
200 | /* Wake up the parent thread */ | ||
201 | SDL_SemPost(args->wait); | ||
202 | |||
203 | /* Run the function */ | ||
204 | *statusloc = userfunc(userdata); | ||
205 | } | ||
206 | |||
207 | #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD | ||
208 | #undef SDL_CreateThread | ||
209 | DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(int (SDLCALL *fn)(void *), void *data, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread) | ||
210 | #else | ||
211 | DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(int (SDLCALL *fn)(void *), void *data) | ||
212 | #endif | ||
213 | { | ||
214 | SDL_Thread *thread; | ||
215 | thread_args *args; | ||
216 | int ret; | ||
217 | |||
218 | /* Allocate memory for the thread info structure */ | ||
219 | thread = (SDL_Thread *)SDL_malloc(sizeof(*thread)); | ||
220 | if ( thread == NULL ) { | ||
221 | SDL_OutOfMemory(); | ||
222 | return(NULL); | ||
223 | } | ||
224 | SDL_memset(thread, 0, (sizeof *thread)); | ||
225 | thread->status = -1; | ||
226 | |||
227 | /* Set up the arguments for the thread */ | ||
228 | args = (thread_args *)SDL_malloc(sizeof(*args)); | ||
229 | if ( args == NULL ) { | ||
230 | SDL_OutOfMemory(); | ||
231 | SDL_free(thread); | ||
232 | return(NULL); | ||
233 | } | ||
234 | args->func = fn; | ||
235 | args->data = data; | ||
236 | args->info = thread; | ||
237 | args->wait = SDL_CreateSemaphore(0); | ||
238 | if ( args->wait == NULL ) { | ||
239 | SDL_free(thread); | ||
240 | SDL_free(args); | ||
241 | return(NULL); | ||
242 | } | ||
243 | |||
244 | /* Add the thread to the list of available threads */ | ||
245 | SDL_AddThread(thread); | ||
246 | |||
247 | /* Create the thread and go! */ | ||
248 | #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD | ||
249 | ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread); | ||
250 | #else | ||
251 | ret = SDL_SYS_CreateThread(thread, args); | ||
252 | #endif | ||
253 | if ( ret >= 0 ) { | ||
254 | /* Wait for the thread function to use arguments */ | ||
255 | SDL_SemWait(args->wait); | ||
256 | } else { | ||
257 | /* Oops, failed. Gotta free everything */ | ||
258 | SDL_DelThread(thread); | ||
259 | SDL_free(thread); | ||
260 | thread = NULL; | ||
261 | } | ||
262 | SDL_DestroySemaphore(args->wait); | ||
263 | SDL_free(args); | ||
264 | |||
265 | /* Everything is running now */ | ||
266 | return(thread); | ||
267 | } | ||
268 | |||
269 | void SDL_WaitThread(SDL_Thread *thread, int *status) | ||
270 | { | ||
271 | if ( thread ) { | ||
272 | SDL_SYS_WaitThread(thread); | ||
273 | if ( status ) { | ||
274 | *status = thread->status; | ||
275 | } | ||
276 | SDL_DelThread(thread); | ||
277 | SDL_free(thread); | ||
278 | } | ||
279 | } | ||
280 | |||
281 | Uint32 SDL_GetThreadID(SDL_Thread *thread) | ||
282 | { | ||
283 | Uint32 id; | ||
284 | |||
285 | if ( thread ) { | ||
286 | id = thread->threadid; | ||
287 | } else { | ||
288 | id = SDL_ThreadID(); | ||
289 | } | ||
290 | return(id); | ||
291 | } | ||
292 | |||
293 | void SDL_KillThread(SDL_Thread *thread) | ||
294 | { | ||
295 | if ( thread ) { | ||
296 | SDL_SYS_KillThread(thread); | ||
297 | SDL_WaitThread(thread, NULL); | ||
298 | } | ||
299 | } | ||
300 | |||
diff --git a/apps/plugins/sdl/src/thread/SDL_thread_c.h b/apps/plugins/sdl/src/thread/SDL_thread_c.h new file mode 100644 index 0000000000..9534c8a9e0 --- /dev/null +++ b/apps/plugins/sdl/src/thread/SDL_thread_c.h | |||
@@ -0,0 +1,66 @@ | |||
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 | #ifndef _SDL_thread_c_h | ||
25 | #define _SDL_thread_c_h | ||
26 | |||
27 | /* Need the definitions of SYS_ThreadHandle */ | ||
28 | #if SDL_THREADS_DISABLED | ||
29 | #include "generic/SDL_systhread_c.h" | ||
30 | #elif SDL_THREAD_BEOS | ||
31 | #include "beos/SDL_systhread_c.h" | ||
32 | #elif SDL_THREAD_DC | ||
33 | #include "dc/SDL_systhread_c.h" | ||
34 | #elif SDL_THREAD_OS2 | ||
35 | #include "os2/SDL_systhread_c.h" | ||
36 | #elif SDL_THREAD_PTH | ||
37 | #include "pth/SDL_systhread_c.h" | ||
38 | #elif SDL_THREAD_PTHREAD | ||
39 | #include "pthread/SDL_systhread_c.h" | ||
40 | #elif SDL_THREAD_SPROC | ||
41 | #include "irix/SDL_systhread_c.h" | ||
42 | #elif SDL_THREAD_WIN32 | ||
43 | #include "win32/SDL_systhread_c.h" | ||
44 | #elif SDL_THREAD_SYMBIAN | ||
45 | #include "symbian/SDL_systhread_c.h" | ||
46 | #elif SDL_THREAD_ROCKBOX | ||
47 | #include "rockbox/SDL_systhread_c.h" | ||
48 | #else | ||
49 | #error Need thread implementation for this platform | ||
50 | #include "generic/SDL_systhread_c.h" | ||
51 | #endif | ||
52 | #include "../SDL_error_c.h" | ||
53 | |||
54 | /* This is the system-independent thread info structure */ | ||
55 | struct SDL_Thread { | ||
56 | Uint32 threadid; | ||
57 | SYS_ThreadHandle handle; | ||
58 | int status; | ||
59 | SDL_error errbuf; | ||
60 | void *data; | ||
61 | }; | ||
62 | |||
63 | /* This is the function called to run a thread */ | ||
64 | extern void SDL_RunThread(void *data); | ||
65 | |||
66 | #endif /* _SDL_thread_c_h */ | ||
diff --git a/apps/plugins/sdl/src/thread/beos/SDL_syssem.c b/apps/plugins/sdl/src/thread/beos/SDL_syssem.c new file mode 100644 index 0000000000..eba1944bc8 --- /dev/null +++ b/apps/plugins/sdl/src/thread/beos/SDL_syssem.c | |||
@@ -0,0 +1,142 @@ | |||
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 | /* Semaphores in the BeOS environment */ | ||
25 | |||
26 | #include <be/kernel/OS.h> | ||
27 | |||
28 | #include "SDL_thread.h" | ||
29 | |||
30 | |||
31 | struct SDL_semaphore { | ||
32 | sem_id id; | ||
33 | }; | ||
34 | |||
35 | /* Create a counting semaphore */ | ||
36 | SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | ||
37 | { | ||
38 | SDL_sem *sem; | ||
39 | |||
40 | sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); | ||
41 | if ( sem ) { | ||
42 | sem->id = create_sem(initial_value, "SDL semaphore"); | ||
43 | if ( sem->id < B_NO_ERROR ) { | ||
44 | SDL_SetError("create_sem() failed"); | ||
45 | SDL_free(sem); | ||
46 | sem = NULL; | ||
47 | } | ||
48 | } else { | ||
49 | SDL_OutOfMemory(); | ||
50 | } | ||
51 | return(sem); | ||
52 | } | ||
53 | |||
54 | /* Free the semaphore */ | ||
55 | void SDL_DestroySemaphore(SDL_sem *sem) | ||
56 | { | ||
57 | if ( sem ) { | ||
58 | if ( sem->id >= B_NO_ERROR ) { | ||
59 | delete_sem(sem->id); | ||
60 | } | ||
61 | SDL_free(sem); | ||
62 | } | ||
63 | } | ||
64 | |||
65 | int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | ||
66 | { | ||
67 | int32 val; | ||
68 | int retval; | ||
69 | |||
70 | if ( ! sem ) { | ||
71 | SDL_SetError("Passed a NULL semaphore"); | ||
72 | return -1; | ||
73 | } | ||
74 | |||
75 | tryagain: | ||
76 | if ( timeout == SDL_MUTEX_MAXWAIT ) { | ||
77 | val = acquire_sem(sem->id); | ||
78 | } else { | ||
79 | timeout *= 1000; /* BeOS uses a timeout in microseconds */ | ||
80 | val = acquire_sem_etc(sem->id, 1, B_RELATIVE_TIMEOUT, timeout); | ||
81 | } | ||
82 | switch (val) { | ||
83 | case B_INTERRUPTED: | ||
84 | goto tryagain; | ||
85 | case B_NO_ERROR: | ||
86 | retval = 0; | ||
87 | break; | ||
88 | case B_TIMED_OUT: | ||
89 | retval = SDL_MUTEX_TIMEDOUT; | ||
90 | break; | ||
91 | case B_WOULD_BLOCK: | ||
92 | retval = SDL_MUTEX_TIMEDOUT; | ||
93 | break; | ||
94 | default: | ||
95 | SDL_SetError("acquire_sem() failed"); | ||
96 | retval = -1; | ||
97 | break; | ||
98 | } | ||
99 | |||
100 | return retval; | ||
101 | } | ||
102 | |||
103 | int SDL_SemTryWait(SDL_sem *sem) | ||
104 | { | ||
105 | return SDL_SemWaitTimeout(sem, 0); | ||
106 | } | ||
107 | |||
108 | int SDL_SemWait(SDL_sem *sem) | ||
109 | { | ||
110 | return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); | ||
111 | } | ||
112 | |||
113 | /* Returns the current count of the semaphore */ | ||
114 | Uint32 SDL_SemValue(SDL_sem *sem) | ||
115 | { | ||
116 | int32 count; | ||
117 | Uint32 value; | ||
118 | |||
119 | value = 0; | ||
120 | if ( sem ) { | ||
121 | get_sem_count(sem->id, &count); | ||
122 | if ( count > 0 ) { | ||
123 | value = (Uint32)count; | ||
124 | } | ||
125 | } | ||
126 | return value; | ||
127 | } | ||
128 | |||
129 | /* Atomically increases the semaphore's count (not blocking) */ | ||
130 | int SDL_SemPost(SDL_sem *sem) | ||
131 | { | ||
132 | if ( ! sem ) { | ||
133 | SDL_SetError("Passed a NULL semaphore"); | ||
134 | return -1; | ||
135 | } | ||
136 | |||
137 | if ( release_sem(sem->id) != B_NO_ERROR ) { | ||
138 | SDL_SetError("release_sem() failed"); | ||
139 | return -1; | ||
140 | } | ||
141 | return 0; | ||
142 | } | ||
diff --git a/apps/plugins/sdl/src/thread/beos/SDL_systhread.c b/apps/plugins/sdl/src/thread/beos/SDL_systhread.c new file mode 100644 index 0000000000..63b52075f0 --- /dev/null +++ b/apps/plugins/sdl/src/thread/beos/SDL_systhread.c | |||
@@ -0,0 +1,96 @@ | |||
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 | /* BeOS thread management routines for SDL */ | ||
25 | |||
26 | #include <stdio.h> | ||
27 | #include <signal.h> | ||
28 | #include <be/kernel/OS.h> | ||
29 | |||
30 | #include "SDL_mutex.h" | ||
31 | #include "SDL_thread.h" | ||
32 | #include "../SDL_thread_c.h" | ||
33 | #include "../SDL_systhread.h" | ||
34 | |||
35 | |||
36 | static int sig_list[] = { | ||
37 | SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGWINCH, 0 | ||
38 | }; | ||
39 | |||
40 | void SDL_MaskSignals(sigset_t *omask) | ||
41 | { | ||
42 | sigset_t mask; | ||
43 | int i; | ||
44 | |||
45 | sigemptyset(&mask); | ||
46 | for ( i=0; sig_list[i]; ++i ) { | ||
47 | sigaddset(&mask, sig_list[i]); | ||
48 | } | ||
49 | sigprocmask(SIG_BLOCK, &mask, omask); | ||
50 | } | ||
51 | void SDL_UnmaskSignals(sigset_t *omask) | ||
52 | { | ||
53 | sigprocmask(SIG_SETMASK, omask, NULL); | ||
54 | } | ||
55 | |||
56 | static int32 RunThread(void *data) | ||
57 | { | ||
58 | SDL_RunThread(data); | ||
59 | return(0); | ||
60 | } | ||
61 | |||
62 | int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) | ||
63 | { | ||
64 | /* Create the thread and go! */ | ||
65 | thread->handle=spawn_thread(RunThread, "SDL", B_NORMAL_PRIORITY, args); | ||
66 | if ( (thread->handle == B_NO_MORE_THREADS) || | ||
67 | (thread->handle == B_NO_MEMORY) ) { | ||
68 | SDL_SetError("Not enough resources to create thread"); | ||
69 | return(-1); | ||
70 | } | ||
71 | resume_thread(thread->handle); | ||
72 | return(0); | ||
73 | } | ||
74 | |||
75 | void SDL_SYS_SetupThread(void) | ||
76 | { | ||
77 | /* Mask asynchronous signals for this thread */ | ||
78 | SDL_MaskSignals(NULL); | ||
79 | } | ||
80 | |||
81 | Uint32 SDL_ThreadID(void) | ||
82 | { | ||
83 | return((Uint32)find_thread(NULL)); | ||
84 | } | ||
85 | |||
86 | void SDL_SYS_WaitThread(SDL_Thread *thread) | ||
87 | { | ||
88 | status_t the_status; | ||
89 | |||
90 | wait_for_thread(thread->handle, &the_status); | ||
91 | } | ||
92 | |||
93 | void SDL_SYS_KillThread(SDL_Thread *thread) | ||
94 | { | ||
95 | kill_thread(thread->handle); | ||
96 | } | ||
diff --git a/apps/plugins/sdl/src/thread/beos/SDL_systhread_c.h b/apps/plugins/sdl/src/thread/beos/SDL_systhread_c.h new file mode 100644 index 0000000000..f82548e463 --- /dev/null +++ b/apps/plugins/sdl/src/thread/beos/SDL_systhread_c.h | |||
@@ -0,0 +1,31 @@ | |||
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 | #include <signal.h> | ||
25 | #include <be/kernel/OS.h> | ||
26 | |||
27 | typedef thread_id SYS_ThreadHandle; | ||
28 | |||
29 | /* Functions needed to work with system threads in other portions of SDL */ | ||
30 | extern void SDL_MaskSignals(sigset_t *omask); | ||
31 | extern void SDL_UnmaskSignals(sigset_t *omask); | ||
diff --git a/apps/plugins/sdl/src/thread/dc/SDL_syscond.c b/apps/plugins/sdl/src/thread/dc/SDL_syscond.c new file mode 100644 index 0000000000..f6e7223e3d --- /dev/null +++ b/apps/plugins/sdl/src/thread/dc/SDL_syscond.c | |||
@@ -0,0 +1,215 @@ | |||
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 | /* An implementation of condition variables using semaphores and mutexes */ | ||
25 | /* | ||
26 | This implementation borrows heavily from the BeOS condition variable | ||
27 | implementation, written by Christopher Tate and Owen Smith. Thanks! | ||
28 | */ | ||
29 | |||
30 | #include "SDL_thread.h" | ||
31 | |||
32 | struct SDL_cond | ||
33 | { | ||
34 | SDL_mutex *lock; | ||
35 | int waiting; | ||
36 | int signals; | ||
37 | SDL_sem *wait_sem; | ||
38 | SDL_sem *wait_done; | ||
39 | }; | ||
40 | |||
41 | /* Create a condition variable */ | ||
42 | SDL_cond * SDL_CreateCond(void) | ||
43 | { | ||
44 | SDL_cond *cond; | ||
45 | |||
46 | cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); | ||
47 | if ( cond ) { | ||
48 | cond->lock = SDL_CreateMutex(); | ||
49 | cond->wait_sem = SDL_CreateSemaphore(0); | ||
50 | cond->wait_done = SDL_CreateSemaphore(0); | ||
51 | cond->waiting = cond->signals = 0; | ||
52 | if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) { | ||
53 | SDL_DestroyCond(cond); | ||
54 | cond = NULL; | ||
55 | } | ||
56 | } else { | ||
57 | SDL_OutOfMemory(); | ||
58 | } | ||
59 | return(cond); | ||
60 | } | ||
61 | |||
62 | /* Destroy a condition variable */ | ||
63 | void SDL_DestroyCond(SDL_cond *cond) | ||
64 | { | ||
65 | if ( cond ) { | ||
66 | if ( cond->wait_sem ) { | ||
67 | SDL_DestroySemaphore(cond->wait_sem); | ||
68 | } | ||
69 | if ( cond->wait_done ) { | ||
70 | SDL_DestroySemaphore(cond->wait_done); | ||
71 | } | ||
72 | if ( cond->lock ) { | ||
73 | SDL_DestroyMutex(cond->lock); | ||
74 | } | ||
75 | SDL_free(cond); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | /* Restart one of the threads that are waiting on the condition variable */ | ||
80 | int SDL_CondSignal(SDL_cond *cond) | ||
81 | { | ||
82 | if ( ! cond ) { | ||
83 | SDL_SetError("Passed a NULL condition variable"); | ||
84 | return -1; | ||
85 | } | ||
86 | |||
87 | /* If there are waiting threads not already signalled, then | ||
88 | signal the condition and wait for the thread to respond. | ||
89 | */ | ||
90 | SDL_LockMutex(cond->lock); | ||
91 | if ( cond->waiting > cond->signals ) { | ||
92 | ++cond->signals; | ||
93 | SDL_SemPost(cond->wait_sem); | ||
94 | SDL_UnlockMutex(cond->lock); | ||
95 | SDL_SemWait(cond->wait_done); | ||
96 | } else { | ||
97 | SDL_UnlockMutex(cond->lock); | ||
98 | } | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | /* Restart all threads that are waiting on the condition variable */ | ||
104 | int SDL_CondBroadcast(SDL_cond *cond) | ||
105 | { | ||
106 | if ( ! cond ) { | ||
107 | SDL_SetError("Passed a NULL condition variable"); | ||
108 | return -1; | ||
109 | } | ||
110 | |||
111 | /* If there are waiting threads not already signalled, then | ||
112 | signal the condition and wait for the thread to respond. | ||
113 | */ | ||
114 | SDL_LockMutex(cond->lock); | ||
115 | if ( cond->waiting > cond->signals ) { | ||
116 | int i, num_waiting; | ||
117 | |||
118 | num_waiting = (cond->waiting - cond->signals); | ||
119 | cond->signals = cond->waiting; | ||
120 | for ( i=0; i<num_waiting; ++i ) { | ||
121 | SDL_SemPost(cond->wait_sem); | ||
122 | } | ||
123 | /* Now all released threads are blocked here, waiting for us. | ||
124 | Collect them all (and win fabulous prizes!) :-) | ||
125 | */ | ||
126 | SDL_UnlockMutex(cond->lock); | ||
127 | for ( i=0; i<num_waiting; ++i ) { | ||
128 | SDL_SemWait(cond->wait_done); | ||
129 | } | ||
130 | } else { | ||
131 | SDL_UnlockMutex(cond->lock); | ||
132 | } | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | /* Wait on the condition variable for at most 'ms' milliseconds. | ||
138 | The mutex must be locked before entering this function! | ||
139 | The mutex is unlocked during the wait, and locked again after the wait. | ||
140 | |||
141 | Typical use: | ||
142 | |||
143 | Thread A: | ||
144 | SDL_LockMutex(lock); | ||
145 | while ( ! condition ) { | ||
146 | SDL_CondWait(cond); | ||
147 | } | ||
148 | SDL_UnlockMutex(lock); | ||
149 | |||
150 | Thread B: | ||
151 | SDL_LockMutex(lock); | ||
152 | ... | ||
153 | condition = true; | ||
154 | ... | ||
155 | SDL_UnlockMutex(lock); | ||
156 | */ | ||
157 | int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) | ||
158 | { | ||
159 | int retval; | ||
160 | |||
161 | if ( ! cond ) { | ||
162 | SDL_SetError("Passed a NULL condition variable"); | ||
163 | return -1; | ||
164 | } | ||
165 | |||
166 | /* Obtain the protection mutex, and increment the number of waiters. | ||
167 | This allows the signal mechanism to only perform a signal if there | ||
168 | are waiting threads. | ||
169 | */ | ||
170 | SDL_LockMutex(cond->lock); | ||
171 | ++cond->waiting; | ||
172 | SDL_UnlockMutex(cond->lock); | ||
173 | |||
174 | /* Unlock the mutex, as is required by condition variable semantics */ | ||
175 | SDL_UnlockMutex(mutex); | ||
176 | |||
177 | /* Wait for a signal */ | ||
178 | if ( ms == SDL_MUTEX_MAXWAIT ) { | ||
179 | retval = SDL_SemWait(cond->wait_sem); | ||
180 | } else { | ||
181 | retval = SDL_SemWaitTimeout(cond->wait_sem, ms); | ||
182 | } | ||
183 | |||
184 | /* Let the signaler know we have completed the wait, otherwise | ||
185 | the signaler can race ahead and get the condition semaphore | ||
186 | if we are stopped between the mutex unlock and semaphore wait, | ||
187 | giving a deadlock. See the following URL for details: | ||
188 | http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html | ||
189 | */ | ||
190 | SDL_LockMutex(cond->lock); | ||
191 | if ( cond->signals > 0 ) { | ||
192 | /* If we timed out, we need to eat a condition signal */ | ||
193 | if ( retval > 0 ) { | ||
194 | SDL_SemWait(cond->wait_sem); | ||
195 | } | ||
196 | /* We always notify the signal thread that we are done */ | ||
197 | SDL_SemPost(cond->wait_done); | ||
198 | |||
199 | /* Signal handshake complete */ | ||
200 | --cond->signals; | ||
201 | } | ||
202 | --cond->waiting; | ||
203 | SDL_UnlockMutex(cond->lock); | ||
204 | |||
205 | /* Lock the mutex, as is required by condition variable semantics */ | ||
206 | SDL_LockMutex(mutex); | ||
207 | |||
208 | return retval; | ||
209 | } | ||
210 | |||
211 | /* Wait on the condition variable forever */ | ||
212 | int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) | ||
213 | { | ||
214 | return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); | ||
215 | } | ||
diff --git a/apps/plugins/sdl/src/thread/dc/SDL_syscond_c.h b/apps/plugins/sdl/src/thread/dc/SDL_syscond_c.h new file mode 100644 index 0000000000..1120b2d80d --- /dev/null +++ b/apps/plugins/sdl/src/thread/dc/SDL_syscond_c.h | |||
@@ -0,0 +1,23 @@ | |||
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 | |||
diff --git a/apps/plugins/sdl/src/thread/dc/SDL_sysmutex.c b/apps/plugins/sdl/src/thread/dc/SDL_sysmutex.c new file mode 100644 index 0000000000..c6c465131b --- /dev/null +++ b/apps/plugins/sdl/src/thread/dc/SDL_sysmutex.c | |||
@@ -0,0 +1,122 @@ | |||
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 | /* An implementation of mutexes using semaphores */ | ||
25 | |||
26 | #include "SDL_thread.h" | ||
27 | #include "SDL_systhread_c.h" | ||
28 | |||
29 | #include <arch/spinlock.h> | ||
30 | |||
31 | struct SDL_mutex { | ||
32 | int recursive; | ||
33 | Uint32 owner; | ||
34 | spinlock_t mutex; | ||
35 | }; | ||
36 | |||
37 | /* Create a mutex */ | ||
38 | SDL_mutex *SDL_CreateMutex(void) | ||
39 | { | ||
40 | SDL_mutex *mutex; | ||
41 | |||
42 | /* Allocate mutex memory */ | ||
43 | mutex = (SDL_mutex *)SDL_malloc(sizeof(*mutex)); | ||
44 | if ( mutex ) { | ||
45 | spinlock_init(&mutex->mutex); | ||
46 | mutex->recursive = 0; | ||
47 | mutex->owner = 0; | ||
48 | } else { | ||
49 | SDL_OutOfMemory(); | ||
50 | } | ||
51 | return mutex; | ||
52 | } | ||
53 | |||
54 | /* Free the mutex */ | ||
55 | void SDL_DestroyMutex(SDL_mutex *mutex) | ||
56 | { | ||
57 | if ( mutex ) { | ||
58 | SDL_free(mutex); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | /* Lock the semaphore */ | ||
63 | int SDL_mutexP(SDL_mutex *mutex) | ||
64 | { | ||
65 | #if SDL_THREADS_DISABLED | ||
66 | return SDL_arraysize(return ),0; | ||
67 | #else | ||
68 | Uint32 this_thread; | ||
69 | |||
70 | if ( mutex == NULL ) { | ||
71 | SDL_SetError("Passed a NULL mutex"); | ||
72 | return -1; | ||
73 | } | ||
74 | |||
75 | this_thread = SDL_ThreadID(); | ||
76 | if ( mutex->owner == this_thread ) { | ||
77 | ++mutex->recursive; | ||
78 | } else { | ||
79 | /* The order of operations is important. | ||
80 | We set the locking thread id after we obtain the lock | ||
81 | so unlocks from other threads will fail. | ||
82 | */ | ||
83 | spinlock_lock(&mutex->mutex); | ||
84 | mutex->owner = this_thread; | ||
85 | mutex->recursive = 0; | ||
86 | } | ||
87 | |||
88 | return 0; | ||
89 | #endif /* SDL_THREADS_DISABLED */ | ||
90 | } | ||
91 | |||
92 | /* Unlock the mutex */ | ||
93 | int SDL_mutexV(SDL_mutex *mutex) | ||
94 | { | ||
95 | #if SDL_THREADS_DISABLED | ||
96 | return 0; | ||
97 | #else | ||
98 | if ( mutex == NULL ) { | ||
99 | SDL_SetError("Passed a NULL mutex"); | ||
100 | return -1; | ||
101 | } | ||
102 | |||
103 | /* If we don't own the mutex, we can't unlock it */ | ||
104 | if ( SDL_ThreadID() != mutex->owner ) { | ||
105 | SDL_SetError("mutex not owned by this thread"); | ||
106 | return -1; | ||
107 | } | ||
108 | |||
109 | if ( mutex->recursive ) { | ||
110 | --mutex->recursive; | ||
111 | } else { | ||
112 | /* The order of operations is important. | ||
113 | First reset the owner so another thread doesn't lock | ||
114 | the mutex and set the ownership before we reset it, | ||
115 | then release the lock semaphore. | ||
116 | */ | ||
117 | mutex->owner = 0; | ||
118 | spinlock_unlock(&mutex->mutex); | ||
119 | } | ||
120 | return 0; | ||
121 | #endif /* SDL_THREADS_DISABLED */ | ||
122 | } | ||
diff --git a/apps/plugins/sdl/src/thread/dc/SDL_sysmutex_c.h b/apps/plugins/sdl/src/thread/dc/SDL_sysmutex_c.h new file mode 100644 index 0000000000..1120b2d80d --- /dev/null +++ b/apps/plugins/sdl/src/thread/dc/SDL_sysmutex_c.h | |||
@@ -0,0 +1,23 @@ | |||
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 | |||
diff --git a/apps/plugins/sdl/src/thread/dc/SDL_syssem.c b/apps/plugins/sdl/src/thread/dc/SDL_syssem.c new file mode 100644 index 0000000000..9831ccdbd7 --- /dev/null +++ b/apps/plugins/sdl/src/thread/dc/SDL_syssem.c | |||
@@ -0,0 +1,173 @@ | |||
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 | |||
23 | #include <errno.h> | ||
24 | |||
25 | #include "SDL_config.h" | ||
26 | |||
27 | /* An implementation of semaphores using mutexes and condition variables */ | ||
28 | |||
29 | #include "SDL_timer.h" | ||
30 | #include "SDL_thread.h" | ||
31 | #include "SDL_systhread_c.h" | ||
32 | |||
33 | |||
34 | #if SDL_THREADS_DISABLED | ||
35 | |||
36 | SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | ||
37 | { | ||
38 | SDL_SetError("SDL not configured with thread support"); | ||
39 | return (SDL_sem *)0; | ||
40 | } | ||
41 | |||
42 | void SDL_DestroySemaphore(SDL_sem *sem) | ||
43 | { | ||
44 | return; | ||
45 | } | ||
46 | |||
47 | int SDL_SemTryWait(SDL_sem *sem) | ||
48 | { | ||
49 | SDL_SetError("SDL not configured with thread support"); | ||
50 | return -1; | ||
51 | } | ||
52 | |||
53 | int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | ||
54 | { | ||
55 | SDL_SetError("SDL not configured with thread support"); | ||
56 | return -1; | ||
57 | } | ||
58 | |||
59 | int SDL_SemWait(SDL_sem *sem) | ||
60 | { | ||
61 | SDL_SetError("SDL not configured with thread support"); | ||
62 | return -1; | ||
63 | } | ||
64 | |||
65 | Uint32 SDL_SemValue(SDL_sem *sem) | ||
66 | { | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | int SDL_SemPost(SDL_sem *sem) | ||
71 | { | ||
72 | SDL_SetError("SDL not configured with thread support"); | ||
73 | return -1; | ||
74 | } | ||
75 | |||
76 | #else | ||
77 | |||
78 | #include <kos/sem.h> | ||
79 | |||
80 | struct SDL_semaphore | ||
81 | { | ||
82 | semaphore_t sem; | ||
83 | }; | ||
84 | |||
85 | SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | ||
86 | { | ||
87 | return (SDL_sem *)sem_create(initial_value); | ||
88 | } | ||
89 | |||
90 | /* WARNING: | ||
91 | You cannot call this function when another thread is using the semaphore. | ||
92 | */ | ||
93 | void SDL_DestroySemaphore(SDL_sem *sem) | ||
94 | { | ||
95 | if ( ! sem ) { | ||
96 | SDL_SetError("Passed a NULL semaphore"); | ||
97 | return; | ||
98 | } | ||
99 | |||
100 | sem_destroy(&sem->sem); | ||
101 | } | ||
102 | |||
103 | int SDL_SemTryWait(SDL_sem *sem) | ||
104 | { | ||
105 | int retval; | ||
106 | |||
107 | if ( ! sem ) { | ||
108 | SDL_SetError("Passed a NULL semaphore"); | ||
109 | return -1; | ||
110 | } | ||
111 | |||
112 | retval = sem_trywait(&sem->sem); | ||
113 | if (retval==0) return 0; | ||
114 | else return SDL_MUTEX_TIMEDOUT; | ||
115 | |||
116 | return retval; | ||
117 | } | ||
118 | |||
119 | int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | ||
120 | { | ||
121 | int retval; | ||
122 | |||
123 | if ( ! sem ) { | ||
124 | SDL_SetError("Passed a NULL semaphore"); | ||
125 | return -1; | ||
126 | } | ||
127 | |||
128 | /* A timeout of 0 is an easy case */ | ||
129 | if ( timeout == 0 ) { | ||
130 | return SDL_SemTryWait(sem); | ||
131 | } | ||
132 | |||
133 | retval = sem_wait_timed(&sem->sem,timeout); | ||
134 | if (retval==-1) retval= SDL_MUTEX_TIMEDOUT; | ||
135 | |||
136 | return retval; | ||
137 | } | ||
138 | |||
139 | int SDL_SemWait(SDL_sem *sem) | ||
140 | { | ||
141 | int retval; | ||
142 | |||
143 | if ( ! sem ) { | ||
144 | SDL_SetError("Passed a NULL semaphore"); | ||
145 | return -1; | ||
146 | } | ||
147 | |||
148 | while ( ((retval = sem_wait(&sem->sem)) == -1) && (errno == EINTR) ) {} | ||
149 | return retval; | ||
150 | } | ||
151 | |||
152 | Uint32 SDL_SemValue(SDL_sem *sem) | ||
153 | { | ||
154 | if ( ! sem ) { | ||
155 | SDL_SetError("Passed a NULL semaphore"); | ||
156 | return -1; | ||
157 | } | ||
158 | |||
159 | return sem_count(&sem->sem); | ||
160 | } | ||
161 | |||
162 | int SDL_SemPost(SDL_sem *sem) | ||
163 | { | ||
164 | if ( ! sem ) { | ||
165 | SDL_SetError("Passed a NULL semaphore"); | ||
166 | return -1; | ||
167 | } | ||
168 | |||
169 | sem_signal(&sem->sem); | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | #endif /* SDL_THREADS_DISABLED */ | ||
diff --git a/apps/plugins/sdl/src/thread/dc/SDL_syssem_c.h b/apps/plugins/sdl/src/thread/dc/SDL_syssem_c.h new file mode 100644 index 0000000000..1120b2d80d --- /dev/null +++ b/apps/plugins/sdl/src/thread/dc/SDL_syssem_c.h | |||
@@ -0,0 +1,23 @@ | |||
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 | |||
diff --git a/apps/plugins/sdl/src/thread/dc/SDL_systhread.c b/apps/plugins/sdl/src/thread/dc/SDL_systhread.c new file mode 100644 index 0000000000..dd26675491 --- /dev/null +++ b/apps/plugins/sdl/src/thread/dc/SDL_systhread.c | |||
@@ -0,0 +1,60 @@ | |||
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 | /* Thread management routines for SDL */ | ||
25 | |||
26 | #include "SDL_thread.h" | ||
27 | #include "../SDL_thread_c.h" | ||
28 | #include "../SDL_systhread.h" | ||
29 | |||
30 | #include <kos/thread.h> | ||
31 | |||
32 | int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) | ||
33 | { | ||
34 | thread->handle = thd_create(SDL_RunThread,args); | ||
35 | if (thread->handle == NULL) { | ||
36 | SDL_SetError("Not enough resources to create thread"); | ||
37 | return(-1); | ||
38 | } | ||
39 | return(0); | ||
40 | } | ||
41 | |||
42 | void SDL_SYS_SetupThread(void) | ||
43 | { | ||
44 | return; | ||
45 | } | ||
46 | |||
47 | Uint32 SDL_ThreadID(void) | ||
48 | { | ||
49 | return (Uint32)thd_get_current(); | ||
50 | } | ||
51 | |||
52 | void SDL_SYS_WaitThread(SDL_Thread *thread) | ||
53 | { | ||
54 | thd_wait(thread->handle); | ||
55 | } | ||
56 | |||
57 | void SDL_SYS_KillThread(SDL_Thread *thread) | ||
58 | { | ||
59 | thd_destroy(thread->handle); | ||
60 | } | ||
diff --git a/apps/plugins/sdl/src/thread/dc/SDL_systhread_c.h b/apps/plugins/sdl/src/thread/dc/SDL_systhread_c.h new file mode 100644 index 0000000000..3cda1a4a51 --- /dev/null +++ b/apps/plugins/sdl/src/thread/dc/SDL_systhread_c.h | |||
@@ -0,0 +1,24 @@ | |||
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 Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 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 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | typedef struct kthread* SYS_ThreadHandle; | ||
diff --git a/apps/plugins/sdl/src/thread/generic/SDL_syscond.c b/apps/plugins/sdl/src/thread/generic/SDL_syscond.c new file mode 100644 index 0000000000..f6e7223e3d --- /dev/null +++ b/apps/plugins/sdl/src/thread/generic/SDL_syscond.c | |||
@@ -0,0 +1,215 @@ | |||
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 | /* An implementation of condition variables using semaphores and mutexes */ | ||
25 | /* | ||
26 | This implementation borrows heavily from the BeOS condition variable | ||
27 | implementation, written by Christopher Tate and Owen Smith. Thanks! | ||
28 | */ | ||
29 | |||
30 | #include "SDL_thread.h" | ||
31 | |||
32 | struct SDL_cond | ||
33 | { | ||
34 | SDL_mutex *lock; | ||
35 | int waiting; | ||
36 | int signals; | ||
37 | SDL_sem *wait_sem; | ||
38 | SDL_sem *wait_done; | ||
39 | }; | ||
40 | |||
41 | /* Create a condition variable */ | ||
42 | SDL_cond * SDL_CreateCond(void) | ||
43 | { | ||
44 | SDL_cond *cond; | ||
45 | |||
46 | cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); | ||
47 | if ( cond ) { | ||
48 | cond->lock = SDL_CreateMutex(); | ||
49 | cond->wait_sem = SDL_CreateSemaphore(0); | ||
50 | cond->wait_done = SDL_CreateSemaphore(0); | ||
51 | cond->waiting = cond->signals = 0; | ||
52 | if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) { | ||
53 | SDL_DestroyCond(cond); | ||
54 | cond = NULL; | ||
55 | } | ||
56 | } else { | ||
57 | SDL_OutOfMemory(); | ||
58 | } | ||
59 | return(cond); | ||
60 | } | ||
61 | |||
62 | /* Destroy a condition variable */ | ||
63 | void SDL_DestroyCond(SDL_cond *cond) | ||
64 | { | ||
65 | if ( cond ) { | ||
66 | if ( cond->wait_sem ) { | ||
67 | SDL_DestroySemaphore(cond->wait_sem); | ||
68 | } | ||
69 | if ( cond->wait_done ) { | ||
70 | SDL_DestroySemaphore(cond->wait_done); | ||
71 | } | ||
72 | if ( cond->lock ) { | ||
73 | SDL_DestroyMutex(cond->lock); | ||
74 | } | ||
75 | SDL_free(cond); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | /* Restart one of the threads that are waiting on the condition variable */ | ||
80 | int SDL_CondSignal(SDL_cond *cond) | ||
81 | { | ||
82 | if ( ! cond ) { | ||
83 | SDL_SetError("Passed a NULL condition variable"); | ||
84 | return -1; | ||
85 | } | ||
86 | |||
87 | /* If there are waiting threads not already signalled, then | ||
88 | signal the condition and wait for the thread to respond. | ||
89 | */ | ||
90 | SDL_LockMutex(cond->lock); | ||
91 | if ( cond->waiting > cond->signals ) { | ||
92 | ++cond->signals; | ||
93 | SDL_SemPost(cond->wait_sem); | ||
94 | SDL_UnlockMutex(cond->lock); | ||
95 | SDL_SemWait(cond->wait_done); | ||
96 | } else { | ||
97 | SDL_UnlockMutex(cond->lock); | ||
98 | } | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | /* Restart all threads that are waiting on the condition variable */ | ||
104 | int SDL_CondBroadcast(SDL_cond *cond) | ||
105 | { | ||
106 | if ( ! cond ) { | ||
107 | SDL_SetError("Passed a NULL condition variable"); | ||
108 | return -1; | ||
109 | } | ||
110 | |||
111 | /* If there are waiting threads not already signalled, then | ||
112 | signal the condition and wait for the thread to respond. | ||
113 | */ | ||
114 | SDL_LockMutex(cond->lock); | ||
115 | if ( cond->waiting > cond->signals ) { | ||
116 | int i, num_waiting; | ||
117 | |||
118 | num_waiting = (cond->waiting - cond->signals); | ||
119 | cond->signals = cond->waiting; | ||
120 | for ( i=0; i<num_waiting; ++i ) { | ||
121 | SDL_SemPost(cond->wait_sem); | ||
122 | } | ||
123 | /* Now all released threads are blocked here, waiting for us. | ||
124 | Collect them all (and win fabulous prizes!) :-) | ||
125 | */ | ||
126 | SDL_UnlockMutex(cond->lock); | ||
127 | for ( i=0; i<num_waiting; ++i ) { | ||
128 | SDL_SemWait(cond->wait_done); | ||
129 | } | ||
130 | } else { | ||
131 | SDL_UnlockMutex(cond->lock); | ||
132 | } | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | /* Wait on the condition variable for at most 'ms' milliseconds. | ||
138 | The mutex must be locked before entering this function! | ||
139 | The mutex is unlocked during the wait, and locked again after the wait. | ||
140 | |||
141 | Typical use: | ||
142 | |||
143 | Thread A: | ||
144 | SDL_LockMutex(lock); | ||
145 | while ( ! condition ) { | ||
146 | SDL_CondWait(cond); | ||
147 | } | ||
148 | SDL_UnlockMutex(lock); | ||
149 | |||
150 | Thread B: | ||
151 | SDL_LockMutex(lock); | ||
152 | ... | ||
153 | condition = true; | ||
154 | ... | ||
155 | SDL_UnlockMutex(lock); | ||
156 | */ | ||
157 | int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) | ||
158 | { | ||
159 | int retval; | ||
160 | |||
161 | if ( ! cond ) { | ||
162 | SDL_SetError("Passed a NULL condition variable"); | ||
163 | return -1; | ||
164 | } | ||
165 | |||
166 | /* Obtain the protection mutex, and increment the number of waiters. | ||
167 | This allows the signal mechanism to only perform a signal if there | ||
168 | are waiting threads. | ||
169 | */ | ||
170 | SDL_LockMutex(cond->lock); | ||
171 | ++cond->waiting; | ||
172 | SDL_UnlockMutex(cond->lock); | ||
173 | |||
174 | /* Unlock the mutex, as is required by condition variable semantics */ | ||
175 | SDL_UnlockMutex(mutex); | ||
176 | |||
177 | /* Wait for a signal */ | ||
178 | if ( ms == SDL_MUTEX_MAXWAIT ) { | ||
179 | retval = SDL_SemWait(cond->wait_sem); | ||
180 | } else { | ||
181 | retval = SDL_SemWaitTimeout(cond->wait_sem, ms); | ||
182 | } | ||
183 | |||
184 | /* Let the signaler know we have completed the wait, otherwise | ||
185 | the signaler can race ahead and get the condition semaphore | ||
186 | if we are stopped between the mutex unlock and semaphore wait, | ||
187 | giving a deadlock. See the following URL for details: | ||
188 | http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html | ||
189 | */ | ||
190 | SDL_LockMutex(cond->lock); | ||
191 | if ( cond->signals > 0 ) { | ||
192 | /* If we timed out, we need to eat a condition signal */ | ||
193 | if ( retval > 0 ) { | ||
194 | SDL_SemWait(cond->wait_sem); | ||
195 | } | ||
196 | /* We always notify the signal thread that we are done */ | ||
197 | SDL_SemPost(cond->wait_done); | ||
198 | |||
199 | /* Signal handshake complete */ | ||
200 | --cond->signals; | ||
201 | } | ||
202 | --cond->waiting; | ||
203 | SDL_UnlockMutex(cond->lock); | ||
204 | |||
205 | /* Lock the mutex, as is required by condition variable semantics */ | ||
206 | SDL_LockMutex(mutex); | ||
207 | |||
208 | return retval; | ||
209 | } | ||
210 | |||
211 | /* Wait on the condition variable forever */ | ||
212 | int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) | ||
213 | { | ||
214 | return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); | ||
215 | } | ||
diff --git a/apps/plugins/sdl/src/thread/generic/SDL_sysmutex.c b/apps/plugins/sdl/src/thread/generic/SDL_sysmutex.c new file mode 100644 index 0000000000..ecfea876a5 --- /dev/null +++ b/apps/plugins/sdl/src/thread/generic/SDL_sysmutex.c | |||
@@ -0,0 +1,129 @@ | |||
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 | /* An implementation of mutexes using semaphores */ | ||
25 | |||
26 | #include "SDL_thread.h" | ||
27 | #include "SDL_systhread_c.h" | ||
28 | |||
29 | |||
30 | struct SDL_mutex { | ||
31 | int recursive; | ||
32 | Uint32 owner; | ||
33 | SDL_sem *sem; | ||
34 | }; | ||
35 | |||
36 | /* Create a mutex */ | ||
37 | SDL_mutex *SDL_CreateMutex(void) | ||
38 | { | ||
39 | SDL_mutex *mutex; | ||
40 | |||
41 | /* Allocate mutex memory */ | ||
42 | mutex = (SDL_mutex *)SDL_malloc(sizeof(*mutex)); | ||
43 | if ( mutex ) { | ||
44 | /* Create the mutex semaphore, with initial value 1 */ | ||
45 | mutex->sem = SDL_CreateSemaphore(1); | ||
46 | mutex->recursive = 0; | ||
47 | mutex->owner = 0; | ||
48 | if ( ! mutex->sem ) { | ||
49 | SDL_free(mutex); | ||
50 | mutex = NULL; | ||
51 | } | ||
52 | } else { | ||
53 | SDL_OutOfMemory(); | ||
54 | } | ||
55 | return mutex; | ||
56 | } | ||
57 | |||
58 | /* Free the mutex */ | ||
59 | void SDL_DestroyMutex(SDL_mutex *mutex) | ||
60 | { | ||
61 | if ( mutex ) { | ||
62 | if ( mutex->sem ) { | ||
63 | SDL_DestroySemaphore(mutex->sem); | ||
64 | } | ||
65 | SDL_free(mutex); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | /* Lock the semaphore */ | ||
70 | int SDL_mutexP(SDL_mutex *mutex) | ||
71 | { | ||
72 | #if SDL_THREADS_DISABLED | ||
73 | return 0; | ||
74 | #else | ||
75 | Uint32 this_thread; | ||
76 | |||
77 | if ( mutex == NULL ) { | ||
78 | SDL_SetError("Passed a NULL mutex"); | ||
79 | return -1; | ||
80 | } | ||
81 | |||
82 | this_thread = SDL_ThreadID(); | ||
83 | if ( mutex->owner == this_thread ) { | ||
84 | ++mutex->recursive; | ||
85 | } else { | ||
86 | /* The order of operations is important. | ||
87 | We set the locking thread id after we obtain the lock | ||
88 | so unlocks from other threads will fail. | ||
89 | */ | ||
90 | SDL_SemWait(mutex->sem); | ||
91 | mutex->owner = this_thread; | ||
92 | mutex->recursive = 0; | ||
93 | } | ||
94 | |||
95 | return 0; | ||
96 | #endif /* SDL_THREADS_DISABLED */ | ||
97 | } | ||
98 | |||
99 | /* Unlock the mutex */ | ||
100 | int SDL_mutexV(SDL_mutex *mutex) | ||
101 | { | ||
102 | #if SDL_THREADS_DISABLED | ||
103 | return 0; | ||
104 | #else | ||
105 | if ( mutex == NULL ) { | ||
106 | SDL_SetError("Passed a NULL mutex"); | ||
107 | return -1; | ||
108 | } | ||
109 | |||
110 | /* If we don't own the mutex, we can't unlock it */ | ||
111 | if ( SDL_ThreadID() != mutex->owner ) { | ||
112 | SDL_SetError("mutex not owned by this thread"); | ||
113 | return -1; | ||
114 | } | ||
115 | |||
116 | if ( mutex->recursive ) { | ||
117 | --mutex->recursive; | ||
118 | } else { | ||
119 | /* The order of operations is important. | ||
120 | First reset the owner so another thread doesn't lock | ||
121 | the mutex and set the ownership before we reset it, | ||
122 | then release the lock semaphore. | ||
123 | */ | ||
124 | mutex->owner = 0; | ||
125 | SDL_SemPost(mutex->sem); | ||
126 | } | ||
127 | return 0; | ||
128 | #endif /* SDL_THREADS_DISABLED */ | ||
129 | } | ||
diff --git a/apps/plugins/sdl/src/thread/generic/SDL_sysmutex_c.h b/apps/plugins/sdl/src/thread/generic/SDL_sysmutex_c.h new file mode 100644 index 0000000000..1120b2d80d --- /dev/null +++ b/apps/plugins/sdl/src/thread/generic/SDL_sysmutex_c.h | |||
@@ -0,0 +1,23 @@ | |||
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 | |||
diff --git a/apps/plugins/sdl/src/thread/generic/SDL_syssem.c b/apps/plugins/sdl/src/thread/generic/SDL_syssem.c new file mode 100644 index 0000000000..1d289c05d0 --- /dev/null +++ b/apps/plugins/sdl/src/thread/generic/SDL_syssem.c | |||
@@ -0,0 +1,211 @@ | |||
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 | /* An implementation of semaphores using mutexes and condition variables */ | ||
25 | |||
26 | #include "SDL_timer.h" | ||
27 | #include "SDL_thread.h" | ||
28 | #include "SDL_systhread_c.h" | ||
29 | |||
30 | |||
31 | #if SDL_THREADS_DISABLED | ||
32 | |||
33 | SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | ||
34 | { | ||
35 | SDL_SetError("SDL not configured with thread support"); | ||
36 | return (SDL_sem *)0; | ||
37 | } | ||
38 | |||
39 | void SDL_DestroySemaphore(SDL_sem *sem) | ||
40 | { | ||
41 | return; | ||
42 | } | ||
43 | |||
44 | int SDL_SemTryWait(SDL_sem *sem) | ||
45 | { | ||
46 | SDL_SetError("SDL not configured with thread support"); | ||
47 | return -1; | ||
48 | } | ||
49 | |||
50 | int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | ||
51 | { | ||
52 | SDL_SetError("SDL not configured with thread support"); | ||
53 | return -1; | ||
54 | } | ||
55 | |||
56 | int SDL_SemWait(SDL_sem *sem) | ||
57 | { | ||
58 | SDL_SetError("SDL not configured with thread support"); | ||
59 | return -1; | ||
60 | } | ||
61 | |||
62 | Uint32 SDL_SemValue(SDL_sem *sem) | ||
63 | { | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | int SDL_SemPost(SDL_sem *sem) | ||
68 | { | ||
69 | SDL_SetError("SDL not configured with thread support"); | ||
70 | return -1; | ||
71 | } | ||
72 | |||
73 | #else | ||
74 | |||
75 | struct SDL_semaphore | ||
76 | { | ||
77 | Uint32 count; | ||
78 | Uint32 waiters_count; | ||
79 | SDL_mutex *count_lock; | ||
80 | SDL_cond *count_nonzero; | ||
81 | }; | ||
82 | |||
83 | SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | ||
84 | { | ||
85 | SDL_sem *sem; | ||
86 | |||
87 | sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); | ||
88 | if ( ! sem ) { | ||
89 | SDL_OutOfMemory(); | ||
90 | return NULL; | ||
91 | } | ||
92 | sem->count = initial_value; | ||
93 | sem->waiters_count = 0; | ||
94 | |||
95 | sem->count_lock = SDL_CreateMutex(); | ||
96 | sem->count_nonzero = SDL_CreateCond(); | ||
97 | if ( ! sem->count_lock || ! sem->count_nonzero ) { | ||
98 | SDL_DestroySemaphore(sem); | ||
99 | return NULL; | ||
100 | } | ||
101 | |||
102 | return sem; | ||
103 | } | ||
104 | |||
105 | /* WARNING: | ||
106 | You cannot call this function when another thread is using the semaphore. | ||
107 | */ | ||
108 | void SDL_DestroySemaphore(SDL_sem *sem) | ||
109 | { | ||
110 | if ( sem ) { | ||
111 | sem->count = 0xFFFFFFFF; | ||
112 | while ( sem->waiters_count > 0) { | ||
113 | SDL_CondSignal(sem->count_nonzero); | ||
114 | SDL_Delay(10); | ||
115 | } | ||
116 | SDL_DestroyCond(sem->count_nonzero); | ||
117 | if ( sem->count_lock ) { | ||
118 | SDL_mutexP(sem->count_lock); | ||
119 | SDL_mutexV(sem->count_lock); | ||
120 | SDL_DestroyMutex(sem->count_lock); | ||
121 | } | ||
122 | SDL_free(sem); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | int SDL_SemTryWait(SDL_sem *sem) | ||
127 | { | ||
128 | int retval; | ||
129 | |||
130 | if ( ! sem ) { | ||
131 | SDL_SetError("Passed a NULL semaphore"); | ||
132 | return -1; | ||
133 | } | ||
134 | |||
135 | retval = SDL_MUTEX_TIMEDOUT; | ||
136 | SDL_LockMutex(sem->count_lock); | ||
137 | if ( sem->count > 0 ) { | ||
138 | --sem->count; | ||
139 | retval = 0; | ||
140 | } | ||
141 | SDL_UnlockMutex(sem->count_lock); | ||
142 | |||
143 | return retval; | ||
144 | } | ||
145 | |||
146 | int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | ||
147 | { | ||
148 | int retval; | ||
149 | |||
150 | if ( ! sem ) { | ||
151 | SDL_SetError("Passed a NULL semaphore"); | ||
152 | return -1; | ||
153 | } | ||
154 | |||
155 | /* A timeout of 0 is an easy case */ | ||
156 | if ( timeout == 0 ) { | ||
157 | return SDL_SemTryWait(sem); | ||
158 | } | ||
159 | |||
160 | SDL_LockMutex(sem->count_lock); | ||
161 | ++sem->waiters_count; | ||
162 | retval = 0; | ||
163 | while ( (sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT) ) { | ||
164 | retval = SDL_CondWaitTimeout(sem->count_nonzero, | ||
165 | sem->count_lock, timeout); | ||
166 | } | ||
167 | --sem->waiters_count; | ||
168 | if (retval == 0) { | ||
169 | --sem->count; | ||
170 | } | ||
171 | SDL_UnlockMutex(sem->count_lock); | ||
172 | |||
173 | return retval; | ||
174 | } | ||
175 | |||
176 | int SDL_SemWait(SDL_sem *sem) | ||
177 | { | ||
178 | return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); | ||
179 | } | ||
180 | |||
181 | Uint32 SDL_SemValue(SDL_sem *sem) | ||
182 | { | ||
183 | Uint32 value; | ||
184 | |||
185 | value = 0; | ||
186 | if ( sem ) { | ||
187 | SDL_LockMutex(sem->count_lock); | ||
188 | value = sem->count; | ||
189 | SDL_UnlockMutex(sem->count_lock); | ||
190 | } | ||
191 | return value; | ||
192 | } | ||
193 | |||
194 | int SDL_SemPost(SDL_sem *sem) | ||
195 | { | ||
196 | if ( ! sem ) { | ||
197 | SDL_SetError("Passed a NULL semaphore"); | ||
198 | return -1; | ||
199 | } | ||
200 | |||
201 | SDL_LockMutex(sem->count_lock); | ||
202 | if ( sem->waiters_count > 0 ) { | ||
203 | SDL_CondSignal(sem->count_nonzero); | ||
204 | } | ||
205 | ++sem->count; | ||
206 | SDL_UnlockMutex(sem->count_lock); | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | #endif /* SDL_THREADS_DISABLED */ | ||
diff --git a/apps/plugins/sdl/src/thread/generic/SDL_systhread.c b/apps/plugins/sdl/src/thread/generic/SDL_systhread.c new file mode 100644 index 0000000000..c380121ff6 --- /dev/null +++ b/apps/plugins/sdl/src/thread/generic/SDL_systhread.c | |||
@@ -0,0 +1,54 @@ | |||
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 | /* Thread management routines for SDL */ | ||
25 | |||
26 | #include "SDL_thread.h" | ||
27 | #include "../SDL_systhread.h" | ||
28 | |||
29 | int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) | ||
30 | { | ||
31 | SDL_SetError("Threads are not supported on this platform"); | ||
32 | return(-1); | ||
33 | } | ||
34 | |||
35 | void SDL_SYS_SetupThread(void) | ||
36 | { | ||
37 | return; | ||
38 | } | ||
39 | |||
40 | Uint32 SDL_ThreadID(void) | ||
41 | { | ||
42 | return(0); | ||
43 | } | ||
44 | |||
45 | void SDL_SYS_WaitThread(SDL_Thread *thread) | ||
46 | { | ||
47 | return; | ||
48 | } | ||
49 | |||
50 | void SDL_SYS_KillThread(SDL_Thread *thread) | ||
51 | { | ||
52 | return; | ||
53 | } | ||
54 | |||
diff --git a/apps/plugins/sdl/src/thread/generic/SDL_systhread_c.h b/apps/plugins/sdl/src/thread/generic/SDL_systhread_c.h new file mode 100644 index 0000000000..1535b50191 --- /dev/null +++ b/apps/plugins/sdl/src/thread/generic/SDL_systhread_c.h | |||
@@ -0,0 +1,25 @@ | |||
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 Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 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 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | /* Stub until we implement threads on this platform */ | ||
25 | typedef int SYS_ThreadHandle; | ||
diff --git a/apps/plugins/sdl/src/thread/irix/SDL_syssem.c b/apps/plugins/sdl/src/thread/irix/SDL_syssem.c new file mode 100644 index 0000000000..208c379cdd --- /dev/null +++ b/apps/plugins/sdl/src/thread/irix/SDL_syssem.c | |||
@@ -0,0 +1,219 @@ | |||
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 | #include "SDL_thread.h" | ||
25 | #include "SDL_timer.h" | ||
26 | |||
27 | |||
28 | #include <stdio.h> | ||
29 | #include <stdlib.h> | ||
30 | #include <sys/types.h> | ||
31 | #include <sys/ipc.h> | ||
32 | #include <sys/sem.h> | ||
33 | #include <errno.h> | ||
34 | |||
35 | #include "SDL_error.h" | ||
36 | #include "SDL_thread.h" | ||
37 | |||
38 | |||
39 | struct SDL_semaphore { | ||
40 | int id; | ||
41 | }; | ||
42 | |||
43 | /* Not defined by many operating systems, use configure to detect */ | ||
44 | /* | ||
45 | #if !defined(HAVE_SEMUN) | ||
46 | union semun { | ||
47 | int val; | ||
48 | struct semid_ds *buf; | ||
49 | ushort *array; | ||
50 | }; | ||
51 | #endif | ||
52 | */ | ||
53 | |||
54 | static struct sembuf op_trywait[2] = { | ||
55 | { 0, -1, (IPC_NOWAIT|SEM_UNDO) } /* Decrement semaphore, no block */ | ||
56 | }; | ||
57 | static struct sembuf op_wait[2] = { | ||
58 | { 0, -1, SEM_UNDO } /* Decrement semaphore */ | ||
59 | }; | ||
60 | static struct sembuf op_post[1] = { | ||
61 | { 0, 1, (IPC_NOWAIT|SEM_UNDO) } /* Increment semaphore */ | ||
62 | }; | ||
63 | |||
64 | /* Create a blockable semaphore */ | ||
65 | SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | ||
66 | { | ||
67 | extern int _creating_thread_lock; /* SDL_threads.c */ | ||
68 | SDL_sem *sem; | ||
69 | union semun init; | ||
70 | |||
71 | sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); | ||
72 | if ( sem == NULL ) { | ||
73 | SDL_OutOfMemory(); | ||
74 | return(NULL); | ||
75 | } | ||
76 | sem->id = semget(IPC_PRIVATE, 1, (0600|IPC_CREAT)); | ||
77 | if ( sem->id < 0 ) { | ||
78 | SDL_SetError("Couldn't create semaphore"); | ||
79 | SDL_free(sem); | ||
80 | return(NULL); | ||
81 | } | ||
82 | init.val = initial_value; /* Initialize semaphore */ | ||
83 | semctl(sem->id, 0, SETVAL, init); | ||
84 | return(sem); | ||
85 | } | ||
86 | |||
87 | void SDL_DestroySemaphore(SDL_sem *sem) | ||
88 | { | ||
89 | if ( sem ) { | ||
90 | #ifdef __IRIX__ | ||
91 | semctl(sem->id, 0, IPC_RMID); | ||
92 | #else | ||
93 | union semun dummy; | ||
94 | dummy.val = 0; | ||
95 | semctl(sem->id, 0, IPC_RMID, dummy); | ||
96 | #endif | ||
97 | SDL_free(sem); | ||
98 | } | ||
99 | } | ||
100 | |||
101 | int SDL_SemTryWait(SDL_sem *sem) | ||
102 | { | ||
103 | int retval; | ||
104 | |||
105 | if ( ! sem ) { | ||
106 | SDL_SetError("Passed a NULL semaphore"); | ||
107 | return -1; | ||
108 | } | ||
109 | |||
110 | retval = 0; | ||
111 | tryagain: | ||
112 | if ( semop(sem->id, op_trywait, 1) < 0 ) { | ||
113 | if ( errno == EINTR ) { | ||
114 | goto tryagain; | ||
115 | } | ||
116 | retval = SDL_MUTEX_TIMEDOUT; | ||
117 | } | ||
118 | return retval; | ||
119 | } | ||
120 | |||
121 | int SDL_SemWait(SDL_sem *sem) | ||
122 | { | ||
123 | int retval; | ||
124 | |||
125 | if ( ! sem ) { | ||
126 | SDL_SetError("Passed a NULL semaphore"); | ||
127 | return -1; | ||
128 | } | ||
129 | |||
130 | retval = 0; | ||
131 | tryagain: | ||
132 | if ( semop(sem->id, op_wait, 1) < 0 ) { | ||
133 | if ( errno == EINTR ) { | ||
134 | goto tryagain; | ||
135 | } | ||
136 | SDL_SetError("Semaphore operation error"); | ||
137 | retval = -1; | ||
138 | } | ||
139 | return retval; | ||
140 | } | ||
141 | |||
142 | int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | ||
143 | { | ||
144 | int retval; | ||
145 | |||
146 | if ( ! sem ) { | ||
147 | SDL_SetError("Passed a NULL semaphore"); | ||
148 | return -1; | ||
149 | } | ||
150 | |||
151 | /* Try the easy cases first */ | ||
152 | if ( timeout == 0 ) { | ||
153 | return SDL_SemTryWait(sem); | ||
154 | } | ||
155 | if ( timeout == SDL_MUTEX_MAXWAIT ) { | ||
156 | return SDL_SemWait(sem); | ||
157 | } | ||
158 | |||
159 | /* Ack! We have to busy wait... */ | ||
160 | timeout += SDL_GetTicks(); | ||
161 | do { | ||
162 | retval = SDL_SemTryWait(sem); | ||
163 | if ( retval == 0 ) { | ||
164 | break; | ||
165 | } | ||
166 | SDL_Delay(1); | ||
167 | } while ( SDL_GetTicks() < timeout ); | ||
168 | |||
169 | return retval; | ||
170 | } | ||
171 | |||
172 | Uint32 SDL_SemValue(SDL_sem *sem) | ||
173 | { | ||
174 | int semval; | ||
175 | Uint32 value; | ||
176 | |||
177 | value = 0; | ||
178 | if ( sem ) { | ||
179 | tryagain: | ||
180 | #ifdef __IRIX__ | ||
181 | semval = semctl(sem->id, 0, GETVAL); | ||
182 | #else | ||
183 | { | ||
184 | union semun arg; | ||
185 | arg.val = 0; | ||
186 | semval = semctl(sem->id, 0, GETVAL, arg); | ||
187 | } | ||
188 | #endif | ||
189 | if ( semval < 0 ) { | ||
190 | if ( errno == EINTR ) { | ||
191 | goto tryagain; | ||
192 | } | ||
193 | } else { | ||
194 | value = (Uint32)semval; | ||
195 | } | ||
196 | } | ||
197 | return value; | ||
198 | } | ||
199 | |||
200 | int SDL_SemPost(SDL_sem *sem) | ||
201 | { | ||
202 | int retval; | ||
203 | |||
204 | if ( ! sem ) { | ||
205 | SDL_SetError("Passed a NULL semaphore"); | ||
206 | return -1; | ||
207 | } | ||
208 | |||
209 | retval = 0; | ||
210 | tryagain: | ||
211 | if ( semop(sem->id, op_post, 1) < 0 ) { | ||
212 | if ( errno == EINTR ) { | ||
213 | goto tryagain; | ||
214 | } | ||
215 | SDL_SetError("Semaphore operation error"); | ||
216 | retval = -1; | ||
217 | } | ||
218 | return retval; | ||
219 | } | ||
diff --git a/apps/plugins/sdl/src/thread/irix/SDL_systhread.c b/apps/plugins/sdl/src/thread/irix/SDL_systhread.c new file mode 100644 index 0000000000..7ae7fc6771 --- /dev/null +++ b/apps/plugins/sdl/src/thread/irix/SDL_systhread.c | |||
@@ -0,0 +1,85 @@ | |||
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 | /* IRIX thread management routines for SDL */ | ||
25 | |||
26 | #include <errno.h> | ||
27 | #include <signal.h> | ||
28 | #include <sys/types.h> | ||
29 | #include <sys/wait.h> | ||
30 | #include <sys/prctl.h> | ||
31 | |||
32 | #include "SDL_thread.h" | ||
33 | #include "../SDL_systhread.h" | ||
34 | |||
35 | |||
36 | static int sig_list[] = { | ||
37 | SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCLD, SIGWINCH, | ||
38 | SIGVTALRM, SIGPROF, 0 | ||
39 | }; | ||
40 | |||
41 | |||
42 | int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) | ||
43 | { | ||
44 | /* Create the thread and go! */ | ||
45 | if ( sproc(SDL_RunThread, PR_SALL, args) < 0 ) { | ||
46 | SDL_SetError("Not enough resources to create thread"); | ||
47 | return(-1); | ||
48 | } | ||
49 | return(0); | ||
50 | } | ||
51 | |||
52 | void SDL_SYS_SetupThread(void) | ||
53 | { | ||
54 | int i; | ||
55 | sigset_t mask; | ||
56 | |||
57 | /* Mask asynchronous signals for this thread */ | ||
58 | sigemptyset(&mask); | ||
59 | for ( i=0; sig_list[i]; ++i ) { | ||
60 | sigaddset(&mask, sig_list[i]); | ||
61 | } | ||
62 | sigprocmask(SIG_BLOCK, &mask, NULL); | ||
63 | } | ||
64 | |||
65 | /* WARNING: This may not work for systems with 64-bit pid_t */ | ||
66 | Uint32 SDL_ThreadID(void) | ||
67 | { | ||
68 | return((Uint32)getpid()); | ||
69 | } | ||
70 | |||
71 | /* WARNING: This may not work for systems with 64-bit pid_t */ | ||
72 | void SDL_WaitThread(SDL_Thread *thread, int *status) | ||
73 | { | ||
74 | errno = 0; | ||
75 | while ( errno != ECHILD ) { | ||
76 | waitpid(thread->handle, NULL, 0); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | /* WARNING: This may not work for systems with 64-bit pid_t */ | ||
81 | void SDL_KillThread(SDL_Thread *thread) | ||
82 | { | ||
83 | kill(thread->handle, SIGKILL); | ||
84 | } | ||
85 | |||
diff --git a/apps/plugins/sdl/src/thread/irix/SDL_systhread_c.h b/apps/plugins/sdl/src/thread/irix/SDL_systhread_c.h new file mode 100644 index 0000000000..ee28634fb1 --- /dev/null +++ b/apps/plugins/sdl/src/thread/irix/SDL_systhread_c.h | |||
@@ -0,0 +1,27 @@ | |||
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 Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 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 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | #include <sys/types.h> | ||
25 | |||
26 | typedef pid_t SYS_ThreadHandle; | ||
27 | |||
diff --git a/apps/plugins/sdl/src/thread/os2/SDL_syscond.c b/apps/plugins/sdl/src/thread/os2/SDL_syscond.c new file mode 100644 index 0000000000..3e80594c2a --- /dev/null +++ b/apps/plugins/sdl/src/thread/os2/SDL_syscond.c | |||
@@ -0,0 +1,215 @@ | |||
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 | /* An implementation of condition variables using semaphores and mutexes */ | ||
25 | /* | ||
26 | This implementation borrows heavily from the BeOS condition variable | ||
27 | implementation, written by Christopher Tate and Owen Smith. Thanks! | ||
28 | */ | ||
29 | |||
30 | #include "SDL_thread.h" | ||
31 | |||
32 | struct SDL_cond | ||
33 | { | ||
34 | SDL_mutex *lock; | ||
35 | int waiting; | ||
36 | int signals; | ||
37 | SDL_sem *wait_sem; | ||
38 | SDL_sem *wait_done; | ||
39 | }; | ||
40 | |||
41 | /* Create a condition variable */ | ||
42 | DECLSPEC SDL_cond * SDLCALL SDL_CreateCond(void) | ||
43 | { | ||
44 | SDL_cond *cond; | ||
45 | |||
46 | cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); | ||
47 | if ( cond ) { | ||
48 | cond->lock = SDL_CreateMutex(); | ||
49 | cond->wait_sem = SDL_CreateSemaphore(0); | ||
50 | cond->wait_done = SDL_CreateSemaphore(0); | ||
51 | cond->waiting = cond->signals = 0; | ||
52 | if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) { | ||
53 | SDL_DestroyCond(cond); | ||
54 | cond = NULL; | ||
55 | } | ||
56 | } else { | ||
57 | SDL_OutOfMemory(); | ||
58 | } | ||
59 | return(cond); | ||
60 | } | ||
61 | |||
62 | /* Destroy a condition variable */ | ||
63 | DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond *cond) | ||
64 | { | ||
65 | if ( cond ) { | ||
66 | if ( cond->wait_sem ) { | ||
67 | SDL_DestroySemaphore(cond->wait_sem); | ||
68 | } | ||
69 | if ( cond->wait_done ) { | ||
70 | SDL_DestroySemaphore(cond->wait_done); | ||
71 | } | ||
72 | if ( cond->lock ) { | ||
73 | SDL_DestroyMutex(cond->lock); | ||
74 | } | ||
75 | SDL_free(cond); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | /* Restart one of the threads that are waiting on the condition variable */ | ||
80 | DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond *cond) | ||
81 | { | ||
82 | if ( ! cond ) { | ||
83 | SDL_SetError("Passed a NULL condition variable"); | ||
84 | return -1; | ||
85 | } | ||
86 | |||
87 | /* If there are waiting threads not already signalled, then | ||
88 | signal the condition and wait for the thread to respond. | ||
89 | */ | ||
90 | SDL_LockMutex(cond->lock); | ||
91 | if ( cond->waiting > cond->signals ) { | ||
92 | ++cond->signals; | ||
93 | SDL_SemPost(cond->wait_sem); | ||
94 | SDL_UnlockMutex(cond->lock); | ||
95 | SDL_SemWait(cond->wait_done); | ||
96 | } else { | ||
97 | SDL_UnlockMutex(cond->lock); | ||
98 | } | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | /* Restart all threads that are waiting on the condition variable */ | ||
104 | DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond *cond) | ||
105 | { | ||
106 | if ( ! cond ) { | ||
107 | SDL_SetError("Passed a NULL condition variable"); | ||
108 | return -1; | ||
109 | } | ||
110 | |||
111 | /* If there are waiting threads not already signalled, then | ||
112 | signal the condition and wait for the thread to respond. | ||
113 | */ | ||
114 | SDL_LockMutex(cond->lock); | ||
115 | if ( cond->waiting > cond->signals ) { | ||
116 | int i, num_waiting; | ||
117 | |||
118 | num_waiting = (cond->waiting - cond->signals); | ||
119 | cond->signals = cond->waiting; | ||
120 | for ( i=0; i<num_waiting; ++i ) { | ||
121 | SDL_SemPost(cond->wait_sem); | ||
122 | } | ||
123 | /* Now all released threads are blocked here, waiting for us. | ||
124 | Collect them all (and win fabulous prizes!) :-) | ||
125 | */ | ||
126 | SDL_UnlockMutex(cond->lock); | ||
127 | for ( i=0; i<num_waiting; ++i ) { | ||
128 | SDL_SemWait(cond->wait_done); | ||
129 | } | ||
130 | } else { | ||
131 | SDL_UnlockMutex(cond->lock); | ||
132 | } | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | /* Wait on the condition variable for at most 'ms' milliseconds. | ||
138 | The mutex must be locked before entering this function! | ||
139 | The mutex is unlocked during the wait, and locked again after the wait. | ||
140 | |||
141 | Typical use: | ||
142 | |||
143 | Thread A: | ||
144 | SDL_LockMutex(lock); | ||
145 | while ( ! condition ) { | ||
146 | SDL_CondWait(cond); | ||
147 | } | ||
148 | SDL_UnlockMutex(lock); | ||
149 | |||
150 | Thread B: | ||
151 | SDL_LockMutex(lock); | ||
152 | ... | ||
153 | condition = true; | ||
154 | ... | ||
155 | SDL_UnlockMutex(lock); | ||
156 | */ | ||
157 | DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) | ||
158 | { | ||
159 | int retval; | ||
160 | |||
161 | if ( ! cond ) { | ||
162 | SDL_SetError("Passed a NULL condition variable"); | ||
163 | return -1; | ||
164 | } | ||
165 | |||
166 | /* Obtain the protection mutex, and increment the number of waiters. | ||
167 | This allows the signal mechanism to only perform a signal if there | ||
168 | are waiting threads. | ||
169 | */ | ||
170 | SDL_LockMutex(cond->lock); | ||
171 | ++cond->waiting; | ||
172 | SDL_UnlockMutex(cond->lock); | ||
173 | |||
174 | /* Unlock the mutex, as is required by condition variable semantics */ | ||
175 | SDL_UnlockMutex(mutex); | ||
176 | |||
177 | /* Wait for a signal */ | ||
178 | if ( ms == SDL_MUTEX_MAXWAIT ) { | ||
179 | retval = SDL_SemWait(cond->wait_sem); | ||
180 | } else { | ||
181 | retval = SDL_SemWaitTimeout(cond->wait_sem, ms); | ||
182 | } | ||
183 | |||
184 | /* Let the signaler know we have completed the wait, otherwise | ||
185 | the signaler can race ahead and get the condition semaphore | ||
186 | if we are stopped between the mutex unlock and semaphore wait, | ||
187 | giving a deadlock. See the following URL for details: | ||
188 | http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html | ||
189 | */ | ||
190 | SDL_LockMutex(cond->lock); | ||
191 | if ( cond->signals > 0 ) { | ||
192 | /* If we timed out, we need to eat a condition signal */ | ||
193 | if ( retval > 0 ) { | ||
194 | SDL_SemWait(cond->wait_sem); | ||
195 | } | ||
196 | /* We always notify the signal thread that we are done */ | ||
197 | SDL_SemPost(cond->wait_done); | ||
198 | |||
199 | /* Signal handshake complete */ | ||
200 | --cond->signals; | ||
201 | } | ||
202 | --cond->waiting; | ||
203 | SDL_UnlockMutex(cond->lock); | ||
204 | |||
205 | /* Lock the mutex, as is required by condition variable semantics */ | ||
206 | SDL_LockMutex(mutex); | ||
207 | |||
208 | return retval; | ||
209 | } | ||
210 | |||
211 | /* Wait on the condition variable forever */ | ||
212 | DECLSPEC int SDLCALL SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) | ||
213 | { | ||
214 | return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); | ||
215 | } | ||
diff --git a/apps/plugins/sdl/src/thread/os2/SDL_syscond_c.h b/apps/plugins/sdl/src/thread/os2/SDL_syscond_c.h new file mode 100644 index 0000000000..1120b2d80d --- /dev/null +++ b/apps/plugins/sdl/src/thread/os2/SDL_syscond_c.h | |||
@@ -0,0 +1,23 @@ | |||
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 | |||
diff --git a/apps/plugins/sdl/src/thread/os2/SDL_sysmutex.c b/apps/plugins/sdl/src/thread/os2/SDL_sysmutex.c new file mode 100644 index 0000000000..1e21897656 --- /dev/null +++ b/apps/plugins/sdl/src/thread/os2/SDL_sysmutex.c | |||
@@ -0,0 +1,108 @@ | |||
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 | /* Mutex functions using the OS/2 API */ | ||
25 | |||
26 | #define INCL_DOSERRORS | ||
27 | #define INCL_DOSSEMAPHORES | ||
28 | #include <os2.h> | ||
29 | |||
30 | #include "SDL_mutex.h" | ||
31 | |||
32 | |||
33 | struct SDL_mutex { | ||
34 | HMTX hmtxID; | ||
35 | }; | ||
36 | |||
37 | /* Create a mutex */ | ||
38 | DECLSPEC SDL_mutex * SDLCALL SDL_CreateMutex(void) | ||
39 | { | ||
40 | SDL_mutex *mutex; | ||
41 | APIRET ulrc; | ||
42 | |||
43 | /* Allocate mutex memory */ | ||
44 | mutex = (SDL_mutex *)SDL_malloc(sizeof(*mutex)); | ||
45 | if (mutex) | ||
46 | { | ||
47 | /* Create the mutex, with initial value signaled */ | ||
48 | ulrc = DosCreateMutexSem(NULL, // Create unnamed semaphore | ||
49 | &(mutex->hmtxID), // Pointer to handle | ||
50 | 0L, // Flags: create it private (not shared) | ||
51 | FALSE); // Initial value: unowned | ||
52 | if (ulrc!=NO_ERROR) | ||
53 | { | ||
54 | SDL_SetError("Couldn't create mutex"); | ||
55 | SDL_free(mutex); | ||
56 | mutex = NULL; | ||
57 | } | ||
58 | } else { | ||
59 | SDL_OutOfMemory(); | ||
60 | } | ||
61 | return(mutex); | ||
62 | } | ||
63 | |||
64 | /* Free the mutex */ | ||
65 | DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex *mutex) | ||
66 | { | ||
67 | if ( mutex ) | ||
68 | { | ||
69 | if ( mutex->hmtxID ) | ||
70 | { | ||
71 | DosCloseMutexSem(mutex->hmtxID); | ||
72 | mutex->hmtxID = 0; | ||
73 | } | ||
74 | SDL_free(mutex); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | /* Lock the mutex */ | ||
79 | DECLSPEC int SDLCALL SDL_mutexP(SDL_mutex *mutex) | ||
80 | { | ||
81 | if ( mutex == NULL ) | ||
82 | { | ||
83 | SDL_SetError("Passed a NULL mutex"); | ||
84 | return -1; | ||
85 | } | ||
86 | if ( DosRequestMutexSem(mutex->hmtxID, SEM_INDEFINITE_WAIT) != NO_ERROR ) | ||
87 | { | ||
88 | SDL_SetError("Couldn't wait on mutex"); | ||
89 | return -1; | ||
90 | } | ||
91 | return(0); | ||
92 | } | ||
93 | |||
94 | /* Unlock the mutex */ | ||
95 | DECLSPEC int SDLCALL SDL_mutexV(SDL_mutex *mutex) | ||
96 | { | ||
97 | if ( mutex == NULL ) | ||
98 | { | ||
99 | SDL_SetError("Passed a NULL mutex"); | ||
100 | return -1; | ||
101 | } | ||
102 | if ( DosReleaseMutexSem(mutex->hmtxID) != NO_ERROR ) | ||
103 | { | ||
104 | SDL_SetError("Couldn't release mutex"); | ||
105 | return -1; | ||
106 | } | ||
107 | return(0); | ||
108 | } | ||
diff --git a/apps/plugins/sdl/src/thread/os2/SDL_syssem.c b/apps/plugins/sdl/src/thread/os2/SDL_syssem.c new file mode 100644 index 0000000000..d6dfba67bb --- /dev/null +++ b/apps/plugins/sdl/src/thread/os2/SDL_syssem.c | |||
@@ -0,0 +1,192 @@ | |||
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 | |||
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 | } | ||
diff --git a/apps/plugins/sdl/src/thread/os2/SDL_systhread.c b/apps/plugins/sdl/src/thread/os2/SDL_systhread.c new file mode 100644 index 0000000000..33f815a5fb --- /dev/null +++ b/apps/plugins/sdl/src/thread/os2/SDL_systhread.c | |||
@@ -0,0 +1,108 @@ | |||
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 | /* OS/2 thread management routines for SDL */ | ||
25 | |||
26 | #include <process.h> | ||
27 | #define INCL_DOSERRORS | ||
28 | #define INCL_DOSPROCESS | ||
29 | #include <os2.h> | ||
30 | |||
31 | #include "SDL_thread.h" | ||
32 | #include "../SDL_systhread.h" | ||
33 | #include "../SDL_thread_c.h" | ||
34 | |||
35 | typedef struct ThreadStartParms | ||
36 | { | ||
37 | void *args; | ||
38 | pfnSDL_CurrentEndThread pfnCurrentEndThread; | ||
39 | } tThreadStartParms, *pThreadStartParms; | ||
40 | |||
41 | static void threadfunc(void *pparm) | ||
42 | { | ||
43 | pThreadStartParms pThreadParms = pparm; | ||
44 | pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL; | ||
45 | |||
46 | // Call the thread function! | ||
47 | SDL_RunThread(pThreadParms->args); | ||
48 | |||
49 | // Get the current endthread we have to use! | ||
50 | if (pThreadParms) | ||
51 | { | ||
52 | pfnCurrentEndThread = pThreadParms->pfnCurrentEndThread; | ||
53 | SDL_free(pThreadParms); | ||
54 | } | ||
55 | // Call endthread! | ||
56 | if (pfnCurrentEndThread) | ||
57 | (*pfnCurrentEndThread)(); | ||
58 | } | ||
59 | |||
60 | int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread) | ||
61 | { | ||
62 | pThreadStartParms pThreadParms = SDL_malloc(sizeof(tThreadStartParms)); | ||
63 | if (!pThreadParms) | ||
64 | { | ||
65 | SDL_SetError("Not enough memory to create thread"); | ||
66 | return(-1); | ||
67 | } | ||
68 | |||
69 | // Save the function which we will have to call to clear the RTL of calling app! | ||
70 | pThreadParms->pfnCurrentEndThread = pfnEndThread; | ||
71 | // Also save the real parameters we have to pass to thread function | ||
72 | pThreadParms->args = args; | ||
73 | // Start the thread using the runtime library of calling app! | ||
74 | thread->threadid = thread->handle = (*pfnBeginThread)(threadfunc, NULL, 512*1024, pThreadParms); | ||
75 | if ((int)thread->threadid <= 0) | ||
76 | { | ||
77 | SDL_SetError("Not enough resources to create thread"); | ||
78 | return(-1); | ||
79 | } | ||
80 | return(0); | ||
81 | } | ||
82 | |||
83 | void SDL_SYS_SetupThread(void) | ||
84 | { | ||
85 | return; | ||
86 | } | ||
87 | |||
88 | DECLSPEC Uint32 SDLCALL SDL_ThreadID(void) | ||
89 | { | ||
90 | PTIB tib; | ||
91 | DosGetInfoBlocks(&tib, NULL); | ||
92 | return((Uint32) (tib->tib_ptib2->tib2_ultid)); | ||
93 | } | ||
94 | |||
95 | void SDL_SYS_WaitThread(SDL_Thread *thread) | ||
96 | { | ||
97 | TID tid = thread->handle; | ||
98 | DosWaitThread(&tid, DCWW_WAIT); | ||
99 | } | ||
100 | |||
101 | /* WARNING: This function is really a last resort. | ||
102 | * Threads should be signaled and then exit by themselves. | ||
103 | * TerminateThread() doesn't perform stack and DLL cleanup. | ||
104 | */ | ||
105 | void SDL_SYS_KillThread(SDL_Thread *thread) | ||
106 | { | ||
107 | DosKillThread(thread->handle); | ||
108 | } | ||
diff --git a/apps/plugins/sdl/src/thread/os2/SDL_systhread_c.h b/apps/plugins/sdl/src/thread/os2/SDL_systhread_c.h new file mode 100644 index 0000000000..3b94dfed53 --- /dev/null +++ b/apps/plugins/sdl/src/thread/os2/SDL_systhread_c.h | |||
@@ -0,0 +1,28 @@ | |||
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 Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 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 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | #define INCL_DOSPROCESS | ||
25 | #include <os2.h> | ||
26 | |||
27 | typedef TID SYS_ThreadHandle; | ||
28 | |||
diff --git a/apps/plugins/sdl/src/thread/pth/SDL_syscond.c b/apps/plugins/sdl/src/thread/pth/SDL_syscond.c new file mode 100644 index 0000000000..ede74aaeae --- /dev/null +++ b/apps/plugins/sdl/src/thread/pth/SDL_syscond.c | |||
@@ -0,0 +1,164 @@ | |||
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 | /* | ||
25 | * GNU pth conditions variables | ||
26 | * | ||
27 | * Patrice Mandin | ||
28 | */ | ||
29 | |||
30 | #include <pth.h> | ||
31 | |||
32 | #include "SDL_thread.h" | ||
33 | #include "SDL_sysmutex_c.h" | ||
34 | |||
35 | struct SDL_cond | ||
36 | { | ||
37 | pth_cond_t condpth_p; | ||
38 | }; | ||
39 | |||
40 | /* Create a condition variable */ | ||
41 | SDL_cond * SDL_CreateCond(void) | ||
42 | { | ||
43 | SDL_cond *cond; | ||
44 | |||
45 | cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); | ||
46 | if ( cond ) { | ||
47 | if ( pth_cond_init(&(cond->condpth_p)) < 0 ) { | ||
48 | SDL_SetError("pthread_cond_init() failed"); | ||
49 | SDL_free(cond); | ||
50 | cond = NULL; | ||
51 | } | ||
52 | } else { | ||
53 | SDL_OutOfMemory(); | ||
54 | } | ||
55 | return(cond); | ||
56 | } | ||
57 | |||
58 | /* Destroy a condition variable */ | ||
59 | void SDL_DestroyCond(SDL_cond *cond) | ||
60 | { | ||
61 | if ( cond ) { | ||
62 | SDL_free(cond); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | /* Restart one of the threads that are waiting on the condition variable */ | ||
67 | int SDL_CondSignal(SDL_cond *cond) | ||
68 | { | ||
69 | int retval; | ||
70 | |||
71 | if ( ! cond ) { | ||
72 | SDL_SetError("Passed a NULL condition variable"); | ||
73 | return -1; | ||
74 | } | ||
75 | |||
76 | retval = 0; | ||
77 | if ( pth_cond_notify(&(cond->condpth_p), FALSE) != 0 ) { | ||
78 | SDL_SetError("pth_cond_notify() failed"); | ||
79 | retval = -1; | ||
80 | } | ||
81 | return retval; | ||
82 | } | ||
83 | |||
84 | /* Restart all threads that are waiting on the condition variable */ | ||
85 | int SDL_CondBroadcast(SDL_cond *cond) | ||
86 | { | ||
87 | int retval; | ||
88 | |||
89 | if ( ! cond ) { | ||
90 | SDL_SetError("Passed a NULL condition variable"); | ||
91 | return -1; | ||
92 | } | ||
93 | |||
94 | retval = 0; | ||
95 | if ( pth_cond_notify(&(cond->condpth_p), TRUE) != 0 ) { | ||
96 | SDL_SetError("pth_cond_notify() failed"); | ||
97 | retval = -1; | ||
98 | } | ||
99 | return retval; | ||
100 | } | ||
101 | |||
102 | /* Wait on the condition variable for at most 'ms' milliseconds. | ||
103 | The mutex must be locked before entering this function! | ||
104 | The mutex is unlocked during the wait, and locked again after the wait. | ||
105 | |||
106 | Typical use: | ||
107 | |||
108 | Thread A: | ||
109 | SDL_LockMutex(lock); | ||
110 | while ( ! condition ) { | ||
111 | SDL_CondWait(cond); | ||
112 | } | ||
113 | SDL_UnlockMutex(lock); | ||
114 | |||
115 | Thread B: | ||
116 | SDL_LockMutex(lock); | ||
117 | ... | ||
118 | condition = true; | ||
119 | ... | ||
120 | SDL_UnlockMutex(lock); | ||
121 | */ | ||
122 | int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) | ||
123 | { | ||
124 | int retval; | ||
125 | pth_event_t ev; | ||
126 | int sec; | ||
127 | |||
128 | if ( ! cond ) { | ||
129 | SDL_SetError("Passed a NULL condition variable"); | ||
130 | return -1; | ||
131 | } | ||
132 | |||
133 | retval = 0; | ||
134 | |||
135 | sec = ms/1000; | ||
136 | ev = pth_event(PTH_EVENT_TIME, pth_timeout(sec,(ms-sec*1000)*1000)); | ||
137 | |||
138 | if ( pth_cond_await(&(cond->condpth_p), &(mutex->mutexpth_p), ev) != 0 ) { | ||
139 | SDL_SetError("pth_cond_await() failed"); | ||
140 | retval = -1; | ||
141 | } | ||
142 | |||
143 | pth_event_free(ev, PTH_FREE_ALL); | ||
144 | |||
145 | return retval; | ||
146 | } | ||
147 | |||
148 | /* Wait on the condition variable forever */ | ||
149 | int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) | ||
150 | { | ||
151 | int retval; | ||
152 | |||
153 | if ( ! cond ) { | ||
154 | SDL_SetError("Passed a NULL condition variable"); | ||
155 | return -1; | ||
156 | } | ||
157 | |||
158 | retval = 0; | ||
159 | if ( pth_cond_await(&(cond->condpth_p), &(mutex->mutexpth_p), NULL) != 0 ) { | ||
160 | SDL_SetError("pth_cond_await() failed"); | ||
161 | retval = -1; | ||
162 | } | ||
163 | return retval; | ||
164 | } | ||
diff --git a/apps/plugins/sdl/src/thread/pth/SDL_sysmutex.c b/apps/plugins/sdl/src/thread/pth/SDL_sysmutex.c new file mode 100644 index 0000000000..ca83b92c24 --- /dev/null +++ b/apps/plugins/sdl/src/thread/pth/SDL_sysmutex.c | |||
@@ -0,0 +1,87 @@ | |||
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 | /* | ||
25 | * GNU pth mutexes | ||
26 | * | ||
27 | * Patrice Mandin | ||
28 | */ | ||
29 | |||
30 | #include <pth.h> | ||
31 | |||
32 | #include "SDL_mutex.h" | ||
33 | #include "SDL_sysmutex_c.h" | ||
34 | |||
35 | /* Create a mutex */ | ||
36 | SDL_mutex *SDL_CreateMutex(void) | ||
37 | { | ||
38 | SDL_mutex *mutex; | ||
39 | |||
40 | /* Allocate mutex memory */ | ||
41 | mutex = (SDL_mutex *)SDL_malloc(sizeof(*mutex)); | ||
42 | if ( mutex ) { | ||
43 | /* Create the mutex, with initial value signaled */ | ||
44 | if (!pth_mutex_init(&(mutex->mutexpth_p))) { | ||
45 | SDL_SetError("Couldn't create mutex"); | ||
46 | SDL_free(mutex); | ||
47 | mutex = NULL; | ||
48 | } | ||
49 | } else { | ||
50 | SDL_OutOfMemory(); | ||
51 | } | ||
52 | return(mutex); | ||
53 | } | ||
54 | |||
55 | /* Free the mutex */ | ||
56 | void SDL_DestroyMutex(SDL_mutex *mutex) | ||
57 | { | ||
58 | if ( mutex ) { | ||
59 | SDL_free(mutex); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | /* Lock the mutex */ | ||
64 | int SDL_mutexP(SDL_mutex *mutex) | ||
65 | { | ||
66 | if ( mutex == NULL ) { | ||
67 | SDL_SetError("Passed a NULL mutex"); | ||
68 | return -1; | ||
69 | } | ||
70 | |||
71 | pth_mutex_acquire(&(mutex->mutexpth_p), FALSE, NULL); | ||
72 | |||
73 | return(0); | ||
74 | } | ||
75 | |||
76 | /* Unlock the mutex */ | ||
77 | int SDL_mutexV(SDL_mutex *mutex) | ||
78 | { | ||
79 | if ( mutex == NULL ) { | ||
80 | SDL_SetError("Passed a NULL mutex"); | ||
81 | return -1; | ||
82 | } | ||
83 | |||
84 | pth_mutex_release(&(mutex->mutexpth_p)); | ||
85 | |||
86 | return(0); | ||
87 | } | ||
diff --git a/apps/plugins/sdl/src/thread/pth/SDL_sysmutex_c.h b/apps/plugins/sdl/src/thread/pth/SDL_sysmutex_c.h new file mode 100644 index 0000000000..d29060e9ff --- /dev/null +++ b/apps/plugins/sdl/src/thread/pth/SDL_sysmutex_c.h | |||
@@ -0,0 +1,31 @@ | |||
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 | #ifndef _SDL_SYSMUTEX_C_H_ | ||
25 | #define _SDL_SYSMUTEX_C_H_ | ||
26 | |||
27 | struct SDL_mutex { | ||
28 | pth_mutex_t mutexpth_p; | ||
29 | }; | ||
30 | |||
31 | #endif /* _SDL_SYSMUTEX_C_H_ */ | ||
diff --git a/apps/plugins/sdl/src/thread/pth/SDL_systhread.c b/apps/plugins/sdl/src/thread/pth/SDL_systhread.c new file mode 100644 index 0000000000..bfccaf340f --- /dev/null +++ b/apps/plugins/sdl/src/thread/pth/SDL_systhread.c | |||
@@ -0,0 +1,103 @@ | |||
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 | /* | ||
25 | * GNU pth threads | ||
26 | * | ||
27 | * Patrice Mandin | ||
28 | */ | ||
29 | |||
30 | #include <pth.h> | ||
31 | #include <signal.h> | ||
32 | |||
33 | #include "SDL_thread.h" | ||
34 | #include "../SDL_thread_c.h" | ||
35 | #include "../SDL_systhread.h" | ||
36 | |||
37 | /* List of signals to mask in the subthreads */ | ||
38 | static int sig_list[] = { | ||
39 | SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH, | ||
40 | SIGVTALRM, SIGPROF, 0 | ||
41 | }; | ||
42 | |||
43 | static void *RunThread(void *data) | ||
44 | { | ||
45 | SDL_RunThread(data); | ||
46 | pth_exit((void*)0); | ||
47 | return((void *)0); /* Prevent compiler warning */ | ||
48 | } | ||
49 | |||
50 | int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) | ||
51 | { | ||
52 | pth_attr_t type; | ||
53 | |||
54 | /* Create a new attribute */ | ||
55 | type = pth_attr_new(); | ||
56 | if ( type == NULL ) { | ||
57 | SDL_SetError("Couldn't initialize pth attributes"); | ||
58 | return(-1); | ||
59 | } | ||
60 | pth_attr_set(type, PTH_ATTR_JOINABLE, TRUE); | ||
61 | |||
62 | /* Create the thread and go! */ | ||
63 | thread->handle = pth_spawn(type, RunThread, args); | ||
64 | if ( thread->handle == NULL ) { | ||
65 | SDL_SetError("Not enough resources to create thread"); | ||
66 | return(-1); | ||
67 | } | ||
68 | return(0); | ||
69 | } | ||
70 | |||
71 | void SDL_SYS_SetupThread(void) | ||
72 | { | ||
73 | int i; | ||
74 | sigset_t mask; | ||
75 | int oldstate; | ||
76 | |||
77 | /* Mask asynchronous signals for this thread */ | ||
78 | sigemptyset(&mask); | ||
79 | for ( i=0; sig_list[i]; ++i ) { | ||
80 | sigaddset(&mask, sig_list[i]); | ||
81 | } | ||
82 | pth_sigmask(SIG_BLOCK, &mask, 0); | ||
83 | |||
84 | /* Allow ourselves to be asynchronously cancelled */ | ||
85 | pth_cancel_state(PTH_CANCEL_ASYNCHRONOUS, &oldstate); | ||
86 | } | ||
87 | |||
88 | /* WARNING: This may not work for systems with 64-bit pid_t */ | ||
89 | Uint32 SDL_ThreadID(void) | ||
90 | { | ||
91 | return((Uint32)pth_self()); | ||
92 | } | ||
93 | |||
94 | void SDL_SYS_WaitThread(SDL_Thread *thread) | ||
95 | { | ||
96 | pth_join(thread->handle, NULL); | ||
97 | } | ||
98 | |||
99 | void SDL_SYS_KillThread(SDL_Thread *thread) | ||
100 | { | ||
101 | pth_cancel(thread->handle); | ||
102 | pth_join(thread->handle, NULL); | ||
103 | } | ||
diff --git a/apps/plugins/sdl/src/thread/pth/SDL_systhread_c.h b/apps/plugins/sdl/src/thread/pth/SDL_systhread_c.h new file mode 100644 index 0000000000..50bb26df54 --- /dev/null +++ b/apps/plugins/sdl/src/thread/pth/SDL_systhread_c.h | |||
@@ -0,0 +1,31 @@ | |||
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 Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 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 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | #ifndef _SDL_SYSTHREAD_C_H_ | ||
25 | #define _SDL_SYSTHREAD_C_H_ | ||
26 | |||
27 | #include <pth.h> | ||
28 | |||
29 | typedef pth_t SYS_ThreadHandle; | ||
30 | |||
31 | #endif /* _SDL_SYSTHREAD_C_H_ */ | ||
diff --git a/apps/plugins/sdl/src/thread/pthread/SDL_syscond.c b/apps/plugins/sdl/src/thread/pthread/SDL_syscond.c new file mode 100644 index 0000000000..15bce96614 --- /dev/null +++ b/apps/plugins/sdl/src/thread/pthread/SDL_syscond.c | |||
@@ -0,0 +1,155 @@ | |||
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 | #include <sys/time.h> | ||
25 | #include <unistd.h> | ||
26 | #include <errno.h> | ||
27 | #include <pthread.h> | ||
28 | |||
29 | #include "SDL_thread.h" | ||
30 | #include "SDL_sysmutex_c.h" | ||
31 | |||
32 | struct SDL_cond | ||
33 | { | ||
34 | pthread_cond_t cond; | ||
35 | }; | ||
36 | |||
37 | /* Create a condition variable */ | ||
38 | SDL_cond * SDL_CreateCond(void) | ||
39 | { | ||
40 | SDL_cond *cond; | ||
41 | |||
42 | cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); | ||
43 | if ( cond ) { | ||
44 | if ( pthread_cond_init(&cond->cond, NULL) < 0 ) { | ||
45 | SDL_SetError("pthread_cond_init() failed"); | ||
46 | SDL_free(cond); | ||
47 | cond = NULL; | ||
48 | } | ||
49 | } | ||
50 | return(cond); | ||
51 | } | ||
52 | |||
53 | /* Destroy a condition variable */ | ||
54 | void SDL_DestroyCond(SDL_cond *cond) | ||
55 | { | ||
56 | if ( cond ) { | ||
57 | pthread_cond_destroy(&cond->cond); | ||
58 | SDL_free(cond); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | /* Restart one of the threads that are waiting on the condition variable */ | ||
63 | int SDL_CondSignal(SDL_cond *cond) | ||
64 | { | ||
65 | int retval; | ||
66 | |||
67 | if ( ! cond ) { | ||
68 | SDL_SetError("Passed a NULL condition variable"); | ||
69 | return -1; | ||
70 | } | ||
71 | |||
72 | retval = 0; | ||
73 | if ( pthread_cond_signal(&cond->cond) != 0 ) { | ||
74 | SDL_SetError("pthread_cond_signal() failed"); | ||
75 | retval = -1; | ||
76 | } | ||
77 | return retval; | ||
78 | } | ||
79 | |||
80 | /* Restart all threads that are waiting on the condition variable */ | ||
81 | int SDL_CondBroadcast(SDL_cond *cond) | ||
82 | { | ||
83 | int retval; | ||
84 | |||
85 | if ( ! cond ) { | ||
86 | SDL_SetError("Passed a NULL condition variable"); | ||
87 | return -1; | ||
88 | } | ||
89 | |||
90 | retval = 0; | ||
91 | if ( pthread_cond_broadcast(&cond->cond) != 0 ) { | ||
92 | SDL_SetError("pthread_cond_broadcast() failed"); | ||
93 | retval = -1; | ||
94 | } | ||
95 | return retval; | ||
96 | } | ||
97 | |||
98 | int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) | ||
99 | { | ||
100 | int retval; | ||
101 | struct timeval delta; | ||
102 | struct timespec abstime; | ||
103 | |||
104 | if ( ! cond ) { | ||
105 | SDL_SetError("Passed a NULL condition variable"); | ||
106 | return -1; | ||
107 | } | ||
108 | |||
109 | gettimeofday(&delta, NULL); | ||
110 | |||
111 | abstime.tv_sec = delta.tv_sec + (ms/1000); | ||
112 | abstime.tv_nsec = (delta.tv_usec + (ms%1000) * 1000) * 1000; | ||
113 | if ( abstime.tv_nsec > 1000000000 ) { | ||
114 | abstime.tv_sec += 1; | ||
115 | abstime.tv_nsec -= 1000000000; | ||
116 | } | ||
117 | |||
118 | tryagain: | ||
119 | retval = pthread_cond_timedwait(&cond->cond, &mutex->id, &abstime); | ||
120 | switch (retval) { | ||
121 | case EINTR: | ||
122 | goto tryagain; | ||
123 | break; | ||
124 | case ETIMEDOUT: | ||
125 | retval = SDL_MUTEX_TIMEDOUT; | ||
126 | break; | ||
127 | case 0: | ||
128 | break; | ||
129 | default: | ||
130 | SDL_SetError("pthread_cond_timedwait() failed"); | ||
131 | retval = -1; | ||
132 | break; | ||
133 | } | ||
134 | return retval; | ||
135 | } | ||
136 | |||
137 | /* Wait on the condition variable, unlocking the provided mutex. | ||
138 | The mutex must be locked before entering this function! | ||
139 | */ | ||
140 | int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) | ||
141 | { | ||
142 | int retval; | ||
143 | |||
144 | if ( ! cond ) { | ||
145 | SDL_SetError("Passed a NULL condition variable"); | ||
146 | return -1; | ||
147 | } | ||
148 | |||
149 | retval = 0; | ||
150 | if ( pthread_cond_wait(&cond->cond, &mutex->id) != 0 ) { | ||
151 | SDL_SetError("pthread_cond_wait() failed"); | ||
152 | retval = -1; | ||
153 | } | ||
154 | return retval; | ||
155 | } | ||
diff --git a/apps/plugins/sdl/src/thread/pthread/SDL_sysmutex.c b/apps/plugins/sdl/src/thread/pthread/SDL_sysmutex.c new file mode 100644 index 0000000000..c3b8ce2c37 --- /dev/null +++ b/apps/plugins/sdl/src/thread/pthread/SDL_sysmutex.c | |||
@@ -0,0 +1,153 @@ | |||
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 | #include <pthread.h> | ||
25 | |||
26 | #include "SDL_thread.h" | ||
27 | |||
28 | #if !SDL_THREAD_PTHREAD_RECURSIVE_MUTEX && \ | ||
29 | !SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP | ||
30 | #define FAKE_RECURSIVE_MUTEX | ||
31 | #endif | ||
32 | |||
33 | struct SDL_mutex { | ||
34 | pthread_mutex_t id; | ||
35 | #if FAKE_RECURSIVE_MUTEX | ||
36 | int recursive; | ||
37 | pthread_t owner; | ||
38 | #endif | ||
39 | }; | ||
40 | |||
41 | SDL_mutex *SDL_CreateMutex (void) | ||
42 | { | ||
43 | SDL_mutex *mutex; | ||
44 | pthread_mutexattr_t attr; | ||
45 | |||
46 | /* Allocate the structure */ | ||
47 | mutex = (SDL_mutex *)SDL_calloc(1, sizeof(*mutex)); | ||
48 | if ( mutex ) { | ||
49 | pthread_mutexattr_init(&attr); | ||
50 | #if SDL_THREAD_PTHREAD_RECURSIVE_MUTEX | ||
51 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); | ||
52 | #elif SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP | ||
53 | pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP); | ||
54 | #else | ||
55 | /* No extra attributes necessary */ | ||
56 | #endif | ||
57 | if ( pthread_mutex_init(&mutex->id, &attr) != 0 ) { | ||
58 | SDL_SetError("pthread_mutex_init() failed"); | ||
59 | SDL_free(mutex); | ||
60 | mutex = NULL; | ||
61 | } | ||
62 | } else { | ||
63 | SDL_OutOfMemory(); | ||
64 | } | ||
65 | return(mutex); | ||
66 | } | ||
67 | |||
68 | void SDL_DestroyMutex(SDL_mutex *mutex) | ||
69 | { | ||
70 | if ( mutex ) { | ||
71 | pthread_mutex_destroy(&mutex->id); | ||
72 | SDL_free(mutex); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | /* Lock the mutex */ | ||
77 | int SDL_mutexP(SDL_mutex *mutex) | ||
78 | { | ||
79 | int retval; | ||
80 | #if FAKE_RECURSIVE_MUTEX | ||
81 | pthread_t this_thread; | ||
82 | #endif | ||
83 | |||
84 | if ( mutex == NULL ) { | ||
85 | SDL_SetError("Passed a NULL mutex"); | ||
86 | return -1; | ||
87 | } | ||
88 | |||
89 | retval = 0; | ||
90 | #if FAKE_RECURSIVE_MUTEX | ||
91 | this_thread = pthread_self(); | ||
92 | if ( mutex->owner == this_thread ) { | ||
93 | ++mutex->recursive; | ||
94 | } else { | ||
95 | /* The order of operations is important. | ||
96 | We set the locking thread id after we obtain the lock | ||
97 | so unlocks from other threads will fail. | ||
98 | */ | ||
99 | if ( pthread_mutex_lock(&mutex->id) == 0 ) { | ||
100 | mutex->owner = this_thread; | ||
101 | mutex->recursive = 0; | ||
102 | } else { | ||
103 | SDL_SetError("pthread_mutex_lock() failed"); | ||
104 | retval = -1; | ||
105 | } | ||
106 | } | ||
107 | #else | ||
108 | if ( pthread_mutex_lock(&mutex->id) < 0 ) { | ||
109 | SDL_SetError("pthread_mutex_lock() failed"); | ||
110 | retval = -1; | ||
111 | } | ||
112 | #endif | ||
113 | return retval; | ||
114 | } | ||
115 | |||
116 | int SDL_mutexV(SDL_mutex *mutex) | ||
117 | { | ||
118 | int retval; | ||
119 | |||
120 | if ( mutex == NULL ) { | ||
121 | SDL_SetError("Passed a NULL mutex"); | ||
122 | return -1; | ||
123 | } | ||
124 | |||
125 | retval = 0; | ||
126 | #if FAKE_RECURSIVE_MUTEX | ||
127 | /* We can only unlock the mutex if we own it */ | ||
128 | if ( pthread_self() == mutex->owner ) { | ||
129 | if ( mutex->recursive ) { | ||
130 | --mutex->recursive; | ||
131 | } else { | ||
132 | /* The order of operations is important. | ||
133 | First reset the owner so another thread doesn't lock | ||
134 | the mutex and set the ownership before we reset it, | ||
135 | then release the lock semaphore. | ||
136 | */ | ||
137 | mutex->owner = 0; | ||
138 | pthread_mutex_unlock(&mutex->id); | ||
139 | } | ||
140 | } else { | ||
141 | SDL_SetError("mutex not owned by this thread"); | ||
142 | retval = -1; | ||
143 | } | ||
144 | |||
145 | #else | ||
146 | if ( pthread_mutex_unlock(&mutex->id) < 0 ) { | ||
147 | SDL_SetError("pthread_mutex_unlock() failed"); | ||
148 | retval = -1; | ||
149 | } | ||
150 | #endif /* FAKE_RECURSIVE_MUTEX */ | ||
151 | |||
152 | return retval; | ||
153 | } | ||
diff --git a/apps/plugins/sdl/src/thread/pthread/SDL_sysmutex_c.h b/apps/plugins/sdl/src/thread/pthread/SDL_sysmutex_c.h new file mode 100644 index 0000000000..5258890156 --- /dev/null +++ b/apps/plugins/sdl/src/thread/pthread/SDL_sysmutex_c.h | |||
@@ -0,0 +1,31 @@ | |||
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 | #ifndef _SDL_mutex_c_h | ||
25 | #define _SDL_mutex_c_h | ||
26 | |||
27 | struct SDL_mutex { | ||
28 | pthread_mutex_t id; | ||
29 | }; | ||
30 | |||
31 | #endif /* _SDL_mutex_c_h */ | ||
diff --git a/apps/plugins/sdl/src/thread/pthread/SDL_syssem.c b/apps/plugins/sdl/src/thread/pthread/SDL_syssem.c new file mode 100644 index 0000000000..a03870fa35 --- /dev/null +++ b/apps/plugins/sdl/src/thread/pthread/SDL_syssem.c | |||
@@ -0,0 +1,190 @@ | |||
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 | #include <pthread.h> | ||
25 | #include <semaphore.h> | ||
26 | #include <errno.h> | ||
27 | #include <sys/time.h> | ||
28 | |||
29 | #include "SDL_thread.h" | ||
30 | #include "SDL_timer.h" | ||
31 | |||
32 | /* Wrapper around POSIX 1003.1b semaphores */ | ||
33 | |||
34 | #ifdef __MACOSX__ | ||
35 | /* Mac OS X doesn't support sem_getvalue() as of version 10.4 */ | ||
36 | #include "../generic/SDL_syssem.c" | ||
37 | #else | ||
38 | |||
39 | struct SDL_semaphore { | ||
40 | sem_t sem; | ||
41 | }; | ||
42 | |||
43 | /* Create a semaphore, initialized with value */ | ||
44 | SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | ||
45 | { | ||
46 | SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem)); | ||
47 | if ( sem ) { | ||
48 | if ( sem_init(&sem->sem, 0, initial_value) < 0 ) { | ||
49 | SDL_SetError("sem_init() failed"); | ||
50 | SDL_free(sem); | ||
51 | sem = NULL; | ||
52 | } | ||
53 | } else { | ||
54 | SDL_OutOfMemory(); | ||
55 | } | ||
56 | return sem; | ||
57 | } | ||
58 | |||
59 | void SDL_DestroySemaphore(SDL_sem *sem) | ||
60 | { | ||
61 | if ( sem ) { | ||
62 | sem_destroy(&sem->sem); | ||
63 | SDL_free(sem); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | int SDL_SemTryWait(SDL_sem *sem) | ||
68 | { | ||
69 | int retval; | ||
70 | |||
71 | if ( ! sem ) { | ||
72 | SDL_SetError("Passed a NULL semaphore"); | ||
73 | return -1; | ||
74 | } | ||
75 | retval = SDL_MUTEX_TIMEDOUT; | ||
76 | if ( sem_trywait(&sem->sem) == 0 ) { | ||
77 | retval = 0; | ||
78 | } | ||
79 | return retval; | ||
80 | } | ||
81 | |||
82 | int SDL_SemWait(SDL_sem *sem) | ||
83 | { | ||
84 | int retval; | ||
85 | |||
86 | if ( ! sem ) { | ||
87 | SDL_SetError("Passed a NULL semaphore"); | ||
88 | return -1; | ||
89 | } | ||
90 | |||
91 | while ( ((retval = sem_wait(&sem->sem)) == -1) && (errno == EINTR) ) {} | ||
92 | if ( retval < 0 ) { | ||
93 | SDL_SetError("sem_wait() failed"); | ||
94 | } | ||
95 | return retval; | ||
96 | } | ||
97 | |||
98 | int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | ||
99 | { | ||
100 | int retval; | ||
101 | #ifdef HAVE_SEM_TIMEDWAIT | ||
102 | struct timeval now; | ||
103 | struct timespec ts_timeout; | ||
104 | #else | ||
105 | Uint32 end; | ||
106 | #endif | ||
107 | |||
108 | if ( ! sem ) { | ||
109 | SDL_SetError("Passed a NULL semaphore"); | ||
110 | return -1; | ||
111 | } | ||
112 | |||
113 | /* Try the easy cases first */ | ||
114 | if ( timeout == 0 ) { | ||
115 | return SDL_SemTryWait(sem); | ||
116 | } | ||
117 | if ( timeout == SDL_MUTEX_MAXWAIT ) { | ||
118 | return SDL_SemWait(sem); | ||
119 | } | ||
120 | |||
121 | #ifdef HAVE_SEM_TIMEDWAIT | ||
122 | /* Setup the timeout. sem_timedwait doesn't wait for | ||
123 | * a lapse of time, but until we reach a certain time. | ||
124 | * This time is now plus the timeout. | ||
125 | */ | ||
126 | gettimeofday(&now, NULL); | ||
127 | |||
128 | /* Add our timeout to current time */ | ||
129 | now.tv_usec += (timeout % 1000) * 1000; | ||
130 | now.tv_sec += timeout / 1000; | ||
131 | |||
132 | /* Wrap the second if needed */ | ||
133 | if ( now.tv_usec >= 1000000 ) { | ||
134 | now.tv_usec -= 1000000; | ||
135 | now.tv_sec ++; | ||
136 | } | ||
137 | |||
138 | /* Convert to timespec */ | ||
139 | ts_timeout.tv_sec = now.tv_sec; | ||
140 | ts_timeout.tv_nsec = now.tv_usec * 1000; | ||
141 | |||
142 | /* Wait. */ | ||
143 | do | ||
144 | retval = sem_timedwait(&sem->sem, &ts_timeout); | ||
145 | while (retval == -1 && errno == EINTR); | ||
146 | |||
147 | if (retval == -1) | ||
148 | SDL_SetError(strerror(errno)); | ||
149 | #else | ||
150 | end = SDL_GetTicks() + timeout; | ||
151 | while ((retval = SDL_SemTryWait(sem)) == SDL_MUTEX_TIMEDOUT) { | ||
152 | if ((SDL_GetTicks() - end) >= 0) { | ||
153 | break; | ||
154 | } | ||
155 | SDL_Delay(0); | ||
156 | } | ||
157 | #endif /* HAVE_SEM_TIMEDWAIT */ | ||
158 | |||
159 | return retval; | ||
160 | } | ||
161 | |||
162 | Uint32 SDL_SemValue(SDL_sem *sem) | ||
163 | { | ||
164 | int ret = 0; | ||
165 | if ( sem ) { | ||
166 | sem_getvalue(&sem->sem, &ret); | ||
167 | if ( ret < 0 ) { | ||
168 | ret = 0; | ||
169 | } | ||
170 | } | ||
171 | return (Uint32)ret; | ||
172 | } | ||
173 | |||
174 | int SDL_SemPost(SDL_sem *sem) | ||
175 | { | ||
176 | int retval; | ||
177 | |||
178 | if ( ! sem ) { | ||
179 | SDL_SetError("Passed a NULL semaphore"); | ||
180 | return -1; | ||
181 | } | ||
182 | |||
183 | retval = sem_post(&sem->sem); | ||
184 | if ( retval < 0 ) { | ||
185 | SDL_SetError("sem_post() failed"); | ||
186 | } | ||
187 | return retval; | ||
188 | } | ||
189 | |||
190 | #endif /* __MACOSX__ */ | ||
diff --git a/apps/plugins/sdl/src/thread/pthread/SDL_systhread.c b/apps/plugins/sdl/src/thread/pthread/SDL_systhread.c new file mode 100644 index 0000000000..40cc3b717d --- /dev/null +++ b/apps/plugins/sdl/src/thread/pthread/SDL_systhread.c | |||
@@ -0,0 +1,120 @@ | |||
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 | #include <pthread.h> | ||
25 | #include <signal.h> | ||
26 | |||
27 | #include "SDL_thread.h" | ||
28 | #include "../SDL_thread_c.h" | ||
29 | #include "../SDL_systhread.h" | ||
30 | |||
31 | /* List of signals to mask in the subthreads */ | ||
32 | static int sig_list[] = { | ||
33 | SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH, | ||
34 | SIGVTALRM, SIGPROF, 0 | ||
35 | }; | ||
36 | |||
37 | #ifdef __RISCOS__ | ||
38 | /* RISC OS needs to know the main thread for | ||
39 | * it's timer and event processing. */ | ||
40 | int riscos_using_threads = 0; | ||
41 | Uint32 riscos_main_thread = 0; /* Thread running events */ | ||
42 | #endif | ||
43 | |||
44 | |||
45 | static void *RunThread(void *data) | ||
46 | { | ||
47 | SDL_RunThread(data); | ||
48 | pthread_exit((void*)0); | ||
49 | return((void *)0); /* Prevent compiler warning */ | ||
50 | } | ||
51 | |||
52 | int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) | ||
53 | { | ||
54 | pthread_attr_t type; | ||
55 | |||
56 | /* Set the thread attributes */ | ||
57 | if ( pthread_attr_init(&type) != 0 ) { | ||
58 | SDL_SetError("Couldn't initialize pthread attributes"); | ||
59 | return(-1); | ||
60 | } | ||
61 | pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE); | ||
62 | |||
63 | /* Create the thread and go! */ | ||
64 | if ( pthread_create(&thread->handle, &type, RunThread, args) != 0 ) { | ||
65 | SDL_SetError("Not enough resources to create thread"); | ||
66 | return(-1); | ||
67 | } | ||
68 | |||
69 | #ifdef __RISCOS__ | ||
70 | if (riscos_using_threads == 0) { | ||
71 | riscos_using_threads = 1; | ||
72 | riscos_main_thread = SDL_ThreadID(); | ||
73 | } | ||
74 | #endif | ||
75 | |||
76 | return(0); | ||
77 | } | ||
78 | |||
79 | void SDL_SYS_SetupThread(void) | ||
80 | { | ||
81 | int i; | ||
82 | sigset_t mask; | ||
83 | |||
84 | /* Mask asynchronous signals for this thread */ | ||
85 | sigemptyset(&mask); | ||
86 | for ( i=0; sig_list[i]; ++i ) { | ||
87 | sigaddset(&mask, sig_list[i]); | ||
88 | } | ||
89 | pthread_sigmask(SIG_BLOCK, &mask, 0); | ||
90 | |||
91 | #ifdef PTHREAD_CANCEL_ASYNCHRONOUS | ||
92 | /* Allow ourselves to be asynchronously cancelled */ | ||
93 | { int oldstate; | ||
94 | pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); | ||
95 | } | ||
96 | #endif | ||
97 | } | ||
98 | |||
99 | /* WARNING: This may not work for systems with 64-bit pid_t */ | ||
100 | Uint32 SDL_ThreadID(void) | ||
101 | { | ||
102 | return((Uint32)((size_t)pthread_self())); | ||
103 | } | ||
104 | |||
105 | void SDL_SYS_WaitThread(SDL_Thread *thread) | ||
106 | { | ||
107 | pthread_join(thread->handle, 0); | ||
108 | } | ||
109 | |||
110 | void SDL_SYS_KillThread(SDL_Thread *thread) | ||
111 | { | ||
112 | #ifdef PTHREAD_CANCEL_ASYNCHRONOUS | ||
113 | pthread_cancel(thread->handle); | ||
114 | #else | ||
115 | #ifdef __FREEBSD__ | ||
116 | #warning For some reason, this doesnt actually kill a thread - FreeBSD 3.2 | ||
117 | #endif | ||
118 | pthread_kill(thread->handle, SIGKILL); | ||
119 | #endif | ||
120 | } | ||
diff --git a/apps/plugins/sdl/src/thread/pthread/SDL_systhread_c.h b/apps/plugins/sdl/src/thread/pthread/SDL_systhread_c.h new file mode 100644 index 0000000000..33ed750ff2 --- /dev/null +++ b/apps/plugins/sdl/src/thread/pthread/SDL_systhread_c.h | |||
@@ -0,0 +1,26 @@ | |||
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 Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 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 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | #include <pthread.h> | ||
25 | |||
26 | typedef pthread_t SYS_ThreadHandle; | ||
diff --git a/apps/plugins/sdl/src/thread/riscos/SDL_syscond.c b/apps/plugins/sdl/src/thread/riscos/SDL_syscond.c new file mode 100644 index 0000000000..ee5566647f --- /dev/null +++ b/apps/plugins/sdl/src/thread/riscos/SDL_syscond.c | |||
@@ -0,0 +1,160 @@ | |||
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 | /* RISC OS implementations uses pthreads based on linux code */ | ||
25 | |||
26 | #if SDL_THREADS_DISABLED | ||
27 | #include "../generic/SDL_syscond.c" | ||
28 | #else | ||
29 | #include <sys/time.h> | ||
30 | #include <unistd.h> | ||
31 | #include <pthread.h> | ||
32 | |||
33 | #include "SDL_thread.h" | ||
34 | #include "SDL_sysmutex_c.h" | ||
35 | |||
36 | struct SDL_cond | ||
37 | { | ||
38 | pthread_cond_t cond; | ||
39 | }; | ||
40 | |||
41 | /* Create a condition variable */ | ||
42 | SDL_cond * SDL_CreateCond(void) | ||
43 | { | ||
44 | SDL_cond *cond; | ||
45 | |||
46 | cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); | ||
47 | if ( cond ) { | ||
48 | if ( pthread_cond_init(&cond->cond, NULL) < 0 ) { | ||
49 | SDL_SetError("pthread_cond_init() failed"); | ||
50 | SDL_free(cond); | ||
51 | cond = NULL; | ||
52 | } | ||
53 | } | ||
54 | return(cond); | ||
55 | } | ||
56 | |||
57 | /* Destroy a condition variable */ | ||
58 | void SDL_DestroyCond(SDL_cond *cond) | ||
59 | { | ||
60 | if ( cond ) { | ||
61 | pthread_cond_destroy(&cond->cond); | ||
62 | SDL_free(cond); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | /* Restart one of the threads that are waiting on the condition variable */ | ||
67 | int SDL_CondSignal(SDL_cond *cond) | ||
68 | { | ||
69 | int retval; | ||
70 | |||
71 | if ( ! cond ) { | ||
72 | SDL_SetError("Passed a NULL condition variable"); | ||
73 | return -1; | ||
74 | } | ||
75 | |||
76 | retval = 0; | ||
77 | if ( pthread_cond_signal(&cond->cond) != 0 ) { | ||
78 | SDL_SetError("pthread_cond_signal() failed"); | ||
79 | retval = -1; | ||
80 | } | ||
81 | return retval; | ||
82 | } | ||
83 | |||
84 | /* Restart all threads that are waiting on the condition variable */ | ||
85 | int SDL_CondBroadcast(SDL_cond *cond) | ||
86 | { | ||
87 | int retval; | ||
88 | |||
89 | if ( ! cond ) { | ||
90 | SDL_SetError("Passed a NULL condition variable"); | ||
91 | return -1; | ||
92 | } | ||
93 | |||
94 | retval = 0; | ||
95 | if ( pthread_cond_broadcast(&cond->cond) != 0 ) { | ||
96 | SDL_SetError("pthread_cond_broadcast() failed"); | ||
97 | retval = -1; | ||
98 | } | ||
99 | return retval; | ||
100 | } | ||
101 | |||
102 | int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) | ||
103 | { | ||
104 | int retval; | ||
105 | struct timeval delta; | ||
106 | struct timespec abstime; | ||
107 | |||
108 | if ( ! cond ) { | ||
109 | SDL_SetError("Passed a NULL condition variable"); | ||
110 | return -1; | ||
111 | } | ||
112 | |||
113 | gettimeofday(&delta, NULL); | ||
114 | |||
115 | abstime.tv_sec = delta.tv_sec + (ms/1000); | ||
116 | abstime.tv_nsec = (delta.tv_usec + (ms%1000) * 1000) * 1000; | ||
117 | if ( abstime.tv_nsec > 1000000000 ) { | ||
118 | abstime.tv_sec += 1; | ||
119 | abstime.tv_nsec -= 1000000000; | ||
120 | } | ||
121 | |||
122 | tryagain: | ||
123 | retval = pthread_cond_timedwait(&cond->cond, &mutex->id, &abstime); | ||
124 | switch (retval) { | ||
125 | case EINTR: | ||
126 | goto tryagain; | ||
127 | break; | ||
128 | case ETIMEDOUT: | ||
129 | retval = SDL_MUTEX_TIMEDOUT; | ||
130 | break; | ||
131 | case 0: | ||
132 | break; | ||
133 | default: | ||
134 | SDL_SetError("pthread_cond_timedwait() failed"); | ||
135 | retval = -1; | ||
136 | break; | ||
137 | } | ||
138 | return retval; | ||
139 | } | ||
140 | |||
141 | /* Wait on the condition variable, unlocking the provided mutex. | ||
142 | The mutex must be locked before entering this function! | ||
143 | */ | ||
144 | int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) | ||
145 | { | ||
146 | int retval; | ||
147 | |||
148 | if ( ! cond ) { | ||
149 | SDL_SetError("Passed a NULL condition variable"); | ||
150 | return -1; | ||
151 | } | ||
152 | |||
153 | retval = 0; | ||
154 | if ( pthread_cond_wait(&cond->cond, &mutex->id) != 0 ) { | ||
155 | SDL_SetError("pthread_cond_wait() failed"); | ||
156 | retval = -1; | ||
157 | } | ||
158 | return retval; | ||
159 | } | ||
160 | #endif | ||
diff --git a/apps/plugins/sdl/src/thread/riscos/SDL_sysmutex.c b/apps/plugins/sdl/src/thread/riscos/SDL_sysmutex.c new file mode 100644 index 0000000000..e9ac139b36 --- /dev/null +++ b/apps/plugins/sdl/src/thread/riscos/SDL_sysmutex.c | |||
@@ -0,0 +1,153 @@ | |||
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 | /* RISC OS implementations uses pthreads based on linux code */ | ||
25 | |||
26 | #include "SDL_thread.h" | ||
27 | |||
28 | #if SDL_THREADS_DISABLED | ||
29 | #include "../generic/SDL_sysmutex.c" | ||
30 | #else | ||
31 | |||
32 | #include <pthread.h> | ||
33 | |||
34 | struct SDL_mutex { | ||
35 | pthread_mutex_t id; | ||
36 | #if SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX | ||
37 | int recursive; | ||
38 | pthread_t owner; | ||
39 | #endif | ||
40 | }; | ||
41 | |||
42 | SDL_mutex *SDL_CreateMutex (void) | ||
43 | { | ||
44 | SDL_mutex *mutex; | ||
45 | pthread_mutexattr_t attr; | ||
46 | |||
47 | /* Allocate the structure */ | ||
48 | mutex = (SDL_mutex *)SDL_calloc(1, sizeof(*mutex)); | ||
49 | if ( mutex ) { | ||
50 | pthread_mutexattr_init(&attr); | ||
51 | #if SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX | ||
52 | /* No extra attributes necessary */ | ||
53 | #else | ||
54 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); | ||
55 | #endif /* SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX */ | ||
56 | if ( pthread_mutex_init(&mutex->id, &attr) != 0 ) { | ||
57 | SDL_SetError("pthread_mutex_init() failed"); | ||
58 | SDL_free(mutex); | ||
59 | mutex = NULL; | ||
60 | } | ||
61 | } else { | ||
62 | SDL_OutOfMemory(); | ||
63 | } | ||
64 | return(mutex); | ||
65 | } | ||
66 | |||
67 | void SDL_DestroyMutex(SDL_mutex *mutex) | ||
68 | { | ||
69 | if ( mutex ) { | ||
70 | pthread_mutex_destroy(&mutex->id); | ||
71 | SDL_free(mutex); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | /* Lock the mutex */ | ||
76 | int SDL_mutexP(SDL_mutex *mutex) | ||
77 | { | ||
78 | int retval; | ||
79 | #if SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX | ||
80 | pthread_t this_thread; | ||
81 | #endif | ||
82 | |||
83 | if ( mutex == NULL ) { | ||
84 | SDL_SetError("Passed a NULL mutex"); | ||
85 | return -1; | ||
86 | } | ||
87 | |||
88 | retval = 0; | ||
89 | #if SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX | ||
90 | this_thread = pthread_self(); | ||
91 | if ( mutex->owner == this_thread ) { | ||
92 | ++mutex->recursive; | ||
93 | } else { | ||
94 | /* The order of operations is important. | ||
95 | We set the locking thread id after we obtain the lock | ||
96 | so unlocks from other threads will fail. | ||
97 | */ | ||
98 | if ( pthread_mutex_lock(&mutex->id) == 0 ) { | ||
99 | mutex->owner = this_thread; | ||
100 | mutex->recursive = 0; | ||
101 | } else { | ||
102 | SDL_SetError("pthread_mutex_lock() failed"); | ||
103 | retval = -1; | ||
104 | } | ||
105 | } | ||
106 | #else | ||
107 | if ( pthread_mutex_lock(&mutex->id) < 0 ) { | ||
108 | SDL_SetError("pthread_mutex_lock() failed"); | ||
109 | retval = -1; | ||
110 | } | ||
111 | #endif | ||
112 | return retval; | ||
113 | } | ||
114 | |||
115 | int SDL_mutexV(SDL_mutex *mutex) | ||
116 | { | ||
117 | int retval; | ||
118 | |||
119 | if ( mutex == NULL ) { | ||
120 | SDL_SetError("Passed a NULL mutex"); | ||
121 | return -1; | ||
122 | } | ||
123 | |||
124 | retval = 0; | ||
125 | #if SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX | ||
126 | /* We can only unlock the mutex if we own it */ | ||
127 | if ( pthread_self() == mutex->owner ) { | ||
128 | if ( mutex->recursive ) { | ||
129 | --mutex->recursive; | ||
130 | } else { | ||
131 | /* The order of operations is important. | ||
132 | First reset the owner so another thread doesn't lock | ||
133 | the mutex and set the ownership before we reset it, | ||
134 | then release the lock semaphore. | ||
135 | */ | ||
136 | mutex->owner = 0; | ||
137 | pthread_mutex_unlock(&mutex->id); | ||
138 | } | ||
139 | } else { | ||
140 | SDL_SetError("mutex not owned by this thread"); | ||
141 | retval = -1; | ||
142 | } | ||
143 | |||
144 | #else | ||
145 | if ( pthread_mutex_unlock(&mutex->id) < 0 ) { | ||
146 | SDL_SetError("pthread_mutex_unlock() failed"); | ||
147 | retval = -1; | ||
148 | } | ||
149 | #endif /* SDL_THREAD_PTHREAD_NO_RECURSIVE_MUTEX */ | ||
150 | |||
151 | return retval; | ||
152 | } | ||
153 | #endif | ||
diff --git a/apps/plugins/sdl/src/thread/riscos/SDL_sysmutex_c.h b/apps/plugins/sdl/src/thread/riscos/SDL_sysmutex_c.h new file mode 100644 index 0000000000..2391c3c108 --- /dev/null +++ b/apps/plugins/sdl/src/thread/riscos/SDL_sysmutex_c.h | |||
@@ -0,0 +1,34 @@ | |||
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 | #ifndef _SDL_mutex_c_h | ||
25 | #define _SDL_mutex_c_h | ||
26 | |||
27 | #if !SDL_THREADS_DISABLED | ||
28 | struct SDL_mutex { | ||
29 | pthread_mutex_t id; | ||
30 | }; | ||
31 | #endif | ||
32 | |||
33 | |||
34 | #endif /* _SDL_mutex_c_h */ | ||
diff --git a/apps/plugins/sdl/src/thread/riscos/SDL_syssem.c b/apps/plugins/sdl/src/thread/riscos/SDL_syssem.c new file mode 100644 index 0000000000..127211bf76 --- /dev/null +++ b/apps/plugins/sdl/src/thread/riscos/SDL_syssem.c | |||
@@ -0,0 +1,203 @@ | |||
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 | |||
23 | #include <errno.h> | ||
24 | |||
25 | #include "SDL_config.h" | ||
26 | |||
27 | /* RISC OS semiphores based on linux code */ | ||
28 | |||
29 | |||
30 | #include "SDL_timer.h" | ||
31 | #include "SDL_thread.h" | ||
32 | #include "SDL_systhread_c.h" | ||
33 | |||
34 | #if !SDL_THREADS_DISABLED | ||
35 | |||
36 | SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | ||
37 | { | ||
38 | SDL_SetError("SDL not configured with thread support"); | ||
39 | return (SDL_sem *)0; | ||
40 | } | ||
41 | |||
42 | void SDL_DestroySemaphore(SDL_sem *sem) | ||
43 | { | ||
44 | return; | ||
45 | } | ||
46 | |||
47 | int SDL_SemTryWait(SDL_sem *sem) | ||
48 | { | ||
49 | SDL_SetError("SDL not configured with thread support"); | ||
50 | return -1; | ||
51 | } | ||
52 | |||
53 | int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | ||
54 | { | ||
55 | SDL_SetError("SDL not configured with thread support"); | ||
56 | return -1; | ||
57 | } | ||
58 | |||
59 | int SDL_SemWait(SDL_sem *sem) | ||
60 | { | ||
61 | SDL_SetError("SDL not configured with thread support"); | ||
62 | return -1; | ||
63 | } | ||
64 | |||
65 | Uint32 SDL_SemValue(SDL_sem *sem) | ||
66 | { | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | int SDL_SemPost(SDL_sem *sem) | ||
71 | { | ||
72 | SDL_SetError("SDL not configured with thread support"); | ||
73 | return -1; | ||
74 | } | ||
75 | |||
76 | #else | ||
77 | |||
78 | |||
79 | #include <unistd.h> /* For getpid() */ | ||
80 | #include <pthread.h> | ||
81 | #include <semaphore.h> | ||
82 | |||
83 | struct SDL_semaphore { | ||
84 | sem_t *sem; | ||
85 | sem_t sem_data; | ||
86 | }; | ||
87 | |||
88 | /* Create a semaphore, initialized with value */ | ||
89 | SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | ||
90 | { | ||
91 | SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem)); | ||
92 | if ( sem ) { | ||
93 | if ( sem_init(&sem->sem_data, 0, initial_value) < 0 ) { | ||
94 | SDL_SetError("sem_init() failed"); | ||
95 | SDL_free(sem); | ||
96 | sem = NULL; | ||
97 | } else { | ||
98 | sem->sem = &sem->sem_data; | ||
99 | } | ||
100 | } else { | ||
101 | SDL_OutOfMemory(); | ||
102 | } | ||
103 | return sem; | ||
104 | } | ||
105 | |||
106 | void SDL_DestroySemaphore(SDL_sem *sem) | ||
107 | { | ||
108 | if ( sem ) { | ||
109 | sem_destroy(sem->sem); | ||
110 | SDL_free(sem); | ||
111 | } | ||
112 | } | ||
113 | |||
114 | int SDL_SemTryWait(SDL_sem *sem) | ||
115 | { | ||
116 | int retval; | ||
117 | |||
118 | if ( ! sem ) { | ||
119 | SDL_SetError("Passed a NULL semaphore"); | ||
120 | return -1; | ||
121 | } | ||
122 | retval = SDL_MUTEX_TIMEDOUT; | ||
123 | if ( sem_trywait(sem->sem) == 0 ) { | ||
124 | retval = 0; | ||
125 | } | ||
126 | return retval; | ||
127 | } | ||
128 | |||
129 | int SDL_SemWait(SDL_sem *sem) | ||
130 | { | ||
131 | int retval; | ||
132 | |||
133 | if ( ! sem ) { | ||
134 | SDL_SetError("Passed a NULL semaphore"); | ||
135 | return -1; | ||
136 | } | ||
137 | |||
138 | while ( ((retval = sem_wait(sem->sem)) == -1) && (errno == EINTR) ) {} | ||
139 | if ( retval < 0 ) { | ||
140 | SDL_SetError("sem_wait() failed"); | ||
141 | } | ||
142 | return retval; | ||
143 | } | ||
144 | |||
145 | int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | ||
146 | { | ||
147 | int retval; | ||
148 | |||
149 | if ( ! sem ) { | ||
150 | SDL_SetError("Passed a NULL semaphore"); | ||
151 | return -1; | ||
152 | } | ||
153 | |||
154 | /* Try the easy cases first */ | ||
155 | if ( timeout == 0 ) { | ||
156 | return SDL_SemTryWait(sem); | ||
157 | } | ||
158 | if ( timeout == SDL_MUTEX_MAXWAIT ) { | ||
159 | return SDL_SemWait(sem); | ||
160 | } | ||
161 | |||
162 | /* Ack! We have to busy wait... */ | ||
163 | timeout += SDL_GetTicks(); | ||
164 | do { | ||
165 | retval = SDL_SemTryWait(sem); | ||
166 | if ( retval == 0 ) { | ||
167 | break; | ||
168 | } | ||
169 | SDL_Delay(1); | ||
170 | } while ( SDL_GetTicks() < timeout ); | ||
171 | |||
172 | return retval; | ||
173 | } | ||
174 | |||
175 | Uint32 SDL_SemValue(SDL_sem *sem) | ||
176 | { | ||
177 | int ret = 0; | ||
178 | if ( sem ) { | ||
179 | sem_getvalue(sem->sem, &ret); | ||
180 | if ( ret < 0 ) { | ||
181 | ret = 0; | ||
182 | } | ||
183 | } | ||
184 | return (Uint32)ret; | ||
185 | } | ||
186 | |||
187 | int SDL_SemPost(SDL_sem *sem) | ||
188 | { | ||
189 | int retval; | ||
190 | |||
191 | if ( ! sem ) { | ||
192 | SDL_SetError("Passed a NULL semaphore"); | ||
193 | return -1; | ||
194 | } | ||
195 | |||
196 | retval = sem_post(sem->sem); | ||
197 | if ( retval < 0 ) { | ||
198 | SDL_SetError("sem_post() failed"); | ||
199 | } | ||
200 | return retval; | ||
201 | } | ||
202 | |||
203 | #endif /* !SDL_THREADS_DISABLED */ | ||
diff --git a/apps/plugins/sdl/src/thread/riscos/SDL_systhread.c b/apps/plugins/sdl/src/thread/riscos/SDL_systhread.c new file mode 100644 index 0000000000..38fc333ae8 --- /dev/null +++ b/apps/plugins/sdl/src/thread/riscos/SDL_systhread.c | |||
@@ -0,0 +1,144 @@ | |||
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 | /* RISC OS version based on pthreads linux source */ | ||
25 | |||
26 | #include "SDL_thread.h" | ||
27 | #include "../SDL_systhread.h" | ||
28 | |||
29 | #if SDL_THREADS_DISABLED | ||
30 | |||
31 | int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) | ||
32 | { | ||
33 | SDL_SetError("Threads have not been compiled into this version of the library"); | ||
34 | return(-1); | ||
35 | } | ||
36 | |||
37 | void SDL_SYS_SetupThread(void) | ||
38 | { | ||
39 | return; | ||
40 | } | ||
41 | |||
42 | Uint32 SDL_ThreadID(void) | ||
43 | { | ||
44 | return(0); | ||
45 | } | ||
46 | |||
47 | void SDL_SYS_WaitThread(SDL_Thread *thread) | ||
48 | { | ||
49 | return; | ||
50 | } | ||
51 | |||
52 | void SDL_SYS_KillThread(SDL_Thread *thread) | ||
53 | { | ||
54 | return; | ||
55 | } | ||
56 | |||
57 | #else | ||
58 | |||
59 | #include <signal.h> | ||
60 | |||
61 | /* List of signals to mask in the subthreads */ | ||
62 | static int sig_list[] = { | ||
63 | SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH, | ||
64 | SIGVTALRM, SIGPROF, 0 | ||
65 | }; | ||
66 | |||
67 | #include <pthread.h> | ||
68 | |||
69 | int riscos_using_threads = 0; | ||
70 | Uint32 riscos_main_thread = 0; /* Thread running events */ | ||
71 | |||
72 | static void *RunThread(void *data) | ||
73 | { | ||
74 | SDL_RunThread(data); | ||
75 | pthread_exit((void*)0); | ||
76 | return((void *)0); /* Prevent compiler warning */ | ||
77 | } | ||
78 | |||
79 | int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) | ||
80 | { | ||
81 | pthread_attr_t type; | ||
82 | |||
83 | /* Set the thread attributes */ | ||
84 | if ( pthread_attr_init(&type) != 0 ) { | ||
85 | SDL_SetError("Couldn't initialize pthread attributes"); | ||
86 | return(-1); | ||
87 | } | ||
88 | pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE); | ||
89 | |||
90 | /* Create the thread and go! */ | ||
91 | if ( pthread_create(&thread->handle, &type, RunThread, args) != 0 ) { | ||
92 | SDL_SetError("Not enough resources to create thread"); | ||
93 | return(-1); | ||
94 | } | ||
95 | |||
96 | if (riscos_using_threads == 0) | ||
97 | { | ||
98 | riscos_using_threads = 1; | ||
99 | riscos_main_thread = SDL_ThreadID(); | ||
100 | } | ||
101 | |||
102 | return(0); | ||
103 | } | ||
104 | |||
105 | void SDL_SYS_SetupThread(void) | ||
106 | { | ||
107 | int i; | ||
108 | sigset_t mask; | ||
109 | |||
110 | /* Mask asynchronous signals for this thread */ | ||
111 | sigemptyset(&mask); | ||
112 | for ( i=0; sig_list[i]; ++i ) { | ||
113 | sigaddset(&mask, sig_list[i]); | ||
114 | } | ||
115 | pthread_sigmask(SIG_BLOCK, &mask, 0); | ||
116 | |||
117 | #ifdef PTHREAD_CANCEL_ASYNCHRONOUS | ||
118 | /* Allow ourselves to be asynchronously cancelled */ | ||
119 | { int oldstate; | ||
120 | pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate); | ||
121 | } | ||
122 | #endif | ||
123 | } | ||
124 | |||
125 | Uint32 SDL_ThreadID(void) | ||
126 | { | ||
127 | return((Uint32)pthread_self()); | ||
128 | } | ||
129 | |||
130 | void SDL_SYS_WaitThread(SDL_Thread *thread) | ||
131 | { | ||
132 | pthread_join(thread->handle, 0); | ||
133 | } | ||
134 | |||
135 | void SDL_SYS_KillThread(SDL_Thread *thread) | ||
136 | { | ||
137 | #ifdef PTHREAD_CANCEL_ASYNCHRONOUS | ||
138 | pthread_cancel(thread->handle); | ||
139 | #else | ||
140 | pthread_kill(thread->handle, SIGKILL); | ||
141 | #endif | ||
142 | } | ||
143 | |||
144 | #endif | ||
diff --git a/apps/plugins/sdl/src/thread/riscos/SDL_systhread_c.h b/apps/plugins/sdl/src/thread/riscos/SDL_systhread_c.h new file mode 100644 index 0000000000..9e1d2c8c5c --- /dev/null +++ b/apps/plugins/sdl/src/thread/riscos/SDL_systhread_c.h | |||
@@ -0,0 +1,34 @@ | |||
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 Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 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 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | #if SDL_THREADS_DISABLED | ||
25 | |||
26 | typedef int SYS_ThreadHandle; | ||
27 | |||
28 | #else | ||
29 | |||
30 | #include <pthread.h> | ||
31 | |||
32 | typedef pthread_t SYS_ThreadHandle; | ||
33 | |||
34 | #endif | ||
diff --git a/apps/plugins/sdl/src/thread/rockbox/SDL_syscond.c b/apps/plugins/sdl/src/thread/rockbox/SDL_syscond.c new file mode 100644 index 0000000000..f6e7223e3d --- /dev/null +++ b/apps/plugins/sdl/src/thread/rockbox/SDL_syscond.c | |||
@@ -0,0 +1,215 @@ | |||
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 | /* An implementation of condition variables using semaphores and mutexes */ | ||
25 | /* | ||
26 | This implementation borrows heavily from the BeOS condition variable | ||
27 | implementation, written by Christopher Tate and Owen Smith. Thanks! | ||
28 | */ | ||
29 | |||
30 | #include "SDL_thread.h" | ||
31 | |||
32 | struct SDL_cond | ||
33 | { | ||
34 | SDL_mutex *lock; | ||
35 | int waiting; | ||
36 | int signals; | ||
37 | SDL_sem *wait_sem; | ||
38 | SDL_sem *wait_done; | ||
39 | }; | ||
40 | |||
41 | /* Create a condition variable */ | ||
42 | SDL_cond * SDL_CreateCond(void) | ||
43 | { | ||
44 | SDL_cond *cond; | ||
45 | |||
46 | cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); | ||
47 | if ( cond ) { | ||
48 | cond->lock = SDL_CreateMutex(); | ||
49 | cond->wait_sem = SDL_CreateSemaphore(0); | ||
50 | cond->wait_done = SDL_CreateSemaphore(0); | ||
51 | cond->waiting = cond->signals = 0; | ||
52 | if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) { | ||
53 | SDL_DestroyCond(cond); | ||
54 | cond = NULL; | ||
55 | } | ||
56 | } else { | ||
57 | SDL_OutOfMemory(); | ||
58 | } | ||
59 | return(cond); | ||
60 | } | ||
61 | |||
62 | /* Destroy a condition variable */ | ||
63 | void SDL_DestroyCond(SDL_cond *cond) | ||
64 | { | ||
65 | if ( cond ) { | ||
66 | if ( cond->wait_sem ) { | ||
67 | SDL_DestroySemaphore(cond->wait_sem); | ||
68 | } | ||
69 | if ( cond->wait_done ) { | ||
70 | SDL_DestroySemaphore(cond->wait_done); | ||
71 | } | ||
72 | if ( cond->lock ) { | ||
73 | SDL_DestroyMutex(cond->lock); | ||
74 | } | ||
75 | SDL_free(cond); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | /* Restart one of the threads that are waiting on the condition variable */ | ||
80 | int SDL_CondSignal(SDL_cond *cond) | ||
81 | { | ||
82 | if ( ! cond ) { | ||
83 | SDL_SetError("Passed a NULL condition variable"); | ||
84 | return -1; | ||
85 | } | ||
86 | |||
87 | /* If there are waiting threads not already signalled, then | ||
88 | signal the condition and wait for the thread to respond. | ||
89 | */ | ||
90 | SDL_LockMutex(cond->lock); | ||
91 | if ( cond->waiting > cond->signals ) { | ||
92 | ++cond->signals; | ||
93 | SDL_SemPost(cond->wait_sem); | ||
94 | SDL_UnlockMutex(cond->lock); | ||
95 | SDL_SemWait(cond->wait_done); | ||
96 | } else { | ||
97 | SDL_UnlockMutex(cond->lock); | ||
98 | } | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | /* Restart all threads that are waiting on the condition variable */ | ||
104 | int SDL_CondBroadcast(SDL_cond *cond) | ||
105 | { | ||
106 | if ( ! cond ) { | ||
107 | SDL_SetError("Passed a NULL condition variable"); | ||
108 | return -1; | ||
109 | } | ||
110 | |||
111 | /* If there are waiting threads not already signalled, then | ||
112 | signal the condition and wait for the thread to respond. | ||
113 | */ | ||
114 | SDL_LockMutex(cond->lock); | ||
115 | if ( cond->waiting > cond->signals ) { | ||
116 | int i, num_waiting; | ||
117 | |||
118 | num_waiting = (cond->waiting - cond->signals); | ||
119 | cond->signals = cond->waiting; | ||
120 | for ( i=0; i<num_waiting; ++i ) { | ||
121 | SDL_SemPost(cond->wait_sem); | ||
122 | } | ||
123 | /* Now all released threads are blocked here, waiting for us. | ||
124 | Collect them all (and win fabulous prizes!) :-) | ||
125 | */ | ||
126 | SDL_UnlockMutex(cond->lock); | ||
127 | for ( i=0; i<num_waiting; ++i ) { | ||
128 | SDL_SemWait(cond->wait_done); | ||
129 | } | ||
130 | } else { | ||
131 | SDL_UnlockMutex(cond->lock); | ||
132 | } | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | /* Wait on the condition variable for at most 'ms' milliseconds. | ||
138 | The mutex must be locked before entering this function! | ||
139 | The mutex is unlocked during the wait, and locked again after the wait. | ||
140 | |||
141 | Typical use: | ||
142 | |||
143 | Thread A: | ||
144 | SDL_LockMutex(lock); | ||
145 | while ( ! condition ) { | ||
146 | SDL_CondWait(cond); | ||
147 | } | ||
148 | SDL_UnlockMutex(lock); | ||
149 | |||
150 | Thread B: | ||
151 | SDL_LockMutex(lock); | ||
152 | ... | ||
153 | condition = true; | ||
154 | ... | ||
155 | SDL_UnlockMutex(lock); | ||
156 | */ | ||
157 | int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) | ||
158 | { | ||
159 | int retval; | ||
160 | |||
161 | if ( ! cond ) { | ||
162 | SDL_SetError("Passed a NULL condition variable"); | ||
163 | return -1; | ||
164 | } | ||
165 | |||
166 | /* Obtain the protection mutex, and increment the number of waiters. | ||
167 | This allows the signal mechanism to only perform a signal if there | ||
168 | are waiting threads. | ||
169 | */ | ||
170 | SDL_LockMutex(cond->lock); | ||
171 | ++cond->waiting; | ||
172 | SDL_UnlockMutex(cond->lock); | ||
173 | |||
174 | /* Unlock the mutex, as is required by condition variable semantics */ | ||
175 | SDL_UnlockMutex(mutex); | ||
176 | |||
177 | /* Wait for a signal */ | ||
178 | if ( ms == SDL_MUTEX_MAXWAIT ) { | ||
179 | retval = SDL_SemWait(cond->wait_sem); | ||
180 | } else { | ||
181 | retval = SDL_SemWaitTimeout(cond->wait_sem, ms); | ||
182 | } | ||
183 | |||
184 | /* Let the signaler know we have completed the wait, otherwise | ||
185 | the signaler can race ahead and get the condition semaphore | ||
186 | if we are stopped between the mutex unlock and semaphore wait, | ||
187 | giving a deadlock. See the following URL for details: | ||
188 | http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html | ||
189 | */ | ||
190 | SDL_LockMutex(cond->lock); | ||
191 | if ( cond->signals > 0 ) { | ||
192 | /* If we timed out, we need to eat a condition signal */ | ||
193 | if ( retval > 0 ) { | ||
194 | SDL_SemWait(cond->wait_sem); | ||
195 | } | ||
196 | /* We always notify the signal thread that we are done */ | ||
197 | SDL_SemPost(cond->wait_done); | ||
198 | |||
199 | /* Signal handshake complete */ | ||
200 | --cond->signals; | ||
201 | } | ||
202 | --cond->waiting; | ||
203 | SDL_UnlockMutex(cond->lock); | ||
204 | |||
205 | /* Lock the mutex, as is required by condition variable semantics */ | ||
206 | SDL_LockMutex(mutex); | ||
207 | |||
208 | return retval; | ||
209 | } | ||
210 | |||
211 | /* Wait on the condition variable forever */ | ||
212 | int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) | ||
213 | { | ||
214 | return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); | ||
215 | } | ||
diff --git a/apps/plugins/sdl/src/thread/rockbox/SDL_sysmutex.c b/apps/plugins/sdl/src/thread/rockbox/SDL_sysmutex.c new file mode 100644 index 0000000000..db1687000b --- /dev/null +++ b/apps/plugins/sdl/src/thread/rockbox/SDL_sysmutex.c | |||
@@ -0,0 +1,120 @@ | |||
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 | /* An implementation of mutexes using semaphores */ | ||
25 | |||
26 | #include "SDL_thread.h" | ||
27 | #include "SDL_systhread_c.h" | ||
28 | |||
29 | |||
30 | struct SDL_mutex { | ||
31 | int recursive; | ||
32 | Uint32 owner; | ||
33 | struct mutex m; | ||
34 | }; | ||
35 | |||
36 | /* Create a mutex */ | ||
37 | SDL_mutex *SDL_CreateMutex(void) | ||
38 | { | ||
39 | SDL_mutex *mutex; | ||
40 | |||
41 | /* Allocate mutex memory */ | ||
42 | mutex = (SDL_mutex *)SDL_malloc(sizeof(*mutex)); | ||
43 | if ( mutex ) { | ||
44 | rb->mutex_init(&mutex->m); | ||
45 | mutex->recursive = 0; | ||
46 | mutex->owner = 0; | ||
47 | } else { | ||
48 | SDL_OutOfMemory(); | ||
49 | } | ||
50 | return mutex; | ||
51 | } | ||
52 | |||
53 | /* Free the mutex */ | ||
54 | void SDL_DestroyMutex(SDL_mutex *mutex) | ||
55 | { | ||
56 | if ( mutex ) { | ||
57 | SDL_free(mutex); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | int SDL_mutexP(SDL_mutex *mutex) | ||
62 | { | ||
63 | #if SDL_THREADS_DISABLED | ||
64 | return 0; | ||
65 | #else | ||
66 | Uint32 this_thread; | ||
67 | |||
68 | if ( mutex == NULL ) { | ||
69 | SDL_SetError("Passed a NULL mutex"); | ||
70 | return -1; | ||
71 | } | ||
72 | |||
73 | this_thread = SDL_ThreadID(); | ||
74 | if ( mutex->owner == this_thread ) { | ||
75 | ++mutex->recursive; | ||
76 | } else { | ||
77 | /* The order of operations is important. | ||
78 | We set the locking thread id after we obtain the lock | ||
79 | so unlocks from other threads will fail. | ||
80 | */ | ||
81 | rb->mutex_lock(&mutex->m); | ||
82 | mutex->owner = this_thread; | ||
83 | mutex->recursive = 0; | ||
84 | } | ||
85 | |||
86 | return 0; | ||
87 | #endif /* SDL_THREADS_DISABLED */ | ||
88 | } | ||
89 | |||
90 | /* Unlock the mutex */ | ||
91 | int SDL_mutexV(SDL_mutex *mutex) | ||
92 | { | ||
93 | #if SDL_THREADS_DISABLED | ||
94 | return 0; | ||
95 | #else | ||
96 | if ( mutex == NULL ) { | ||
97 | SDL_SetError("Passed a NULL mutex"); | ||
98 | return -1; | ||
99 | } | ||
100 | |||
101 | /* If we don't own the mutex, we can't unlock it */ | ||
102 | if ( SDL_ThreadID() != mutex->owner ) { | ||
103 | SDL_SetError("mutex not owned by this thread"); | ||
104 | return -1; | ||
105 | } | ||
106 | |||
107 | if ( mutex->recursive ) { | ||
108 | --mutex->recursive; | ||
109 | } else { | ||
110 | /* The order of operations is important. | ||
111 | First reset the owner so another thread doesn't lock | ||
112 | the mutex and set the ownership before we reset it, | ||
113 | then release the lock semaphore. | ||
114 | */ | ||
115 | mutex->owner = 0; | ||
116 | rb->mutex_unlock(&mutex->m); | ||
117 | } | ||
118 | return 0; | ||
119 | #endif /* SDL_THREADS_DISABLED */ | ||
120 | } | ||
diff --git a/apps/plugins/sdl/src/thread/rockbox/SDL_sysmutex_c.h b/apps/plugins/sdl/src/thread/rockbox/SDL_sysmutex_c.h new file mode 100644 index 0000000000..1120b2d80d --- /dev/null +++ b/apps/plugins/sdl/src/thread/rockbox/SDL_sysmutex_c.h | |||
@@ -0,0 +1,23 @@ | |||
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 | |||
diff --git a/apps/plugins/sdl/src/thread/rockbox/SDL_syssem.c b/apps/plugins/sdl/src/thread/rockbox/SDL_syssem.c new file mode 100644 index 0000000000..d75afe3c6f --- /dev/null +++ b/apps/plugins/sdl/src/thread/rockbox/SDL_syssem.c | |||
@@ -0,0 +1,170 @@ | |||
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 | /* An implementation of semaphores using mutexes and condition variables */ | ||
25 | |||
26 | #include "SDL_timer.h" | ||
27 | #include "SDL_thread.h" | ||
28 | #include "SDL_systhread_c.h" | ||
29 | |||
30 | |||
31 | #if SDL_THREADS_DISABLED | ||
32 | |||
33 | SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | ||
34 | { | ||
35 | SDL_SetError("SDL not configured with thread support"); | ||
36 | return (SDL_sem *)0; | ||
37 | } | ||
38 | |||
39 | void SDL_DestroySemaphore(SDL_sem *sem) | ||
40 | { | ||
41 | return; | ||
42 | } | ||
43 | |||
44 | int SDL_SemTryWait(SDL_sem *sem) | ||
45 | { | ||
46 | SDL_SetError("SDL not configured with thread support"); | ||
47 | return -1; | ||
48 | } | ||
49 | |||
50 | int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | ||
51 | { | ||
52 | SDL_SetError("SDL not configured with thread support"); | ||
53 | return -1; | ||
54 | } | ||
55 | |||
56 | int SDL_SemWait(SDL_sem *sem) | ||
57 | { | ||
58 | SDL_SetError("SDL not configured with thread support"); | ||
59 | return -1; | ||
60 | } | ||
61 | |||
62 | Uint32 SDL_SemValue(SDL_sem *sem) | ||
63 | { | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | int SDL_SemPost(SDL_sem *sem) | ||
68 | { | ||
69 | SDL_SetError("SDL not configured with thread support"); | ||
70 | return -1; | ||
71 | } | ||
72 | |||
73 | #else | ||
74 | |||
75 | struct SDL_semaphore | ||
76 | { | ||
77 | struct semaphore s; | ||
78 | }; | ||
79 | |||
80 | SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | ||
81 | { | ||
82 | SDL_sem *sem; | ||
83 | |||
84 | sem = (SDL_sem *)SDL_malloc(sizeof(*sem)); | ||
85 | if ( ! sem ) { | ||
86 | SDL_OutOfMemory(); | ||
87 | return NULL; | ||
88 | } | ||
89 | |||
90 | rb->semaphore_init(&sem->s, 99, initial_value); | ||
91 | |||
92 | return sem; | ||
93 | } | ||
94 | |||
95 | /* WARNING: | ||
96 | You cannot call this function when another thread is using the semaphore. | ||
97 | */ | ||
98 | void SDL_DestroySemaphore(SDL_sem *sem) | ||
99 | { | ||
100 | if ( sem ) { | ||
101 | SDL_free(sem); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | int SDL_SemTryWait(SDL_sem *sem) | ||
106 | { | ||
107 | int retval; | ||
108 | |||
109 | if ( ! sem ) { | ||
110 | SDL_SetError("Passed a NULL semaphore"); | ||
111 | return -1; | ||
112 | } | ||
113 | |||
114 | retval = SDL_MUTEX_TIMEDOUT; | ||
115 | |||
116 | if(rb->semaphore_wait(&sem->s, 0) == OBJ_WAIT_SUCCEEDED) | ||
117 | retval = 0; | ||
118 | |||
119 | return retval; | ||
120 | } | ||
121 | |||
122 | int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | ||
123 | { | ||
124 | if ( ! sem ) { | ||
125 | SDL_SetError("Passed a NULL semaphore"); | ||
126 | return -1; | ||
127 | } | ||
128 | |||
129 | /* A timeout of 0 is an easy case */ | ||
130 | if ( timeout == 0 ) { | ||
131 | return SDL_SemTryWait(sem); | ||
132 | } | ||
133 | |||
134 | if(rb->semaphore_wait(&sem->s, timeout / (1000 / HZ)) == OBJ_WAIT_SUCCEEDED) | ||
135 | return 0; | ||
136 | else | ||
137 | return SDL_MUTEX_TIMEDOUT; | ||
138 | |||
139 | return SDL_MUTEX_TIMEDOUT; | ||
140 | } | ||
141 | |||
142 | int SDL_SemWait(SDL_sem *sem) | ||
143 | { | ||
144 | return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); | ||
145 | } | ||
146 | |||
147 | Uint32 SDL_SemValue(SDL_sem *sem) | ||
148 | { | ||
149 | Uint32 value; | ||
150 | |||
151 | value = 0; | ||
152 | if ( sem ) { | ||
153 | value = sem->s.count; | ||
154 | } | ||
155 | return value; | ||
156 | } | ||
157 | |||
158 | int SDL_SemPost(SDL_sem *sem) | ||
159 | { | ||
160 | if ( ! sem ) { | ||
161 | SDL_SetError("Passed a NULL semaphore"); | ||
162 | return -1; | ||
163 | } | ||
164 | |||
165 | rb->semaphore_release(&sem->s); | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | #endif /* SDL_THREADS_DISABLED */ | ||
diff --git a/apps/plugins/sdl/src/thread/rockbox/SDL_systhread.c b/apps/plugins/sdl/src/thread/rockbox/SDL_systhread.c new file mode 100644 index 0000000000..214cbe4597 --- /dev/null +++ b/apps/plugins/sdl/src/thread/rockbox/SDL_systhread.c | |||
@@ -0,0 +1,89 @@ | |||
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 | |||
23 | #include "SDL_config.h" | ||
24 | |||
25 | #if SDL_THREAD_ROCKBOX | ||
26 | |||
27 | /* Thread management routines for rockbox */ | ||
28 | |||
29 | #include "SDL_thread.h" | ||
30 | |||
31 | #include "../SDL_systhread.h" | ||
32 | #include "../SDL_thread_c.h" | ||
33 | |||
34 | #include "plugin.h" | ||
35 | |||
36 | static void *global_args = NULL; | ||
37 | |||
38 | static void rbsdl_runthread(void) | ||
39 | { | ||
40 | void *args = global_args; | ||
41 | global_args = NULL; | ||
42 | SDL_RunThread(args); | ||
43 | } | ||
44 | |||
45 | #define MAX_THREAD 4 | ||
46 | static char names[MAX_THREAD][16]; | ||
47 | static long stacks[MAX_THREAD][DEFAULT_STACK_SIZE / sizeof(long)]; | ||
48 | |||
49 | int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) | ||
50 | { | ||
51 | static int threadnum = 0; | ||
52 | snprintf(names[threadnum], 16, "sdl_%d", threadnum); | ||
53 | |||
54 | while(global_args) rb->yield(); /* busy wait */ | ||
55 | |||
56 | global_args = args; | ||
57 | |||
58 | thread->handle = rb->create_thread(rbsdl_runthread, stacks[threadnum], DEFAULT_STACK_SIZE, | ||
59 | 0, names[threadnum] /* collisions allowed? */ | ||
60 | IF_PRIO(, PRIORITY_USER_INTERFACE) | ||
61 | IF_COP(, COP)); | ||
62 | |||
63 | threadnum++; | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | void SDL_SYS_SetupThread(void) | ||
69 | { | ||
70 | return; | ||
71 | } | ||
72 | |||
73 | Uint32 SDL_ThreadID(void) | ||
74 | { | ||
75 | return rb->thread_self(); | ||
76 | } | ||
77 | |||
78 | void SDL_SYS_WaitThread(SDL_Thread *thread) | ||
79 | { | ||
80 | rb->thread_wait(thread->handle); | ||
81 | } | ||
82 | |||
83 | void SDL_SYS_KillThread(SDL_Thread *thread) | ||
84 | { | ||
85 | #warning How do we do this? | ||
86 | return; | ||
87 | } | ||
88 | |||
89 | #endif | ||
diff --git a/apps/plugins/sdl/src/thread/rockbox/SDL_systhread_c.h b/apps/plugins/sdl/src/thread/rockbox/SDL_systhread_c.h new file mode 100644 index 0000000000..f4385c3cdd --- /dev/null +++ b/apps/plugins/sdl/src/thread/rockbox/SDL_systhread_c.h | |||
@@ -0,0 +1,24 @@ | |||
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 Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 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 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | typedef unsigned int SYS_ThreadHandle; | ||
diff --git a/apps/plugins/sdl/src/thread/symbian/SDL_sysmutex.cpp b/apps/plugins/sdl/src/thread/symbian/SDL_sysmutex.cpp new file mode 100644 index 0000000000..f4b1aeaad2 --- /dev/null +++ b/apps/plugins/sdl/src/thread/symbian/SDL_sysmutex.cpp | |||
@@ -0,0 +1,130 @@ | |||
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 Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 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 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@devolution.com | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | SDL_sysmutex.cpp | ||
25 | |||
26 | Epoc version by Markus Mertama (w@iki.fi) | ||
27 | */ | ||
28 | |||
29 | |||
30 | #ifdef SAVE_RCSID | ||
31 | static char rcsid = | ||
32 | "@(#) $Id: SDL_sysmutex.c,v 1.1.2.3 2000/06/22 15:25:23 hercules Exp $"; | ||
33 | #endif | ||
34 | |||
35 | /* Mutex functions using the Win32 API */ | ||
36 | |||
37 | //#include <stdio.h> | ||
38 | //#include <stdlib.h> | ||
39 | |||
40 | #include <e32std.h> | ||
41 | |||
42 | #include "epoc_sdl.h" | ||
43 | |||
44 | #include "SDL_error.h" | ||
45 | #include "SDL_mutex.h" | ||
46 | |||
47 | |||
48 | #ifdef EKA2 //??? | ||
49 | struct SDL_mutex | ||
50 | { | ||
51 | TInt handle; | ||
52 | }; | ||
53 | #else | ||
54 | struct _SDL_mutex | ||
55 | { | ||
56 | TInt handle; | ||
57 | }; | ||
58 | #endif | ||
59 | |||
60 | extern TInt CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny*, TAny*); | ||
61 | |||
62 | TInt NewMutex(const TDesC& aName, TAny* aPtr1, TAny*) | ||
63 | { | ||
64 | return ((RMutex*)aPtr1)->CreateGlobal(aName); | ||
65 | } | ||
66 | |||
67 | void DeleteMutex(TAny* aMutex) | ||
68 | { | ||
69 | SDL_DestroyMutex ((SDL_mutex*) aMutex); | ||
70 | } | ||
71 | |||
72 | /* Create a mutex */ | ||
73 | SDL_mutex *SDL_CreateMutex(void) | ||
74 | { | ||
75 | RMutex rmutex; | ||
76 | |||
77 | TInt status = CreateUnique(NewMutex, &rmutex, NULL); | ||
78 | if(status != KErrNone) | ||
79 | { | ||
80 | SDL_SetError("Couldn't create mutex"); | ||
81 | } | ||
82 | SDL_mutex* mutex = new /*(ELeave)*/ SDL_mutex; | ||
83 | mutex->handle = rmutex.Handle(); | ||
84 | EpocSdlEnv::AppendCleanupItem(TSdlCleanupItem(DeleteMutex, mutex)); | ||
85 | return(mutex); | ||
86 | } | ||
87 | |||
88 | /* Free the mutex */ | ||
89 | void SDL_DestroyMutex(SDL_mutex *mutex) | ||
90 | { | ||
91 | if ( mutex ) | ||
92 | { | ||
93 | RMutex rmutex; | ||
94 | rmutex.SetHandle(mutex->handle); | ||
95 | if(rmutex.IsHeld()) | ||
96 | { | ||
97 | rmutex.Signal(); | ||
98 | } | ||
99 | rmutex.Close(); | ||
100 | EpocSdlEnv::RemoveCleanupItem(mutex); | ||
101 | delete(mutex); | ||
102 | mutex = NULL; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | /* Lock the mutex */ | ||
107 | int SDL_mutexP(SDL_mutex *mutex) | ||
108 | { | ||
109 | if ( mutex == NULL ) { | ||
110 | SDL_SetError("Passed a NULL mutex"); | ||
111 | return -1; | ||
112 | } | ||
113 | RMutex rmutex; | ||
114 | rmutex.SetHandle(mutex->handle); | ||
115 | rmutex.Wait(); | ||
116 | return(0); | ||
117 | } | ||
118 | |||
119 | /* Unlock the mutex */ | ||
120 | int SDL_mutexV(SDL_mutex *mutex) | ||
121 | { | ||
122 | if ( mutex == NULL ) { | ||
123 | SDL_SetError("Passed a NULL mutex"); | ||
124 | return -1; | ||
125 | } | ||
126 | RMutex rmutex; | ||
127 | rmutex.SetHandle(mutex->handle); | ||
128 | rmutex.Signal(); | ||
129 | return(0); | ||
130 | } | ||
diff --git a/apps/plugins/sdl/src/thread/symbian/SDL_syssem.cpp b/apps/plugins/sdl/src/thread/symbian/SDL_syssem.cpp new file mode 100644 index 0000000000..00f9901ee5 --- /dev/null +++ b/apps/plugins/sdl/src/thread/symbian/SDL_syssem.cpp | |||
@@ -0,0 +1,214 @@ | |||
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 Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 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 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@devolution.com | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | SDL_syssem.cpp | ||
25 | |||
26 | Epoc version by Markus Mertama (w@iki.fi) | ||
27 | */ | ||
28 | |||
29 | #ifdef SAVE_RCSID | ||
30 | static char rcsid = | ||
31 | "@(#) $Id: SDL_syssem.c,v 1.1.2.4 2000/06/22 15:24:48 hercules Exp $"; | ||
32 | #endif | ||
33 | |||
34 | /* Semaphore functions using the Win32 API */ | ||
35 | |||
36 | //#include <stdio.h> | ||
37 | //#include <stdlib.h> | ||
38 | #include <e32std.h> | ||
39 | |||
40 | #include "SDL_error.h" | ||
41 | #include "SDL_thread.h" | ||
42 | |||
43 | |||
44 | #define SDL_MUTEX_TIMEOUT -2 | ||
45 | |||
46 | struct SDL_semaphore | ||
47 | { | ||
48 | TInt handle; | ||
49 | TInt count; | ||
50 | }; | ||
51 | |||
52 | |||
53 | extern TInt CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny*, TAny*); | ||
54 | #ifndef EKA2 | ||
55 | extern TInt NewThread(const TDesC& aName, TAny* aPtr1, TAny* aPtr2); | ||
56 | #endif | ||
57 | |||
58 | TInt NewSema(const TDesC& aName, TAny* aPtr1, TAny* aPtr2) | ||
59 | { | ||
60 | TInt value = *((TInt*) aPtr2); | ||
61 | return ((RSemaphore*)aPtr1)->CreateGlobal(aName, value); | ||
62 | } | ||
63 | |||
64 | /* Create a semaphore */ | ||
65 | SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) | ||
66 | { | ||
67 | RSemaphore s; | ||
68 | TInt status = CreateUnique(NewSema, &s, &initial_value); | ||
69 | if(status != KErrNone) | ||
70 | { | ||
71 | SDL_SetError("Couldn't create semaphore"); | ||
72 | } | ||
73 | SDL_semaphore* sem = new /*(ELeave)*/ SDL_semaphore; | ||
74 | sem->handle = s.Handle(); | ||
75 | sem->count = initial_value; | ||
76 | return(sem); | ||
77 | } | ||
78 | |||
79 | /* Free the semaphore */ | ||
80 | void SDL_DestroySemaphore(SDL_sem *sem) | ||
81 | { | ||
82 | if ( sem ) | ||
83 | { | ||
84 | RSemaphore sema; | ||
85 | sema.SetHandle(sem->handle); | ||
86 | while(--sem->count) | ||
87 | sema.Signal(); | ||
88 | sema.Close(); | ||
89 | delete sem; | ||
90 | sem = NULL; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | #ifndef EKA2 | ||
95 | |||
96 | struct TInfo | ||
97 | { | ||
98 | TInfo(TInt aTime, TInt aHandle) : | ||
99 | iTime(aTime), iHandle(aHandle), iVal(0) {} | ||
100 | TInt iTime; | ||
101 | TInt iHandle; | ||
102 | TInt iVal; | ||
103 | }; | ||
104 | |||
105 | |||
106 | |||
107 | TBool ThreadRun(TAny* aInfo) | ||
108 | { | ||
109 | TInfo* info = STATIC_CAST(TInfo*, aInfo); | ||
110 | User::After(info->iTime); | ||
111 | RSemaphore sema; | ||
112 | sema.SetHandle(info->iHandle); | ||
113 | sema.Signal(); | ||
114 | info->iVal = SDL_MUTEX_TIMEOUT; | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | #endif | ||
119 | |||
120 | |||
121 | void _WaitAll(SDL_sem *sem) | ||
122 | { | ||
123 | //since SemTryWait may changed the counter. | ||
124 | //this may not be atomic, but hopes it works. | ||
125 | RSemaphore sema; | ||
126 | sema.SetHandle(sem->handle); | ||
127 | sema.Wait(); | ||
128 | while(sem->count < 0) | ||
129 | { | ||
130 | sema.Wait(); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) | ||
135 | { | ||
136 | if ( ! sem ) { | ||
137 | SDL_SetError("Passed a NULL sem"); | ||
138 | return -1; | ||
139 | } | ||
140 | |||
141 | if ( timeout == SDL_MUTEX_MAXWAIT ) | ||
142 | { | ||
143 | _WaitAll(sem); | ||
144 | return SDL_MUTEX_MAXWAIT; | ||
145 | } | ||
146 | |||
147 | #ifdef EKA2 | ||
148 | |||
149 | RSemaphore sema; | ||
150 | sema.SetHandle(sem->handle); | ||
151 | if(KErrNone == sema.Wait(timeout)) | ||
152 | return 0; | ||
153 | return -1; | ||
154 | #else | ||
155 | RThread thread; | ||
156 | |||
157 | TInfo* info = new (ELeave)TInfo(timeout, sem->handle); | ||
158 | |||
159 | TInt status = CreateUnique(NewThread, &thread, info); | ||
160 | |||
161 | if(status != KErrNone) | ||
162 | return status; | ||
163 | |||
164 | thread.Resume(); | ||
165 | |||
166 | _WaitAll(sem); | ||
167 | |||
168 | if(thread.ExitType() == EExitPending) | ||
169 | { | ||
170 | thread.Kill(SDL_MUTEX_TIMEOUT); | ||
171 | } | ||
172 | |||
173 | thread.Close(); | ||
174 | |||
175 | return info->iVal; | ||
176 | #endif | ||
177 | } | ||
178 | |||
179 | int SDL_SemTryWait(SDL_sem *sem) | ||
180 | { | ||
181 | if(sem->count > 0) | ||
182 | { | ||
183 | sem->count--; | ||
184 | } | ||
185 | return SDL_MUTEX_TIMEOUT; | ||
186 | } | ||
187 | |||
188 | int SDL_SemWait(SDL_sem *sem) | ||
189 | { | ||
190 | return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); | ||
191 | } | ||
192 | |||
193 | /* Returns the current count of the semaphore */ | ||
194 | Uint32 SDL_SemValue(SDL_sem *sem) | ||
195 | { | ||
196 | if ( ! sem ) { | ||
197 | SDL_SetError("Passed a NULL sem"); | ||
198 | return 0; | ||
199 | } | ||
200 | return sem->count; | ||
201 | } | ||
202 | |||
203 | int SDL_SemPost(SDL_sem *sem) | ||
204 | { | ||
205 | if ( ! sem ) { | ||
206 | SDL_SetError("Passed a NULL sem"); | ||
207 | return -1; | ||
208 | } | ||
209 | sem->count++; | ||
210 | RSemaphore sema; | ||
211 | sema.SetHandle(sem->handle); | ||
212 | sema.Signal(); | ||
213 | return 0; | ||
214 | } | ||
diff --git a/apps/plugins/sdl/src/thread/symbian/SDL_systhread.cpp b/apps/plugins/sdl/src/thread/symbian/SDL_systhread.cpp new file mode 100644 index 0000000000..5e7adc5540 --- /dev/null +++ b/apps/plugins/sdl/src/thread/symbian/SDL_systhread.cpp | |||
@@ -0,0 +1,146 @@ | |||
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 Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 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 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@devolution.com | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | SDL_systhread.cpp | ||
25 | Epoc thread management routines for SDL | ||
26 | |||
27 | Epoc version by Markus Mertama (w@iki.fi) | ||
28 | */ | ||
29 | |||
30 | #include "epoc_sdl.h" | ||
31 | |||
32 | //#include <stdlib.h> | ||
33 | //#include <stdio.h> | ||
34 | |||
35 | |||
36 | |||
37 | extern "C" { | ||
38 | #undef NULL | ||
39 | #include "SDL_error.h" | ||
40 | #include "SDL_thread.h" | ||
41 | #include "SDL_systhread.h" | ||
42 | #include "SDL_thread_c.h" | ||
43 | } | ||
44 | |||
45 | #include <e32std.h> | ||
46 | #include "epoc_sdl.h" | ||
47 | |||
48 | |||
49 | static int object_count; | ||
50 | |||
51 | int RunThread(TAny* data) | ||
52 | { | ||
53 | CTrapCleanup* cleanup = CTrapCleanup::New(); | ||
54 | TRAPD(err, SDL_RunThread(data)); | ||
55 | EpocSdlEnv::CleanupItems(); | ||
56 | delete cleanup; | ||
57 | return(err); | ||
58 | } | ||
59 | |||
60 | |||
61 | TInt NewThread(const TDesC& aName, TAny* aPtr1, TAny* aPtr2) | ||
62 | { | ||
63 | return ((RThread*)(aPtr1))->Create(aName, | ||
64 | RunThread, | ||
65 | KDefaultStackSize, | ||
66 | NULL, | ||
67 | aPtr2); | ||
68 | } | ||
69 | |||
70 | int CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny* aPtr1, TAny* aPtr2) | ||
71 | { | ||
72 | TBuf<16> name; | ||
73 | TInt status = KErrNone; | ||
74 | do | ||
75 | { | ||
76 | object_count++; | ||
77 | name.Format(_L("SDL_%x"), object_count); | ||
78 | status = aFunc(name, aPtr1, aPtr2); | ||
79 | } | ||
80 | while(status == KErrAlreadyExists); | ||
81 | return status; | ||
82 | } | ||
83 | |||
84 | |||
85 | int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) | ||
86 | { | ||
87 | RThread rthread; | ||
88 | |||
89 | const TInt status = CreateUnique(NewThread, &rthread, args); | ||
90 | if (status != KErrNone) | ||
91 | { | ||
92 | delete(((RThread*)(thread->handle))); | ||
93 | thread->handle = NULL; | ||
94 | SDL_SetError("Not enough resources to create thread"); | ||
95 | return(-1); | ||
96 | } | ||
97 | rthread.Resume(); | ||
98 | thread->handle = rthread.Handle(); | ||
99 | return(0); | ||
100 | } | ||
101 | |||
102 | void SDL_SYS_SetupThread(void) | ||
103 | { | ||
104 | return; | ||
105 | } | ||
106 | |||
107 | Uint32 SDL_ThreadID(void) | ||
108 | { | ||
109 | RThread current; | ||
110 | const TThreadId id = current.Id(); | ||
111 | return id; | ||
112 | } | ||
113 | |||
114 | void SDL_SYS_WaitThread(SDL_Thread *thread) | ||
115 | { | ||
116 | SDL_TRACE1("Close thread", thread); | ||
117 | RThread t; | ||
118 | const TInt err = t.Open(thread->threadid); | ||
119 | if(err == KErrNone && t.ExitType() == EExitPending) | ||
120 | { | ||
121 | TRequestStatus status; | ||
122 | t.Logon(status); | ||
123 | User::WaitForRequest(status); | ||
124 | } | ||
125 | t.Close(); | ||
126 | |||
127 | /* RUndertaker taker; | ||
128 | taker.Create(); | ||
129 | TRequestStatus status; | ||
130 | taker.Logon(status, thread->handle); | ||
131 | User::WaitForRequest(status); | ||
132 | taker.Close();*/ | ||
133 | SDL_TRACE1("Closed thread", thread); | ||
134 | } | ||
135 | |||
136 | /* WARNING: This function is really a last resort. | ||
137 | * Threads should be signaled and then exit by themselves. | ||
138 | * TerminateThread() doesn't perform stack and DLL cleanup. | ||
139 | */ | ||
140 | void SDL_SYS_KillThread(SDL_Thread *thread) | ||
141 | { | ||
142 | RThread rthread; | ||
143 | rthread.SetHandle(thread->handle); | ||
144 | rthread.Kill(0); | ||
145 | rthread.Close(); | ||
146 | } | ||
diff --git a/apps/plugins/sdl/src/thread/symbian/SDL_systhread_c.h b/apps/plugins/sdl/src/thread/symbian/SDL_systhread_c.h new file mode 100644 index 0000000000..f5f1729cda --- /dev/null +++ b/apps/plugins/sdl/src/thread/symbian/SDL_systhread_c.h | |||
@@ -0,0 +1,30 @@ | |||
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 Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 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 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@devolution.com | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | SDL_systhread_c.h | ||
25 | |||
26 | Epoc version by Markus Mertama (w@iki.fi) | ||
27 | */ | ||
28 | |||
29 | typedef int SYS_ThreadHandle; | ||
30 | |||
diff --git a/apps/plugins/sdl/src/thread/win32/SDL_sysmutex.c b/apps/plugins/sdl/src/thread/win32/SDL_sysmutex.c new file mode 100644 index 0000000000..1d7805c062 --- /dev/null +++ b/apps/plugins/sdl/src/thread/win32/SDL_sysmutex.c | |||
@@ -0,0 +1,95 @@ | |||
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 | /* Mutex functions using the Win32 API */ | ||
25 | |||
26 | #define WIN32_LEAN_AND_MEAN | ||
27 | #include <windows.h> | ||
28 | |||
29 | #include "SDL_mutex.h" | ||
30 | |||
31 | |||
32 | struct SDL_mutex { | ||
33 | HANDLE id; | ||
34 | }; | ||
35 | |||
36 | /* Create a mutex */ | ||
37 | SDL_mutex *SDL_CreateMutex(void) | ||
38 | { | ||
39 | SDL_mutex *mutex; | ||
40 | |||
41 | /* Allocate mutex memory */ | ||
42 | mutex = (SDL_mutex *)SDL_malloc(sizeof(*mutex)); | ||
43 | if ( mutex ) { | ||
44 | /* Create the mutex, with initial value signaled */ | ||
45 | mutex->id = CreateMutex(NULL, FALSE, NULL); | ||
46 | if ( ! mutex->id ) { | ||
47 | SDL_SetError("Couldn't create mutex"); | ||
48 | SDL_free(mutex); | ||
49 | mutex = NULL; | ||
50 | } | ||
51 | } else { | ||
52 | SDL_OutOfMemory(); | ||
53 | } | ||
54 | return(mutex); | ||
55 | } | ||
56 | |||
57 | /* Free the mutex */ | ||
58 | void SDL_DestroyMutex(SDL_mutex *mutex) | ||
59 | { | ||
60 | if ( mutex ) { | ||
61 | if ( mutex->id ) { | ||
62 | CloseHandle(mutex->id); | ||
63 | mutex->id = 0; | ||
64 | } | ||
65 | SDL_free(mutex); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | /* Lock the mutex */ | ||
70 | int SDL_mutexP(SDL_mutex *mutex) | ||
71 | { | ||
72 | if ( mutex == NULL ) { | ||
73 | SDL_SetError("Passed a NULL mutex"); | ||
74 | return -1; | ||
75 | } | ||
76 | if ( WaitForSingleObject(mutex->id, INFINITE) == WAIT_FAILED ) { | ||
77 | SDL_SetError("Couldn't wait on mutex"); | ||
78 | return -1; | ||
79 | } | ||
80 | return(0); | ||
81 | } | ||
82 | |||
83 | /* Unlock the mutex */ | ||
84 | int SDL_mutexV(SDL_mutex *mutex) | ||
85 | { | ||
86 | if ( mutex == NULL ) { | ||
87 | SDL_SetError("Passed a NULL mutex"); | ||
88 | return -1; | ||
89 | } | ||
90 | if ( ReleaseMutex(mutex->id) == FALSE ) { | ||
91 | SDL_SetError("Couldn't release mutex"); | ||
92 | return -1; | ||
93 | } | ||
94 | return(0); | ||
95 | } | ||
diff --git a/apps/plugins/sdl/src/thread/win32/SDL_syssem.c b/apps/plugins/sdl/src/thread/win32/SDL_syssem.c new file mode 100644 index 0000000000..261d24cbfe --- /dev/null +++ b/apps/plugins/sdl/src/thread/win32/SDL_syssem.c | |||
@@ -0,0 +1,164 @@ | |||
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 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 | volatile LONG 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 = (LONG) 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 (Uint32) 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 | } | ||
diff --git a/apps/plugins/sdl/src/thread/win32/SDL_systhread.c b/apps/plugins/sdl/src/thread/win32/SDL_systhread.c new file mode 100644 index 0000000000..55cb88a58c --- /dev/null +++ b/apps/plugins/sdl/src/thread/win32/SDL_systhread.c | |||
@@ -0,0 +1,162 @@ | |||
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 | /* Win32 thread management routines for SDL */ | ||
25 | |||
26 | #define WIN32_LEAN_AND_MEAN | ||
27 | #include <windows.h> | ||
28 | |||
29 | #include "SDL_thread.h" | ||
30 | #include "../SDL_thread_c.h" | ||
31 | #include "../SDL_systhread.h" | ||
32 | |||
33 | #ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD | ||
34 | #ifndef _WIN32_WCE | ||
35 | /* We'll use the C library from this DLL */ | ||
36 | #include <process.h> | ||
37 | #endif | ||
38 | |||
39 | #if defined(__WATCOMC__) | ||
40 | /* This is for Watcom targets except OS2 */ | ||
41 | #if __WATCOMC__ < 1240 | ||
42 | #define __watcall | ||
43 | #endif | ||
44 | typedef unsigned long (__watcall *pfnSDL_CurrentBeginThread) (void *, unsigned, | ||
45 | unsigned (__stdcall *func)(void *), void *arg, | ||
46 | unsigned, unsigned *threadID); | ||
47 | typedef void (__watcall *pfnSDL_CurrentEndThread)(unsigned code); | ||
48 | #elif (defined(__MINGW32__) && (__GNUC__ < 4)) | ||
49 | typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned, | ||
50 | unsigned (__stdcall *func)(void *), void *arg, | ||
51 | unsigned, unsigned *threadID); | ||
52 | typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code); | ||
53 | #else | ||
54 | typedef uintptr_t (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned, | ||
55 | unsigned (__stdcall *func)(void *), void *arg, | ||
56 | unsigned, unsigned *threadID); | ||
57 | typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code); | ||
58 | #endif | ||
59 | #endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */ | ||
60 | |||
61 | |||
62 | typedef struct ThreadStartParms | ||
63 | { | ||
64 | void *args; | ||
65 | pfnSDL_CurrentEndThread pfnCurrentEndThread; | ||
66 | } tThreadStartParms, *pThreadStartParms; | ||
67 | |||
68 | static DWORD RunThread(void *data) | ||
69 | { | ||
70 | pThreadStartParms pThreadParms = (pThreadStartParms)data; | ||
71 | pfnSDL_CurrentEndThread pfnCurrentEndThread = NULL; | ||
72 | |||
73 | // Call the thread function! | ||
74 | SDL_RunThread(pThreadParms->args); | ||
75 | |||
76 | // Get the current endthread we have to use! | ||
77 | if (pThreadParms) | ||
78 | { | ||
79 | pfnCurrentEndThread = pThreadParms->pfnCurrentEndThread; | ||
80 | SDL_free(pThreadParms); | ||
81 | } | ||
82 | // Call endthread! | ||
83 | if (pfnCurrentEndThread) | ||
84 | (*pfnCurrentEndThread)(0); | ||
85 | return(0); | ||
86 | } | ||
87 | |||
88 | static DWORD WINAPI RunThreadViaCreateThread(LPVOID data) | ||
89 | { | ||
90 | return RunThread(data); | ||
91 | } | ||
92 | |||
93 | static unsigned __stdcall RunThreadViaBeginThreadEx(void *data) | ||
94 | { | ||
95 | return (unsigned) RunThread(data); | ||
96 | } | ||
97 | |||
98 | #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD | ||
99 | int SDL_SYS_CreateThread(SDL_Thread *thread, void *args, pfnSDL_CurrentBeginThread pfnBeginThread, pfnSDL_CurrentEndThread pfnEndThread) | ||
100 | { | ||
101 | #else | ||
102 | int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) | ||
103 | { | ||
104 | #ifdef _WIN32_WCE | ||
105 | pfnSDL_CurrentBeginThread pfnBeginThread = NULL; | ||
106 | pfnSDL_CurrentEndThread pfnEndThread = NULL; | ||
107 | #else | ||
108 | pfnSDL_CurrentBeginThread pfnBeginThread = _beginthreadex; | ||
109 | pfnSDL_CurrentEndThread pfnEndThread = _endthreadex; | ||
110 | #endif | ||
111 | #endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */ | ||
112 | pThreadStartParms pThreadParms = (pThreadStartParms)SDL_malloc(sizeof(tThreadStartParms)); | ||
113 | if (!pThreadParms) { | ||
114 | SDL_OutOfMemory(); | ||
115 | return(-1); | ||
116 | } | ||
117 | |||
118 | // Save the function which we will have to call to clear the RTL of calling app! | ||
119 | pThreadParms->pfnCurrentEndThread = pfnEndThread; | ||
120 | // Also save the real parameters we have to pass to thread function | ||
121 | pThreadParms->args = args; | ||
122 | |||
123 | if (pfnBeginThread) { | ||
124 | unsigned threadid = 0; | ||
125 | thread->handle = (SYS_ThreadHandle) | ||
126 | ((size_t) pfnBeginThread(NULL, 0, RunThreadViaBeginThreadEx, | ||
127 | pThreadParms, 0, &threadid)); | ||
128 | } else { | ||
129 | DWORD threadid = 0; | ||
130 | thread->handle = CreateThread(NULL, 0, RunThreadViaCreateThread, pThreadParms, 0, &threadid); | ||
131 | } | ||
132 | if (thread->handle == NULL) { | ||
133 | SDL_SetError("Not enough resources to create thread"); | ||
134 | return(-1); | ||
135 | } | ||
136 | return(0); | ||
137 | } | ||
138 | |||
139 | void SDL_SYS_SetupThread(void) | ||
140 | { | ||
141 | return; | ||
142 | } | ||
143 | |||
144 | Uint32 SDL_ThreadID(void) | ||
145 | { | ||
146 | return((Uint32)GetCurrentThreadId()); | ||
147 | } | ||
148 | |||
149 | void SDL_SYS_WaitThread(SDL_Thread *thread) | ||
150 | { | ||
151 | WaitForSingleObject(thread->handle, INFINITE); | ||
152 | CloseHandle(thread->handle); | ||
153 | } | ||
154 | |||
155 | /* WARNING: This function is really a last resort. | ||
156 | * Threads should be signaled and then exit by themselves. | ||
157 | * TerminateThread() doesn't perform stack and DLL cleanup. | ||
158 | */ | ||
159 | void SDL_SYS_KillThread(SDL_Thread *thread) | ||
160 | { | ||
161 | TerminateThread(thread->handle, FALSE); | ||
162 | } | ||
diff --git a/apps/plugins/sdl/src/thread/win32/SDL_systhread_c.h b/apps/plugins/sdl/src/thread/win32/SDL_systhread_c.h new file mode 100644 index 0000000000..10b0a7d6b5 --- /dev/null +++ b/apps/plugins/sdl/src/thread/win32/SDL_systhread_c.h | |||
@@ -0,0 +1,28 @@ | |||
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 Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 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 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | #define WIN32_LEAN_AND_MEAN | ||
25 | #include <windows.h> | ||
26 | |||
27 | typedef HANDLE SYS_ThreadHandle; | ||
28 | |||
diff --git a/apps/plugins/sdl/src/thread/win32/win_ce_semaphore.c b/apps/plugins/sdl/src/thread/win32/win_ce_semaphore.c new file mode 100644 index 0000000000..9db45c4391 --- /dev/null +++ b/apps/plugins/sdl/src/thread/win32/win_ce_semaphore.c | |||
@@ -0,0 +1,216 @@ | |||
1 | /* win_ce_semaphore.c | ||
2 | |||
3 | Copyright (c) 1998, Johnson M. Hart | ||
4 | (with corrections 2001 by Rainer Loritz) | ||
5 | Permission is granted for any and all use providing that this | ||
6 | copyright is properly acknowledged. | ||
7 | There are no assurances of suitability for any use whatsoever. | ||
8 | |||
9 | WINDOWS CE: There is a collection of Windows CE functions to simulate | ||
10 | semaphores using only a mutex and an event. As Windows CE events cannot | ||
11 | be named, these simulated semaphores cannot be named either. | ||
12 | |||
13 | Implementation notes: | ||
14 | 1. All required internal data structures are allocated on the process's heap. | ||
15 | 2. Where appropriate, a new error code is returned (see the header | ||
16 | file), or, if the error is a Win32 error, that code is unchanged. | ||
17 | 3. Notice the new handle type "SYNCHHANDLE" that has handles, counters, | ||
18 | and other information. This structure will grow as new objects are added | ||
19 | to this set; some members are specific to only one or two of the objects. | ||
20 | 4. Mutexes are used for critical sections. These could be replaced with | ||
21 | CRITICAL_SECTION objects but then this would give up the time out | ||
22 | capability. | ||
23 | 5. The implementation shows several interesting aspects of synchronization, some | ||
24 | of which are specific to Win32 and some of which are general. These are pointed | ||
25 | out in the comments as appropriate. | ||
26 | 6. The wait function emulates WaitForSingleObject only. An emulation of | ||
27 | WaitForMultipleObjects is much harder to implement outside the kernel, | ||
28 | and it is not clear how to handle a mixture of WCE semaphores and normal | ||
29 | events and mutexes. */ | ||
30 | |||
31 | #define WIN32_LEAN_AND_MEAN | ||
32 | #include <windows.h> | ||
33 | |||
34 | #include "win_ce_semaphore.h" | ||
35 | |||
36 | static SYNCHHANDLE CleanUp (SYNCHHANDLE hSynch, DWORD Flags); | ||
37 | |||
38 | SYNCHHANDLE CreateSemaphoreCE ( | ||
39 | |||
40 | LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, /* pointer to security attributes */ | ||
41 | LONG lInitialCount, /* initial count */ | ||
42 | LONG lMaximumCount, /* maximum count */ | ||
43 | LPCTSTR lpName ) | ||
44 | |||
45 | /* Semaphore for use with Windows CE that does not support them directly. | ||
46 | Requires a counter, a mutex to protect the counter, and an | ||
47 | autoreset event. | ||
48 | |||
49 | Here are the rules that must always hold between the autoreset event | ||
50 | and the mutex (any violation of these rules by the CE semaphore functions | ||
51 | will, in all likelihood, result in a defect): | ||
52 | 1. No thread can set, pulse, or reset the event, | ||
53 | nor can it access any part of the SYNCHHANDLE structure, | ||
54 | without first gaining ownership of the mutex. | ||
55 | BUT, a thread can wait on the event without owning the mutex | ||
56 | (this is clearly necessary or else the event could never be set). | ||
57 | 2. The event is in a signaled state if and only if the current semaphore | ||
58 | count ("CurCount") is greater than zero. | ||
59 | 3. The semaphore count is always >= 0 and <= the maximum count */ | ||
60 | |||
61 | { | ||
62 | SYNCHHANDLE hSynch = NULL, result = NULL; | ||
63 | |||
64 | __try | ||
65 | { | ||
66 | if (lInitialCount > lMaximumCount || lMaximumCount < 0 || lInitialCount < 0) | ||
67 | { | ||
68 | /* Bad parameters */ | ||
69 | SetLastError (SYNCH_ERROR); | ||
70 | __leave; | ||
71 | } | ||
72 | |||
73 | hSynch = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, SYNCH_HANDLE_SIZE); | ||
74 | if (hSynch == NULL) __leave; | ||
75 | |||
76 | hSynch->MaxCount = lMaximumCount; | ||
77 | hSynch->CurCount = lInitialCount; | ||
78 | hSynch->lpName = lpName; | ||
79 | |||
80 | hSynch->hMutex = CreateMutex (lpSemaphoreAttributes, FALSE, NULL); | ||
81 | |||
82 | WaitForSingleObject (hSynch->hMutex, INFINITE); | ||
83 | /* Create the event. It is initially signaled if and only if the | ||
84 | initial count is > 0 */ | ||
85 | hSynch->hEvent = CreateEvent (lpSemaphoreAttributes, FALSE, | ||
86 | lInitialCount > 0, NULL); | ||
87 | ReleaseMutex (hSynch->hMutex); | ||
88 | hSynch->hSemph = NULL; | ||
89 | } | ||
90 | __finally | ||
91 | { | ||
92 | /* Return with the handle, or, if there was any error, return | ||
93 | a null after closing any open handles and freeing any allocated memory. */ | ||
94 | result=CleanUp(hSynch, 6 /* An event and a mutex, but no semaphore. */); | ||
95 | } | ||
96 | |||
97 | return result; | ||
98 | } | ||
99 | |||
100 | BOOL ReleaseSemaphoreCE (SYNCHHANDLE hSemCE, LONG cReleaseCount, LPLONG lpPreviousCount) | ||
101 | /* Windows CE equivalent to ReleaseSemaphore. */ | ||
102 | { | ||
103 | BOOL Result = TRUE; | ||
104 | |||
105 | /* Gain access to the object to assure that the release count | ||
106 | would not cause the total count to exceed the maximum. */ | ||
107 | |||
108 | __try | ||
109 | { | ||
110 | WaitForSingleObject (hSemCE->hMutex, INFINITE); | ||
111 | /* reply only if asked to */ | ||
112 | if (lpPreviousCount!=NULL) | ||
113 | *lpPreviousCount = hSemCE->CurCount; | ||
114 | if (hSemCE->CurCount + cReleaseCount > hSemCE->MaxCount || cReleaseCount <= 0) | ||
115 | { | ||
116 | SetLastError (SYNCH_ERROR); | ||
117 | Result = FALSE; | ||
118 | __leave; | ||
119 | } | ||
120 | hSemCE->CurCount += cReleaseCount; | ||
121 | |||
122 | /* Set the autoreset event, releasing exactly one waiting thread, now or | ||
123 | in the future. */ | ||
124 | |||
125 | SetEvent (hSemCE->hEvent); | ||
126 | } | ||
127 | __finally | ||
128 | { | ||
129 | ReleaseMutex (hSemCE->hMutex); | ||
130 | } | ||
131 | |||
132 | return Result; | ||
133 | } | ||
134 | |||
135 | DWORD WaitForSemaphoreCE (SYNCHHANDLE hSemCE, DWORD dwMilliseconds) | ||
136 | /* Windows CE semaphore equivalent of WaitForSingleObject. */ | ||
137 | { | ||
138 | DWORD WaitResult; | ||
139 | |||
140 | WaitResult = WaitForSingleObject (hSemCE->hMutex, dwMilliseconds); | ||
141 | if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0) return WaitResult; | ||
142 | while (hSemCE->CurCount <= 0) | ||
143 | { | ||
144 | |||
145 | /* The count is 0, and the thread must wait on the event (which, by | ||
146 | the rules, is currently reset) for semaphore resources to become | ||
147 | available. First, of course, the mutex must be released so that another | ||
148 | thread will be capable of setting the event. */ | ||
149 | |||
150 | ReleaseMutex (hSemCE->hMutex); | ||
151 | |||
152 | /* Wait for the event to be signaled, indicating a semaphore state change. | ||
153 | The event is autoreset and signaled with a SetEvent (not PulseEvent) | ||
154 | so exactly one waiting thread (whether or not there is currently | ||
155 | a waiting thread) is released as a result of the SetEvent. */ | ||
156 | |||
157 | WaitResult = WaitForSingleObject (hSemCE->hEvent, dwMilliseconds); | ||
158 | if (WaitResult != WAIT_OBJECT_0) return WaitResult; | ||
159 | |||
160 | /* This is where the properties of setting of an autoreset event is critical | ||
161 | to assure that, even if the semaphore state changes between the | ||
162 | preceding Wait and the next, and even if NO threads are waiting | ||
163 | on the event at the time of the SetEvent, at least one thread | ||
164 | will be released. | ||
165 | Pulsing a manual reset event would appear to work, but it would have | ||
166 | a defect which could appear if the semaphore state changed between | ||
167 | the two waits. */ | ||
168 | |||
169 | WaitResult = WaitForSingleObject (hSemCE->hMutex, dwMilliseconds); | ||
170 | if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0) return WaitResult; | ||
171 | |||
172 | } | ||
173 | /* The count is not zero and this thread owns the mutex. */ | ||
174 | |||
175 | hSemCE->CurCount--; | ||
176 | /* The event is now unsignaled, BUT, the semaphore count may not be | ||
177 | zero, in which case the event should be signaled again | ||
178 | before releasing the mutex. */ | ||
179 | |||
180 | if (hSemCE->CurCount > 0) SetEvent (hSemCE->hEvent); | ||
181 | ReleaseMutex (hSemCE->hMutex); | ||
182 | return WaitResult; | ||
183 | } | ||
184 | |||
185 | BOOL CloseSynchHandle (SYNCHHANDLE hSynch) | ||
186 | /* Close a synchronization handle. | ||
187 | Improvement: Test for a valid handle before dereferencing the handle. */ | ||
188 | { | ||
189 | BOOL Result = TRUE; | ||
190 | if (hSynch->hEvent != NULL) Result = Result && CloseHandle (hSynch->hEvent); | ||
191 | if (hSynch->hMutex != NULL) Result = Result && CloseHandle (hSynch->hMutex); | ||
192 | if (hSynch->hSemph != NULL) Result = Result && CloseHandle (hSynch->hSemph); | ||
193 | HeapFree (GetProcessHeap (), 0, hSynch); | ||
194 | return (Result); | ||
195 | } | ||
196 | |||
197 | static SYNCHHANDLE CleanUp (SYNCHHANDLE hSynch, DWORD Flags) | ||
198 | { /* Prepare to return from a create of a synchronization handle. | ||
199 | If there was any failure, free any allocated resources. | ||
200 | "Flags" indicates which Win32 objects are required in the | ||
201 | synchronization handle. */ | ||
202 | |||
203 | BOOL ok = TRUE; | ||
204 | |||
205 | if (hSynch == NULL) return NULL; | ||
206 | if ((Flags & 4) == 1 && (hSynch->hEvent == NULL)) ok = FALSE; | ||
207 | if ((Flags & 2) == 1 && (hSynch->hMutex == NULL)) ok = FALSE; | ||
208 | if ((Flags & 1) == 1 && (hSynch->hEvent == NULL)) ok = FALSE; | ||
209 | if (!ok) | ||
210 | { | ||
211 | CloseSynchHandle (hSynch); | ||
212 | return NULL; | ||
213 | } | ||
214 | /* Everything worked */ | ||
215 | return hSynch; | ||
216 | } | ||
diff --git a/apps/plugins/sdl/src/thread/win32/win_ce_semaphore.h b/apps/plugins/sdl/src/thread/win32/win_ce_semaphore.h new file mode 100644 index 0000000000..af2d7b613d --- /dev/null +++ b/apps/plugins/sdl/src/thread/win32/win_ce_semaphore.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* win_ce_semaphore.h - header file to go with win_ce_semaphore.c */ | ||
2 | |||
3 | typedef struct _SYNCH_HANDLE_STRUCTURE { | ||
4 | HANDLE hEvent; | ||
5 | HANDLE hMutex; | ||
6 | HANDLE hSemph; | ||
7 | LONG MaxCount; | ||
8 | volatile LONG CurCount; | ||
9 | LPCTSTR lpName; | ||
10 | } SYNCH_HANDLE_STRUCTURE, *SYNCHHANDLE; | ||
11 | |||
12 | #define SYNCH_HANDLE_SIZE sizeof (SYNCH_HANDLE_STRUCTURE) | ||
13 | |||
14 | /* Error codes - all must have bit 29 set */ | ||
15 | #define SYNCH_ERROR 0X20000000 /* EXERCISE - REFINE THE ERROR NUMBERS */ | ||
16 | |||
17 | extern SYNCHHANDLE CreateSemaphoreCE (LPSECURITY_ATTRIBUTES, LONG, LONG, LPCTSTR); | ||
18 | |||
19 | extern BOOL ReleaseSemaphoreCE (SYNCHHANDLE, LONG, LPLONG); | ||
20 | extern DWORD WaitForSemaphoreCE (SYNCHHANDLE, DWORD); | ||
21 | |||
22 | extern BOOL CloseSynchHandle (SYNCHHANDLE); | ||