| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367 |
- /*
- This file is part of libmicrohttpd
- Copyright (C) 2016 Karlson2k (Evgeny Grin)
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- /**
- * @file microhttpd/mhd_threads.c
- * @brief Implementation for thread functions
- * @author Karlson2k (Evgeny Grin)
- */
- #include "mhd_threads.h"
- #ifdef MHD_USE_W32_THREADS
- #include "mhd_limits.h"
- #include <process.h>
- #endif
- #ifdef MHD_USE_THREAD_NAME_
- #include <stdlib.h>
- #ifdef HAVE_PTHREAD_NP_H
- #include <pthread_np.h>
- #endif /* HAVE_PTHREAD_NP_H */
- #endif /* MHD_USE_THREAD_NAME_ */
- #include <errno.h>
- #ifndef MHD_USE_THREAD_NAME_
- #define MHD_set_thread_name_(t, n) (void)
- #define MHD_set_cur_thread_name_(n) (void)
- #else /* MHD_USE_THREAD_NAME_ */
- #if defined(MHD_USE_POSIX_THREADS)
- #if defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD) || \
- defined(HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI)
- # define MHD_USE_THREAD_ATTR_SETNAME 1
- #endif /* HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD || HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI */
- #if defined(HAVE_PTHREAD_SETNAME_NP_GNU) || \
- defined(HAVE_PTHREAD_SET_NAME_NP_FREEBSD) \
- || defined(HAVE_PTHREAD_SETNAME_NP_NETBSD)
- /**
- * Set thread name
- *
- * @param thread_id ID of thread
- * @param thread_name name to set
- * @return non-zero on success, zero otherwise
- */
- static int
- MHD_set_thread_name_ (const MHD_thread_ID_ thread_id,
- const char *thread_name)
- {
- if (NULL == thread_name)
- return 0;
- #if defined(HAVE_PTHREAD_SETNAME_NP_GNU)
- return ! pthread_setname_np (thread_id, thread_name);
- #elif defined(HAVE_PTHREAD_SET_NAME_NP_FREEBSD)
- /* FreeBSD and OpenBSD use different name and void return type */
- pthread_set_name_np (thread_id, thread_name);
- return ! 0;
- #elif defined(HAVE_PTHREAD_SETNAME_NP_NETBSD)
- /* NetBSD use 3 arguments: second argument is string in printf-like format,
- * third argument is single argument for printf;
- * OSF1 use 3 arguments too, but last one always must be zero (NULL).
- * MHD doesn't use '%' in thread names, so both form are used in same way.
- */return ! pthread_setname_np (thread_id, thread_name, 0);
- #endif /* HAVE_PTHREAD_SETNAME_NP_NETBSD */
- }
- #ifndef __QNXNTO__
- /**
- * Set current thread name
- * @param n name to set
- * @return non-zero on success, zero otherwise
- */
- #define MHD_set_cur_thread_name_(n) MHD_set_thread_name_ (pthread_self (),(n))
- #else /* __QNXNTO__ */
- /* Special case for QNX Neutrino - using zero for thread ID sets name faster. */
- #define MHD_set_cur_thread_name_(n) MHD_set_thread_name_ (0,(n))
- #endif /* __QNXNTO__ */
- #elif defined(HAVE_PTHREAD_SETNAME_NP_DARWIN)
- /**
- * Set current thread name
- * @param n name to set
- * @return non-zero on success, zero otherwise
- */
- #define MHD_set_cur_thread_name_(n) (! (pthread_setname_np ((n))))
- #endif /* HAVE_PTHREAD_SETNAME_NP_DARWIN */
- #elif defined(MHD_USE_W32_THREADS)
- #ifndef _MSC_FULL_VER
- /* Thread name available only for VC-compiler */
- #else /* _MSC_FULL_VER */
- /**
- * Set thread name
- *
- * @param thread_id ID of thread, -1 for current thread
- * @param thread_name name to set
- * @return non-zero on success, zero otherwise
- */
- static int
- MHD_set_thread_name_ (const MHD_thread_ID_ thread_id,
- const char *thread_name)
- {
- static const DWORD VC_SETNAME_EXC = 0x406D1388;
- #pragma pack(push,8)
- struct thread_info_struct
- {
- DWORD type; /* Must be 0x1000. */
- LPCSTR name; /* Pointer to name (in user address space). */
- DWORD ID; /* Thread ID (-1 = caller thread). */
- DWORD flags; /* Reserved for future use, must be zero. */
- } thread_info;
- #pragma pack(pop)
- if (NULL == thread_name)
- return 0;
- thread_info.type = 0x1000;
- thread_info.name = thread_name;
- thread_info.ID = thread_id;
- thread_info.flags = 0;
- __try
- { /* This exception is intercepted by debugger */
- RaiseException (VC_SETNAME_EXC,
- 0,
- sizeof (thread_info) / sizeof(ULONG_PTR),
- (ULONG_PTR *) &thread_info);
- }
- __except (EXCEPTION_EXECUTE_HANDLER)
- {}
- return ! 0;
- }
- /**
- * Set current thread name
- * @param n name to set
- * @return non-zero on success, zero otherwise
- */
- #define MHD_set_cur_thread_name_(n) MHD_set_thread_name_ (-1,(n))
- #endif /* _MSC_FULL_VER */
- #endif /* MHD_USE_W32_THREADS */
- #endif /* MHD_USE_THREAD_NAME_ */
- /**
- * Create a thread and set the attributes according to our options.
- *
- * @param thread handle to initialize
- * @param stack_size size of stack for new thread, 0 for default
- * @param start_routine main function of thread
- * @param arg argument for start_routine
- * @return non-zero on success; zero otherwise (with errno set)
- */
- int
- MHD_create_thread_ (MHD_thread_handle_ID_ *thread,
- size_t stack_size,
- MHD_THREAD_START_ROUTINE_ start_routine,
- void *arg)
- {
- #if defined(MHD_USE_POSIX_THREADS)
- int res;
- if (0 != stack_size)
- {
- pthread_attr_t attr;
- res = pthread_attr_init (&attr);
- if (0 == res)
- {
- res = pthread_attr_setstacksize (&attr,
- stack_size);
- if (0 == res)
- res = pthread_create (&(thread->handle),
- &attr,
- start_routine,
- arg);
- pthread_attr_destroy (&attr);
- }
- }
- else
- res = pthread_create (&(thread->handle),
- NULL,
- start_routine,
- arg);
- if (0 != res)
- errno = res;
- return ! res;
- #elif defined(MHD_USE_W32_THREADS)
- #if SIZE_MAX != UINT_MAX
- if (stack_size > UINT_MAX)
- {
- errno = EINVAL;
- return 0;
- }
- #endif /* SIZE_MAX != UINT_MAX */
- thread->handle = (MHD_thread_handle_)
- _beginthreadex (NULL,
- (unsigned int) stack_size,
- start_routine,
- arg,
- 0,
- NULL);
- if ((MHD_thread_handle_) - 1 == thread->handle)
- return 0;
- return ! 0;
- #endif
- }
- #ifdef MHD_USE_THREAD_NAME_
- #ifndef MHD_USE_THREAD_ATTR_SETNAME
- struct MHD_named_helper_param_
- {
- /**
- * Real thread start routine
- */
- MHD_THREAD_START_ROUTINE_ start_routine;
- /**
- * Argument for thread start routine
- */
- void *arg;
- /**
- * Name for thread
- */
- const char *name;
- };
- static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
- named_thread_starter (void *data)
- {
- struct MHD_named_helper_param_ *const param =
- (struct MHD_named_helper_param_ *) data;
- void *arg;
- MHD_THREAD_START_ROUTINE_ thr_func;
- if (NULL == data)
- return (MHD_THRD_RTRN_TYPE_) 0;
- MHD_set_cur_thread_name_ (param->name);
- arg = param->arg;
- thr_func = param->start_routine;
- free (data);
- return thr_func (arg);
- }
- #endif /* ! MHD_USE_THREAD_ATTR_SETNAME */
- /**
- * Create a named thread and set the attributes according to our options.
- *
- * @param thread handle to initialize
- * @param thread_name name for new thread
- * @param stack_size size of stack for new thread, 0 for default
- * @param start_routine main function of thread
- * @param arg argument for start_routine
- * @return non-zero on success; zero otherwise (with errno set)
- */
- int
- MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread,
- const char*thread_name,
- size_t stack_size,
- MHD_THREAD_START_ROUTINE_ start_routine,
- void *arg)
- {
- #if defined(MHD_USE_THREAD_ATTR_SETNAME)
- int res;
- pthread_attr_t attr;
- res = pthread_attr_init (&attr);
- if (0 == res)
- {
- #if defined(HAVE_PTHREAD_ATTR_SETNAME_NP_NETBSD)
- /* NetBSD use 3 arguments: second argument is string in printf-like format,
- * third argument is single argument for printf;
- * OSF1 use 3 arguments too, but last one always must be zero (NULL).
- * MHD doesn't use '%' in thread names, so both form are used in same way.
- */res = pthread_attr_setname_np (&attr, thread_name, 0);
- #elif defined(HAVE_PTHREAD_ATTR_SETNAME_NP_IBMI)
- res = pthread_attr_setname_np (&attr, thread_name);
- #else
- #error No pthread_attr_setname_np() function.
- #endif
- if ((res == 0) && (0 != stack_size) )
- res = pthread_attr_setstacksize (&attr,
- stack_size);
- if (0 == res)
- res = pthread_create (&(thread->handle),
- &attr,
- start_routine,
- arg);
- pthread_attr_destroy (&attr);
- }
- if (0 != res)
- errno = res;
- return ! res;
- #else /* ! MHD_USE_THREAD_ATTR_SETNAME */
- struct MHD_named_helper_param_ *param;
- if (NULL == thread_name)
- {
- errno = EINVAL;
- return 0;
- }
- param = malloc (sizeof (struct MHD_named_helper_param_));
- if (NULL == param)
- return 0;
- param->start_routine = start_routine;
- param->arg = arg;
- param->name = thread_name;
- /* Set thread name in thread itself to avoid problems with
- * threads which terminated before name is set in other thread.
- */
- if (! MHD_create_thread_ (thread,
- stack_size,
- &named_thread_starter,
- (void*) param))
- {
- free (param);
- return 0;
- }
- return ! 0;
- #endif /* ! MHD_USE_THREAD_ATTR_SETNAME */
- }
- #endif /* MHD_USE_THREAD_NAME_ */
|