GNU libmicrohttpd 0.9.77
Loading...
Searching...
No Matches
mhd_threads.c
Go to the documentation of this file.
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2016 Karlson2k (Evgeny Grin)
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 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 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19*/
20
27#include "mhd_threads.h"
28#ifdef MHD_USE_W32_THREADS
29#include "mhd_limits.h"
30#include <process.h>
31#endif
32#ifdef MHD_USE_THREAD_NAME_
33#include <stdlib.h>
34#ifdef HAVE_PTHREAD_NP_H
35#include <pthread_np.h>
36#endif /* HAVE_PTHREAD_NP_H */
37#endif /* MHD_USE_THREAD_NAME_ */
38#include <errno.h>
39
40
41#ifndef MHD_USE_THREAD_NAME_
42
43#define MHD_set_thread_name_(t, n) (void)
44#define MHD_set_cur_thread_name_(n) (void)
45
46#else /* MHD_USE_THREAD_NAME_ */
47
48#if defined(MHD_USE_POSIX_THREADS)
49#if defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD) || \
50 defined(HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI)
51# define MHD_USE_THREAD_ATTR_SETNAME 1
52#endif \
53 /* HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD || HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI */
54
55#if defined(HAVE_PTHREAD_SETNAME_NP_GNU) || \
56 defined(HAVE_PTHREAD_SET_NAME_NP_FREEBSD) \
57 || defined(HAVE_PTHREAD_SETNAME_NP_NETBSD)
58
66static int
67MHD_set_thread_name_ (const MHD_thread_ID_ thread_id,
68 const char *thread_name)
69{
70 if (NULL == thread_name)
71 return 0;
72
73#if defined(HAVE_PTHREAD_SETNAME_NP_GNU)
74 return ! pthread_setname_np (thread_id, thread_name);
75#elif defined(HAVE_PTHREAD_SET_NAME_NP_FREEBSD)
76 /* FreeBSD and OpenBSD use different name and void return type */
77 pthread_set_name_np (thread_id, thread_name);
78 return ! 0;
79#elif defined(HAVE_PTHREAD_SETNAME_NP_NETBSD)
80 /* NetBSD use 3 arguments: second argument is string in printf-like format,
81 * third argument is single argument for printf;
82 * OSF1 use 3 arguments too, but last one always must be zero (NULL).
83 * MHD doesn't use '%' in thread names, so both form are used in same way.
84 */return ! pthread_setname_np (thread_id, thread_name, 0);
85#endif /* HAVE_PTHREAD_SETNAME_NP_NETBSD */
86}
87
88
89#ifndef __QNXNTO__
95#define MHD_set_cur_thread_name_(n) MHD_set_thread_name_ (pthread_self (),(n))
96#else /* __QNXNTO__ */
97/* Special case for QNX Neutrino - using zero for thread ID sets name faster. */
98#define MHD_set_cur_thread_name_(n) MHD_set_thread_name_ (0,(n))
99#endif /* __QNXNTO__ */
100#elif defined(HAVE_PTHREAD_SETNAME_NP_DARWIN)
101
107#define MHD_set_cur_thread_name_(n) (! (pthread_setname_np ((n))))
108#endif /* HAVE_PTHREAD_SETNAME_NP_DARWIN */
109
110#elif defined(MHD_USE_W32_THREADS)
111#ifndef _MSC_FULL_VER
112/* Thread name available only for VC-compiler */
113#else /* _MSC_FULL_VER */
121static int
122MHD_set_thread_name_ (const MHD_thread_ID_ thread_id,
123 const char *thread_name)
124{
125 static const DWORD VC_SETNAME_EXC = 0x406D1388;
126#pragma pack(push,8)
127 struct thread_info_struct
128 {
129 DWORD type; /* Must be 0x1000. */
130 LPCSTR name; /* Pointer to name (in user address space). */
131 DWORD ID; /* Thread ID (-1 = caller thread). */
132 DWORD flags; /* Reserved for future use, must be zero. */
133 } thread_info;
134#pragma pack(pop)
135
136 if (NULL == thread_name)
137 return 0;
138
139 thread_info.type = 0x1000;
140 thread_info.name = thread_name;
141 thread_info.ID = thread_id;
142 thread_info.flags = 0;
143
144 __try
145 { /* This exception is intercepted by debugger */
146 RaiseException (VC_SETNAME_EXC,
147 0,
148 sizeof (thread_info) / sizeof(ULONG_PTR),
149 (ULONG_PTR *) &thread_info);
150 }
151 __except (EXCEPTION_EXECUTE_HANDLER)
152 {}
153
154 return ! 0;
155}
156
157
163#define MHD_set_cur_thread_name_(n) MHD_set_thread_name_ (-1,(n))
164#endif /* _MSC_FULL_VER */
165#endif /* MHD_USE_W32_THREADS */
166
167#endif /* MHD_USE_THREAD_NAME_ */
168
169
179int
180MHD_create_thread_ (MHD_thread_handle_ID_ *thread,
181 size_t stack_size,
182 MHD_THREAD_START_ROUTINE_ start_routine,
183 void *arg)
184{
185#if defined(MHD_USE_POSIX_THREADS)
186 int res;
187
188 if (0 != stack_size)
189 {
190 pthread_attr_t attr;
191 res = pthread_attr_init (&attr);
192 if (0 == res)
193 {
194 res = pthread_attr_setstacksize (&attr,
195 stack_size);
196 if (0 == res)
197 res = pthread_create (&(thread->handle),
198 &attr,
199 start_routine,
200 arg);
201 pthread_attr_destroy (&attr);
202 }
203 }
204 else
205 res = pthread_create (&(thread->handle),
206 NULL,
207 start_routine,
208 arg);
209
210 if (0 != res)
211 errno = res;
212
213 return ! res;
214#elif defined(MHD_USE_W32_THREADS)
215#if SIZE_MAX != UINT_MAX
216 if (stack_size > UINT_MAX)
217 {
218 errno = EINVAL;
219 return 0;
220 }
221#endif /* SIZE_MAX != UINT_MAX */
222
223 thread->handle = (MHD_thread_handle_)
224 _beginthreadex (NULL,
225 (unsigned int) stack_size,
226 start_routine,
227 arg,
228 0,
229 NULL);
230
231 if ((MHD_thread_handle_) - 1 == thread->handle)
232 return 0;
233
234 return ! 0;
235#endif
236}
237
238
239#ifdef MHD_USE_THREAD_NAME_
240
241#ifndef MHD_USE_THREAD_ATTR_SETNAME
242struct MHD_named_helper_param_
243{
247 MHD_THREAD_START_ROUTINE_ start_routine;
248
252 void *arg;
253
257 const char *name;
258};
259
260
261static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
262named_thread_starter (void *data)
263{
264 struct MHD_named_helper_param_ *const param =
265 (struct MHD_named_helper_param_ *) data;
266 void *arg;
268
269 if (NULL == data)
270 return (MHD_THRD_RTRN_TYPE_) 0;
271
272 MHD_set_cur_thread_name_ (param->name);
273
274 arg = param->arg;
275 thr_func = param->start_routine;
276 free (data);
277
278 return thr_func (arg);
279}
280
281
282#endif /* ! MHD_USE_THREAD_ATTR_SETNAME */
283
284
295int
296MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread,
297 const char *thread_name,
298 size_t stack_size,
299 MHD_THREAD_START_ROUTINE_ start_routine,
300 void *arg)
301{
302#if defined(MHD_USE_THREAD_ATTR_SETNAME)
303 int res;
304 pthread_attr_t attr;
305
306 res = pthread_attr_init (&attr);
307 if (0 == res)
308 {
309#if defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD)
310 /* NetBSD use 3 arguments: second argument is string in printf-like format,
311 * third argument is single argument for printf;
312 * OSF1 use 3 arguments too, but last one always must be zero (NULL).
313 * MHD doesn't use '%' in thread names, so both form are used in same way.
314 */res = pthread_attr_setname_np (&attr, thread_name, 0);
315#elif defined(HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI)
316 res = pthread_attr_setname_np (&attr, thread_name);
317#else
318#error No pthread_attr_setname_np() function.
319#endif
320 if ((res == 0) && (0 != stack_size) )
321 res = pthread_attr_setstacksize (&attr,
322 stack_size);
323 if (0 == res)
324 res = pthread_create (&(thread->handle),
325 &attr,
326 start_routine,
327 arg);
328 pthread_attr_destroy (&attr);
329 }
330 if (0 != res)
331 errno = res;
332
333 return ! res;
334#else /* ! MHD_USE_THREAD_ATTR_SETNAME */
335 struct MHD_named_helper_param_ *param;
336
337 if (NULL == thread_name)
338 {
339 errno = EINVAL;
340 return 0;
341 }
342
343 param = malloc (sizeof (struct MHD_named_helper_param_));
344 if (NULL == param)
345 return 0;
346
347 param->start_routine = start_routine;
348 param->arg = arg;
349 param->name = thread_name;
350
351 /* Set thread name in thread itself to avoid problems with
352 * threads which terminated before name is set in other thread.
353 */
354 if (! MHD_create_thread_ (thread,
355 stack_size,
356 &named_thread_starter,
357 (void *) param))
358 {
359 free (param);
360 return 0;
361 }
362
363 return ! 0;
364#endif /* ! MHD_USE_THREAD_ATTR_SETNAME */
365}
366
367
368#endif /* MHD_USE_THREAD_NAME_ */
#define UINT_MAX
Definition mhd_limits.h:45
int MHD_create_thread_(MHD_thread_handle_ID_ *thread, size_t stack_size, MHD_THREAD_START_ROUTINE_ start_routine, void *arg)
#define MHD_set_cur_thread_name_(n)
Definition mhd_threads.c:44
#define MHD_set_thread_name_(t, n)
Definition mhd_threads.c:43
MHD_THRD_RTRN_TYPE_(MHD_THRD_CALL_SPEC_ * MHD_THREAD_START_ROUTINE_)(void *cls)
#define MHD_create_named_thread_(t, n, s, r, a)
#define NULL
Header for platform-independent threads abstraction.
void * data