This source file includes following definitions.
- get_current_process_id
- get_current_thread_id
- get_current_thread
- demangle_name
- gen_backtrace
- SIG_to_string
- abort_handler
- set_backtrace_on_signal
- dump_bt_to_cerr
- set_backtrace_on_terminate
- create
- suspend
- resume
- state
- exit
- terminate
- cleanup
- set_kernel_priority
- set_kernel_affinity
- get_kernel_affinity
- get_kernel_priority
- set_cancelstate
- sleep
- wait_thread_exit
- create
- suspend
- resume
- state
- is_running
- exit
- terminate
- cleanup
- set_kernel_priority
- get_kernel_priority
- get_current_process_id
- get_current_thread_id
- get_current_thread
- set_kernel_affinity
- get_kernel_affinity
- set_cancelstate
- sleep
- wait_thread_exit
- demangle_name
- gen_backtrace
- set_backtrace_on_signal
- set_backtrace_on_terminate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include "../core/deleter.hpp"
22
23 #include <cxxabi.h>
24 #include <execinfo.h>
25 #include <signal.h>
26
27 namespace jmmcg { namespace ppd {
28
29
30
31
32
33 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::api_params_type::pid_type __fastcall
34 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::get_current_process_id() noexcept(true) {
35 return getpid();
36 }
37
38 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::api_params_type::tid_type __fastcall
39 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::get_current_thread_id() noexcept(true) {
40 return pthread_self();
41 }
42
43 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::api_params_type::handle_type __fastcall
44 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::get_current_thread() noexcept(true) {
45 return pthread_self();
46 }
47
48 template<> inline void __fastcall
49 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::demangle_name(char * const mangled_name, demangled_name_t &demangled_name) noexcept(true) {
50
51 char *begin=strchr(mangled_name, '(');
52 if (begin) {
53 ++begin;
54 }
55 char *end=strrchr(mangled_name, '+');
56
57 if (begin && end) {
58 *end='\0';
59 int demangleStatus=-1;
60 size_t length=sizeof(demangled_name_t);
61
62 const char *ret=abi::__cxa_demangle(begin, demangled_name, &length, &demangleStatus);
63 if (ret!=demangled_name || demangleStatus!=0) {
64 ::strcpy(demangled_name, begin);
65 }
66 }
67 }
68
69
70
71
72 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::demangled_names_t __fastcall
73 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::gen_backtrace() noexcept(true) {
74
75 void *buffer[max_num_fn_ptrs];
76 const int num_fn_ptrs_ret=::backtrace(buffer, max_num_fn_ptrs);
77 const free_ptr<char **> fn_strings(::backtrace_symbols(buffer, num_fn_ptrs_ret));
78 if (fn_strings.ptr==NULL) {
79 JMMCG_TRACE(_T("backtrace_symbols() failure."));
80 }
81 demangled_names_t demangled_names;
82 demangled_names[0]='\0';
83 demangled_names_t::iterator demangled_ptr=demangled_names.begin();
84 for (int j=0; j<num_fn_ptrs_ret; ++j) {
85 demangled_name_t demangled_name;
86 demangled_name[0]='\0';
87 demangle_name(fn_strings.ptr[j], demangled_name);
88 ::strcpy(demangled_ptr, demangled_name);
89 demangled_ptr+=strlen(demangled_name);
90 *demangled_ptr='\n';
91 ++demangled_ptr;
92 }
93 *demangled_ptr='\0';
94 return demangled_names;
95 }
96
97 inline char const * SIG_to_string(int signal_number) noexcept(true) {
98 static char const * const signal_names[]={
99 "SIGILL /* Illegal instruction (ANSI). */",
100 "SIGABRT /* Abort (ANSI). */",
101 "SIGBUS /* BUS error (4.2 BSD). */",
102 "SIGFPE /* Floating-point exception (ANSI). */",
103 "SIGSEGV /* Segmentation violation (ANSI). */",
104 "SIGSTKFLT /* Stack fault. */",
105 "SIGSYS /* Bad system call. */",
106 "unknown"
107 };
108 switch (signal_number) {
109 case SIGILL:
110 return signal_names[0];
111 case SIGABRT:
112 return signal_names[1];
113 case SIGBUS:
114 return signal_names[2];
115 case SIGFPE:
116 return signal_names[3];
117 case SIGSEGV:
118 return signal_names[4];
119 case SIGSTKFLT:
120 return signal_names[5];
121 case SIGSYS:
122 return signal_names[6];
123 default:
124 return signal_names[7];
125 };
126 }
127
128 inline std::ostream &
129 operator<<(std::ostream &os, siginfo_t const &si) noexcept(true) {
130 os
131 <<"Signal number=0x"<<std::hex<<si.si_signo
132 <<", "<<TStringToString(dump_crt_errno(si.si_errno))
133 <<", signal code=0x"<<std::hex<<si.si_code;
134 return os;
135 }
136
137 extern "C" inline void abort_handler(int signal_number, siginfo_t *info, void *) noexcept(true) {
138 try {
139
140 std::cerr<<"Signal trapped=0x"<<std::hex<<signal_number<<_T(", ")<<SIG_to_string(signal_number)<<std::endl
141 <<*info<<std::endl
142 <<api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::gen_backtrace().begin()<<std::endl;
143 } catch (...) {
144 std::cerr<<"Error with backtracing..."<<std::endl;
145 }
146 ::abort();
147 }
148
149 template<> inline void __fastcall
150 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::set_backtrace_on_signal() noexcept(true) {
151 struct sigaction new_sa;
152 sigemptyset(&new_sa.sa_mask);
153 new_sa.sa_handler=nullptr;
154 new_sa.sa_sigaction=abort_handler;
155 new_sa.sa_flags=0;
156 new_sa.sa_flags&=SA_SIGINFO;
157 [[maybe_unused]] int ret=sigaction(SIGABRT, &new_sa, 0);
158 assert(ret==0);
159 ret=sigaction(SIGILL, &new_sa, 0);
160 assert(ret==0);
161 ret=sigaction(SIGTRAP, &new_sa, 0);
162 assert(ret==0);
163 ret=sigaction(SIGABRT, &new_sa, 0);
164 assert(ret==0);
165 ret=sigaction(SIGBUS, &new_sa, 0);
166 assert(ret==0);
167 ret=sigaction(SIGFPE, &new_sa, 0);
168 assert(ret==0);
169 ret=sigaction(SIGSEGV, &new_sa, 0);
170 assert(ret==0);
171 ret=sigaction(SIGSTKFLT, &new_sa, 0);
172 assert(ret==0);
173 ret=sigaction(SIGSYS, &new_sa, 0);
174 assert(ret==0);
175 }
176
177 inline void dump_bt_to_cerr() {
178 auto const &bt=api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::gen_backtrace();
179 std::cerr<<bt.begin()<<std::endl;
180 }
181
182 template<> inline void __fastcall
183 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::set_backtrace_on_terminate() noexcept(true) {
184 std::set_terminate(&dump_bt_to_cerr);
185 }
186
187
188
189
190
191
192
193 template<> inline bool __fastcall
194 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::create(const api_params_type::creation_flags creflag, api_params_type &parms) noexcept(true) {
195 parms.id=get_current_thread_id();
196 assert(parms.work_fn);
197 if (creflag==api_params_type::create_running) {
198 (*parms.work_fn)(parms.arglist);
199 }
200 return true;
201 }
202
203 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::api_params_type::suspend_count __fastcall
204 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::suspend(api_params_type const &) noexcept(true) {
205 return static_cast<api_params_type::suspend_count>(0);
206 }
207
208
209 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::api_params_type::suspend_count __fastcall
210 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::resume(api_params_type const &parms) noexcept(true) {
211 (*parms.work_fn)(parms.arglist);
212 return static_cast<api_params_type::suspend_count>(0);
213 }
214
215 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::api_params_type::states __fastcall
216 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::state(api_params_type &) noexcept(true) {
217 return static_cast<api_params_type::states>(api_params_type::no_kernel_thread);
218 }
219
220 template<> inline void __fastcall
221 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::exit(api_params_type::states &) noexcept(true) {
222 }
223
224 template<> inline void __fastcall
225 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::terminate(api_params_type::handle_type) noexcept(false) {
226 }
227
228 template<> inline void __fastcall
229 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::cleanup(api_params_type::handle_type) noexcept(false) {
230 }
231
232 template<> inline void __fastcall
233 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::set_kernel_priority(api_params_type::handle_type, const api_params_type::priority_type) noexcept(false) {
234 }
235
236 template<> inline void __fastcall
237 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::set_kernel_affinity(typename api_params_type::handle_type const, const api_params_type::processor_mask_type) noexcept(false) {
238 }
239
240 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::api_params_type::processor_mask_type __fastcall
241 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::get_kernel_affinity(typename api_params_type::handle_type const) noexcept(false) {
242 return api_params_type::processor_mask_type();
243 }
244
245 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::api_params_type::priority_type __fastcall
246 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::get_kernel_priority(api_params_type::handle_type) noexcept(false) {
247 return api_params_type::normal;
248 }
249
250 template<> inline void __fastcall
251 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::set_cancelstate(api_params_type::thread_cancel_state) noexcept(false) {
252 }
253
254 template<> inline void __fastcall
255 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::sleep(const api_params_type::suspend_period_ms) noexcept(false) {
256 }
257
258 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::api_params_type::states __fastcall
259 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::wait_thread_exit(api_params_type &, const lock_traits::timeout_type) noexcept(false) {
260 return api_params_type::no_kernel_thread;
261 }
262
263 template<> inline bool
264 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::create(const api_params_type::creation_flags, api_params_type &cp) noexcept(true) {
265 assert(cp.work_fn);
266 assert(cp.arglist);
267 const int ret=pthread_create(&cp.id, static_cast<const pthread_attr_t *>(cp.initflag), cp.work_fn, cp.arglist);
268 assert(ret==0 && cp.id!=0);
269 return !static_cast<bool>(ret);
270 }
271
272 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::api_params_type::suspend_count
273 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::suspend(api_params_type const &) noexcept(true) {
274 return static_cast<api_params_type::suspend_count>(0);
275 }
276
277 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::api_params_type::suspend_count
278 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::resume(api_params_type const &) noexcept(true) {
279 return static_cast<api_params_type::suspend_count>(0);
280 }
281
282 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::api_params_type::states
283 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::state(api_params_type &thread) noexcept(true) {
284 if (thread.state!=api_params_type::no_kernel_thread) {
285 api_params_type::states exit_code=api_params_type::unknown;
286 const int ret=pthread_tryjoin_np(thread.id, reinterpret_cast<void **>(&exit_code));
287 thread.state=static_cast<api_params_type::states>(exit_code);
288 switch (ret) {
289 case 0:
290 thread.id=0;
291 if (!thread.state) {
292 thread.state=api_params_type::no_kernel_thread;
293 } else if (thread.state==static_cast<api_params_type::states>(reinterpret_cast<long>(PTHREAD_CANCELED))) {
294 thread.state=api_params_type::cancelled;
295 }
296 break;
297 case EDEADLK:
298 thread.state=api_params_type::deadlocked_with_another_thread;
299 break;
300 case EINVAL:
301 thread.state=api_params_type::invalid_thread;
302 break;
303 case ESRCH:
304 thread.state=api_params_type::thread_id_not_found;
305 break;
306 case EBUSY:
307 thread.state=api_params_type::active;
308 break;
309 default:
310 thread.state=api_params_type::get_exit_code_failure;
311 }
312 return thread.state;
313 } else {
314 return thread.state;
315 }
316 }
317
318 template<> inline bool __fastcall
319 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::is_running(api_params_type &thread) noexcept(true) {
320 api_params_type::states const st=state(thread);
321 return st==api_params_type::active || st==api_params_type::deadlocked_with_another_thread;
322 }
323
324 template<> inline void
325 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::exit(api_params_type::states &exit_code) noexcept(true) {
326 pthread_exit(static_cast<void *>(&exit_code));
327 }
328
329 template<> inline void
330 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::terminate(api_params_type::handle_type thread) noexcept(false) {
331 assert(thread);
332 const int pth_err=pthread_cancel(thread);
333 if (pth_err) {
334 assert(pth_err==ESRCH);
335 info::function fun(__LINE__, __PRETTY_FUNCTION__, typeid(void), info::function::argument(_T("api_params_type::handle_type thread"), tostring(thread)));
336 fun.add_arg(info::function::argument(_T("Return code"), tostring(pth_err)));
337 throw lock_traits::exception_type(_T("Could not send a cancel request to the thread."), fun, JMMCG_REVISION_HDR(_T("$Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/unix/thread_api_traits_impl.hpp 2288 2018-06-25 17:15:01Z jmmcg $")));
338 }
339 }
340
341 template<> inline void
342 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::cleanup(api_params_type::handle_type thread) noexcept(false) {
343 if (thread) {
344 void *exit_code_p=reinterpret_cast<void *>(api_params_type::unknown);
345 const int pth_err=pthread_join(thread, &exit_code_p);
346 const api_params_type::states exit_code=static_cast<api_params_type::states>(reinterpret_cast<long>(exit_code_p));
347 if (pth_err) {
348 info::function fun(__LINE__, __PRETTY_FUNCTION__, typeid(void), info::function::argument(_T("api_params_type::handle_type thread"), tostring(thread)));
349 fun.add_arg(info::function::argument(_T("Return code"), tostring(pth_err)));
350 fun.add_arg(info::function::argument(_T("Return code from thread"), tostring(exit_code)));
351 throw lock_traits::exception_type(_T("Could not join with the requested thread."), fun, JMMCG_REVISION_HDR(_T("$Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/unix/thread_api_traits_impl.hpp 2288 2018-06-25 17:15:01Z jmmcg $")));
352 }
353 }
354 }
355
356 template<> inline void
357 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::set_kernel_priority(api_params_type::handle_type, const api_params_type::priority_type priority) noexcept(false) {
358
359 const int schedule_policy=sched_getscheduler(0);
360 if (schedule_policy!=-1) {
361 const int max_priority=sched_get_priority_max(schedule_policy);
362 const int min_priority=sched_get_priority_min(schedule_policy);
363 if ((max_priority!=-1) && (min_priority!=-1)) {
364 sched_param param;
365 int err=sched_getparam(0, ¶m);
366 if (err!=-1) {
367 const int checked_priority=(std::min(std::max(static_cast<int>(priority), min_priority), max_priority));
368 param.sched_priority=checked_priority;
369 err=sched_setparam(0, ¶m);
370 if (err!=-1) {
371 return;
372 } else {
373 throw lock_traits::exception_type(_T("Failed to set the new priority."), info::function(__LINE__, __PRETTY_FUNCTION__, typeid(void), info::function::argument(_T("api_params_type::priority_type priority"), tostring(priority))), JMMCG_REVISION_HDR(_T("$Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/unix/thread_api_traits_impl.hpp 2288 2018-06-25 17:15:01Z jmmcg $")));
374 }
375 } else {
376 throw lock_traits::exception_type(_T("Failed to get the existing scheduler details."), info::function(__LINE__, __PRETTY_FUNCTION__, typeid(void), info::function::argument(_T("api_params_type::priority_type priority"), tostring(priority))), JMMCG_REVISION_HDR(_T("$Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/unix/thread_api_traits_impl.hpp 2288 2018-06-25 17:15:01Z jmmcg $")));
377 }
378 } else {
379 throw lock_traits::exception_type(_T("Failed to get the max & min priorities of the scheduler."), info::function(__LINE__, __PRETTY_FUNCTION__, typeid(void), info::function::argument(_T("api_params_type::priority_type priority"), tostring(priority))), JMMCG_REVISION_HDR(_T("$Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/unix/thread_api_traits_impl.hpp 2288 2018-06-25 17:15:01Z jmmcg $")));
380 }
381 } else {
382 throw lock_traits::exception_type(_T("Failed to get the type of scheduler in use."), info::function(__LINE__, __PRETTY_FUNCTION__, typeid(void), info::function::argument(_T("api_params_type::priority_type priority"), tostring(priority))), JMMCG_REVISION_HDR(_T("$Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/unix/thread_api_traits_impl.hpp 2288 2018-06-25 17:15:01Z jmmcg $")));
383 }
384 }
385
386 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::api_params_type::priority_type
387 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::get_kernel_priority(api_params_type::handle_type thread) noexcept(false) {
388 sched_param param;
389 const int err=sched_getparam(0, ¶m);
390 if (err!=-1) {
391 return static_cast<api_params_type::priority_type>(param.sched_priority);
392 } else {
393 info::function fun(__LINE__, __PRETTY_FUNCTION__, typeid(void), info::function::argument(_T("typename api_params_type::handle_type thread"), tostring(thread)));
394 fun.add_arg(info::function::argument(_T("Return code"), tostring(err)));
395 throw lock_traits::exception_type(_T("Could not get the kernel priority of the specified thread."), fun, JMMCG_REVISION_HDR(_T("$Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/unix/thread_api_traits_impl.hpp 2288 2018-06-25 17:15:01Z jmmcg $")));
396 }
397 }
398
399 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::api_params_type::pid_type
400 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::get_current_process_id() noexcept(true) {
401 return getpid();
402 }
403
404 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::api_params_type::tid_type
405 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::get_current_thread_id() noexcept(true) {
406 return pthread_self();
407 }
408
409 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::api_params_type::handle_type
410 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::get_current_thread() noexcept(true) {
411 return pthread_self();
412 }
413
414 template<> inline void __fastcall
415 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::set_kernel_affinity(typename api_params_type::handle_type const thread_id, api_params_type::processor_mask_type const mask) noexcept(false) {
416 const int pth_err=pthread_setaffinity_np(thread_id, sizeof(api_params_type::processor_mask_type), &mask.mask());
417 if (pth_err) {
418 info::function fun(__LINE__, __PRETTY_FUNCTION__, typeid(void), info::function::argument(_T("typename api_params_type::handle_type const thread_id"), tostring(thread_id)));
419 fun.add_arg(info::function::argument(_T("api_params_type::processor_mask_type const mask"), tostring(mask)));
420 fun.add_arg(info::function::argument(_T("Return code"), tostring(pth_err)));
421 throw lock_traits::exception_type(_T("Could not set the kernel affinity of the specified thread."), fun, JMMCG_REVISION_HDR(_T("$Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/unix/thread_api_traits_impl.hpp 2288 2018-06-25 17:15:01Z jmmcg $")));
422 }
423 }
424
425 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::api_params_type::processor_mask_type __fastcall
426 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::get_kernel_affinity(typename api_params_type::handle_type const thread_id) noexcept(false) {
427 api_params_type::processor_mask_type mask;
428 const int pth_err=pthread_getaffinity_np(thread_id, sizeof(api_params_type::processor_mask_type), &mask.mask());
429 if (pth_err) {
430 info::function fun(__LINE__, __PRETTY_FUNCTION__, typeid(void), info::function::argument(_T("typename api_params_type::handle_type const thread_id"), tostring(thread_id)));
431 fun.add_arg(info::function::argument(_T("Return code"), tostring(pth_err)));
432 throw lock_traits::exception_type(_T("Could not get the kernel affinity of the specified thread."), fun, JMMCG_REVISION_HDR(_T("$Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/unix/thread_api_traits_impl.hpp 2288 2018-06-25 17:15:01Z jmmcg $")));
433 }
434 return mask;
435 }
436
437 template<> inline void __fastcall
438 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::set_cancelstate(api_params_type::thread_cancel_state state) noexcept(false) {
439 int old_state;
440 const int pth_err=pthread_setcancelstate(state, &old_state);
441 if (pth_err) {
442 info::function fun(__LINE__, __PRETTY_FUNCTION__, typeid(void), info::function::argument(_T("api_params_type::thread_cancel_state state"), tostring(state)));
443 fun.add_arg(info::function::argument(_T("Return code"), tostring(pth_err)));
444 throw lock_traits::exception_type(_T("Could not set the cancel state of the current thread."), fun, JMMCG_REVISION_HDR(_T("$Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/unix/thread_api_traits_impl.hpp 2288 2018-06-25 17:15:01Z jmmcg $")));
445 }
446 }
447
448 template<> inline void
449 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::sleep(const api_params_type::suspend_period_ms period) noexcept(false) {
450 if (period) {
451 assert(period<=std::numeric_limits<api_params_type::suspend_period_ms>::max()/1000);
452 const timespec period_ns={
453 static_cast<long>(period/1000),
454 static_cast<long>((period%1000)*1000000)
455 };
456 timespec requested;
457 const int err=::nanosleep(&period_ns, &requested);
458 if (err) {
459 info::function fun(__LINE__, __PRETTY_FUNCTION__, typeid(void), info::function::argument(_T("api_params_type::suspend_period_ms period"), tostring(period)));
460 fun.add_arg(info::function::argument(_T("Return code"), tostring(err)));
461 throw lock_traits::exception_type(_T("Could not suspend for the requested period."), fun, JMMCG_REVISION_HDR(_T("$Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/unix/thread_api_traits_impl.hpp 2288 2018-06-25 17:15:01Z jmmcg $")));
462 }
463 } else {
464 const int err=::sched_yield();
465 if (err) {
466 info::function fun(__LINE__, __PRETTY_FUNCTION__, typeid(void), info::function::argument(_T("api_params_type::suspend_period_ms period"), tostring(period)));
467 fun.add_arg(info::function::argument(_T("Return code"), tostring(err)));
468 throw lock_traits::exception_type(_T("Period of zero implies a yield, which failed."), fun, JMMCG_REVISION_HDR(_T("$Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/unix/thread_api_traits_impl.hpp 2288 2018-06-25 17:15:01Z jmmcg $")));
469 }
470 }
471 }
472
473 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::api_params_type::states
474 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::wait_thread_exit(api_params_type &thread, const lock_traits::timeout_type) noexcept(false) {
475 if (thread.id) {
476 api_params_type::states exit_code=api_params_type::unknown;
477 assert(thread.detach_state()==api_params_type::joinable);
478
479 const int ret=pthread_join(thread.id, reinterpret_cast<void **>(&exit_code));
480 thread.state=exit_code;
481 switch (ret) {
482 case 0:
483 thread.id=0;
484 if (!thread.state) {
485 thread.state=api_params_type::no_kernel_thread;
486 }
487 break;
488 case EDEADLK:
489 thread.state=api_params_type::deadlocked_with_another_thread;
490 break;
491 case EINVAL:
492 thread.state=api_params_type::invalid_thread;
493 break;
494 case ESRCH:
495 thread.state=api_params_type::thread_id_not_found;
496 break;
497 case EBUSY:
498 thread.state=api_params_type::active;
499 break;
500 default:
501 thread.state=api_params_type::get_exit_code_failure;
502 }
503 return thread.state;
504 } else {
505 return thread.state;
506 }
507 }
508
509 template<> inline void __fastcall
510 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::demangle_name(char * const mangled_name, demangled_name_t &demangled_name) noexcept(true) {
511 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::demangle_name(mangled_name, demangled_name);
512 }
513
514 template<> inline api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::demangled_names_t __fastcall
515 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::gen_backtrace() noexcept(true) {
516 return api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::gen_backtrace();
517 }
518
519 template<> inline void __fastcall
520 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::set_backtrace_on_signal() noexcept(true) {
521 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::set_backtrace_on_signal();
522 }
523
524 template<> inline void __fastcall
525 api_threading_traits<generic_traits::api_type::posix_pthreads, heavyweight_threading>::set_backtrace_on_terminate() noexcept(true) {
526 api_threading_traits<generic_traits::api_type::posix_pthreads, sequential_mode>::set_backtrace_on_terminate();
527 }
528
529 } }