mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
Refactored threads support
Some platforms do not have any "invalid" value of thread handle/ID. Added tracking of the thread initialisation on such platforms to avoid accidental match with uninitialised value.
This commit is contained in:
@@ -1151,7 +1151,7 @@ MHD_connection_close_ (struct MHD_Connection *connection,
|
||||
mhd_assert (! connection->suspended);
|
||||
#ifdef MHD_USE_THREADS
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
MHD_thread_ID_is_current_thread_ (connection->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (connection->tid) );
|
||||
#endif /* MHD_USE_THREADS */
|
||||
if ( (NULL != daemon->notify_completed) &&
|
||||
(connection->rq.client_aware) )
|
||||
@@ -1195,7 +1195,7 @@ MHD_connection_finish_forward_ (struct MHD_Connection *connection)
|
||||
#ifdef MHD_USE_THREADS
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
(0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
|
||||
MHD_thread_ID_is_current_thread_ (daemon->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
|
||||
#endif /* MHD_USE_THREADS */
|
||||
|
||||
if (0 == (daemon->options & MHD_USE_TLS))
|
||||
@@ -6249,7 +6249,7 @@ cleanup_connection (struct MHD_Connection *connection)
|
||||
struct MHD_Daemon *daemon = connection->daemon;
|
||||
#ifdef MHD_USE_THREADS
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
MHD_thread_ID_is_current_thread_ (connection->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (connection->tid) );
|
||||
mhd_assert (NULL == daemon->worker_pool);
|
||||
#endif /* MHD_USE_THREADS */
|
||||
|
||||
@@ -6456,7 +6456,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
|
||||
enum MHD_Result ret;
|
||||
#ifdef MHD_USE_THREADS
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
MHD_thread_ID_is_current_thread_ (connection->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (connection->tid) );
|
||||
#endif /* MHD_USE_THREADS */
|
||||
/* 'daemon' is not used if epoll is not available and asserts are disabled */
|
||||
(void) daemon; /* Mute compiler warning */
|
||||
@@ -7140,7 +7140,7 @@ MHD_queue_response (struct MHD_Connection *connection,
|
||||
#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
|
||||
if ( (! connection->suspended) &&
|
||||
(0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
|
||||
(! MHD_thread_ID_is_current_thread_ (connection->tid)) )
|
||||
(! MHD_thread_handle_ID_is_current_thread_ (connection->tid)) )
|
||||
{
|
||||
#ifdef HAVE_MESSAGES
|
||||
MHD_DLOG (daemon,
|
||||
|
||||
+73
-18
@@ -1171,6 +1171,13 @@ call_handlers (struct MHD_Connection *con,
|
||||
bool on_fasttrack = (con->state == MHD_CONNECTION_INIT);
|
||||
ret = MHD_YES;
|
||||
|
||||
mhd_assert ((0 == (con->daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
|
||||
(MHD_thread_handle_ID_is_valid_ID_ (con->tid)));
|
||||
mhd_assert ((0 != (con->daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
|
||||
(! MHD_thread_handle_ID_is_valid_ID_ (con->tid)));
|
||||
mhd_assert ((0 == (con->daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
|
||||
(MHD_thread_handle_ID_is_current_thread_ (con->tid)));
|
||||
|
||||
#ifdef HTTPS_SUPPORT
|
||||
if (con->tls_read_ready)
|
||||
read_ready = true;
|
||||
@@ -1322,7 +1329,7 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
|
||||
|
||||
#ifdef MHD_USE_THREADS
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
MHD_thread_ID_is_current_thread_ (connection->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (connection->tid) );
|
||||
#endif /* MHD_USE_THREADS */
|
||||
if (daemon->shutdown)
|
||||
{
|
||||
@@ -1670,7 +1677,7 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
|
||||
struct MHD_Daemon *daemon = con->daemon;
|
||||
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
MHD_thread_ID_is_current_thread_ (con->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (con->tid) );
|
||||
/* Here, we need to bi-directionally forward
|
||||
until the application tells us that it is done
|
||||
with the socket; */
|
||||
@@ -1896,7 +1903,7 @@ thread_main_handle_connection (void *data)
|
||||
const bool use_poll = 0;
|
||||
#endif /* ! HAVE_POLL */
|
||||
bool was_suspended = false;
|
||||
MHD_thread_init_ (&(con->tid));
|
||||
MHD_thread_handle_ID_set_current_thread_ID_ (&(con->tid));
|
||||
|
||||
while ( (! daemon->shutdown) &&
|
||||
(MHD_CONNECTION_CLOSED != con->state) )
|
||||
@@ -2524,6 +2531,9 @@ new_connection_prepare_ (struct MHD_Daemon *daemon,
|
||||
connection->sk_nonblck = non_blck;
|
||||
connection->is_nonip = sk_is_nonip;
|
||||
connection->sk_spipe_suppress = sk_spipe_supprs;
|
||||
#ifdef MHD_USE_THREADS
|
||||
MHD_thread_handle_ID_set_invalid_ (&connection->tid);
|
||||
#endif /* MHD_USE_THREADS */
|
||||
connection->daemon = daemon;
|
||||
connection->connection_timeout_ms = daemon->connection_timeout_ms;
|
||||
connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
|
||||
@@ -2743,7 +2753,7 @@ new_connection_process_ (struct MHD_Daemon *daemon,
|
||||
/* Function manipulate connection and timeout DL-lists,
|
||||
* must be called only within daemon thread. */
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
MHD_thread_ID_is_current_thread_ (daemon->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
|
||||
mhd_assert (NULL == daemon->worker_pool);
|
||||
#endif /* MHD_USE_THREADS */
|
||||
|
||||
@@ -3102,7 +3112,7 @@ internal_suspend_connection_ (struct MHD_Connection *connection)
|
||||
#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
(0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
|
||||
MHD_thread_ID_is_current_thread_ (daemon->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
#endif
|
||||
if (connection->resuming)
|
||||
@@ -3199,7 +3209,7 @@ MHD_suspend_connection (struct MHD_Connection *connection)
|
||||
#ifdef MHD_USE_THREADS
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
(0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
|
||||
MHD_thread_ID_is_current_thread_ (daemon->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
|
||||
#endif /* MHD_USE_THREADS */
|
||||
|
||||
if (0 == (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME))
|
||||
@@ -3323,7 +3333,7 @@ resume_suspended_connections (struct MHD_Daemon *daemon)
|
||||
#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
|
||||
mhd_assert (NULL == daemon->worker_pool);
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
MHD_thread_ID_is_current_thread_ (daemon->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
|
||||
#endif
|
||||
|
||||
ret = MHD_NO;
|
||||
@@ -3664,7 +3674,7 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
|
||||
|
||||
#ifdef MHD_USE_THREADS
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
MHD_thread_ID_is_current_thread_ (daemon->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
|
||||
mhd_assert (NULL == daemon->worker_pool);
|
||||
#endif /* MHD_USE_THREADS */
|
||||
|
||||
@@ -3888,7 +3898,7 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
|
||||
struct MHD_Connection *pos;
|
||||
#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
MHD_thread_ID_is_current_thread_ (daemon->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
|
||||
mhd_assert (NULL == daemon->worker_pool);
|
||||
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
@@ -3902,7 +3912,7 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
|
||||
(! pos->thread_joined) &&
|
||||
(! MHD_join_thread_tid_ (&pos->tid)) )
|
||||
(! MHD_thread_handle_ID_join_thread_ (pos->tid)) )
|
||||
MHD_PANIC (_ ("Failed to join a thread.\n"));
|
||||
#endif
|
||||
#ifdef UPGRADE_SUPPORT
|
||||
@@ -4075,7 +4085,7 @@ MHD_get_timeout64 (struct MHD_Daemon *daemon,
|
||||
|
||||
#ifdef MHD_USE_THREADS
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
MHD_thread_ID_is_current_thread_ (daemon->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
|
||||
#endif /* MHD_USE_THREADS */
|
||||
|
||||
if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
|
||||
@@ -4340,6 +4350,13 @@ internal_run_from_select (struct MHD_Daemon *daemon,
|
||||
(fd_set *) _MHD_DROP_CONST (read_fd_set))) )
|
||||
MHD_itc_clear_ (daemon->itc);
|
||||
|
||||
mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
|
||||
(MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
|
||||
mhd_assert ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
|
||||
(! MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
|
||||
mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
|
||||
(MHD_thread_handle_ID_is_current_thread_ (daemon->tid)));
|
||||
|
||||
/* Process externally added connection if any */
|
||||
if (daemon->have_new)
|
||||
new_connections_list_process_ (daemon);
|
||||
@@ -4693,6 +4710,13 @@ MHD_poll_all (struct MHD_Daemon *daemon,
|
||||
struct MHD_UpgradeResponseHandle *urhn;
|
||||
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
|
||||
|
||||
mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
|
||||
(MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
|
||||
mhd_assert ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
|
||||
(! MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
|
||||
mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
|
||||
(MHD_thread_handle_ID_is_current_thread_ (daemon->tid)));
|
||||
|
||||
if ( (0 != (daemon->options & MHD_TEST_ALLOW_SUSPEND_RESUME)) &&
|
||||
(MHD_NO != resume_suspended_connections (daemon)) )
|
||||
millisec = 0;
|
||||
@@ -4907,6 +4931,9 @@ MHD_poll_listen_socket (struct MHD_Daemon *daemon,
|
||||
int poll_itc_idx;
|
||||
MHD_socket ls;
|
||||
|
||||
mhd_assert (MHD_thread_handle_ID_is_valid_ID_ (daemon->tid));
|
||||
mhd_assert (MHD_thread_handle_ID_is_current_thread_ (daemon->tid));
|
||||
|
||||
memset (&p,
|
||||
0,
|
||||
sizeof (p));
|
||||
@@ -5070,7 +5097,7 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon)
|
||||
|
||||
#ifdef MHD_USE_THREADS
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
MHD_thread_ID_is_current_thread_ (daemon->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
|
||||
#endif /* MHD_USE_THREADS */
|
||||
|
||||
num_events = MAX_EVENTS;
|
||||
@@ -5209,6 +5236,13 @@ MHD_epoll (struct MHD_Daemon *daemon,
|
||||
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
|
||||
bool need_to_accept;
|
||||
|
||||
mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
|
||||
(MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
|
||||
mhd_assert ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
|
||||
(! MHD_thread_handle_ID_is_valid_ID_ (daemon->tid)));
|
||||
mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
|
||||
(MHD_thread_handle_ID_is_current_thread_ (daemon->tid)));
|
||||
|
||||
if (-1 == daemon->epoll_fd)
|
||||
return MHD_NO; /* we're down! */
|
||||
if (daemon->shutdown)
|
||||
@@ -5569,6 +5603,8 @@ MHD_run_wait (struct MHD_Daemon *daemon,
|
||||
(0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) )
|
||||
return MHD_NO;
|
||||
|
||||
mhd_assert (! MHD_thread_handle_ID_is_valid_handle_ (daemon->tid));
|
||||
|
||||
if (0 > millisec)
|
||||
millisec = -1;
|
||||
#ifdef HAVE_POLL
|
||||
@@ -5611,7 +5647,7 @@ close_connection (struct MHD_Connection *pos)
|
||||
|
||||
#ifdef MHD_USE_THREADS
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
MHD_thread_ID_is_current_thread_ (daemon->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
|
||||
mhd_assert (NULL == daemon->worker_pool);
|
||||
#endif /* MHD_USE_THREADS */
|
||||
|
||||
@@ -5665,7 +5701,7 @@ MHD_polling_thread (void *cls)
|
||||
int err;
|
||||
#endif /* HAVE_PTHREAD_SIGMASK */
|
||||
|
||||
MHD_thread_init_ (&(daemon->tid));
|
||||
MHD_thread_handle_ID_set_current_thread_ID_ (&(daemon->tid));
|
||||
#ifdef HAVE_PTHREAD_SIGMASK
|
||||
if ((0 == sigemptyset (&s_mask)) &&
|
||||
(0 == sigaddset (&s_mask, SIGPIPE)))
|
||||
@@ -7173,6 +7209,9 @@ MHD_start_daemon_va (unsigned int flags,
|
||||
daemon->unescape_callback = &unescape_wrapper;
|
||||
daemon->connection_timeout_ms = 0; /* no timeout */
|
||||
MHD_itc_set_invalid_ (daemon->itc);
|
||||
#ifdef MHD_USE_THREADS
|
||||
MHD_thread_handle_ID_set_invalid_ (&daemon->tid);
|
||||
#endif /* MHD_USE_THREADS */
|
||||
#ifdef SOMAXCONN
|
||||
daemon->listen_backlog_size = SOMAXCONN;
|
||||
#else /* !SOMAXCONN */
|
||||
@@ -8175,7 +8214,7 @@ close_all_connections (struct MHD_Daemon *daemon)
|
||||
#ifdef MHD_USE_THREADS
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
(0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
|
||||
MHD_thread_ID_is_current_thread_ (daemon->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (daemon->tid) );
|
||||
mhd_assert (NULL == daemon->worker_pool);
|
||||
#endif /* MHD_USE_THREADS */
|
||||
mhd_assert (daemon->shutdown);
|
||||
@@ -8288,7 +8327,7 @@ close_all_connections (struct MHD_Daemon *daemon)
|
||||
* MHD_resume_connection() during finishing of "upgraded"
|
||||
* thread. */
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
if (! MHD_join_thread_tid_ (&pos->tid))
|
||||
if (! MHD_thread_handle_ID_join_thread_ (pos->tid))
|
||||
MHD_PANIC (_ ("Failed to join a thread.\n"));
|
||||
pos->thread_joined = true;
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
@@ -8320,7 +8359,7 @@ close_all_connections (struct MHD_Daemon *daemon)
|
||||
if (! pos->thread_joined)
|
||||
{
|
||||
MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
if (! MHD_join_thread_tid_ (&pos->tid))
|
||||
if (! MHD_thread_handle_ID_join_thread_ (pos->tid))
|
||||
MHD_PANIC (_ ("Failed to join a thread.\n"));
|
||||
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
|
||||
pos->thread_joined = true;
|
||||
@@ -8380,6 +8419,14 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
|
||||
return;
|
||||
if ( (daemon->shutdown) && (NULL == daemon->master) )
|
||||
MHD_PANIC (_ ("MHD_stop_daemon() was called twice."));
|
||||
|
||||
mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
|
||||
(NULL != daemon->worker_pool) || \
|
||||
(MHD_thread_handle_ID_is_valid_handle_ (daemon->tid)));
|
||||
mhd_assert (((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) &&
|
||||
(NULL == daemon->worker_pool)) || \
|
||||
(! MHD_thread_handle_ID_is_valid_handle_ (daemon->tid)));
|
||||
|
||||
/* Slave daemons must be stopped by master daemon. */
|
||||
mhd_assert ( (NULL == daemon->master) || (daemon->shutdown) );
|
||||
|
||||
@@ -8458,7 +8505,7 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
|
||||
mhd_assert (false); /* Should never happen */
|
||||
}
|
||||
|
||||
if (! MHD_join_thread_tid_ (&daemon->tid))
|
||||
if (! MHD_thread_handle_ID_join_thread_ (daemon->tid))
|
||||
{
|
||||
MHD_PANIC (_ ("Failed to join a thread.\n"));
|
||||
}
|
||||
@@ -8556,6 +8603,14 @@ MHD_get_daemon_info (struct MHD_Daemon *daemon,
|
||||
{
|
||||
if (NULL == daemon)
|
||||
return NULL;
|
||||
|
||||
mhd_assert ((0 == (daemon->options & MHD_USE_SELECT_INTERNALLY)) || \
|
||||
(NULL != daemon->worker_pool) || \
|
||||
(MHD_thread_handle_ID_is_valid_handle_ (daemon->tid)));
|
||||
mhd_assert (((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) &&
|
||||
(NULL == daemon->worker_pool)) || \
|
||||
(! MHD_thread_handle_ID_is_valid_handle_ (daemon->tid)));
|
||||
|
||||
switch (info_type)
|
||||
{
|
||||
case MHD_DAEMON_INFO_KEY_SIZE:
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#endif /* HAVE_PTHREAD_NP_H */
|
||||
#endif /* MHD_USE_THREAD_NAME_ */
|
||||
#include <errno.h>
|
||||
#include "mhd_assert.h"
|
||||
|
||||
|
||||
#ifndef MHD_USE_THREAD_NAME_
|
||||
@@ -66,7 +67,7 @@
|
||||
* @return non-zero on success, zero otherwise
|
||||
*/
|
||||
static int
|
||||
MHD_set_thread_name_ (const MHD_thread_ID_ thread_id,
|
||||
MHD_set_thread_name_ (const MHD_thread_ID_native_ thread_id,
|
||||
const char *thread_name)
|
||||
{
|
||||
if (NULL == thread_name)
|
||||
@@ -122,7 +123,7 @@ MHD_set_thread_name_ (const MHD_thread_ID_ thread_id,
|
||||
* @return non-zero on success, zero otherwise
|
||||
*/
|
||||
static int
|
||||
MHD_set_thread_name_ (const MHD_thread_ID_ thread_id,
|
||||
MHD_set_thread_name_ (const MHD_thread_ID_native_ thread_id,
|
||||
const char *thread_name)
|
||||
{
|
||||
static const DWORD VC_SETNAME_EXC = 0x406D1388;
|
||||
@@ -164,7 +165,7 @@ MHD_set_thread_name_ (const MHD_thread_ID_ thread_id,
|
||||
* @return non-zero on success, zero otherwise
|
||||
*/
|
||||
#define MHD_set_cur_thread_name_(n) \
|
||||
MHD_set_thread_name_ ((MHD_thread_ID_) -1,(n))
|
||||
MHD_set_thread_name_ ((MHD_thread_ID_native_) -1,(n))
|
||||
#endif /* _MSC_FULL_VER */
|
||||
#endif /* MHD_USE_W32_THREADS */
|
||||
|
||||
@@ -176,20 +177,29 @@ MHD_set_thread_name_ (const MHD_thread_ID_ thread_id,
|
||||
*
|
||||
* If thread is created, thread handle must be freed by MHD_join_thread_().
|
||||
*
|
||||
* @param thread handle to initialize
|
||||
* @param handle_id handle to initialise
|
||||
* @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,
|
||||
MHD_create_thread_ (MHD_thread_handle_ID_ *handle_id,
|
||||
size_t stack_size,
|
||||
MHD_THREAD_START_ROUTINE_ start_routine,
|
||||
void *arg)
|
||||
{
|
||||
#if defined(MHD_USE_POSIX_THREADS)
|
||||
int res;
|
||||
#if defined(MHD_thread_handle_ID_get_native_handle_ptr_)
|
||||
pthread_t *const new_tid_ptr =
|
||||
MHD_thread_handle_ID_get_native_handle_ptr_ (handle_id);
|
||||
#else /* ! MHD_thread_handle_ID_get_native_handle_ptr_ */
|
||||
pthread_t new_tid;
|
||||
pthread_t *const new_tid_ptr = &new_tid;
|
||||
#endif /* ! MHD_thread_handle_ID_get_native_handle_ptr_ */
|
||||
|
||||
mhd_assert (! MHD_thread_handle_ID_is_valid_handle_ (*handle_id));
|
||||
|
||||
if (0 != stack_size)
|
||||
{
|
||||
@@ -200,7 +210,7 @@ MHD_create_thread_ (MHD_thread_handle_ID_ *thread,
|
||||
res = pthread_attr_setstacksize (&attr,
|
||||
stack_size);
|
||||
if (0 == res)
|
||||
res = pthread_create (&(thread->handle),
|
||||
res = pthread_create (new_tid_ptr,
|
||||
&attr,
|
||||
start_routine,
|
||||
arg);
|
||||
@@ -208,18 +218,28 @@ MHD_create_thread_ (MHD_thread_handle_ID_ *thread,
|
||||
}
|
||||
}
|
||||
else
|
||||
res = pthread_create (&(thread->handle),
|
||||
res = pthread_create (new_tid_ptr,
|
||||
NULL,
|
||||
start_routine,
|
||||
arg);
|
||||
|
||||
if (0 != res)
|
||||
{
|
||||
errno = res;
|
||||
MHD_thread_handle_ID_set_invalid_ (handle_id);
|
||||
}
|
||||
#if ! defined(MHD_thread_handle_ID_get_native_handle_ptr_)
|
||||
else
|
||||
MHD_thread_handle_ID_set_native_handle_ (handle_id, new_tid);
|
||||
#endif /* ! MHD_thread_handle_ID_set_current_thread_ID_ */
|
||||
|
||||
return ! res;
|
||||
#elif defined(MHD_USE_W32_THREADS)
|
||||
uintptr_t thr_handle;
|
||||
#if SIZEOF_SIZE_T != SIZEOF_UNSIGNED_INT
|
||||
|
||||
mhd_assert (! MHD_thread_handle_ID_is_valid_handle_ (*handle_id));
|
||||
|
||||
if (stack_size > UINT_MAX)
|
||||
{
|
||||
errno = EINVAL;
|
||||
@@ -232,11 +252,13 @@ MHD_create_thread_ (MHD_thread_handle_ID_ *thread,
|
||||
arg,
|
||||
0,
|
||||
NULL);
|
||||
thread->handle = (MHD_thread_handle_) thr_handle;
|
||||
|
||||
if ((MHD_thread_handle_) 0 == thread->handle)
|
||||
if ((MHD_thread_handle_native_) 0 == (MHD_thread_handle_native_) thr_handle)
|
||||
return 0;
|
||||
|
||||
MHD_thread_handle_ID_set_native_handle_ (handle_id, \
|
||||
(MHD_thread_handle_native_) \
|
||||
thr_handle);
|
||||
|
||||
return ! 0;
|
||||
#endif
|
||||
}
|
||||
@@ -291,7 +313,7 @@ named_thread_starter (void *data)
|
||||
/**
|
||||
* Create a named thread and set the attributes according to our options.
|
||||
*
|
||||
* @param thread handle to initialize
|
||||
* @param handle_id handle to initialise
|
||||
* @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
|
||||
@@ -299,7 +321,7 @@ named_thread_starter (void *data)
|
||||
* @return non-zero on success; zero otherwise (with errno set)
|
||||
*/
|
||||
int
|
||||
MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread,
|
||||
MHD_create_named_thread_ (MHD_thread_handle_ID_ *handle_id,
|
||||
const char *thread_name,
|
||||
size_t stack_size,
|
||||
MHD_THREAD_START_ROUTINE_ start_routine,
|
||||
@@ -308,15 +330,22 @@ MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread,
|
||||
#if defined(MHD_USE_THREAD_ATTR_SETNAME)
|
||||
int res;
|
||||
pthread_attr_t attr;
|
||||
#if defined(MHD_thread_handle_ID_get_native_handle_ptr_)
|
||||
pthread_t *const new_tid_ptr =
|
||||
MHD_thread_handle_ID_get_native_handle_ptr_ (handle_id);
|
||||
#else /* ! MHD_thread_handle_ID_get_native_handle_ptr_ */
|
||||
pthread_t new_tid;
|
||||
pthread_t *const new_tid_ptr = &new_tid;
|
||||
#endif /* ! MHD_thread_handle_ID_get_native_handle_ptr_ */
|
||||
|
||||
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.
|
||||
/* NetBSD uses 3 arguments: second argument is string in printf-like format,
|
||||
* third argument is single argument for printf;
|
||||
* OSF1 uses 3 arguments too, but last one always must be zero (NULL).
|
||||
* MHD doesn't use '%' in thread names, so both forms are used in same way.
|
||||
*/
|
||||
res = pthread_attr_setname_np (&attr,
|
||||
thread_name,
|
||||
@@ -331,14 +360,21 @@ MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread,
|
||||
res = pthread_attr_setstacksize (&attr,
|
||||
stack_size);
|
||||
if (0 == res)
|
||||
res = pthread_create (&(thread->handle),
|
||||
res = pthread_create (new_tid_ptr,
|
||||
&attr,
|
||||
start_routine,
|
||||
arg);
|
||||
pthread_attr_destroy (&attr);
|
||||
}
|
||||
if (0 != res)
|
||||
{
|
||||
errno = res;
|
||||
MHD_thread_handle_ID_set_invalid_ (handle_id);
|
||||
}
|
||||
#if ! defined(MHD_thread_handle_ID_get_native_handle_ptr_)
|
||||
else
|
||||
MHD_thread_handle_ID_set_native_handle_ (handle_id, new_tid);
|
||||
#endif /* ! MHD_thread_handle_ID_set_current_thread_ID_ */
|
||||
|
||||
return ! res;
|
||||
#else /* ! MHD_USE_THREAD_ATTR_SETNAME */
|
||||
@@ -361,12 +397,16 @@ MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread,
|
||||
/* 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,
|
||||
if (! MHD_create_thread_ (handle_id,
|
||||
stack_size,
|
||||
&named_thread_starter,
|
||||
(void *) param))
|
||||
{
|
||||
int err_num;
|
||||
|
||||
err_num = errno;
|
||||
free (param);
|
||||
errno = err_num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+385
-71
@@ -64,6 +64,14 @@
|
||||
# error No threading API is available.
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
# include <stdbool.h>
|
||||
#endif /* HAVE_STDBOOL_H */
|
||||
|
||||
#if defined(MHD_USE_POSIX_THREADS) && defined(MHD_USE_W32_THREADS)
|
||||
# error Both MHD_USE_POSIX_THREADS and MHD_USE_W32_THREADS are defined
|
||||
#endif /* MHD_USE_POSIX_THREADS && MHD_USE_W32_THREADS */
|
||||
|
||||
#ifndef MHD_NO_THREAD_NAMES
|
||||
# if defined(MHD_USE_POSIX_THREADS)
|
||||
# if defined(HAVE_PTHREAD_SETNAME_NP_GNU) || \
|
||||
@@ -82,26 +90,305 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* ** Thread handle - used to control the thread ** */
|
||||
|
||||
#if defined(MHD_USE_POSIX_THREADS)
|
||||
typedef pthread_t MHD_thread_handle_;
|
||||
/**
|
||||
* Wait until specified thread is ended and free thread handle on success.
|
||||
* @param thread handle to watch
|
||||
* @return nonzero on success, zero otherwise
|
||||
*/
|
||||
# define MHD_join_thread_(native_handle) \
|
||||
(! pthread_join ((native_handle), NULL))
|
||||
#elif defined(MHD_USE_W32_THREADS)
|
||||
typedef HANDLE MHD_thread_handle_;
|
||||
/**
|
||||
* Wait until specified thread is ended and free thread handle on success.
|
||||
* @param thread handle to watch
|
||||
* @return nonzero on success, zero otherwise
|
||||
*/
|
||||
# define MHD_join_thread_(native_handle) \
|
||||
( (WAIT_OBJECT_0 == WaitForSingleObject ( (native_handle), INFINITE)) ? \
|
||||
(CloseHandle ( (native_handle)), ! 0) : 0 )
|
||||
#endif
|
||||
|
||||
#if defined(MHD_USE_POSIX_THREADS)
|
||||
# define MHD_THRD_RTRN_TYPE_ void*
|
||||
# define MHD_THRD_CALL_SPEC_
|
||||
/**
|
||||
* The native type to control the thread from other threads
|
||||
*/
|
||||
typedef pthread_t MHD_thread_handle_native_;
|
||||
#elif defined(MHD_USE_W32_THREADS)
|
||||
# define MHD_THRD_RTRN_TYPE_ unsigned
|
||||
# define MHD_THRD_CALL_SPEC_ __stdcall
|
||||
/**
|
||||
* The native type to control the thread from other threads
|
||||
*/
|
||||
typedef HANDLE MHD_thread_handle_native_;
|
||||
#endif
|
||||
|
||||
#if defined(MHD_USE_POSIX_THREADS)
|
||||
typedef pthread_t MHD_thread_ID_;
|
||||
# if defined(__gnu_linux__) || \
|
||||
(defined(__linux__) && defined(__GLIBC__))
|
||||
/* The next part of code is disabled because it relies on undocumented
|
||||
behaviour.
|
||||
It could be enabled for neglectable performance and size improvements. */
|
||||
# if 0 /* Disabled code */
|
||||
/**
|
||||
* The native invalid value for native thread handle
|
||||
*/
|
||||
# define MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ \
|
||||
((MHD_thread_handle_native_) 0)
|
||||
# endif /* Disabled code */
|
||||
# endif /* __gnu_linux__ || (__linux__ && __GLIBC__) */
|
||||
#elif defined(MHD_USE_W32_THREADS)
|
||||
typedef DWORD MHD_thread_ID_;
|
||||
/**
|
||||
* The native invalid value for native thread handle
|
||||
*/
|
||||
# define MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ \
|
||||
((MHD_thread_handle_native_) NULL)
|
||||
#endif /* MHD_USE_W32_THREADS */
|
||||
|
||||
#if ! defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_)
|
||||
/**
|
||||
* Structure with thread handle and validity flag
|
||||
*/
|
||||
struct MHD_thread_handle_struct_
|
||||
{
|
||||
bool valid; /**< true if native handle is set */
|
||||
MHD_thread_handle_native_ native; /**< the native thread handle */
|
||||
};
|
||||
/**
|
||||
* Type with thread handle that can be set to invalid value
|
||||
*/
|
||||
typedef struct MHD_thread_handle_struct_ MHD_thread_handle_;
|
||||
|
||||
/**
|
||||
* Set variable pointed by @a handle_ptr to invalid (unset) value
|
||||
*/
|
||||
# define MHD_thread_handle_set_invalid_(handle_ptr) \
|
||||
((handle_ptr)->valid = false)
|
||||
/**
|
||||
* Set native handle in variable pointed by @a handle_ptr
|
||||
* to @a native_val value
|
||||
*/
|
||||
# define MHD_thread_handle_set_native_(handle_ptr,native_val) \
|
||||
((handle_ptr)->valid = true, (handle_ptr)->native = native_val)
|
||||
/**
|
||||
* Check whether native handle value is set in @a handle_var variable
|
||||
*/
|
||||
# define MHD_thread_handle_is_valid_(handle_var) \
|
||||
((handle_var).valid)
|
||||
/**
|
||||
* Get native handle value from @a handle_var variable
|
||||
*/
|
||||
# define MHD_thread_handle_get_native_(handle_var) \
|
||||
((handle_var).native)
|
||||
#else /* MHD_THREAD_HANDLE_NATIVE_INVALID_ */
|
||||
/**
|
||||
* Type with thread handle that can be set to invalid value
|
||||
*/
|
||||
typedef MHD_thread_handle_native_ MHD_thread_handle_;
|
||||
|
||||
/**
|
||||
* Set variable pointed by @a handle_ptr to invalid (unset) value
|
||||
*/
|
||||
# define MHD_thread_handle_set_invalid_(handle_ptr) \
|
||||
((*(handle_ptr)) = MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_)
|
||||
/**
|
||||
* Set native handle in the variable pointed by @a handle_ptr
|
||||
* to @a native_val value
|
||||
*/
|
||||
# define MHD_thread_handle_set_native_(handle_ptr,native_val) \
|
||||
((*(handle_ptr)) = native_val)
|
||||
/**
|
||||
* Check whether native handle value is set in @a handle_var variable
|
||||
*/
|
||||
# define MHD_thread_handle_is_valid_(handle_var) \
|
||||
(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ != handle_var)
|
||||
/**
|
||||
* Get native handle value from @a handle_var variable
|
||||
*/
|
||||
# define MHD_thread_handle_get_native_(handle_var) \
|
||||
(handle_var)
|
||||
/**
|
||||
* Get pointer to native handle stored the variable pointed by @a handle_ptr
|
||||
* @note This macro could not available if direct manipulation of
|
||||
* the native handle is not possible
|
||||
*/
|
||||
# define MHD_thread_handle_get_native_ptr_(handle_ptr) \
|
||||
(handle_ptr)
|
||||
#endif /* MHD_THREAD_HANDLE_NATIVE_INVALID_ */
|
||||
|
||||
|
||||
/* ** Thread ID - used to check threads match ** */
|
||||
|
||||
#if defined(MHD_USE_POSIX_THREADS)
|
||||
/**
|
||||
* The native type used to check whether current thread matches expected thread
|
||||
*/
|
||||
typedef pthread_t MHD_thread_ID_native_;
|
||||
|
||||
/**
|
||||
* Function to get the current thread native ID.
|
||||
*/
|
||||
# define MHD_thread_ID_native_current_ pthread_self
|
||||
|
||||
/**
|
||||
* Check whether two native thread IDs are equal.
|
||||
* @return non-zero if equal, zero if not equal
|
||||
*/
|
||||
# define MHD_thread_ID_native_equal_(id1,id2) \
|
||||
(pthread_equal(id1,id2))
|
||||
#elif defined(MHD_USE_W32_THREADS)
|
||||
/**
|
||||
* The native type used to check whether current thread matches expected thread
|
||||
*/
|
||||
typedef DWORD MHD_thread_ID_native_;
|
||||
|
||||
/**
|
||||
* Function to get the current thread native ID.
|
||||
*/
|
||||
# define MHD_thread_ID_native_current_ GetCurrentThreadId
|
||||
|
||||
/**
|
||||
* Check whether two native thread IDs are equal.
|
||||
* @return non-zero if equal, zero if not equal
|
||||
*/
|
||||
# define MHD_thread_ID_native_equal_(id1,id2) \
|
||||
((id1) == (id2))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check whether specified thread ID matches current thread.
|
||||
* @param id the thread ID to match
|
||||
* @return nonzero on match, zero otherwise
|
||||
*/
|
||||
#define MHD_thread_ID_native_is_current_thread_(id) \
|
||||
MHD_thread_ID_native_equal_(id, MHD_thread_ID_native_current_())
|
||||
|
||||
|
||||
#if defined(MHD_USE_POSIX_THREADS)
|
||||
# if defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_)
|
||||
/**
|
||||
* The native invalid value for native thread ID
|
||||
*/
|
||||
# define MHD_THREAD_ID_NATIVE_VALUE_INVALID_ \
|
||||
MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_
|
||||
# endif /* MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_ */
|
||||
#elif defined(MHD_USE_W32_THREADS)
|
||||
/**
|
||||
* The native invalid value for native thread ID
|
||||
*/
|
||||
# define MHD_THREAD_ID_NATIVE_VALUE_INVALID_ \
|
||||
((MHD_thread_ID_native_) 0)
|
||||
#endif /* MHD_USE_W32_THREADS */
|
||||
|
||||
#if ! defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
|
||||
/**
|
||||
* Structure with thread id and validity flag
|
||||
*/
|
||||
struct MHD_thread_ID_struct_
|
||||
{
|
||||
bool valid; /**< true if native ID is set */
|
||||
MHD_thread_ID_native_ native; /**< the native thread ID */
|
||||
};
|
||||
/**
|
||||
* Type with thread ID that can be set to invalid value
|
||||
*/
|
||||
typedef struct MHD_thread_ID_struct_ MHD_thread_ID_;
|
||||
|
||||
/**
|
||||
* Set variable pointed by @a ID_ptr to invalid (unset) value
|
||||
*/
|
||||
# define MHD_thread_ID_set_invalid_(ID_ptr) \
|
||||
((ID_ptr)->valid = false)
|
||||
/**
|
||||
* Set native ID in variable pointed by @a ID_ptr
|
||||
* to @a native_val value
|
||||
*/
|
||||
# define MHD_thread_ID_set_native_(ID_ptr,native_val) \
|
||||
((ID_ptr)->valid = true, (ID_ptr)->native = native_val)
|
||||
/**
|
||||
* Check whether native ID value is set in @a ID_var variable
|
||||
*/
|
||||
# define MHD_thread_ID_is_valid_(ID_var) \
|
||||
((ID_var).valid)
|
||||
/**
|
||||
* Get native ID value from @a ID_var variable
|
||||
*/
|
||||
# define MHD_thread_ID_get_native_(ID_var) \
|
||||
((ID_var).native)
|
||||
/**
|
||||
* Check whether @a ID_var variable is equal current thread
|
||||
*/
|
||||
# define MHD_thread_ID_is_current_thread_(ID_var) \
|
||||
(MHD_thread_ID_is_valid_(ID_var) && \
|
||||
MHD_thread_ID_native_is_current_thread_((ID_var).native))
|
||||
#else /* MHD_THREAD_ID_NATIVE_INVALID_ */
|
||||
/**
|
||||
* Type with thread ID that can be set to invalid value
|
||||
*/
|
||||
typedef MHD_thread_ID_native_ MHD_thread_ID_;
|
||||
|
||||
/**
|
||||
* Set variable pointed by @a ID_ptr to invalid (unset) value
|
||||
*/
|
||||
# define MHD_thread_ID_set_invalid_(ID_ptr) \
|
||||
((*(ID_ptr)) = MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
|
||||
/**
|
||||
* Set native ID in variable pointed by @a ID_ptr
|
||||
* to @a native_val value
|
||||
*/
|
||||
# define MHD_thread_ID_set_native_(ID_ptr,native_val) \
|
||||
((*(ID_ptr)) = native_val)
|
||||
/**
|
||||
* Check whether native ID value is set in @a ID_var variable
|
||||
*/
|
||||
# define MHD_thread_ID_is_valid_(ID_var) \
|
||||
(MHD_THREAD_ID_NATIVE_VALUE_INVALID_ != ID_var)
|
||||
/**
|
||||
* Get native ID value from @a ID_var variable
|
||||
*/
|
||||
# define MHD_thread_ID_get_native_(ID_var) \
|
||||
(ID_var)
|
||||
/**
|
||||
* Check whether @a ID_var variable is equal current thread
|
||||
*/
|
||||
# define MHD_thread_ID_is_current_thread_(ID_var) \
|
||||
MHD_thread_ID_native_is_current_thread_(ID_var)
|
||||
#endif /* MHD_THREAD_ID_NATIVE_INVALID_ */
|
||||
|
||||
/**
|
||||
* Set current thread ID in variable pointed by @a ID_ptr
|
||||
*/
|
||||
# define MHD_thread_ID_set_current_thread_(ID_ptr) \
|
||||
MHD_thread_ID_set_native_(ID_ptr,MHD_thread_ID_native_current_())
|
||||
|
||||
|
||||
#if defined(MHD_USE_POSIX_THREADS)
|
||||
# if defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) && \
|
||||
! defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
|
||||
# error \
|
||||
MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is defined, but MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is not defined
|
||||
# elif ! defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) && \
|
||||
defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_)
|
||||
# error \
|
||||
MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is not defined, but MHD_THREAD_ID_NATIVE_VALUE_INVALID_ is defined
|
||||
# endif
|
||||
#endif /* MHD_USE_POSIX_THREADS */
|
||||
|
||||
/* When staring a new thread, the kernel (and thread implementation) may
|
||||
* pause the calling (initial) thread and start the new thread.
|
||||
* If thread identifier is assigned to variable in the initial thread then
|
||||
* the value of the identifier variable will be undefined in the new thread
|
||||
* until the initial thread continue processing.
|
||||
* However, it is also possible that the new thread created, but not executed
|
||||
* for some time while the initial thread continue execution. In this case any
|
||||
* variable assigned in the new thread will be undefined for some time until
|
||||
* they really processed by the new thread.
|
||||
* To avoid data races, a special structure MHD_thread_handle_ID_ is used.
|
||||
* The "handle" is assigned by calling (initial) thread and should be always
|
||||
* defined when checked in the initial thread.
|
||||
* The "ID" is assigned by the new thread and should be always defined when
|
||||
* checked inside the new thread.
|
||||
*/
|
||||
/* Depending on implementation, pthread_create() MAY set thread ID into
|
||||
* provided pointer and after it start thread OR start thread and after
|
||||
* it set thread ID. In the latter case, to avoid data races, additional
|
||||
@@ -109,95 +396,122 @@ typedef DWORD MHD_thread_ID_;
|
||||
* is known for setting thread ID BEFORE starting thread macro
|
||||
* MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD could be defined
|
||||
* to save some resources. */
|
||||
/* #define MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD 1 */
|
||||
|
||||
/* * handle - must be valid when other thread knows that particular thread
|
||||
is started.
|
||||
* ID - must be valid when code is executed inside thread */
|
||||
#if defined(MHD_USE_POSIX_THREADS)
|
||||
# ifdef MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD
|
||||
#if defined(MHD_USE_POSIX_THREADS) && \
|
||||
defined(MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD) && \
|
||||
defined(MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_) && \
|
||||
defined(MHD_THREAD_ID_NATIVE_VALUE_INVALID_) && \
|
||||
defined(MHD_thread_handle_get_native_ptr_)
|
||||
union _MHD_thread_handle_ID_
|
||||
{
|
||||
MHD_thread_handle_ handle; /**< To be used in other threads */
|
||||
MHD_thread_ID_ ID; /**< To be used in thread itself */
|
||||
MHD_thread_ID_ ID; /**< To be used in the thread itself */
|
||||
};
|
||||
typedef union _MHD_thread_handle_ID_ MHD_thread_handle_ID_;
|
||||
# else /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */
|
||||
# define MHD_THREAD_HANDLE_ID_IS_UNION 1
|
||||
#else /* !MHD_USE_POSIX_THREADS
|
||||
|| !MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD
|
||||
|| !MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_
|
||||
|| !MHD_THREAD_ID_NATIVE_VALUE_INVALID_
|
||||
|| !MHD_thread_handle_get_native_ptr_ */
|
||||
struct _MHD_thread_handle_ID_
|
||||
{
|
||||
MHD_thread_handle_ handle; /**< To be used in other threads */
|
||||
MHD_thread_ID_ ID; /**< To be used in thread itself */
|
||||
MHD_thread_ID_ ID; /**< To be used in the thread itself */
|
||||
};
|
||||
typedef struct _MHD_thread_handle_ID_ MHD_thread_handle_ID_;
|
||||
# endif /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */
|
||||
#elif defined(MHD_USE_W32_THREADS)
|
||||
struct _MHD_thread_handle_ID_
|
||||
{
|
||||
MHD_thread_handle_ handle; /**< To be used in other threads */
|
||||
MHD_thread_ID_ ID; /**< To be used in thread itself */
|
||||
};
|
||||
typedef struct _MHD_thread_handle_ID_ MHD_thread_handle_ID_;
|
||||
#endif
|
||||
#endif /* !MHD_USE_POSIX_THREADS
|
||||
|| !MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD
|
||||
|| !MHD_THREAD_HANDLE_NATIVE_VALUE_INVALID_
|
||||
|| !MHD_THREAD_ID_NATIVE_VALUE_INVALID_
|
||||
|| !MHD_thread_handle_get_native_ptr_ */
|
||||
|
||||
#if defined(MHD_USE_POSIX_THREADS)
|
||||
/**
|
||||
* Wait until specified thread is ended and free thread handle on success.
|
||||
* @param thread handle to watch
|
||||
* @return nonzero on success, zero otherwise
|
||||
* Set MHD_thread_handle_ID_ to invalid value
|
||||
*/
|
||||
#define MHD_join_thread_(thread) (! pthread_join ((thread), NULL))
|
||||
#elif defined(MHD_USE_W32_THREADS)
|
||||
#define MHD_thread_handle_ID_set_invalid_(hndl_id_ptr) \
|
||||
(MHD_thread_handle_set_invalid_(&((hndl_id_ptr)->handle)), \
|
||||
MHD_thread_ID_set_invalid_(&((hndl_id_ptr)->ID)))
|
||||
|
||||
/**
|
||||
* Wait until specified thread is ended and free thread handle on success.
|
||||
* @param thread handle to watch
|
||||
* @return nonzero on success, zero otherwise
|
||||
* Check whether thread handle is valid.
|
||||
* To be used in threads other then the thread specified by @a hndl_id.
|
||||
*/
|
||||
#define MHD_join_thread_(thread) \
|
||||
( (WAIT_OBJECT_0 == WaitForSingleObject ( (thread), INFINITE)) ? \
|
||||
(CloseHandle ( (thread)), ! 0) : 0 )
|
||||
#endif
|
||||
#define MHD_thread_handle_ID_is_valid_handle_(hndl_id) \
|
||||
MHD_thread_handle_is_valid_((hndl_id).handle)
|
||||
|
||||
#define MHD_join_thread_tid_(thread_handle_ID_ptr) \
|
||||
(MHD_join_thread_((thread_handle_ID_ptr)->handle))
|
||||
/**
|
||||
* Set native handle in variable pointed by @a hndl_id_ptr
|
||||
* to @a native_val value
|
||||
*/
|
||||
#define MHD_thread_handle_ID_set_native_handle_(hndl_id_ptr,native_val) \
|
||||
MHD_thread_handle_set_native_(&((hndl_id_ptr)->handle),native_val)
|
||||
|
||||
#if defined(MHD_thread_handle_get_native_ptr_)
|
||||
/**
|
||||
* Get pointer to native handle stored the variable pointed by @a hndl_id_ptr
|
||||
* @note This macro could not available if direct manipulation of
|
||||
* the native handle is not possible
|
||||
*/
|
||||
# define MHD_thread_handle_ID_get_native_handle_ptr_(hndl_id_ptr) \
|
||||
MHD_thread_handle_get_native_ptr_(&((hndl_id_ptr)->handle))
|
||||
#endif /* MHD_thread_handle_get_native_ptr_ */
|
||||
|
||||
/**
|
||||
* Get native thread handle from MHD_thread_handle_ID_ variable.
|
||||
*/
|
||||
#define MHD_thread_handle_ID_get_native_handle_(hndl_id) \
|
||||
MHD_thread_handle_get_native_((hndl_id).handle)
|
||||
|
||||
/**
|
||||
* Check whether thread ID is valid.
|
||||
* To be used in the thread itself.
|
||||
*/
|
||||
#define MHD_thread_handle_ID_is_valid_ID_(hndl_id) \
|
||||
MHD_thread_ID_is_valid_((hndl_id).ID)
|
||||
|
||||
#if defined(MHD_THREAD_HANDLE_ID_IS_UNION)
|
||||
# if defined(MHD_USE_W32_THREADS)
|
||||
# error MHD_thread_handle_ID_ cannot be a union with W32 threads
|
||||
# endif /* MHD_USE_W32_THREADS */
|
||||
/**
|
||||
* Set current thread ID in the variable pointed by @a hndl_id_ptr
|
||||
*/
|
||||
# define MHD_thread_handle_ID_set_current_thread_ID_(hndl_id_ptr) (void) 0
|
||||
#else /* ! MHD_THREAD_HANDLE_ID_IS_UNION */
|
||||
/**
|
||||
* Set current thread ID in the variable pointed by @a hndl_id_ptr
|
||||
*/
|
||||
# define MHD_thread_handle_ID_set_current_thread_ID_(hndl_id_ptr) \
|
||||
MHD_thread_ID_set_current_thread_(&((hndl_id_ptr)->ID))
|
||||
#endif /* ! MHD_THREAD_HANDLE_ID_IS_UNION */
|
||||
|
||||
#if defined(MHD_USE_POSIX_THREADS)
|
||||
/**
|
||||
* Check whether provided thread ID matches current thread.
|
||||
* @param ID thread ID to match
|
||||
* @return nonzero on match, zero otherwise
|
||||
*/
|
||||
# define MHD_thread_ID_is_current_thread_(tid) \
|
||||
(pthread_equal ((tid).ID, pthread_self ()))
|
||||
#elif defined(MHD_USE_W32_THREADS)
|
||||
#define MHD_thread_handle_ID_is_current_thread_(hndl_id) \
|
||||
MHD_thread_ID_is_current_thread_((hndl_id).ID)
|
||||
|
||||
/**
|
||||
* Check whether provided thread ID matches current thread.
|
||||
* @param ID thread ID to match
|
||||
* @return nonzero on match, zero otherwise
|
||||
* Wait until specified thread is ended and free thread handle on success.
|
||||
* @param hndl_id_ handle with ID to watch
|
||||
* @return nonzero on success, zero otherwise
|
||||
*/
|
||||
# define MHD_thread_ID_is_current_thread_(tid) \
|
||||
(GetCurrentThreadId () == (tid).ID)
|
||||
#endif
|
||||
#define MHD_thread_handle_ID_join_thread_(hndl_id) \
|
||||
MHD_join_thread_(MHD_thread_handle_ID_get_native_handle_(hndl_id))
|
||||
|
||||
#if defined(MHD_USE_POSIX_THREADS)
|
||||
# ifdef MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD
|
||||
/**
|
||||
* Initialise thread ID.
|
||||
* @param thread_handle_ID_ptr pointer to thread handle-ID
|
||||
*/
|
||||
#define MHD_thread_init_(thread_handle_ID_ptr) (void) 0
|
||||
# else /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */
|
||||
/**
|
||||
* Initialise thread ID.
|
||||
* @param thread_handle_ID_ptr pointer to thread handle-ID
|
||||
*/
|
||||
#define MHD_thread_init_(thread_handle_ID_ptr) ((thread_handle_ID_ptr)->ID = \
|
||||
pthread_self ())
|
||||
# endif /* ! MHD_PTHREAD_CREATE__SET_ID_BEFORE_START_THREAD */
|
||||
# define MHD_THRD_RTRN_TYPE_ void*
|
||||
# define MHD_THRD_CALL_SPEC_
|
||||
#elif defined(MHD_USE_W32_THREADS)
|
||||
/**
|
||||
* Initialise thread ID.
|
||||
* @param thread_handle_ID_ptr pointer to thread handle-ID
|
||||
*/
|
||||
#define MHD_thread_init_(thread_handle_ID_ptr) ((thread_handle_ID_ptr)->ID = \
|
||||
GetCurrentThreadId ())
|
||||
# define MHD_THRD_RTRN_TYPE_ unsigned
|
||||
# define MHD_THRD_CALL_SPEC_ __stdcall
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -215,14 +529,14 @@ typedef MHD_THRD_RTRN_TYPE_
|
||||
*
|
||||
* If thread is created, thread handle must be freed by MHD_join_thread_().
|
||||
*
|
||||
* @param thread handle to initialize
|
||||
* @param handle_id handle to initialise
|
||||
* @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,
|
||||
MHD_create_thread_ (MHD_thread_handle_ID_ *handle_id,
|
||||
size_t stack_size,
|
||||
MHD_THREAD_START_ROUTINE_ start_routine,
|
||||
void *arg);
|
||||
@@ -233,7 +547,7 @@ MHD_create_thread_ (MHD_thread_handle_ID_ *thread,
|
||||
/**
|
||||
* Create a named thread and set the attributes according to our options.
|
||||
*
|
||||
* @param thread handle to initialize
|
||||
* @param handle_id handle to initialise
|
||||
* @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
|
||||
@@ -241,7 +555,7 @@ MHD_create_thread_ (MHD_thread_handle_ID_ *thread,
|
||||
* @return non-zero on success; zero otherwise
|
||||
*/
|
||||
int
|
||||
MHD_create_named_thread_ (MHD_thread_handle_ID_ *thread,
|
||||
MHD_create_named_thread_ (MHD_thread_handle_ID_ *handle_id,
|
||||
const char *thread_name,
|
||||
size_t stack_size,
|
||||
MHD_THREAD_START_ROUTINE_ start_routine,
|
||||
|
||||
@@ -1941,7 +1941,7 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response,
|
||||
|
||||
#ifdef MHD_USE_THREADS
|
||||
mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
|
||||
MHD_thread_ID_is_current_thread_ (connection->tid) );
|
||||
MHD_thread_handle_ID_is_current_thread_ (connection->tid) );
|
||||
#endif /* MHD_USE_THREADS */
|
||||
|
||||
/* "Upgrade" responses accepted only if MHD_ALLOW_UPGRADE is enabled */
|
||||
|
||||
@@ -322,7 +322,7 @@ main (int argc, char *const *argv)
|
||||
*/
|
||||
for (i = 0; i < 5 && result == 0; i++)
|
||||
{
|
||||
MHD_thread_handle_ sel_thrd;
|
||||
MHD_thread_handle_native_ sel_thrd;
|
||||
/* fprintf(stdout, "Creating, binding and listening socket...\n"); */
|
||||
MHD_socket listen_socket = start_socket_listen (AF_INET);
|
||||
if (MHD_INVALID_SOCKET == listen_socket)
|
||||
|
||||
Reference in New Issue
Block a user