Fix BSD and macOS builds w.r.t. pthread_setname_np (bug#38632)

pthread_setname_np takes only a single argument on BSD and macOS,
and affects the current thread only.

* configure.ac: Add check for single-argument pthread_setname_np
* src/systhread.c (sys_thread_set_name): New (w32 and pthread versions).
(sys_thread_create): Remove name argument and name-setting.
(w32_beginthread_wrapper): Remove name-setting.
* src/systhread.h (sys_thread_create, sys_thread_set_name):
Update prototypes.
* src/thread.c (run_thread): Call sys_thread_set_name.
(Fmake_thread): Adapt call to sys_thread_create.
* src/thread.h (struct thread_state): Adjust comment.
This commit is contained in:
Mattias Engdegård 2020-01-07 17:08:25 +01:00
parent f54b24304d
commit 73fd8a4b53
5 changed files with 55 additions and 33 deletions

View file

@ -4183,6 +4183,23 @@ getpwent endpwent getgrent endgrent \
cfmakeraw cfsetspeed __executable_start log2 pthread_setname_np)
LIBS=$OLD_LIBS
if test "$ac_cv_func_pthread_setname_np" = "yes"; then
AC_CACHE_CHECK(
[whether pthread_setname_np takes a single argument],
[emacs_cv_pthread_setname_np_1arg],
[AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#include <pthread.h>]],
[[pthread_setname_np ("a");]])],
[emacs_cv_pthread_setname_np_1arg=yes],
[emacs_cv_pthread_setname_np_1arg=no])])
if test "$emacs_cv_pthread_setname_np_1arg" = "yes"; then
AC_DEFINE(
HAVE_PTHREAD_SETNAME_NP_1ARG, 1,
[Define to 1 if pthread_setname_np takes a single argument.])
fi
fi
dnl No need to check for posix_memalign if aligned_alloc works.
AC_CHECK_FUNCS([aligned_alloc posix_memalign], [break])
AC_CHECK_DECLS([aligned_alloc], [], [], [[#include <stdlib.h>]])

View file

@ -200,9 +200,28 @@ sys_thread_equal (sys_thread_t t, sys_thread_t u)
return pthread_equal (t, u);
}
void
sys_thread_set_name (const char *name)
{
#ifdef HAVE_PTHREAD_SETNAME_NP
/* We need to truncate here otherwise pthread_setname_np
fails to set the name. TASK_COMM_LEN is what the length
is called in the Linux kernel headers (Bug#38632). */
#define TASK_COMM_LEN 16
char p_name[TASK_COMM_LEN];
strncpy (p_name, name, TASK_COMM_LEN - 1);
p_name[TASK_COMM_LEN - 1] = '\0';
#ifdef HAVE_PTHREAD_SETNAME_NP_1ARG
pthread_setname_np (p_name);
#else
pthread_setname_np (pthread_self (), p_name);
#endif
#endif
}
bool
sys_thread_create (sys_thread_t *thread_ptr, const char *name,
thread_creation_function *func, void *arg)
sys_thread_create (sys_thread_t *thread_ptr, thread_creation_function *func,
void *arg)
{
pthread_attr_t attr;
bool result = false;
@ -221,22 +240,7 @@ sys_thread_create (sys_thread_t *thread_ptr, const char *name,
}
if (!pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED))
{
result = pthread_create (thread_ptr, &attr, func, arg) == 0;
#ifdef HAVE_PTHREAD_SETNAME_NP
if (result && name != NULL)
{
/* We need to truncate here otherwise pthread_setname_np
fails to set the name. TASK_COMM_LEN is what the length
is called in the Linux kernel headers (Bug#38632). */
#define TASK_COMM_LEN 16
char p_name[TASK_COMM_LEN];
strncpy (p_name, name, TASK_COMM_LEN - 1);
p_name[TASK_COMM_LEN - 1] = '\0';
pthread_setname_np (*thread_ptr, p_name);
}
#endif
}
result = pthread_create (thread_ptr, &attr, func, arg) == 0;
out: ;
int error = pthread_attr_destroy (&attr);
@ -457,26 +461,24 @@ w32_set_thread_name (DWORD thread_id, const char *name)
static thread_creation_function *thread_start_address;
void
sys_thread_set_name (const char *name)
{
w32_set_thread_name (GetCurrentThreadId (), name);
}
/* _beginthread wants a void function, while we are passed a function
that returns a pointer. So we use a wrapper. See the command in
w32term.h about the need for ALIGN_STACK attribute. */
static void ALIGN_STACK
w32_beginthread_wrapper (void *arg)
{
/* FIXME: This isn't very clean: systhread.c is not supposed to know
that ARG is a pointer to a thread_state object, or be familiar
with thread_state object's structure in general. */
struct thread_state *this_thread = arg;
if (this_thread->thread_name)
w32_set_thread_name (GetCurrentThreadId (), this_thread->thread_name);
(void)thread_start_address (arg);
}
bool
sys_thread_create (sys_thread_t *thread_ptr, const char *name,
thread_creation_function *func, void *arg)
sys_thread_create (sys_thread_t *thread_ptr, thread_creation_function *func,
void *arg)
{
/* FIXME: Do threads that run Lisp require some minimum amount of
stack? Zero here means each thread will get the same amount as

View file

@ -112,10 +112,11 @@ extern sys_thread_t sys_thread_self (void)
extern bool sys_thread_equal (sys_thread_t, sys_thread_t)
ATTRIBUTE_WARN_UNUSED_RESULT;
extern bool sys_thread_create (sys_thread_t *, const char *,
thread_creation_function *, void *)
extern bool sys_thread_create (sys_thread_t *, thread_creation_function *,
void *)
ATTRIBUTE_WARN_UNUSED_RESULT;
extern void sys_thread_yield (void);
extern void sys_thread_set_name (const char *);
#endif /* SYSTHREAD_H */

View file

@ -725,6 +725,9 @@ run_thread (void *state)
self->m_stack_bottom = self->stack_top = (char *) &stack_pos;
self->thread_id = sys_thread_self ();
if (self->thread_name)
sys_thread_set_name (self->thread_name);
acquire_global_lock (self);
/* Put a dummy catcher at top-level so that handlerlist is never NULL.
@ -832,7 +835,7 @@ If NAME is given, it must be a string; it names the new thread. */)
else
new_thread->thread_name = NULL;
sys_thread_t thr;
if (! sys_thread_create (&thr, c_name, run_thread, new_thread))
if (! sys_thread_create (&thr, run_thread, new_thread))
{
/* Restore the previous situation. */
all_threads = all_threads->next_thread;

View file

@ -169,8 +169,7 @@ struct thread_state
interrupter should broadcast to this condition. */
sys_cond_t *wait_condvar;
/* Thread's name in the locale encoding. Actually used only on
WINDOWSNT. */
/* Thread's name in the locale encoding. */
char *thread_name;
/* This thread might have released the global lock. If so, this is