GNU libmicrohttpd 0.9.73
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 */
85 return ! pthread_setname_np (thread_id, thread_name, 0);
86#endif /* HAVE_PTHREAD_SETNAME_NP_NETBSD */
87}
88
89
90#ifndef __QNXNTO__
96#define MHD_set_cur_thread_name_(n) MHD_set_thread_name_ (pthread_self (),(n))
97#else /* __QNXNTO__ */
98/* Special case for QNX Neutrino - using zero for thread ID sets name faster. */
99#define MHD_set_cur_thread_name_(n) MHD_set_thread_name_ (0,(n))
100#endif /* __QNXNTO__ */
101#elif defined(HAVE_PTHREAD_SETNAME_NP_DARWIN)
102
108#define MHD_set_cur_thread_name_(n) (! (pthread_setname_np ((n))))
109#endif /* HAVE_PTHREAD_SETNAME_NP_DARWIN */
110
111#elif defined(MHD_USE_W32_THREADS)
112#ifndef _MSC_FULL_VER
113/* Thread name available only for VC-compiler */
114#else /* _MSC_FULL_VER */
122static int
123MHD_set_thread_name_ (const MHD_thread_ID_ thread_id,
124 const char *thread_name)
125{
126 static const DWORD VC_SETNAME_EXC = 0x406D1388;
127#pragma pack(push,8)
128 struct thread_info_struct
129 {
130 DWORD type; /* Must be 0x1000. */
131 LPCSTR name; /* Pointer to name (in user address space). */
132 DWORD ID; /* Thread ID (-1 = caller thread). */
133 DWORD flags; /* Reserved for future use, must be zero. */
134 } thread_info;
135#pragma pack(pop)
136
137 if (NULL == thread_name)
138 return 0;
139
140 thread_info.type = 0x1000;
141 thread_info.name = thread_name;
142 thread_info.ID = thread_id;
143 thread_info.flags = 0;
144
145 __try
146 { /* This exception is intercepted by debugger */
147 RaiseException (VC_SETNAME_EXC,
148 0,
149 sizeof (thread_info) / sizeof(ULONG_PTR),
150 (ULONG_PTR *) &thread_info);
151 }
152 __except (EXCEPTION_EXECUTE_HANDLER)
153 {}
154
155 return ! 0;
156}
157
158
164#define MHD_set_cur_thread_name_(n) MHD_set_thread_name_ (-1,(n))
165#endif /* _MSC_FULL_VER */
166#endif /* MHD_USE_W32_THREADS */
167
168#endif /* MHD_USE_THREAD_NAME_ */
169
170
180int
181MHD_create_thread_ (MHD_thread_handle_ID_ *thread,
182 size_t stack_size,
183 MHD_THREAD_START_ROUTINE_ start_routine,
184 void *arg)
185{
186#if defined(MHD_USE_POSIX_THREADS)
187 int res;
188
189 if (0 != stack_size)
190 {
191 pthread_attr_t attr;
192 res = pthread_attr_init (&attr);
193 if (0 == res)
194 {
195 res = pthread_attr_setstacksize (&attr,
196 stack_size);
197 if (0 == res)
198 res = pthread_create (&(thread->handle),
199 &attr,
200 start_routine,
201 arg);
202 pthread_attr_destroy (&attr);
203 }
204 }
205 else
206 res = pthread_create (&(thread->handle),
207 NULL,
208 start_routine,
209 arg);
210
211 if (0 != res)
212 errno = res;
213
214 return ! res;
215#elif defined(MHD_USE_W32_THREADS)
216#if SIZE_MAX != UINT_MAX
217 if (stack_size > UINT_MAX)
218 {
219 errno = EINVAL;
220 return 0;
221 }
222#endif /* SIZE_MAX != UINT_MAX */
223
224 thread->handle = (MHD_thread_handle_)
225 _beginthreadex (NULL,
226 (unsigned int) stack_size,
227 start_routine,
228 arg,
229 0,
230 NULL);
231
232 if ((MHD_thread_handle_) - 1 == thread->handle)
233 return 0;
234
235 return ! 0;
236#endif
237}
238
239
240#ifdef MHD_USE_THREAD_NAME_
241
242#ifndef MHD_USE_THREAD_ATTR_SETNAME
243struct MHD_named_helper_param_
244{
248 MHD_THREAD_START_ROUTINE_ start_routine;
249
253 void *arg;
254
258 const char *name;
259};
260
261
262static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
263named_thread_starter (void *data)
264{
265 struct MHD_named_helper_param_ *const param =
266 (struct MHD_named_helper_param_ *) data;
267 void *arg;
269
270 if (NULL == data)
271 return (MHD_THRD_RTRN_TYPE_) 0;
272
273 MHD_set_cur_thread_name_ (param->name);
274
275 arg = param->arg;
276 thr_func = param->start_routine;
277 free (data);
278
279 return thr_func (arg);
280}
281
282
283#endif /* ! MHD_USE_THREAD_ATTR_SETNAME */
284
285
296int
297MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread,
298 const char*thread_name,
299 size_t stack_size,
300 MHD_THREAD_START_ROUTINE_ start_routine,
301 void *arg)
302{
303#if defined(MHD_USE_THREAD_ATTR_SETNAME)
304 int res;
305 pthread_attr_t attr;
306
307 res = pthread_attr_init (&attr);
308 if (0 == res)
309 {
310#if defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD)
311 /* NetBSD use 3 arguments: second argument is string in printf-like format,
312 * third argument is single argument for printf;
313 * OSF1 use 3 arguments too, but last one always must be zero (NULL).
314 * MHD doesn't use '%' in thread names, so both form are used in same way.
315 */
316 res = pthread_attr_setname_np (&attr,
317 thread_name,
318 0);
319#elif defined(HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI)
320 res = pthread_attr_setname_np (&attr,
321 thread_name);
322#else
323#error No pthread_attr_setname_np() function.
324#endif
325 if ((res == 0) && (0 != stack_size) )
326 res = pthread_attr_setstacksize (&attr,
327 stack_size);
328 if (0 == res)
329 res = pthread_create (&(thread->handle),
330 &attr,
331 start_routine,
332 arg);
333 pthread_attr_destroy (&attr);
334 }
335 if (0 != res)
336 errno = res;
337
338 return ! res;
339#else /* ! MHD_USE_THREAD_ATTR_SETNAME */
340 struct MHD_named_helper_param_ *param;
341
342 if (NULL == thread_name)
343 {
344 errno = EINVAL;
345 return 0;
346 }
347
348 param = malloc (sizeof (struct MHD_named_helper_param_));
349 if (NULL == param)
350 return 0;
351
352 param->start_routine = start_routine;
353 param->arg = arg;
354 param->name = thread_name;
355
356 /* Set thread name in thread itself to avoid problems with
357 * threads which terminated before name is set in other thread.
358 */
359 if (! MHD_create_thread_ (thread,
360 stack_size,
361 &named_thread_starter,
362 (void*) param))
363 {
364 free (param);
365 return 0;
366 }
367
368 return ! 0;
369#endif /* ! MHD_USE_THREAD_ATTR_SETNAME */
370}
371
372
373#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:3125