Mercurial > sdl-ios-xcode
annotate src/thread/linux/SDL_systhread.c @ 968:4675910b0b7b
Date: Mon, 11 Oct 2004 15:17:27 +0300 (EEST)
From: Hannu Savolainen
Subject: Re: SDL uses obsolete OSS features
I did some work on getting OSS to work better with SDL. There have been
some problems with select which should be fixed now.
I'm having some problems in understanding what is the purpose of the
DSP_WaitAudio() routine. I added a return to the very beginning of this
routine and commendted out the define for USE_BLOCKING_WRITES. At least
lbreakout2 seems to work as well as earlier. The latencies are the same.
An ordinary blocking write does exactly the same thing than DSP_WaitAudio
does. So I would recommend using the USE_BLOCKING_WRITES approach and
removing everything from the DSP_WaitAudio routine. Also enabling
USE_BLOCKING_WRITES makes it possible to simplify DSP_PlayAudio() because
you don't need to handle the partial writes (the do-while loop).
Attached is a patch against SDL-1.2.7. After these changes SDL will use
OSS as it's designed to be used (make it as simple as possible). This code
should work with all OSS implementations because it uses only the very
fundamental features that have been there since the jurassic times.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Fri, 12 Nov 2004 21:39:04 +0000 |
parents | b8d311d90021 |
children | fd068ab116ee |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
0 | 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 | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* Linux thread management routines for SDL */ | |
29 | |
30 #include "SDL_error.h" | |
31 #include "SDL_thread.h" | |
32 #include "SDL_systhread.h" | |
33 | |
34 #ifdef FORK_HACK | |
35 | |
36 #include <unistd.h> | |
37 | |
38 int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) | |
39 { | |
40 SDL_SetError("Threads are not supported on this platform"); | |
41 return(-1); | |
42 } | |
43 void SDL_SYS_SetupThread(void) | |
44 { | |
45 return; | |
46 } | |
47 Uint32 SDL_ThreadID(void) | |
48 { | |
49 return((Uint32)getpid()); | |
50 } | |
51 void SDL_SYS_WaitThread(SDL_Thread *thread) | |
52 { | |
53 return; | |
54 } | |
55 void SDL_SYS_KillThread(SDL_Thread *thread) | |
56 { | |
57 return; | |
58 } | |
59 | |
60 #else | |
61 | |
62 #include <signal.h> | |
63 | |
64 #if !defined(MACOSX) /* pthread_sigmask seems to be missing on MacOS X? */ | |
65 /* List of signals to mask in the subthreads */ | |
66 static int sig_list[] = { | |
67 SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH, | |
68 SIGVTALRM, SIGPROF, 0 | |
69 }; | |
70 #endif /* !MACOSX */ | |
71 | |
72 #ifdef SDL_USE_PTHREADS | |
73 | |
74 #include <pthread.h> | |
75 | |
76 | |
77 static void *RunThread(void *data) | |
78 { | |
79 SDL_RunThread(data); | |
80 pthread_exit((void*)0); | |
81 return((void *)0); /* Prevent compiler warning */ | |
82 } | |
83 | |
84 int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) | |
85 { | |
86 pthread_attr_t type; | |
87 | |
88 /* Set the thread attributes */ | |
89 if ( pthread_attr_init(&type) != 0 ) { | |
90 SDL_SetError("Couldn't initialize pthread attributes"); | |
91 return(-1); | |
92 } | |
93 pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE); | |
94 | |
95 /* Create the thread and go! */ | |
96 if ( pthread_create(&thread->handle, &type, RunThread, args) != 0 ) { | |
97 SDL_SetError("Not enough resources to create thread"); | |
98 return(-1); | |
99 } | |
100 return(0); | |
101 } | |
102 | |
103 void SDL_SYS_SetupThread(void) | |
104 { | |
105 #if !defined(MACOSX) /* pthread_sigmask seems to be missing on MacOS X? */ | |
106 int i; | |
107 sigset_t mask; | |
108 | |
109 /* Mask asynchronous signals for this thread */ | |
110 sigemptyset(&mask); | |
111 for ( i=0; sig_list[i]; ++i ) { | |
112 sigaddset(&mask, sig_list[i]); | |
113 } | |
114 pthread_sigmask(SIG_BLOCK, &mask, 0); | |
115 #endif /* !MACOSX */ | |
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 /* WARNING: This may not work for systems with 64-bit pid_t */ | |
126 Uint32 SDL_ThreadID(void) | |
127 { | |
128 return((Uint32)pthread_self()); | |
129 } | |
130 | |
131 void SDL_SYS_WaitThread(SDL_Thread *thread) | |
132 { | |
133 pthread_join(thread->handle, 0); | |
134 } | |
135 | |
136 void SDL_SYS_KillThread(SDL_Thread *thread) | |
137 { | |
138 #ifdef PTHREAD_CANCEL_ASYNCHRONOUS | |
139 pthread_cancel(thread->handle); | |
140 #else | |
141 #ifdef __FreeBSD__ | |
142 #warning For some reason, this doesnt actually kill a thread - FreeBSD 3.2 | |
143 #endif | |
144 pthread_kill(thread->handle, SIGKILL); | |
145 #endif | |
146 } | |
147 | |
148 #else /* Linux-specific clone() based implementation */ | |
149 | |
150 #include <stdlib.h> | |
151 #include <errno.h> | |
152 #include <unistd.h> | |
153 #include <sys/wait.h> | |
154 | |
155 | |
156 /* Stack size for child thread */ | |
157 #define STACKSIZE 16384*4 /* 16384 is too small */ | |
158 | |
159 #ifdef __GLIBC__ | |
160 #include <sched.h> | |
161 #else | |
162 /* From <linux/sched.h> */ | |
163 #define CLONE_VM 0x00000100 /* set if VM shared */ | |
164 #define CLONE_FS 0x00000200 /* set if fs info shared */ | |
165 #define CLONE_FILES 0x00000400 /* set if open files shared */ | |
166 #define CLONE_SIGHAND 0x00000800 /* set if signal handlers shared */ | |
167 #define CLONE_PID 0x00001000 /* set if pid shared */ | |
168 | |
169 /* The infamous "start_thread" function, courtesy Linus Torvalds */ | |
170 extern int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); | |
171 #endif | |
172 | |
173 static int RunThread(void *data) | |
174 { | |
175 SDL_RunThread(data); | |
176 return(0); | |
177 } | |
178 | |
179 int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) | |
180 { | |
181 void *stack; | |
182 | |
183 /* Allocate memory for thread stack */ | |
184 stack = malloc(STACKSIZE); | |
185 if ( stack == (void *)0 ) { | |
186 SDL_OutOfMemory(); | |
187 return(-1); | |
188 } | |
189 thread->data = stack; | |
190 | |
191 /* Adjust the stack since it actually grows down */ | |
192 stack = (void *) ((char *)stack + STACKSIZE); | |
193 | |
194 /* Create the thread and go! */ | |
195 thread->handle = clone(RunThread, stack, | |
196 (CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND), args); | |
197 if ( thread->handle < 0 ) { | |
198 free(thread->data); | |
199 SDL_SetError("Not enough resources to create thread"); | |
200 return(-1); | |
201 } | |
202 return(0); | |
203 } | |
204 | |
205 void SDL_SYS_SetupThread(void) | |
206 { | |
207 int i; | |
208 sigset_t mask; | |
209 | |
210 /* Mask asynchronous signals for this thread */ | |
211 sigemptyset(&mask); | |
212 for ( i=0; sig_list[i]; ++i ) { | |
213 sigaddset(&mask, sig_list[i]); | |
214 } | |
215 sigprocmask(SIG_BLOCK, &mask, 0); | |
216 } | |
217 | |
218 /* WARNING: This may not work for systems with 64-bit pid_t */ | |
219 Uint32 SDL_ThreadID(void) | |
220 { | |
221 return((Uint32)getpid()); | |
222 } | |
223 | |
224 void SDL_SYS_WaitThread(SDL_Thread *thread) | |
225 { | |
226 #ifdef __WCLONE | |
227 errno = 0; | |
228 while ( errno != ECHILD ) { | |
229 waitpid(thread->handle, 0, __WCLONE); | |
230 } | |
231 #else | |
232 /* Ack, ugly ugly hack -- | |
233 wait() doesn't work, waitpid() doesn't work, and ignoring SIG_CHLD | |
234 doesn't work .. and the child thread is still a zombie, so kill() | |
235 doesn't work. | |
236 */ | |
237 char command[1024]; | |
238 | |
239 sprintf(command, | |
240 "ps ax|fgrep -v fgrep|fgrep -v '<zombie>'|fgrep %d >/dev/null", | |
241 thread->handle); | |
242 while ( system(command) == 0 ) | |
243 sleep(1); | |
244 #endif | |
245 free(thread->data); | |
246 } | |
247 | |
248 void SDL_SYS_KillThread(SDL_Thread *thread) | |
249 { | |
250 kill(thread->handle, SIGKILL); | |
251 } | |
252 | |
253 #endif /* SDL_USE_PTHREADS */ | |
254 | |
255 #endif /* FORK_HACK */ |