GNU libmicrohttpd 0.9.76
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#ifdef HAVE_STDLIB_H
34#include <stdlib.h>
35#endif /* HAVE_STDLIB_H */
36#ifdef HAVE_PTHREAD_NP_H
37#include <pthread_np.h>
38#endif /* HAVE_PTHREAD_NP_H */
39#endif /* MHD_USE_THREAD_NAME_ */
40#include <errno.h>
41
42
43#ifndef MHD_USE_THREAD_NAME_
44
45#define MHD_set_thread_name_(t, n) (void)
46#define MHD_set_cur_thread_name_(n) (void)
47
48#else /* MHD_USE_THREAD_NAME_ */
49
50#if defined(MHD_USE_POSIX_THREADS)
51#if defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD) || \
52 defined(HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI)
53# define MHD_USE_THREAD_ATTR_SETNAME 1
54#endif /* HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD || \
55 HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI */
56
57#if defined(HAVE_PTHREAD_SETNAME_NP_GNU) || \
58 defined(HAVE_PTHREAD_SET_NAME_NP_FREEBSD) \
59 || defined(HAVE_PTHREAD_SETNAME_NP_NETBSD)
60
68static int
69MHD_set_thread_name_ (const MHD_thread_ID_ thread_id,
70 const char *thread_name)
71{
72 if (NULL == thread_name)
73 return 0;
74
75#if defined(HAVE_PTHREAD_SETNAME_NP_GNU)
76 return ! pthread_setname_np (thread_id, thread_name);
77#elif defined(HAVE_PTHREAD_SET_NAME_NP_FREEBSD)
78 /* FreeBSD and OpenBSD use different function name and void return type */
79 pthread_set_name_np (thread_id, thread_name);
80 return ! 0;
81#elif defined(HAVE_PTHREAD_SETNAME_NP_NETBSD)
82 /* NetBSD use 3 arguments: second argument is string in printf-like format,
83 * third argument is a single argument for printf();
84 * OSF1 use 3 arguments too, but last one always must be zero (NULL).
85 * MHD doesn't use '%' in thread names, so both form are used in same way.
86 */
87 return ! pthread_setname_np (thread_id, thread_name, 0);
88#endif /* HAVE_PTHREAD_SETNAME_NP_NETBSD */
89}
90
91
92#ifndef __QNXNTO__
98#define MHD_set_cur_thread_name_(n) MHD_set_thread_name_ (pthread_self (),(n))
99#else /* __QNXNTO__ */
100/* Special case for QNX Neutrino - using zero for thread ID sets name faster. */
101#define MHD_set_cur_thread_name_(n) MHD_set_thread_name_ (0,(n))
102#endif /* __QNXNTO__ */
103#elif defined(HAVE_PTHREAD_SETNAME_NP_DARWIN)
104
110#define MHD_set_cur_thread_name_(n) (! (pthread_setname_np ((n))))
111#endif /* HAVE_PTHREAD_SETNAME_NP_DARWIN */
112
113#elif defined(MHD_USE_W32_THREADS)
114#ifndef _MSC_FULL_VER
115/* Thread name available only for VC-compiler */
116#else /* _MSC_FULL_VER */
124static int
125MHD_set_thread_name_ (const MHD_thread_ID_ thread_id,
126 const char *thread_name)
127{
128 static const DWORD VC_SETNAME_EXC = 0x406D1388;
129#pragma pack(push,8)
130 struct thread_info_struct
131 {
132 DWORD type; /* Must be 0x1000. */
133 LPCSTR name; /* Pointer to name (in user address space). */
134 DWORD ID; /* Thread ID (-1 = caller thread). */
135 DWORD flags; /* Reserved for future use, must be zero. */
136 } thread_info;
137#pragma pack(pop)
138
139 if (NULL == thread_name)
140 return 0;
141
142 thread_info.type = 0x1000;
143 thread_info.name = thread_name;
144 thread_info.ID = thread_id;
145 thread_info.flags = 0;
146
147 __try
148 { /* This exception is intercepted by debugger */
149 RaiseException (VC_SETNAME_EXC,
150 0,
151 sizeof (thread_info) / sizeof(ULONG_PTR),
152 (ULONG_PTR *) &thread_info);
153 }
154 __except (EXCEPTION_EXECUTE_HANDLER)
155 {}
156
157 return ! 0;
158}
159
160
166#define MHD_set_cur_thread_name_(n) MHD_set_thread_name_ (-1,(n))
167#endif /* _MSC_FULL_VER */
168#endif /* MHD_USE_W32_THREADS */
169
170#endif /* MHD_USE_THREAD_NAME_ */
171
172
182int
183MHD_create_thread_ (MHD_thread_handle_ID_ *thread,
184 size_t stack_size,
185 MHD_THREAD_START_ROUTINE_ start_routine,
186 void *arg)
187{
188#if defined(MHD_USE_POSIX_THREADS)
189 int res;
190
191 if (0 != stack_size)
192 {
193 pthread_attr_t attr;
194 res = pthread_attr_init (&attr);
195 if (0 == res)
196 {
197 res = pthread_attr_setstacksize (&attr,
198 stack_size);
199 if (0 == res)
200 res = pthread_create (&(thread->handle),
201 &attr,
202 start_routine,
203 arg);
204 pthread_attr_destroy (&attr);
205 }
206 }
207 else
208 res = pthread_create (&(thread->handle),
209 NULL,
210 start_routine,
211 arg);
212
213 if (0 != res)
214 errno = res;
215
216 return ! res;
217#elif defined(MHD_USE_W32_THREADS)
218#if SIZEOF_SIZE_T != SIZEOF_UNSIGNED_INT
219 if (stack_size > UINT_MAX)
220 {
221 errno = EINVAL;
222 return 0;
223 }
224#endif /* SIZEOF_SIZE_T != SIZEOF_UNSIGNED_INT */
225
226 thread->handle = (MHD_thread_handle_)
227 _beginthreadex (NULL,
228 (unsigned int) stack_size,
229 start_routine,
230 arg,
231 0,
232 NULL);
233
234 if ((MHD_thread_handle_) - 1 == thread->handle)
235 return 0;
236
237 return ! 0;
238#endif
239}
240
241
242#ifdef MHD_USE_THREAD_NAME_
243
244#ifndef MHD_USE_THREAD_ATTR_SETNAME
245struct MHD_named_helper_param_
246{
250 MHD_THREAD_START_ROUTINE_ start_routine;
251
255 void *arg;
256
260 const char *name;
261};
262
263
264static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
265named_thread_starter (void *data)
266{
267 struct MHD_named_helper_param_ *const param =
268 (struct MHD_named_helper_param_ *) data;
269 void *arg;
271
272 if (NULL == data)
273 return (MHD_THRD_RTRN_TYPE_) 0;
274
275 MHD_set_cur_thread_name_ (param->name);
276
277 arg = param->arg;
278 thr_func = param->start_routine;
279 free (data);
280
281 return thr_func (arg);
282}
283
284
285#endif /* ! MHD_USE_THREAD_ATTR_SETNAME */
286
287
298int
299MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread,
300 const char *thread_name,
301 size_t stack_size,
302 MHD_THREAD_START_ROUTINE_ start_routine,
303 void *arg)
304{
305#if defined(MHD_USE_THREAD_ATTR_SETNAME)
306 int res;
307 pthread_attr_t attr;
308
309 res = pthread_attr_init (&attr);
310 if (0 == res)
311 {
312#if defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD)
313 /* NetBSD use 3 arguments: second argument is string in printf-like format,
314 * third argument is single argument for printf;
315 * OSF1 use 3 arguments too, but last one always must be zero (NULL).
316 * MHD doesn't use '%' in thread names, so both form are used in same way.
317 */
318 res = pthread_attr_setname_np (&attr,
319 thread_name,
320 0);
321#elif defined(HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI)
322 res = pthread_attr_setname_np (&attr,
323 thread_name);
324#else
325#error No pthread_attr_setname_np() function.
326#endif
327 if ((res == 0) && (0 != stack_size) )
328 res = pthread_attr_setstacksize (&attr,
329 stack_size);
330 if (0 == res)
331 res = pthread_create (&(thread->handle),
332 &attr,
333 start_routine,
334 arg);
335 pthread_attr_destroy (&attr);
336 }
337 if (0 != res)
338 errno = res;
339
340 return ! res;
341#else /* ! MHD_USE_THREAD_ATTR_SETNAME */
342 struct MHD_named_helper_param_ *param;
343
344 if (NULL == thread_name)
345 {
346 errno = EINVAL;
347 return 0;
348 }
349
350 param = malloc (sizeof (struct MHD_named_helper_param_));
351 if (NULL == param)
352 return 0;
353
354 param->start_routine = start_routine;
355 param->arg = arg;
356 param->name = thread_name;
357
358 /* Set thread name in thread itself to avoid problems with
359 * threads which terminated before name is set in other thread.
360 */
361 if (! MHD_create_thread_ (thread,
362 stack_size,
363 &named_thread_starter,
364 (void *) param))
365 {
366 free (param);
367 return 0;
368 }
369
370 return ! 0;
371#endif /* ! MHD_USE_THREAD_ATTR_SETNAME */
372}
373
374
375#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)
Definition: mhd_threads.c:180
#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)
Definition: mhd_threads.h:195
#define MHD_create_named_thread_(t, n, s, r, a)
Definition: mhd_threads.h:216
#define NULL
Definition: reason_phrase.c:30
Header for platform-independent threads abstraction.
void * data
Definition: microhttpd.h:3428