Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Latest commit

 

History

History
291 lines (253 loc) · 7.24 KB

SDL_thread.c

File metadata and controls

291 lines (253 loc) · 7.24 KB
 
Apr 26, 2001
Apr 26, 2001
1
2
/*
SDL - Simple DirectMedia Layer
Feb 1, 2006
Feb 1, 2006
3
Copyright (C) 1997-2006 Sam Lantinga
Apr 26, 2001
Apr 26, 2001
4
5
This library is free software; you can redistribute it and/or
Feb 1, 2006
Feb 1, 2006
6
modify it under the terms of the GNU Lesser General Public
Apr 26, 2001
Apr 26, 2001
7
License as published by the Free Software Foundation; either
Feb 1, 2006
Feb 1, 2006
8
version 2.1 of the License, or (at your option) any later version.
Apr 26, 2001
Apr 26, 2001
9
10
11
12
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Feb 1, 2006
Feb 1, 2006
13
Lesser General Public License for more details.
Apr 26, 2001
Apr 26, 2001
14
Feb 1, 2006
Feb 1, 2006
15
16
17
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Apr 26, 2001
Apr 26, 2001
18
19
Sam Lantinga
Dec 14, 2001
Dec 14, 2001
20
slouken@libsdl.org
Apr 26, 2001
Apr 26, 2001
21
*/
Feb 21, 2006
Feb 21, 2006
22
#include "SDL_config.h"
Apr 26, 2001
Apr 26, 2001
23
24
25
26
27
/* System independent thread management routines for SDL */
#include "SDL_mutex.h"
#include "SDL_thread.h"
Feb 16, 2006
Feb 16, 2006
28
29
#include "../SDL_thread_c.h"
#include "../SDL_systhread.h"
Apr 26, 2001
Apr 26, 2001
30
31
32
33
34
35
36
37
38
39
40
41
#define ARRAY_CHUNKSIZE 32
/* The array of threads currently active in the application
(except the main thread)
The manipulation of an array here is safer than using a linked list.
*/
static int SDL_maxthreads = 0;
static int SDL_numthreads = 0;
static SDL_Thread **SDL_Threads = NULL;
static struct SignalSemaphore thread_lock;
int thread_lock_created = 0;
May 28, 2006
May 28, 2006
42
int
May 29, 2006
May 29, 2006
43
SDL_ThreadsInit(void)
Apr 26, 2001
Apr 26, 2001
44
{
May 29, 2006
May 29, 2006
45
InitSemaphore(&thread_lock);
May 28, 2006
May 28, 2006
46
47
thread_lock_created = 1;
return 0;
Apr 26, 2001
Apr 26, 2001
48
49
50
51
52
53
54
}
/* This should never be called...
If this is called by SDL_Quit(), we don't know whether or not we should
clean up threads here. If any threads are still running after this call,
they will no longer have access to any per-thread data.
*/
May 28, 2006
May 28, 2006
55
void
May 29, 2006
May 29, 2006
56
SDL_ThreadsQuit()
Apr 26, 2001
Apr 26, 2001
57
{
May 28, 2006
May 28, 2006
58
thread_lock_created = 0;
Apr 26, 2001
Apr 26, 2001
59
60
61
}
/* Routines for manipulating the thread list */
May 28, 2006
May 28, 2006
62
static void
May 29, 2006
May 29, 2006
63
SDL_AddThread(SDL_Thread * thread)
Apr 26, 2001
Apr 26, 2001
64
{
May 28, 2006
May 28, 2006
65
66
67
68
69
70
71
72
73
SDL_Thread **threads;
/* WARNING:
If the very first threads are created simultaneously, then
there could be a race condition causing memory corruption.
In practice, this isn't a problem because by definition there
is only one thread running the first time this is called.
*/
if (!thread_lock_created) {
May 29, 2006
May 29, 2006
74
if (SDL_ThreadsInit() < 0) {
May 28, 2006
May 28, 2006
75
76
77
return;
}
}
May 29, 2006
May 29, 2006
78
ObtainSemaphore(&thread_lock);
May 28, 2006
May 28, 2006
79
80
/* Expand the list of threads, if necessary */
Apr 26, 2001
Apr 26, 2001
81
#ifdef DEBUG_THREADS
May 29, 2006
May 29, 2006
82
83
printf("Adding thread (%d already - %d max)\n",
SDL_numthreads, SDL_maxthreads);
Apr 26, 2001
Apr 26, 2001
84
#endif
May 28, 2006
May 28, 2006
85
86
if (SDL_numthreads == SDL_maxthreads) {
threads =
May 29, 2006
May 29, 2006
87
88
(SDL_Thread **) SDL_malloc((SDL_maxthreads + ARRAY_CHUNKSIZE) *
(sizeof *threads));
May 28, 2006
May 28, 2006
89
if (threads == NULL) {
May 29, 2006
May 29, 2006
90
SDL_OutOfMemory();
May 28, 2006
May 28, 2006
91
92
goto done;
}
May 29, 2006
May 29, 2006
93
SDL_memcpy(threads, SDL_Threads, SDL_numthreads * (sizeof *threads));
May 28, 2006
May 28, 2006
94
95
SDL_maxthreads += ARRAY_CHUNKSIZE;
if (SDL_Threads) {
May 29, 2006
May 29, 2006
96
SDL_free(SDL_Threads);
May 28, 2006
May 28, 2006
97
98
99
100
101
}
SDL_Threads = threads;
}
SDL_Threads[SDL_numthreads++] = thread;
done:
May 29, 2006
May 29, 2006
102
ReleaseSemaphore(&thread_lock);
Apr 26, 2001
Apr 26, 2001
103
104
}
May 28, 2006
May 28, 2006
105
static void
May 29, 2006
May 29, 2006
106
SDL_DelThread(SDL_Thread * thread)
Apr 26, 2001
Apr 26, 2001
107
{
May 28, 2006
May 28, 2006
108
109
110
int i;
if (thread_lock_created) {
May 29, 2006
May 29, 2006
111
ObtainSemaphore(&thread_lock);
May 28, 2006
May 28, 2006
112
113
114
115
116
117
118
119
120
121
122
for (i = 0; i < SDL_numthreads; ++i) {
if (thread == SDL_Threads[i]) {
break;
}
}
if (i < SDL_numthreads) {
--SDL_numthreads;
while (i < SDL_numthreads) {
SDL_Threads[i] = SDL_Threads[i + 1];
++i;
}
Apr 26, 2001
Apr 26, 2001
123
#ifdef DEBUG_THREADS
May 29, 2006
May 29, 2006
124
125
printf("Deleting thread (%d left - %d max)\n",
SDL_numthreads, SDL_maxthreads);
Apr 26, 2001
Apr 26, 2001
126
#endif
May 28, 2006
May 28, 2006
127
}
May 29, 2006
May 29, 2006
128
ReleaseSemaphore(&thread_lock);
May 28, 2006
May 28, 2006
129
}
Apr 26, 2001
Apr 26, 2001
130
131
132
133
134
135
}
/* The default (non-thread-safe) global error variable */
static SDL_error SDL_global_error;
/* Routine to get the thread-specific error variable */
May 28, 2006
May 28, 2006
136
SDL_error *
May 29, 2006
May 29, 2006
137
SDL_GetErrBuf(void)
Apr 26, 2001
Apr 26, 2001
138
{
May 28, 2006
May 28, 2006
139
140
141
142
143
144
145
SDL_error *errbuf;
errbuf = &SDL_global_error;
if (SDL_Threads) {
int i;
Uint32 this_thread;
May 29, 2006
May 29, 2006
146
147
this_thread = SDL_ThreadID();
ObtainSemaphore(&thread_lock);
May 28, 2006
May 28, 2006
148
149
150
151
152
153
for (i = 0; i < SDL_numthreads; ++i) {
if (this_thread == SDL_Threads[i]->threadid) {
errbuf = &SDL_Threads[i]->errbuf;
break;
}
}
May 29, 2006
May 29, 2006
154
ReleaseSemaphore(&thread_lock);
May 28, 2006
May 28, 2006
155
156
}
return (errbuf);
Apr 26, 2001
Apr 26, 2001
157
158
159
160
}
/* Arguments and callback to setup and run the user thread function */
May 28, 2006
May 28, 2006
161
162
163
164
165
166
typedef struct
{
int (*func) (void *);
void *data;
SDL_Thread *info;
struct Task *wait;
Apr 26, 2001
Apr 26, 2001
167
168
} thread_args;
May 28, 2006
May 28, 2006
169
void
May 29, 2006
May 29, 2006
170
SDL_RunThread(void *data)
Apr 26, 2001
Apr 26, 2001
171
{
May 28, 2006
May 28, 2006
172
173
174
175
176
177
178
179
thread_args *args;
int (*userfunc) (void *);
void *userdata;
int *statusloc;
/* Perform any system-dependent setup
- this function cannot fail, and cannot use SDL_SetError()
*/
May 29, 2006
May 29, 2006
180
SDL_SYS_SetupThread();
May 28, 2006
May 28, 2006
181
182
183
/* Get the thread id */
args = (thread_args *) data;
May 29, 2006
May 29, 2006
184
args->info->threadid = SDL_ThreadID();
May 28, 2006
May 28, 2006
185
186
187
188
189
190
191
/* Figure out what function to run */
userfunc = args->func;
userdata = args->data;
statusloc = &args->info->status;
/* Wake up the parent thread */
May 29, 2006
May 29, 2006
192
Signal(args->wait, SIGBREAKF_CTRL_E);
May 28, 2006
May 28, 2006
193
194
/* Run the function */
May 29, 2006
May 29, 2006
195
*statusloc = userfunc(userdata);
Apr 26, 2001
Apr 26, 2001
196
197
}
May 28, 2006
May 28, 2006
198
SDL_Thread *
May 29, 2006
May 29, 2006
199
SDL_CreateThread(int (*fn) (void *), void *data)
Apr 26, 2001
Apr 26, 2001
200
{
May 28, 2006
May 28, 2006
201
202
203
204
205
SDL_Thread *thread;
thread_args *args;
int ret;
/* Allocate memory for the thread info structure */
May 29, 2006
May 29, 2006
206
thread = (SDL_Thread *) SDL_malloc(sizeof(*thread));
May 28, 2006
May 28, 2006
207
if (thread == NULL) {
May 29, 2006
May 29, 2006
208
SDL_OutOfMemory();
May 28, 2006
May 28, 2006
209
210
return (NULL);
}
May 29, 2006
May 29, 2006
211
SDL_memset(thread, 0, (sizeof *thread));
May 28, 2006
May 28, 2006
212
213
214
thread->status = -1;
/* Set up the arguments for the thread */
May 29, 2006
May 29, 2006
215
args = (thread_args *) SDL_malloc(sizeof(*args));
May 28, 2006
May 28, 2006
216
if (args == NULL) {
May 29, 2006
May 29, 2006
217
218
SDL_OutOfMemory();
SDL_free(thread);
May 28, 2006
May 28, 2006
219
220
221
222
223
return (NULL);
}
args->func = fn;
args->data = data;
args->info = thread;
May 29, 2006
May 29, 2006
224
args->wait = FindTask(NULL);
May 28, 2006
May 28, 2006
225
if (args->wait == NULL) {
May 29, 2006
May 29, 2006
226
227
228
SDL_free(thread);
SDL_free(args);
SDL_OutOfMemory();
May 28, 2006
May 28, 2006
229
230
231
232
return (NULL);
}
/* Add the thread to the list of available threads */
May 29, 2006
May 29, 2006
233
SDL_AddThread(thread);
May 28, 2006
May 28, 2006
234
May 29, 2006
May 29, 2006
235
D(bug("Starting thread...\n"));
May 28, 2006
May 28, 2006
236
237
/* Create the thread and go! */
May 29, 2006
May 29, 2006
238
ret = SDL_SYS_CreateThread(thread, args);
May 28, 2006
May 28, 2006
239
if (ret >= 0) {
May 29, 2006
May 29, 2006
240
D(bug("Waiting for thread CTRL_E...\n"));
May 28, 2006
May 28, 2006
241
/* Wait for the thread function to use arguments */
May 29, 2006
May 29, 2006
242
243
Wait(SIGBREAKF_CTRL_E);
D(bug(" Arrived."));
May 28, 2006
May 28, 2006
244
245
} else {
/* Oops, failed. Gotta free everything */
May 29, 2006
May 29, 2006
246
247
SDL_DelThread(thread);
SDL_free(thread);
May 28, 2006
May 28, 2006
248
249
thread = NULL;
}
May 29, 2006
May 29, 2006
250
SDL_free(args);
May 28, 2006
May 28, 2006
251
252
253
/* Everything is running now */
return (thread);
Apr 26, 2001
Apr 26, 2001
254
255
}
May 28, 2006
May 28, 2006
256
void
May 29, 2006
May 29, 2006
257
SDL_WaitThread(SDL_Thread * thread, int *status)
Apr 26, 2001
Apr 26, 2001
258
{
May 28, 2006
May 28, 2006
259
if (thread) {
May 29, 2006
May 29, 2006
260
SDL_SYS_WaitThread(thread);
May 28, 2006
May 28, 2006
261
262
263
if (status) {
*status = thread->status;
}
May 29, 2006
May 29, 2006
264
265
SDL_DelThread(thread);
SDL_free(thread);
May 28, 2006
May 28, 2006
266
}
Apr 26, 2001
Apr 26, 2001
267
268
}
May 28, 2006
May 28, 2006
269
Uint32
May 29, 2006
May 29, 2006
270
SDL_GetThreadID(SDL_Thread * thread)
May 10, 2001
May 10, 2001
271
{
May 28, 2006
May 28, 2006
272
273
274
275
276
Uint32 id;
if (thread) {
id = thread->threadid;
} else {
May 29, 2006
May 29, 2006
277
id = SDL_ThreadID();
May 28, 2006
May 28, 2006
278
279
}
return (id);
May 10, 2001
May 10, 2001
280
281
}
May 28, 2006
May 28, 2006
282
void
May 29, 2006
May 29, 2006
283
SDL_KillThread(SDL_Thread * thread)
Apr 26, 2001
Apr 26, 2001
284
{
May 28, 2006
May 28, 2006
285
if (thread) {
May 29, 2006
May 29, 2006
286
287
SDL_SYS_KillThread(thread);
SDL_WaitThread(thread, NULL);
May 28, 2006
May 28, 2006
288
}
Apr 26, 2001
Apr 26, 2001
289
290
}
May 28, 2006
May 28, 2006
291
/* vi: set ts=4 sw=4 expandtab: */