From 087b1b0efda81c89493a42debcaa9013ce60cfaf Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 13 Jul 2022 12:30:47 +0000 Subject: tevent: add tevent_cached_getpid() helper This avoids a getpid() syscall per tevent_loop_once() iteration. We provide tevent_cached_getpid() also as helper for external consumers in order to have the logic only once. Note the change to ABI/tevent-0.12.1.sigs will be reverted with the bump to 0.13.0. Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison --- lib/tevent/ABI/tevent-0.12.1.sigs | 1 + lib/tevent/tevent.c | 41 ++++++++++++++++++++++++++++++++++++--- lib/tevent/tevent.h | 16 +++++++++++++++ lib/tevent/tevent_epoll.c | 7 ++++--- lib/tevent/tevent_port.c | 7 ++++--- 5 files changed, 63 insertions(+), 9 deletions(-) (limited to 'lib/tevent') diff --git a/lib/tevent/ABI/tevent-0.12.1.sigs b/lib/tevent/ABI/tevent-0.12.1.sigs index 0e4d1e1fe26..68722a0e62f 100644 --- a/lib/tevent/ABI/tevent-0.12.1.sigs +++ b/lib/tevent/ABI/tevent-0.12.1.sigs @@ -22,6 +22,7 @@ _tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_conte _tevent_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *) tevent_abort: void (struct tevent_context *, const char *) tevent_backend_list: const char **(TALLOC_CTX *) +tevent_cached_getpid: pid_t (void) tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *) tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *) tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *) diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index 81268a1bd7a..262fdaa22ed 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -199,6 +199,7 @@ static void tevent_common_wakeup_fini(struct tevent_context *ev); static pthread_mutex_t tevent_contexts_mutex = PTHREAD_MUTEX_INITIALIZER; static struct tevent_context *tevent_contexts = NULL; static pthread_once_t tevent_atfork_initialized = PTHREAD_ONCE_INIT; +static pid_t tevent_cached_global_pid = 0; static void tevent_atfork_prepare(void) { @@ -263,6 +264,8 @@ static void tevent_atfork_child(void) struct tevent_context *ev; int ret; + tevent_cached_global_pid = getpid(); + for (ev = DLIST_TAIL(tevent_contexts); ev != NULL; ev = DLIST_PREV(ev)) { struct tevent_threaded_context *tctx; @@ -302,9 +305,41 @@ static void tevent_prep_atfork(void) if (ret != 0) { abort(); } + + tevent_cached_global_pid = getpid(); +} + +#endif + +static int tevent_init_globals(void) +{ +#ifdef HAVE_PTHREAD + int ret; + + ret = pthread_once(&tevent_atfork_initialized, tevent_prep_atfork); + if (ret != 0) { + return ret; + } +#endif + + return 0; } +_PUBLIC_ pid_t tevent_cached_getpid(void) +{ +#ifdef HAVE_PTHREAD + tevent_init_globals(); +#ifdef TEVENT_VERIFY_CACHED_GETPID + if (tevent_cached_global_pid != getpid()) { + tevent_abort(NULL, "tevent_cached_global_pid invalid"); + } +#endif + if (tevent_cached_global_pid != 0) { + return tevent_cached_global_pid; + } #endif + return getpid(); +} int tevent_common_context_destructor(struct tevent_context *ev) { @@ -434,13 +469,13 @@ static int tevent_common_context_constructor(struct tevent_context *ev) { int ret; -#ifdef HAVE_PTHREAD - - ret = pthread_once(&tevent_atfork_initialized, tevent_prep_atfork); + ret = tevent_init_globals(); if (ret != 0) { return ret; } +#ifdef HAVE_PTHREAD + ret = pthread_mutex_init(&ev->scheduled_mutex, NULL); if (ret != 0) { return ret; diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 1c337adbf74..656df254be0 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -1909,6 +1909,22 @@ struct timeval tevent_timeval_add(const struct timeval *tv, uint32_t secs, */ struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs); +/** + * + * @brief A cached version of getpid() + * + * We use getpid() in a lot a performance critical situations + * in order to check if caches are still valid in the current process. + * + * Calling getpid() always add the cost of an additional syscall! + * + * When tevent is build with pthread support, we already make use + * of pthread_atfork(), so it's trivial to use it maintain a cache for getpid(). + * + * @return The pid of the current process. + */ +pid_t tevent_cached_getpid(void); + /* @} */ diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 9cbe505c98a..1f1f47b2b21 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -206,7 +206,7 @@ static int epoll_init_ctx(struct epoll_event_context *epoll_ev) "Failed to set close-on-exec, file descriptor may be leaked to children.\n"); } - epoll_ev->pid = getpid(); + epoll_ev->pid = tevent_cached_getpid(); talloc_set_destructor(epoll_ev, epoll_ctx_destructor); return 0; @@ -224,8 +224,9 @@ static void epoll_check_reopen(struct epoll_event_context *epoll_ev) struct tevent_fd *fde; bool *caller_panic_state = epoll_ev->panic_state; bool panic_triggered = false; + pid_t pid = tevent_cached_getpid(); - if (epoll_ev->pid == getpid()) { + if (epoll_ev->pid == pid) { return; } @@ -241,7 +242,7 @@ static void epoll_check_reopen(struct epoll_event_context *epoll_ev) "Failed to set close-on-exec, file descriptor may be leaked to children.\n"); } - epoll_ev->pid = getpid(); + epoll_ev->pid = pid; epoll_ev->panic_state = &panic_triggered; for (fde=epoll_ev->ev->fd_events;fde;fde=fde->next) { fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; diff --git a/lib/tevent/tevent_port.c b/lib/tevent/tevent_port.c index e91d442389d..ccb65a711b2 100644 --- a/lib/tevent/tevent_port.c +++ b/lib/tevent/tevent_port.c @@ -95,7 +95,7 @@ static int port_init_ctx(struct port_event_context *port_ev) "Failed to set close-on-exec, file descriptor may be leaked to children.\n"); } - port_ev->pid = getpid(); + port_ev->pid = tevent_cached_getpid(); talloc_set_destructor(port_ev, port_ctx_destructor); return 0; @@ -199,8 +199,9 @@ static int port_update_event(struct port_event_context *port_ev, struct tevent_f static int port_check_reopen(struct port_event_context *port_ev) { struct tevent_fd *fde; + pid_t pid = tevent_cached_getpid(); - if (port_ev->pid == getpid()) { + if (port_ev->pid == pid) { return 0; } @@ -217,7 +218,7 @@ static int port_check_reopen(struct port_event_context *port_ev) "Failed to set close-on-exec, file descriptor may be leaked to children.\n"); } - port_ev->pid = getpid(); + port_ev->pid = pid; for (fde=port_ev->ev->fd_events;fde;fde=fde->next) { fde->additional_flags &= PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; if (port_update_event(port_ev, fde) != 0) { -- cgit v1.2.1