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 <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
_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 *)
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)
{
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;
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)
{
{
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;
*/
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);
+
/* @} */
"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;
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;
}
"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;
"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;
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;
}
"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) {