Move file I/O and process ID retrieval to OS layer

Adds the File I/O and Process facilities to the OS layer, following
the os.h dispatcher pattern:
This commit is contained in:
guangli-dai 2026-07-26 17:04:34 -07:00 committed by Guangli Dai
parent c4158acac9
commit b62e7d2b06
9 changed files with 226 additions and 74 deletions

View file

@ -10,12 +10,14 @@
* *
* os/posix/<module>.h - the default, used by every POSIX platform. * os/posix/<module>.h - the default, used by every POSIX platform.
* os/<os>/<module>.h - an override, present ONLY when an OS specializes * os/<os>/<module>.h - an override, present ONLY when an OS specializes
* that module. * that module (e.g. windows/file.h).
* *
* A dispatcher picks the OS-specific file when one exists and otherwise falls * A dispatcher picks the OS-specific file when one exists and otherwise falls
* back to posix/ (guarded by JEMALLOC_OS_POSIX), so any POSIX platform builds * back to posix/ (guarded by JEMALLOC_OS_POSIX), so any POSIX platform builds
* without being enumerated anywhere. A non-POSIX platform with no override * without being enumerated anywhere. A non-POSIX platform with no override
* hits a #error. * hits a #error. Each os/<module>.h also declares the function prototypes
* its backends must implement, so a backend with a missing or mismatched
* function fails to compile instead of silently diverging.
* *
* Adding OS support for a module (only when existing module headers cannot be * Adding OS support for a module (only when existing module headers cannot be
* reused): create os/<os>/<module>.h (and later a matching src body when * reused): create os/<os>/<module>.h (and later a matching src body when
@ -23,4 +25,10 @@
* module: create os/<module>.h + os/posix/<module>.h and #include it below. * module: create os/<module>.h + os/posix/<module>.h and #include it below.
*/ */
/* Process */
#include "jemalloc/internal/os/process.h"
/* File I/O */
#include "jemalloc/internal/os/file.h"
#endif /* JEMALLOC_INTERNAL_OS_H */ #endif /* JEMALLOC_INTERNAL_OS_H */

View file

@ -0,0 +1,36 @@
#ifndef JEMALLOC_INTERNAL_OS_FILE_H
#define JEMALLOC_INTERNAL_OS_FILE_H
#include "jemalloc/internal/jemalloc_preamble.h"
#include "jemalloc/internal/os/detect.h"
/*
* File I/O interface.
* Default: posix/. Override: Windows (CRT <io.h>).
*/
/* Functions required for implementation in each backend. */
JEMALLOC_ALWAYS_INLINE ssize_t os_file_write_once(int fd, const void *buf,
size_t bytes);
JEMALLOC_ALWAYS_INLINE ssize_t os_file_read_once(int fd, void *buf,
size_t bytes);
/*
* Full retry-until-bytes-or-error versions of the above: loop over the
* _once primitive until target bytes are transferred or a non-retryable
* error occurs. Retrying on EINTR is a POSIX-only concept (Windows has no
* such signal-interruption semantics for this call), so that decision lives
* entirely in each backend rather than leaking into callers.
*/
JEMALLOC_ALWAYS_INLINE ssize_t os_file_write(int fd, const void *buf,
size_t bytes);
JEMALLOC_ALWAYS_INLINE ssize_t os_file_read(int fd, void *buf, size_t bytes);
#if defined(_WIN32)
# include "jemalloc/internal/os/windows/file.h"
#elif defined(JEMALLOC_OS_POSIX)
# include "jemalloc/internal/os/posix/file.h"
#else
# error "OS layer: no file backend for this platform; add os/<os>/file.h"
#endif
#endif /* JEMALLOC_INTERNAL_OS_FILE_H */

View file

@ -0,0 +1,68 @@
#ifndef JEMALLOC_INTERNAL_OS_POSIX_FILE_H
#define JEMALLOC_INTERNAL_OS_POSIX_FILE_H
/*
* POSIX file-I/O backend (read/write syscalls). Direct syscalls where
* available.
*/
#include "jemalloc/internal/jemalloc_preamble.h"
#ifdef JEMALLOC_USE_SYSCALL
# include <sys/syscall.h>
#endif
JEMALLOC_ALWAYS_INLINE ssize_t
os_file_write_once(int fd, const void *buf, size_t bytes) {
#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_write)
return (ssize_t)syscall(SYS_write, fd, buf, bytes);
#else
return (ssize_t)write(fd, buf, bytes);
#endif
}
JEMALLOC_ALWAYS_INLINE ssize_t
os_file_read_once(int fd, void *buf, size_t bytes) {
#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_read)
return (ssize_t)syscall(SYS_read, fd, buf, bytes);
#else
return (ssize_t)read(fd, buf, bytes);
#endif
}
JEMALLOC_ALWAYS_INLINE ssize_t
os_file_write(int fd, const void *buf, size_t bytes) {
size_t bytes_written = 0;
do {
ssize_t result = os_file_write_once(fd,
&((const byte_t *)buf)[bytes_written], bytes - bytes_written);
if (result < 0) {
if (errno == EINTR) {
continue;
}
return result;
}
bytes_written += result;
} while (bytes_written < bytes);
return bytes_written;
}
JEMALLOC_ALWAYS_INLINE ssize_t
os_file_read(int fd, void *buf, size_t bytes) {
size_t bytes_read = 0;
do {
ssize_t result = os_file_read_once(
fd, &((byte_t *)buf)[bytes_read], bytes - bytes_read);
if (result < 0) {
if (errno == EINTR) {
continue;
}
return result;
} else if (result == 0) {
break;
}
bytes_read += result;
} while (bytes_read < bytes);
return bytes_read;
}
#endif /* JEMALLOC_INTERNAL_OS_POSIX_FILE_H */

View file

@ -0,0 +1,17 @@
#ifndef JEMALLOC_INTERNAL_OS_POSIX_PROCESS_H
#define JEMALLOC_INTERNAL_OS_POSIX_PROCESS_H
/*
* POSIX process backend (getpid()).
*/
#include "jemalloc/internal/jemalloc_preamble.h"
#include <sys/types.h>
#include <unistd.h>
JEMALLOC_ALWAYS_INLINE int
os_process_id(void) {
return (int)getpid();
}
#endif /* JEMALLOC_INTERNAL_OS_POSIX_PROCESS_H */

View file

@ -0,0 +1,23 @@
#ifndef JEMALLOC_INTERNAL_OS_PROCESS_H
#define JEMALLOC_INTERNAL_OS_PROCESS_H
#include "jemalloc/internal/jemalloc_preamble.h"
#include "jemalloc/internal/os/detect.h"
/*
* Process interface.
* Default: posix/. Override: Windows (GetCurrentProcessId).
*/
/* Functions required for implementation in each backend. */
JEMALLOC_ALWAYS_INLINE int os_process_id(void);
#if defined(_WIN32)
# include "jemalloc/internal/os/windows/process.h"
#elif defined(JEMALLOC_OS_POSIX)
# include "jemalloc/internal/os/posix/process.h"
#else
# error "OS layer: no process backend for this platform; add os/<os>/process.h"
#endif
#endif /* JEMALLOC_INTERNAL_OS_PROCESS_H */

View file

@ -0,0 +1,52 @@
#ifndef JEMALLOC_INTERNAL_OS_WINDOWS_FILE_H
#define JEMALLOC_INTERNAL_OS_WINDOWS_FILE_H
/*
* Windows file-I/O backend, via the C runtime io.h (_read/_write).
*/
#include "jemalloc/internal/jemalloc_preamble.h"
#include <io.h>
JEMALLOC_ALWAYS_INLINE ssize_t
os_file_write_once(int fd, const void *buf, size_t bytes) {
return (ssize_t)write(fd, buf, (unsigned int)bytes);
}
JEMALLOC_ALWAYS_INLINE ssize_t
os_file_read_once(int fd, void *buf, size_t bytes) {
return (ssize_t)read(fd, buf, (unsigned int)bytes);
}
/* No EINTR/signal-interruption semantics on Windows: never retry on error. */
JEMALLOC_ALWAYS_INLINE ssize_t
os_file_write(int fd, const void *buf, size_t bytes) {
size_t bytes_written = 0;
do {
ssize_t result = os_file_write_once(fd,
&((const byte_t *)buf)[bytes_written], bytes - bytes_written);
if (result < 0) {
return result;
}
bytes_written += result;
} while (bytes_written < bytes);
return bytes_written;
}
JEMALLOC_ALWAYS_INLINE ssize_t
os_file_read(int fd, void *buf, size_t bytes) {
size_t bytes_read = 0;
do {
ssize_t result = os_file_read_once(
fd, &((byte_t *)buf)[bytes_read], bytes - bytes_read);
if (result < 0) {
return result;
} else if (result == 0) {
break;
}
bytes_read += result;
} while (bytes_read < bytes);
return bytes_read;
}
#endif /* JEMALLOC_INTERNAL_OS_WINDOWS_FILE_H */

View file

@ -0,0 +1,15 @@
#ifndef JEMALLOC_INTERNAL_OS_WINDOWS_PROCESS_H
#define JEMALLOC_INTERNAL_OS_WINDOWS_PROCESS_H
#include "jemalloc/internal/jemalloc_preamble.h"
/*
* Windows process backend (GetCurrentProcessId()).
*/
JEMALLOC_ALWAYS_INLINE int
os_process_id(void) {
return (int)GetCurrentProcessId();
}
#endif /* JEMALLOC_INTERNAL_OS_WINDOWS_PROCESS_H */

View file

@ -1,6 +1,7 @@
#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/jemalloc_preamble.h"
#include "jemalloc/internal/malloc_io.h" #include "jemalloc/internal/malloc_io.h"
#include "jemalloc/internal/os.h"
#include "jemalloc/internal/util.h" #include "jemalloc/internal/util.h"
#ifdef assert #ifdef assert
@ -758,79 +759,14 @@ malloc_printf(const char *format, ...) {
va_end(ap); 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 ssize_t
malloc_write_fd(int fd, const void *buf, size_t count) { malloc_write_fd(int fd, const void *buf, size_t count) {
size_t bytes_written = 0; return os_file_write(fd, buf, count);
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 ssize_t
malloc_read_fd(int fd, void *buf, size_t count) { malloc_read_fd(int fd, void *buf, size_t count) {
size_t bytes_read = 0; return os_file_read(fd, buf, count);
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;
} }
/* /*

View file

@ -6,6 +6,7 @@
#include "jemalloc/internal/jemalloc_internal_inlines_a.h" #include "jemalloc/internal/jemalloc_internal_inlines_a.h"
#include "jemalloc/internal/malloc_io.h" #include "jemalloc/internal/malloc_io.h"
#include "jemalloc/internal/mutex.h" #include "jemalloc/internal/mutex.h"
#include "jemalloc/internal/os.h"
#include "jemalloc/internal/prof.h" #include "jemalloc/internal/prof.h"
#include "jemalloc/internal/prof_data.h" #include "jemalloc/internal/prof_data.h"
#include "jemalloc/internal/prof_inlines.h" #include "jemalloc/internal/prof_inlines.h"
@ -484,11 +485,7 @@ prof_sys_thread_name_fetch(tsd_t *tsd) {
int int
prof_getpid(void) { prof_getpid(void) {
#ifdef _WIN32 return os_process_id();
return GetCurrentProcessId();
#else
return getpid();
#endif
} }
static long static long