diff --git a/CMakeLists.txt b/CMakeLists.txt index e0ecf4fdef18764118882f8d5f344d2d1ce11a6c..2428e35b126914879eef294e6367974fe4ed23cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,7 @@ include(cmake/FindReadline.cmake) include(cmake/FindSphinx.cmake) include(cmake/systemd.cmake) include(cmake/module.cmake) +include(cmake/thread.cmake) if (NOT READLINE_FOUND) message(FATAL_ERROR "readline library not found.") diff --git a/cmake/BuildLibEIO.cmake b/cmake/BuildLibEIO.cmake index 3f4c59a924f242d9e8f7920e53ee3a7efa4ba5aa..48e7582e5a994bcb55232ace7f1d2a573450b520 100644 --- a/cmake/BuildLibEIO.cmake +++ b/cmake/BuildLibEIO.cmake @@ -8,6 +8,10 @@ macro(libeio_build) set(eio_compile_flags "${eio_compile_flags} -Wno-unused-value") set(eio_compile_flags "${eio_compile_flags} -DENABLE_BUNDLED_LIBEIO=1") set(eio_compile_flags "${eio_compile_flags} -DEIO_STACKSIZE=0") + if (TARGET_OS_LINUX) + set(eio_compile_flags + "${eio_compile_flags} -DHAVE_SYS_PRCTL_H -DHAVE_PRCTL_SET_NAME") + endif () set(eio_src ${PROJECT_SOURCE_DIR}/third_party/tarantool_eio.c diff --git a/cmake/BuildLibEV.cmake b/cmake/BuildLibEV.cmake index c9e3a90bdce956dabcd346e6e233f4b70e2d4d34..f8216991c0f20af65989f3dac38d894fb9024546 100644 --- a/cmake/BuildLibEV.cmake +++ b/cmake/BuildLibEV.cmake @@ -29,6 +29,8 @@ macro(libev_build) # # Enable Linux-specific event notification API (man inotify) set(ev_compile_flags "${ev_compile_flags} -DEV_USE_INOTIFY") + set(ev_compile_flags "${ev_compile_flags} -DEV_USE_EVENTFD") + set(ev_compile_flags "${ev_compile_flags} -DEV_USE_SIGNALFD") elseif (TARGET_OS_FREEBSD OR TARGET_OS_DARWIN) # # On FreeBSD build libev loop on top of diff --git a/cmake/thread.cmake b/cmake/thread.cmake new file mode 100644 index 0000000000000000000000000000000000000000..9febca8fae90c35b2cea72c4cce1fd21feb42e25 --- /dev/null +++ b/cmake/thread.cmake @@ -0,0 +1,36 @@ +# +# Doing it in a function to avoid polluting the toplevel namespace +function (do_pthread_checks) + check_include_file(pthread_np.h HAVE_PTHREAD_NP_H) + if (HAVE_PTHREAD_NP_H) + set(INCLUDE_MISC_PTHREAD_HEADERS "#include <pthread_np.h>") + endif () + set(CMAKE_REQUIRED_FLAGS -pedantic-errors) + set(CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE -D_DARWIN_C_SOURCE) + set(CMAKE_REQUIRED_LIBRARIES pthread) + # pthread_setname_np(<thread_id>, <name>) - Linux + check_c_source_compiles(" + #include <pthread.h> + ${INCLUDE_MISC_PTHREAD_HEADERS} + int main() { pthread_setname_np(pthread_self(), \"\"); } + " HAVE_PTHREAD_SETNAME_NP) + # pthread_setname_np(<name>) - OSX + check_c_source_compiles(" + #include <pthread.h> + ${INCLUDE_MISC_PTHREAD_HEADERS} + int main() { pthread_setname_np(\"\"); } + " HAVE_PTHREAD_SETNAME_NP_1) + # pthread_set_name_np(<thread_id>, <name>) - *BSD + check_c_source_compiles(" + #include <pthread.h> + ${INCLUDE_MISC_PTHREAD_HEADERS} + int main() { pthread_set_name_np(pthread_self(), \"\"); } + " HAVE_PTHREAD_SET_NAME_NP) + if (NOT (HAVE_PTHREAD_SETNAME_NP OR + HAVE_PTHREAD_SETNAME_NP_1 OR + HAVE_PTHREAD_SET_NAME_NP)) + message(FATAL_ERROR "No suitable function for setting thread names found") + endif () +endfunction (do_pthread_checks) +do_pthread_checks() + diff --git a/src/fiber.cc b/src/fiber.cc index ea0fccaeb5ec2dd650adc1572bf6cbd31c0a689c..2d8a8a6f56b49c8a808387783a781269f1ad7314 100644 --- a/src/fiber.cc +++ b/src/fiber.cc @@ -583,9 +583,11 @@ fiber_destroy_all(struct cord *cord) fiber_destroy(cord, f); } -void -cord_create(struct cord *cord, const char *name) +static void +cord_init(const char *name) { + struct cord *cord = cord(); + cord->id = pthread_self(); cord->on_exit = NULL; cord->loop = cord->id == main_thread_id ? @@ -613,10 +615,10 @@ cord_create(struct cord *cord, const char *name) ev_async_start(cord->loop, &cord->wakeup_event); ev_idle_init(&cord->idle_event, fiber_schedule_idle); - snprintf(cord->name, sizeof(cord->name), "%s", name); + cord_set_name(name); } -void +static void cord_destroy(struct cord *cord) { slab_cache_set_thread(&cord->slabc); @@ -649,7 +651,7 @@ void *cord_thread_func(void *p) cord() = ct_arg->cord; slab_cache_set_thread(&cord()->slabc); struct cord *cord = cord(); - cord_create(cord, ct_arg->name); + cord_init(ct_arg->name); /** Can't possibly be the main thread */ assert(cord->id != main_thread_id); tt_pthread_mutex_lock(&ct_arg->start_mutex); @@ -879,6 +881,16 @@ cord_costart(struct cord *cord, const char *name, fiber_func f, void *arg) return 0; } +void +cord_set_name(const char *name) +{ + snprintf(cord()->name, sizeof cord()->name, "%s", name); + /* Main thread's name will replace process title in ps, skip it */ + if (cord_is_main()) + return; + tt_pthread_setname(name); +} + bool cord_is_main() { @@ -890,13 +902,13 @@ fiber_init(void) { main_thread_id = pthread_self(); cord() = &main_cord; - cord_create(cord(), "main"); + cord_init("main"); } void fiber_free(void) { - cord_destroy(cord()); + cord_destroy(&main_cord); } int fiber_stat(fiber_stat_cb cb, void *cb_ctx) diff --git a/src/fiber.h b/src/fiber.h index d8f26fb6fd669df799fec833b02077f29109b046..0d51e9088743708c8b3df6174d50dc3ee3ec3ffa 100644 --- a/src/fiber.h +++ b/src/fiber.h @@ -263,14 +263,8 @@ cord_costart(struct cord *cord, const char *name, fiber_func f, void *arg); int cord_join(struct cord *cord); -static inline void -cord_set_name(const char *name) -{ - snprintf(cord()->name, FIBER_NAME_MAX, "%s", name); -} - void -cord_destroy(struct cord *cord); +cord_set_name(const char *name); /** True if this cord represents the process main thread. */ bool diff --git a/src/trivia/config.h.cmake b/src/trivia/config.h.cmake index b8faa6f4bbcb184e341e24741038eb3bdc19443d..a2f27c96822683a1c9a75543a9e7478800adc629 100644 --- a/src/trivia/config.h.cmake +++ b/src/trivia/config.h.cmake @@ -183,6 +183,15 @@ #cmakedefine HAVE_UUIDGEN 1 #cmakedefine HAVE_CLOCK_GETTIME 1 +/** pthread_np.h - non-portable stuff */ +#cmakedefine HAVE_PTHREAD_NP_H 1 +/** pthread_setname_np(pthread_self(), "") - Linux */ +#cmakedefine HAVE_PTHREAD_SETNAME_NP 1 +/** pthread_setname_np("") - OSX */ +#cmakedefine HAVE_PTHREAD_SETNAME_NP_1 1 +/** pthread_set_name_np(pthread_self(), "") - *BSD */ +#cmakedefine HAVE_PTHREAD_SET_NAME_NP 1 + /** \cond public */ /** System configuration dir (e.g /etc) */ diff --git a/src/tt_pthread.h b/src/tt_pthread.h index e37a6e6e9f1bda106ad6e05ccd0d531161ef4466..f5d7b571676e5d57834cb5c0b084da4ddbc464da 100644 --- a/src/tt_pthread.h +++ b/src/tt_pthread.h @@ -34,7 +34,11 @@ #include "trivia/config.h" #include "trivia/util.h" +#include <stdio.h> #include <pthread.h> +#if HAVE_PTHREAD_NP_H +#include <pthread_np.h> +#endif #include "say.h" /** @@ -177,4 +181,25 @@ tt_pthread_error(e); \ }) +/** Set the current thread's name + */ +static inline void +tt_pthread_setname(const char *name) +{ + /* Setting the name fails if the name was too long. Linux limits a + * name to 16 bytes (including the trailing NUL), other OS don't + * even bother to document the limit. + */ + char short_name[16]; + snprintf(short_name, sizeof name, "%s", name); + +#if HAVE_PTHREAD_SETNAME_NP + pthread_setname_np(pthread_self(), short_name); +#elif HAVE_PTHREAD_SETNAME_NP_1 + pthread_setname_np(short_name); +#elif HAVE_PTHREAD_SET_NAME_NP + pthread_set_name_np(pthread_self(), short_name); +#endif +} + #endif /* TARANTOOL_PTHREAD_H_INCLUDED */ diff --git a/third_party/tarantool_ev.h b/third_party/tarantool_ev.h index 0b1556efcf5df3ce12ee1f49cabfbd639e6f3ec0..639dd0eca1f3654f9125dc8f32862400b08d2b9b 100644 --- a/third_party/tarantool_ev.h +++ b/third_party/tarantool_ev.h @@ -43,11 +43,13 @@ #define EV_USE_POLL 1 #define EV_USE_NANOSLEEP 1 #define EV_USE_REALTIME 1 +#define EV_USE_MONOTONIC 1 #define EV_PERIODIC_ENABLE 1 #define EV_IDLE_ENABLE 1 #define EV_STAT_ENABLE 1 #define EV_FORK_ENABLE 1 #define EV_CONFIG_H 0 +#define EV_USE_FLOOR 1 #include "third_party/libev/ev.h" #else /* !defined(ENABLE_BUNDLED_LIBEV) */ #include <ev.h>