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