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_hints.h"
28 #include "SDL_thread.h"
29 #include "../SDL_thread_c.h"
30 #include "../SDL_systhread.h"
31 #include "SDL_systhread_c.h"
32 
33 #ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD
34 /* We'll use the C library from this DLL */
35 #include <process.h>
36 
37 #ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
38 #define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
39 #endif
40 
41 /* Cygwin gcc-3 ... MingW64 (even with a i386 host) does this like MSVC. */
42 #if (defined(__MINGW32__) && (__GNUC__ < 4))
43 typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned,
44  unsigned (__stdcall *func)(void *), void *arg,
45  unsigned, unsigned *threadID);
46 typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code);
47 
48 #elif defined(__WATCOMC__)
49 /* This is for Watcom targets except OS2 */
50 #if __WATCOMC__ < 1240
51 #define __watcall
52 #endif
53 typedef unsigned long (__watcall * pfnSDL_CurrentBeginThread) (void *,
54  unsigned,
55  unsigned
56  (__stdcall *
57  func) (void
58  *),
59  void *arg,
60  unsigned,
61  unsigned
62  *threadID);
63 typedef void (__watcall * pfnSDL_CurrentEndThread) (unsigned code);
64 
65 #else
66 typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
67  unsigned (__stdcall *
68  func) (void
69  *),
70  void *arg, unsigned,
71  unsigned *threadID);
72 typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
73 #endif
74 #endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */
75 
76 
77 typedef struct ThreadStartParms
78 {
79  void *args;
80  pfnSDL_CurrentEndThread pfnCurrentEndThread;
81 } tThreadStartParms, *pThreadStartParms;
82 
83 static DWORD
84 RunThread(void *data)
85 {
86  pThreadStartParms pThreadParms = (pThreadStartParms) data;
87  pfnSDL_CurrentEndThread pfnEndThread = pThreadParms->pfnCurrentEndThread;
88  void *args = pThreadParms->args;
89  SDL_free(pThreadParms);
90  SDL_RunThread(args);
91  if (pfnEndThread != NULL)
92  pfnEndThread(0);
93  return (0);
94 }
95 
96 static DWORD WINAPI
97 RunThreadViaCreateThread(LPVOID data)
98 {
99  return RunThread(data);
100 }
101 
102 static unsigned __stdcall
103 RunThreadViaBeginThreadEx(void *data)
104 {
105  return (unsigned) RunThread(data);
106 }
107 
108 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
109 int
110 SDL_SYS_CreateThread(SDL_Thread * thread, void *args,
111  pfnSDL_CurrentBeginThread pfnBeginThread,
112  pfnSDL_CurrentEndThread pfnEndThread)
113 {
114 #elif defined(__CYGWIN__) || defined(__WINRT__)
115 int
116 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
117 {
118  pfnSDL_CurrentBeginThread pfnBeginThread = NULL;
119  pfnSDL_CurrentEndThread pfnEndThread = NULL;
120 #else
121 int
122 SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
123 {
124  pfnSDL_CurrentBeginThread pfnBeginThread = (pfnSDL_CurrentBeginThread)_beginthreadex;
125  pfnSDL_CurrentEndThread pfnEndThread = (pfnSDL_CurrentEndThread)_endthreadex;
126 #endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
127  pThreadStartParms pThreadParms =
128  (pThreadStartParms) SDL_malloc(sizeof(tThreadStartParms));
129  const DWORD flags = thread->stacksize ? STACK_SIZE_PARAM_IS_A_RESERVATION : 0;
130  if (!pThreadParms) {
131  return SDL_OutOfMemory();
132  }
133  /* Save the function which we will have to call to clear the RTL of calling app! */
134  pThreadParms->pfnCurrentEndThread = pfnEndThread;
135  /* Also save the real parameters we have to pass to thread function */
136  pThreadParms->args = args;
137 
138  /* thread->stacksize == 0 means "system default", same as win32 expects */
139  if (pfnBeginThread) {
140  unsigned threadid = 0;
141  thread->handle = (SYS_ThreadHandle)
142  ((size_t) pfnBeginThread(NULL, (unsigned int) thread->stacksize,
143  RunThreadViaBeginThreadEx,
144  pThreadParms, flags, &threadid));
145  } else {
146  DWORD threadid = 0;
147  thread->handle = CreateThread(NULL, thread->stacksize,
148  RunThreadViaCreateThread,
149  pThreadParms, flags, &threadid);
150  }
151  if (thread->handle == NULL) {
152  return SDL_SetError("Not enough resources to create thread");
153  }
154  return 0;
155 }
156 
157 #pragma pack(push,8)
158 typedef struct tagTHREADNAME_INFO
159 {
160  DWORD dwType; /* must be 0x1000 */
161  LPCSTR szName; /* pointer to name (in user addr space) */
162  DWORD dwThreadID; /* thread ID (-1=caller thread) */
163  DWORD dwFlags; /* reserved for future use, must be zero */
164 } THREADNAME_INFO;
165 #pragma pack(pop)
166 
167 void
168 SDL_SYS_SetupThread(const char *name)
169 {
170  if ((name != NULL) && IsDebuggerPresent()) {
171  THREADNAME_INFO inf;
172 
173  /* C# and friends will try to catch this Exception, let's avoid it. */
175  return;
176  }
177 
178  /* This magic tells the debugger to name a thread if it's listening. */
179  SDL_zero(inf);
180  inf.dwType = 0x1000;
181  inf.szName = name;
182  inf.dwThreadID = (DWORD) -1;
183  inf.dwFlags = 0;
184 
185  /* The debugger catches this, renames the thread, continues on. */
186  RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR*) &inf);
187  }
188 }
189 
191 SDL_ThreadID(void)
192 {
193  return ((SDL_threadID) GetCurrentThreadId());
194 }
195 
196 int
198 {
199  int value;
200 
201  if (priority == SDL_THREAD_PRIORITY_LOW) {
202  value = THREAD_PRIORITY_LOWEST;
203  } else if (priority == SDL_THREAD_PRIORITY_HIGH) {
204  value = THREAD_PRIORITY_HIGHEST;
205  } else {
206  value = THREAD_PRIORITY_NORMAL;
207  }
208  if (!SetThreadPriority(GetCurrentThread(), value)) {
209  return WIN_SetError("SetThreadPriority()");
210  }
211  return 0;
212 }
213 
214 void
216 {
217  WaitForSingleObjectEx(thread->handle, INFINITE, FALSE);
218  CloseHandle(thread->handle);
219 }
220 
221 void
223 {
224  CloseHandle(thread->handle);
225 }
226 
227 #endif /* SDL_THREAD_WINDOWS */
228 
229 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING
Tell SDL not to name threads on Windows.
Definition: SDL_hints.h:700
static void * RunThread(void *data)
Definition: SDL_systhread.c:69
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
int SYS_ThreadHandle
GLuint const GLchar * name
#define SDL_GetHintBoolean
SDL_threadID SDL_ThreadID(void)
Definition: SDL_systhread.c:48
void SDL_SYS_WaitThread(SDL_Thread *thread)
Definition: SDL_systhread.c:60
GLsizei const GLfloat * value
void SDL_free(void *mem)
int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
Definition: SDL_systhread.c:54
void SDL_SYS_DetachThread(SDL_Thread *thread)
Definition: SDL_systhread.c:66
#define SDL_zero(x)
Definition: SDL_stdinc.h:361
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:265
void SDL_SYS_SetupThread(const char *name)
Definition: SDL_systhread.c:42
GLbitfield flags
#define SDL_malloc
#define FALSE
Definition: edid-parse.c:34
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
Definition: SDL_systhread.c:35
size_t stacksize
Definition: SDL_thread_c.h:62
unsigned long SDL_threadID
Definition: SDL_thread.h:49