GNU libmicrohttpd  0.9.29
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 
42 #if defined(MHD_USE_POSIX_THREADS)
43 typedef pthread_t MHD_thread_ID_;
44 #elif defined(MHD_USE_W32_THREADS)
45 typedef DWORD MHD_thread_ID_;
46 #endif
47 
48 
49 #ifndef MHD_USE_THREAD_NAME_
50 
51 #define MHD_set_thread_name_(t, n) (void)
52 #define MHD_set_cur_thread_name_(n) (void)
53 
54 #else /* MHD_USE_THREAD_NAME_ */
55 
56 #if defined(MHD_USE_POSIX_THREADS)
57 #if defined(HAVE_PTHREAD_SETNAME_NP_GNU) || defined(HAVE_PTHREAD_SET_NAME_NP_FREEBSD) \
58  || defined(HAVE_PTHREAD_SETNAME_NP_NETBSD)
59 
67 static int
68 MHD_set_thread_name_(const MHD_thread_ID_ thread_id,
69  const char *thread_name)
70 {
71  if (NULL == thread_name)
72  return 0;
73 
74 #if defined(HAVE_PTHREAD_SETNAME_NP_GNU)
75  return !pthread_setname_np (thread_id, thread_name);
76 #elif defined(HAVE_PTHREAD_SET_NAME_NP_FREEBSD)
77  /* FreeBSD and OpenBSD use different name and void return type */
78  pthread_set_name_np (thread_id, thread_name);
79  return !0;
80 #elif defined(HAVE_PTHREAD_SETNAME_NP_NETBSD)
81  /* NetBSD use 3 arguments: second argument is string in printf-like format,
82  * third argument is single argument for printf;
83  * OSF1 use 3 arguments too, but last one always must be zero (NULL).
84  * MHD doesn't use '%' in thread names, so both form are used in same way.
85  */
86  return !pthread_setname_np (thread_id, thread_name, 0);
87 #endif /* HAVE_PTHREAD_SETNAME_NP_NETBSD */
88 }
89 
90 
91 #ifndef __QNXNTO__
92 
97 #define MHD_set_cur_thread_name_(n) MHD_set_thread_name_(pthread_self(),(n))
98 #else /* __QNXNTO__ */
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 */
115 
122 static int
123 MHD_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 
180 int
181 MHD_create_thread_ (MHD_thread_handle_ *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,
199  &attr,
200  start_routine,
201  arg);
202  pthread_attr_destroy (&attr);
203  }
204  }
205  else
206  res = pthread_create (thread,
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) _beginthreadex (NULL,
225  (unsigned int) stack_size,
226  start_routine,
227  arg,
228  0,
229  NULL);
230  if ((MHD_thread_handle_)-1 == (*thread))
231  return 0;
232 
233  return !0;
234 #endif
235 }
236 
237 #ifdef MHD_USE_THREAD_NAME_
238 
239 struct MHD_named_helper_param_
240 {
244  MHD_THREAD_START_ROUTINE_ start_routine;
245 
249  void *arg;
250 
254  const char *name;
255 };
256 
257 
258 static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
259 named_thread_starter (void *data)
260 {
261  struct MHD_named_helper_param_ * const param =
262  (struct MHD_named_helper_param_ *) data;
263  void * arg;
264  MHD_THREAD_START_ROUTINE_ thr_func;
265 
266  if (NULL == data)
267  return (MHD_THRD_RTRN_TYPE_)0;
268 
269  MHD_set_cur_thread_name_ (param->name);
270 
271  arg = param->arg;
272  thr_func = param->start_routine;
273  free(data);
274 
275  return thr_func(arg);
276 }
277 
278 
289 int
290 MHD_create_named_thread_ (MHD_thread_handle_ *thread,
291  const char* thread_name,
292  size_t stack_size,
293  MHD_THREAD_START_ROUTINE_ start_routine,
294  void *arg)
295 {
296  struct MHD_named_helper_param_ *param;
297 
298  if (NULL == thread_name)
299  {
300  errno = EINVAL;
301  return 0;
302  }
303 
304  param = malloc (sizeof (struct MHD_named_helper_param_));
305  if (NULL == param)
306  return 0;
307 
308  param->start_routine = start_routine;
309  param->arg = arg;
310  param->name = thread_name;
311 
312  /* Set thread name in thread itself to avoid problems with
313  * threads which terminated before name is set in other thread.
314  */
315  if (! MHD_create_thread_(thread,
316  stack_size,
317  &named_thread_starter,
318  (void*)param))
319  {
320  free (param);
321  return 0;
322  }
323 
324  return !0;
325 }
326 
327 #endif /* MHD_USE_THREAD_NAME_ */
#define MHD_set_thread_name_(t, n)
Definition: mhd_threads.c:51
void * data
Definition: microhttpd.h:2108
#define NULL
Definition: reason_phrase.c:30
int MHD_create_thread_(MHD_thread_handle_ *thread, size_t stack_size, MHD_THREAD_START_ROUTINE_ start_routine, void *arg)
Definition: mhd_threads.c:181
#define MHD_create_named_thread_(t, n, s, r, a)
Definition: mhd_threads.h:131
#define MHD_set_cur_thread_name_(n)
Definition: mhd_threads.c:52
limits values definitions
Header for platform-independent threads abstraction.
MHD_THRD_RTRN_TYPE_(MHD_THRD_CALL_SPEC_ * MHD_THREAD_START_ROUTINE_)(void *cls)
Definition: mhd_threads.h:110
#define UINT_MAX
Definition: mhd_limits.h:39