Mercurial > sdl-ios-xcode
annotate src/thread/linux/SDL_systhread.c @ 1282:217f5d5a49e5
Date: Sat, 15 Jan 2005 02:01:51 +0000 (UTC)
From: jimrandomh
Subject: [SDL] Re: Modifier keys pressed during initialization stick
I wrote a simple test program which initializes SDL, prints the SDL
version number, then prints any keydown and keyup events with their
modifiers. (Source code below). Compilation was done using Visual
Studio 6, release mode.
My test sequence was:
Start a command prompt. Type the name of the test program.
shift down
enter down (program starts)
Wait for window to appear
enter up
shift up
spacebar down
spacebar up
Under Windows 98, the output was correct:
SDL 1.2.8
left shift down
shift-return down
shift-return up
left shift up
space down
space up
Under Windows 2000 and under Windows XP, the output was:
SDL 1.2.8
shift-space down
shift-space up
Since shift was not held at the time space was pressed, this is
incorrect. Similar results were observed with launching in different
ways (including double-clicking in Windows Explorer), so it does not
depend on the launching terminal.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 29 Jan 2006 07:57:13 +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 */ |