aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/mhd_threads.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/mhd_threads.c')
-rw-r--r--src/microhttpd/mhd_threads.c274
1 files changed, 274 insertions, 0 deletions
diff --git a/src/microhttpd/mhd_threads.c b/src/microhttpd/mhd_threads.c
new file mode 100644
index 00000000..07da4960
--- /dev/null
+++ b/src/microhttpd/mhd_threads.c
@@ -0,0 +1,274 @@
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
21/**
22 * @file microhttpd/mhd_threads.c
23 * @brief Implementation for thread functions
24 * @author Karlson2k (Evgeny Grin)
25 */
26
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#endif /* MHD_USE_THREAD_NAME_ */
35#include <errno.h>
36
37
38
39#if defined(MHD_USE_POSIX_THREADS)
40typedef pthread_t MHD_thread_ID_;
41#elif defined(MHD_USE_W32_THREADS)
42typedef DWORD MHD_thread_ID_;
43#endif
44
45
46#ifndef MHD_USE_THREAD_NAME_
47
48#define MHD_set_thread_name_(t, n) (void)
49#define MHD_set_cur_thread_name_(n) (void)
50
51#else /* MHD_USE_THREAD_NAME_ */
52
53#if defined(MHD_USE_POSIX_THREADS)
54#ifdef HAVE_PTHREAD_SETNAME_NP
55/**
56 * Set thread name
57 * @param thread_id ID of thread
58 * @param thread_name name to set
59 * @return non-zero on success, zero otherwise
60 */
61static int MHD_set_thread_name_(const MHD_thread_ID_ thread_id, const char *thread_name)
62{
63 if (NULL == thread_name)
64 return 0;
65
66 return !pthread_setname_np (thread_id, thread_name);
67}
68
69/**
70 * Set current thread name
71 * @param n name to set
72 * @return non-zero on success, zero otherwise
73 */
74#define MHD_set_cur_thread_name_(n) MHD_set_thread_name_(pthread_self(),(n))
75#endif /* HAVE_PTHREAD_SETNAME_NP */
76
77#elif defined(MHD_USE_W32_THREADS)
78#ifndef _MSC_FULL_VER
79/* Thread name available only for VC-compiler */
80#else /* _MSC_FULL_VER */
81/**
82 * Set thread name
83 * @param thread_id ID of thread, -1 for current thread
84 * @param thread_name name to set
85 * @return non-zero on success, zero otherwise
86 */
87static int MHD_set_thread_name_(const MHD_thread_ID_ thread_id, const char *thread_name)
88{
89 static const DWORD VC_SETNAME_EXC = 0x406D1388;
90#pragma pack(push,8)
91 struct thread_info_struct
92 {
93 DWORD type; /* Must be 0x1000. */
94 LPCSTR name; /* Pointer to name (in user address space). */
95 DWORD ID; /* Thread ID (-1 = caller thread). */
96 DWORD flags; /* Reserved for future use, must be zero. */
97 } thread_info;
98#pragma pack(pop)
99
100 if (NULL == thread_name)
101 return 0;
102
103 thread_info.type = 0x1000;
104 thread_info.name = thread_name;
105 thread_info.ID = thread_id;
106 thread_info.flags = 0;
107
108 __try
109 { /* This exception is intercepted by debugger */
110 RaiseException(VC_SETNAME_EXC, 0, sizeof(thread_info) / sizeof(ULONG_PTR), (ULONG_PTR*)&thread_info);
111 }
112 __except (EXCEPTION_EXECUTE_HANDLER)
113 {}
114
115 return !0;
116}
117
118
119/**
120 * Set current thread name
121 * @param n name to set
122 * @return non-zero on success, zero otherwise
123 */
124#define MHD_set_cur_thread_name_(n) MHD_set_thread_name_(-1,(n))
125#endif /* _MSC_FULL_VER */
126#endif /* MHD_USE_W32_THREADS */
127
128#endif /* MHD_USE_THREAD_NAME_ */
129
130
131/**
132 * Create a thread and set the attributes according to our options.
133 *
134 * @param thread handle to initialize
135 * @param stack_size size of stack for new thread, 0 for default
136 * @param start_routine main function of thread
137 * @param arg argument for start_routine
138 * @return non-zero on success; zero otherwise (with errno set)
139 */
140int
141MHD_create_thread_ (MHD_thread_handle_ *thread,
142 size_t stack_size,
143 MHD_THREAD_START_ROUTINE_ start_routine,
144 void *arg)
145{
146#if defined(MHD_USE_POSIX_THREADS)
147 int res;
148
149 if (0 != stack_size)
150 {
151 pthread_attr_t attr;
152 res = pthread_attr_init (&attr);
153 if (0 == res)
154 {
155 res = pthread_attr_setstacksize (&attr, stack_size);
156 if (0 == res)
157 res = pthread_create (thread, &attr,
158 start_routine, arg);
159 pthread_attr_destroy (&attr);
160 }
161 }
162 else
163 res = pthread_create (thread, NULL, start_routine, arg);
164
165 if (0 != res)
166 errno = res;
167
168 return !res;
169#elif defined(MHD_USE_W32_THREADS)
170#if SIZE_MAX != UINT_MAX
171 if (stack_size > UINT_MAX)
172 {
173 errno = EINVAL;
174 return 0;
175 }
176#endif /* SIZE_MAX != UINT_MAX */
177
178 *thread = (HANDLE)_beginthreadex(NULL, (unsigned)stack_size, start_routine,
179 arg, 0, NULL);
180 if ((MHD_thread_handle_)-1 == (*thread))
181 return 0;
182
183 return !0;
184#endif
185}
186
187#ifdef MHD_USE_THREAD_NAME_
188
189struct MHD_named_helper_param_
190{
191 /**
192 * Real thread start routine
193 */
194 MHD_THREAD_START_ROUTINE_ start_routine;
195
196 /**
197 * Argument for thread start routine
198 */
199 void *arg;
200
201 /**
202 * Name for thread
203 */
204 const char *name;
205};
206
207static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
208named_thread_starter (void *data)
209{
210 struct MHD_named_helper_param_ * const param =
211 (struct MHD_named_helper_param_ *) data;
212 void * arg;
213 MHD_THREAD_START_ROUTINE_ thr_func;
214
215 if (NULL == data)
216 return (MHD_THRD_RTRN_TYPE_)0;
217
218 MHD_set_cur_thread_name_(param->name);
219
220 arg = param->arg;
221 thr_func = param->start_routine;
222 free(data);
223
224 return thr_func(arg);
225}
226
227
228
229/**
230 * Create a named thread and set the attributes according to our options.
231 *
232 * @param thread handle to initialize
233 * @param thread_name name for new thread
234 * @param stack_size size of stack for new thread, 0 for default
235 * @param start_routine main function of thread
236 * @param arg argument for start_routine
237 * @return non-zero on success; zero otherwise (with errno set)
238 */
239int
240MHD_create_named_thread_ (MHD_thread_handle_ *thread,
241 const char* thread_name,
242 size_t stack_size,
243 MHD_THREAD_START_ROUTINE_ start_routine,
244 void *arg)
245{
246 struct MHD_named_helper_param_ * param;
247
248 if (NULL == thread_name)
249 {
250 errno = EINVAL;
251 return 0;
252 }
253
254 param = malloc(sizeof(struct MHD_named_helper_param_));
255 if (NULL == param)
256 return 0;
257
258 param->start_routine = start_routine;
259 param->arg = arg;
260 param->name = thread_name;
261
262 /* Set thread name in thread itself to avoid problems with
263 * threads which terminated before name is set in other thread.
264 */
265 if (!MHD_create_thread_(thread, stack_size, &named_thread_starter, (void*)param))
266 {
267 free(param);
268 return 0;
269 }
270
271 return !0;
272}
273
274#endif /* MHD_USE_THREAD_NAME_ */