From f890bbed4a738e56e1be2a191e135c48b413dd11 Mon Sep 17 00:00:00 2001 From: lexprfuncall <5360361+lexprfuncall@users.noreply.github.com> Date: Wed, 6 Aug 2025 21:32:16 -0700 Subject: [PATCH] Define malloc_{write,read}_fd as non-inline global functions The static inline definition made more sense when these functions just dispatched to a syscall wrapper. Since they acquired a retry loop, a non-inline definition makes more sense. --- include/jemalloc/internal/malloc_io.h | 86 ++------------------------- src/malloc_io.c | 75 +++++++++++++++++++++++ 2 files changed, 80 insertions(+), 81 deletions(-) diff --git a/include/jemalloc/internal/malloc_io.h b/include/jemalloc/internal/malloc_io.h index 5e0805ed..0f70c3c3 100644 --- a/include/jemalloc/internal/malloc_io.h +++ b/include/jemalloc/internal/malloc_io.h @@ -66,94 +66,18 @@ void malloc_cprintf(write_cb_t *write_cb, void *cbopaque, const char *format, ...) JEMALLOC_FORMAT_PRINTF(3, 4); void malloc_printf(const char *format, ...) JEMALLOC_FORMAT_PRINTF(1, 2); -static inline ssize_t -malloc_write_fd_syscall(int fd, const void *buf, size_t count) { -#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_write) - /* - * Use syscall(2) rather than write(2) when possible in order to avoid - * the possibility of memory allocation within libc. This is necessary - * on FreeBSD; most operating systems do not have this problem though. - * - * syscall() returns long or int, depending on platform, so capture the - * result in the widest plausible type to avoid compiler warnings. - */ - long result = syscall(SYS_write, fd, buf, count); -#else - ssize_t result = (ssize_t)write(fd, buf, -# ifdef _WIN32 - (unsigned int) -# endif - count); -#endif - return (ssize_t)result; -} - -static inline ssize_t -malloc_write_fd(int fd, const void *buf, size_t count) { - size_t bytes_written = 0; - do { - ssize_t result = malloc_write_fd_syscall(fd, - &((const byte_t *)buf)[bytes_written], - count - bytes_written); - if (result < 0) { -#ifndef _WIN32 - if (errno == EINTR) { - continue; - } -#endif - return result; - } - bytes_written += result; - } while (bytes_written < count); - return bytes_written; -} - -static inline ssize_t -malloc_read_fd_syscall(int fd, void *buf, size_t count) { -#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_read) - long result = syscall(SYS_read, fd, buf, count); -#else - ssize_t result = read(fd, buf, -# ifdef _WIN32 - (unsigned int) -# endif - count); -#endif - return (ssize_t)result; -} - -static inline ssize_t -malloc_read_fd(int fd, void *buf, size_t count) { - size_t bytes_read = 0; - do { - ssize_t result = malloc_read_fd_syscall( - fd, &((byte_t *)buf)[bytes_read], count - bytes_read); - if (result < 0) { -#ifndef _WIN32 - if (errno == EINTR) { - continue; - } -#endif - return result; - } else if (result == 0) { - break; - } - bytes_read += result; - } while (bytes_read < count); - return bytes_read; -} +ssize_t malloc_write_fd(int fd, const void *buf, size_t count); +ssize_t malloc_read_fd(int fd, void *buf, size_t count); static inline int malloc_open(const char *path, int flags) { - int fd; #if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_open) - fd = (int)syscall(SYS_open, path, flags); + return (int)syscall(SYS_open, path, flags); #elif defined(JEMALLOC_USE_SYSCALL) && defined(SYS_openat) - fd = (int)syscall(SYS_openat, AT_FDCWD, path, flags); + return (int)syscall(SYS_openat, AT_FDCWD, path, flags); #else - fd = open(path, flags); + return open(path, flags); #endif - return fd; } static inline int diff --git a/src/malloc_io.c b/src/malloc_io.c index 0c5d6c03..779cdc05 100644 --- a/src/malloc_io.c +++ b/src/malloc_io.c @@ -760,6 +760,81 @@ malloc_printf(const char *format, ...) { va_end(ap); } +static ssize_t +malloc_write_fd_syscall(int fd, const void *buf, size_t count) { +#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_write) + /* + * Use syscall(2) rather than write(2) when possible in order to avoid + * the possibility of memory allocation within libc. This is necessary + * on FreeBSD; most operating systems do not have this problem though. + * + * syscall() returns long or int, depending on platform, so capture the + * result in the widest plausible type to avoid compiler warnings. + */ + return (ssize_t)syscall(SYS_write, fd, buf, count); +#else + return (ssize_t)write(fd, buf, +# ifdef _WIN32 + (unsigned int) +# endif + count); +#endif +} + +ssize_t +malloc_write_fd(int fd, const void *buf, size_t count) { + size_t bytes_written = 0; + do { + ssize_t result = malloc_write_fd_syscall(fd, + &((const byte_t *)buf)[bytes_written], + count - bytes_written); + if (result < 0) { +#ifndef _WIN32 + if (errno == EINTR) { + continue; + } +#endif + return result; + } + bytes_written += result; + } while (bytes_written < count); + return bytes_written; +} + +static ssize_t +malloc_read_fd_syscall(int fd, void *buf, size_t count) { +#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_read) + return (ssize_t)syscall(SYS_read, fd, buf, count); +#else + return (ssize_t)read(fd, buf, +# ifdef _WIN32 + (unsigned int) +# endif + count); +#endif +} + +ssize_t +malloc_read_fd(int fd, void *buf, size_t count) { + size_t bytes_read = 0; + do { + ssize_t result = malloc_read_fd_syscall( + fd, &((byte_t *)buf)[bytes_read], count - bytes_read); + if (result < 0) { +#ifndef _WIN32 + if (errno == EINTR) { + continue; + } +#endif + return result; + } else if (result == 0) { + break; + } + bytes_read += result; + } while (bytes_read < count); + return bytes_read; +} + /* * Restore normal assertion macros, in order to make it possible to compile all * C files as a single concatenation.