From d3d693a3a62e4ddb1fc094d562c6a5fc0beb8c37 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Fri, 26 Jul 2019 10:15:47 +0100 Subject: [PATCH] reduce syscalls on opening files - roll CLOEXEC into open on linux open supports() O_CLOEXEC. add test case for this in meson build and ifdef. this rolls 3 syscalls into 1 as we were doing open, then fnctl to get and fcntl to set flags. less syscalls is a good thing as syscalls are not cheap on some architectures or systems. I've seen a syscall on 1 system take 2-3x as long as another and another syscall in the same 2 system comparison take 10x as long. depending on the syscall you may only have a budget of something like 5000 syscalls "per frame" (60fps) before you spend all of your frame time just in syscalls not doing any processing, so we should keep these down if possible and that is what this does. --- header_checks/meson.build | 14 ++++++++++++++ src/lib/eina/eina_file.c | 21 +++++++++++++++------ src/lib/eina/eina_mmap.c | 6 ++++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/header_checks/meson.build b/header_checks/meson.build index ca11d2d..0df5c4c 100644 --- a/header_checks/meson.build +++ b/header_checks/meson.build @@ -123,6 +123,20 @@ function_checks = [ ['dladdr', ['dlfcn.h'], ['dl'], '-D_GNU_SOURCE=1'] ] +open_cloexec = cc.run('''#include + #include + #include + int main(int argc, char **argv) { + int res = open(argv[0], O_RDONLY | O_CLOEXEC); + if (res < 0) return 1; + return 0; + } + ''', + name : 'open works with O_CLOEXEC') +if open_cloexec.compiled() and open_cloexec.returncode() == 0 + config_h.set10('HAVE_OPEN_CLOEXEC', true) +endif + strerror_r_char_p = cc.compiles('''#define _GNU_SOURCE #include int func (void) diff --git a/src/lib/eina/eina_file.c b/src/lib/eina/eina_file.c index cc53f65..068aa12 100644 --- a/src/lib/eina/eina_file.c +++ b/src/lib/eina/eina_file.c @@ -802,19 +802,28 @@ eina_file_open(const char *path, Eina_Bool shared) if (!filename) return NULL; if (shared) + { #ifdef HAVE_SHM_OPEN - fd = shm_open(filename, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO); + fd = shm_open(filename, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO); + if ((fd != -1) && (!eina_file_close_on_exec(fd, EINA_TRUE))) + goto on_error; #else - goto on_error; + goto on_error; #endif + } else - fd = open(filename, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO); + { +#ifdef HAVE_OPEN_CLOEXEC + fd = open(filename, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO | O_CLOEXEC); +#else + fd = open(filename, O_RDONLY, S_IRWXU | S_IRWXG | S_IRWXO); + if ((fd != -1) && (!eina_file_close_on_exec(fd, EINA_TRUE))) + goto on_error; +#endif + } if (fd < 0) goto on_error; - if (!eina_file_close_on_exec(fd, EINA_TRUE)) - goto on_error; - if (fstat(fd, &file_stat)) goto on_error; diff --git a/src/lib/eina/eina_mmap.c b/src/lib/eina/eina_mmap.c index 11d8804..23386da 100644 --- a/src/lib/eina/eina_mmap.c +++ b/src/lib/eina/eina_mmap.c @@ -198,10 +198,16 @@ eina_mmap_safety_enabled_set(Eina_Bool enabled) /* no zero page device - open it */ if (_eina_mmap_zero_fd < 0) { +#ifdef HAVE_OPEN_CLOEXEC + _eina_mmap_zero_fd = open("/dev/zero", O_RDWR | O_CLOEXEC); + /* if we don;'t have one - fail to set up mmap safety */ + if (_eina_mmap_zero_fd < 0) return EINA_FALSE; +#else _eina_mmap_zero_fd = open("/dev/zero", O_RDWR); /* if we don;'t have one - fail to set up mmap safety */ if (_eina_mmap_zero_fd < 0) return EINA_FALSE; eina_file_close_on_exec(_eina_mmap_zero_fd, EINA_TRUE); +#endif } /* set up signal handler for SIGBUS */ sa.sa_sigaction = _eina_mmap_safe_sigbus; -- 2.7.4