SDL  2.0
SDL_systhread.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_THREAD_WINDOWS
24 
25 /* Win32 thread management routines for SDL */
26 
27 #include "SDL_thread.h"
28 #include "../SDL_thread_c.h"
29 #include "../SDL_systhread.h"
30 #include "SDL_systhread_c.h"
31 
32 #ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD
33 /* We'll use the C library from this DLL */
34 #include <process.h>
35 
36 /* Cygwin gcc-3 ... MingW64 (even with a i386 host) does this like MSVC. */
37 #if (defined(__MINGW32__) && (__GNUC__ < 4))
38 typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned,
39  unsigned (__stdcall *func)(void *), void *arg,
40  unsigned, unsigned *threadID);
41 typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code);
42 
43 #elif defined(__WATCOMC__)
44 /* This is for Watcom targets except OS2 */
45 #if __WATCOMC__ < 1240
46 #define __watcall
47 #endif
48 typedef unsigned long (__watcall * pfnSDL_CurrentBeginThread) (void *,
49  unsigned,
50  unsigned
51  (__stdcall *
52  func) (void
53  *),
54  void *arg,
55  unsigned,
56  unsigned
57  *threadID);
58 typedef void (__watcall * pfnSDL_CurrentEndThread) (unsigned code);
59 
60 #else
61 typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
62  unsigned (__stdcall *
63  func) (void
64  *),
65  void *arg, unsigned,
66  unsigned *threadID);
67 typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
68 #endif
69 #endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */
70 
71 
72 typedef struct ThreadStartParms
73 {
74  void *args;
75  pfnSDL_CurrentEndThread pfnCurrentEndThread;
76 } tThreadStartParms, *pThreadStartParms;
77 
78 static DWORD
79 RunThread(void *data)
80 {
81  pThreadStartParms pThreadParms = (pThreadStartParms) data;
82  pfnSDL_CurrentEndThread pfnEndThread = pThreadParms->pfnCurrentEndThread;
83  void *args = pThreadParms->args;
84  SDL_free(pThreadParms);
85  SDL_RunThread(args);
86  if (pfnEndThread != NULL)
87  pfnEndThread(0);
88  return (0);
89 }
90 
91 static DWORD WINAPI
92 RunThreadViaCreateThread(LPVOID data)
93 {
94  return RunThread(data);
95 }
96 
97 static unsigned __stdcall
98 RunThreadViaBeginThreadEx(void *data)
99 {
100  return (unsigned) RunThread(data);
101 }
102 
103 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
104 int
105 SDL_SYS_CreateThread(SDL_Thread * thread, void *args,
106  pfnSDL_CurrentBeginThread pfnBeginThread,
107  pfnSDL_CurrentEndThread pfnEndThread)
108 {
109 #elif defined(__CYGWIN__) || defined(__WINRT__)
110 int
111 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
112 {
113  pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
114  pfnSDL_CurrentEndThread pfnEndThread = NULL;
115 #else
116 int
117 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
118 {
119  pfnSDL_CurrentBeginThread pfnBeginThread = (pfnSDL_CurrentBeginThread)_beginthreadex;
120  pfnSDL_CurrentEndThread pfnEndThread = (pfnSDL_CurrentEndThread)_endthreadex;
121 #endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
122  pThreadStartParms pThreadParms =
123  (pThreadStartParms) SDL_malloc(sizeof(tThreadStartParms));
124  if (!pThreadParms) {
125  return SDL_OutOfMemory();
126  }
127  /* Save the function which we will have to call to clear the RTL of calling app! */
128  pThreadParms->pfnCurrentEndThread = pfnEndThread;
129  /* Also save the real parameters we have to pass to thread function */
130  pThreadParms->args = args;
131 
132  if (pfnBeginThread) {
133  unsigned threadid = 0;
134  thread->handle = (SYS_ThreadHandle)
135  ((size_t) pfnBeginThread(NULL, 0, RunThreadViaBeginThreadEx,
136  pThreadParms, 0, &threadid));
137  } else {
138  DWORD threadid = 0;
139  thread->handle = CreateThread(NULL, 0, RunThreadViaCreateThread,
140  pThreadParms, 0, &threadid);
141  }
142  if (thread->handle == NULL) {
143  return SDL_SetError("Not enough resources to create thread");
144  }
145  return 0;
146 }
147 
148 #if 0 /* !!! FIXME: revisit this later. See https://bugzilla.libsdl.org/show_bug.cgi?id=2089 */
149 #ifdef _MSC_VER
150 #pragma warning(disable : 4733)
151 #pragma pack(push,8)
152 typedef struct tagTHREADNAME_INFO
153 {
154  DWORD dwType; /* must be 0x1000 */
155  LPCSTR szName; /* pointer to name (in user addr space) */
156  DWORD dwThreadID; /* thread ID (-1=caller thread) */
157  DWORD dwFlags; /* reserved for future use, must be zero */
158 } THREADNAME_INFO;
159 #pragma pack(pop)
160 
161 static EXCEPTION_DISPOSITION
162 ignore_exception(void *a, void *b, void *c, void *d)
163 {
164  return ExceptionContinueExecution;
165 }
166 #endif
167 #endif
168 
169 void
170 SDL_SYS_SetupThread(const char *name)
171 {
172  if (name != NULL) {
173  #if 0 /* !!! FIXME: revisit this later. See https://bugzilla.libsdl.org/show_bug.cgi?id=2089 */
174  #if (defined(_MSC_VER) && defined(_M_IX86))
175  /* This magic tells the debugger to name a thread if it's listening.
176  The inline asm sets up SEH (__try/__except) without C runtime
177  support. See Microsoft Systems Journal, January 1997:
178  http://www.microsoft.com/msj/0197/exception/exception.aspx */
179  INT_PTR handler = (INT_PTR) ignore_exception;
180  THREADNAME_INFO inf;
181 
182  inf.dwType = 0x1000;
183  inf.szName = name;
184  inf.dwThreadID = (DWORD) -1;
185  inf.dwFlags = 0;
186 
187  __asm { /* set up SEH */
188  push handler
189  push fs:[0]
190  mov fs:[0],esp
191  }
192 
193  /* The program itself should ignore this bogus exception. */
194  RaiseException(0x406D1388, 0, sizeof(inf)/sizeof(DWORD), (DWORD*)&inf);
195 
196  __asm { /* tear down SEH. */
197  mov eax,[esp]
198  mov fs:[0], eax
199  add esp, 8
200  }
201  #endif
202  #endif
203  }
204 }
205 
207 SDL_ThreadID(void)
208 {
209  return ((SDL_threadID) GetCurrentThreadId());
210 }
211 
212 int
214 {
215  int value;
216 
217  if (priority == SDL_THREAD_PRIORITY_LOW) {
218  value = THREAD_PRIORITY_LOWEST;
219  } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
220  value = THREAD_PRIORITY_HIGHEST;
221  } else {
222  value = THREAD_PRIORITY_NORMAL;
223  }
224  if (!SetThreadPriority(GetCurrentThread(), value)) {
225  return WIN_SetError("SetThreadPriority()");
226  }
227  return 0;
228 }
229 
230 void
232 {
233 #if __WINRT__
234  WaitForSingleObjectEx(thread->handle, INFINITE, FALSE);
235 #else
236  WaitForSingleObject(thread->handle, INFINITE);
237 #endif
238  CloseHandle(thread->handle);
239 }
240 
241 void
243 {
244  CloseHandle(thread->handle);
245 }
246 
247 #endif /* SDL_THREAD_WINDOWS */
248 
249 /* vi: set ts=4 sw=4 expandtab: */
static void * RunThread(void *data)
Definition: SDL_systhread.c:70
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
int SYS_ThreadHandle
GLuint const GLchar * name
SDL_threadID SDL_ThreadID(void)
Definition: SDL_systhread.c:48
void SDL_SYS_WaitThread(SDL_Thread *thread)
Definition: SDL_systhread.c:60
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 ** d
GLsizei const GLfloat * value
void SDL_free(void *mem)
int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
Definition: SDL_systhread.c:54
const GLubyte * c
void SDL_SYS_DetachThread(SDL_Thread *thread)
Definition: SDL_systhread.c:66
unsigned int uintptr_t
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
int WIN_SetError(const char *prefix)
SYS_ThreadHandle handle
Definition: SDL_thread_c.h:57
#define SDL_SetError
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
GLenum func
SDL_ThreadPriority
Definition: SDL_thread.h:59
void SDL_RunThread(void *data)
Definition: SDL_thread.c:264
void SDL_SYS_SetupThread(const char *name)
Definition: SDL_systhread.c:42
#define SDL_malloc
#define FALSE
Definition: edid-parse.c:32
GLboolean GLboolean GLboolean GLboolean a
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
Definition: SDL_systhread.c:35
GLboolean GLboolean GLboolean b
unsigned long SDL_threadID
Definition: SDL_thread.h:49