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