Move error-code handling to OS layer

Move error-code handling functions, namely, errno_set, errno_get, and
strerror to OS layer.
This commit is contained in:
guangli-dai 2026-07-28 14:29:42 -07:00 committed by Guangli Dai
parent 2c87eff72c
commit 21ddfb1e8e
6 changed files with 110 additions and 28 deletions

View file

@ -49,4 +49,11 @@
/* VM */
#include "jemalloc/internal/os/vm.h"
/*
* Error codes. util.h includes os/error.h directly (not via this umbrella)
* since it's reachable too early in the include graph for the full os.h.
* Included here too for discoverability.
*/
#include "jemalloc/internal/os/error.h"
#endif /* JEMALLOC_INTERNAL_OS_H */

View file

@ -0,0 +1,35 @@
#ifndef JEMALLOC_INTERNAL_OS_ERROR_H
#define JEMALLOC_INTERNAL_OS_ERROR_H
#include "jemalloc/internal/jemalloc_preamble.h"
#include "jemalloc/internal/os/detect.h"
/*
* Error-code interface: get/set the calling thread's last-error value, and
* render an error code to a human-readable string.
* Default: posix/. Override: Windows.
*
* Included directly by util.h (not via the os.h umbrella): util.h is itself
* transitively included very early. assert.h includes malloc_io.h then
* util.h, before either has any reason to know about mutex.h/base.h. Thus,
* pulling in the full os.h from util.h would risk the same circular-include
* failure worked around in the VM module (base.h -> mutex.h -> os.h ->
* os/vm.h -> base.h). This module's backends need nothing beyond libc/CRT
* error primitives and malloc_io.h's malloc_snprintf, so including it alone
* from util.h is safe.
*/
/* Functions required for implementation in each backend. */
JEMALLOC_ALWAYS_INLINE int os_errno_get(void);
JEMALLOC_ALWAYS_INLINE void os_errno_set(int errnum);
JEMALLOC_ALWAYS_INLINE int os_strerror(int err, char *buf, size_t buflen);
#if defined(_WIN32)
# include "jemalloc/internal/os/windows/error.h"
#elif defined(JEMALLOC_OS_POSIX)
# include "jemalloc/internal/os/posix/error.h"
#else
# error "OS layer: no error backend for this platform; add os/<os>/error.h"
#endif
#endif /* JEMALLOC_INTERNAL_OS_ERROR_H */

View file

@ -0,0 +1,38 @@
#ifndef JEMALLOC_INTERNAL_OS_POSIX_ERROR_H
#define JEMALLOC_INTERNAL_OS_POSIX_ERROR_H
/*
* POSIX error backend (errno, strerror_r).
*/
#include "jemalloc/internal/jemalloc_preamble.h"
#include "jemalloc/internal/malloc_io.h"
JEMALLOC_ALWAYS_INLINE int
os_errno_get(void) {
return errno;
}
JEMALLOC_ALWAYS_INLINE void
os_errno_set(int errnum) {
errno = errnum;
}
/*
* glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so
* provide a wrapper.
*/
JEMALLOC_ALWAYS_INLINE int
os_strerror(int err, char *buf, size_t buflen) {
#if defined(JEMALLOC_STRERROR_R_RETURNS_CHAR_WITH_GNU_SOURCE) \
&& defined(_GNU_SOURCE)
char *b = strerror_r(err, buf, buflen);
if (b != buf) {
malloc_snprintf(buf, buflen, "%s", b);
}
return 0;
#else
return strerror_r(err, buf, buflen);
#endif
}
#endif /* JEMALLOC_INTERNAL_OS_POSIX_ERROR_H */

View file

@ -0,0 +1,26 @@
#ifndef JEMALLOC_INTERNAL_OS_WINDOWS_ERROR_H
#define JEMALLOC_INTERNAL_OS_WINDOWS_ERROR_H
/*
* Windows error backend (GetLastError/SetLastError, FormatMessageA).
*/
#include "jemalloc/internal/jemalloc_preamble.h"
JEMALLOC_ALWAYS_INLINE int
os_errno_get(void) {
return GetLastError();
}
JEMALLOC_ALWAYS_INLINE void
os_errno_set(int errnum) {
SetLastError(errnum);
}
JEMALLOC_ALWAYS_INLINE int
os_strerror(int err, char *buf, size_t buflen) {
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, (LPSTR)buf,
(DWORD)buflen, NULL);
return 0;
}
#endif /* JEMALLOC_INTERNAL_OS_WINDOWS_ERROR_H */

View file

@ -3,6 +3,7 @@
#include "jemalloc/internal/jemalloc_preamble.h"
#include "jemalloc/internal/jemalloc_internal_types.h"
#include "jemalloc/internal/os/error.h"
#define UTIL_INLINE static inline
@ -66,21 +67,13 @@ max_zu(size_t a, size_t b) {
/* Set error code. */
UTIL_INLINE void
set_errno(int errnum) {
#ifdef _WIN32
SetLastError(errnum);
#else
errno = errnum;
#endif
os_errno_set(errnum);
}
/* Get last error code. */
UTIL_INLINE int
get_errno(void) {
#ifdef _WIN32
return GetLastError();
#else
return errno;
#endif
return os_errno_get();
}
#ifdef _MSC_VER

View file

@ -91,26 +91,9 @@ malloc_write(const char *s) {
}
}
/*
* glibc provides a non-standard strerror_r() when _GNU_SOURCE is defined, so
* provide a wrapper.
*/
int
buferror(int err, char *buf, size_t buflen) {
#ifdef _WIN32
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, (LPSTR)buf,
(DWORD)buflen, NULL);
return 0;
#elif defined(JEMALLOC_STRERROR_R_RETURNS_CHAR_WITH_GNU_SOURCE) \
&& defined(_GNU_SOURCE)
char *b = strerror_r(err, buf, buflen);
if (b != buf) {
malloc_snprintf(buf, buflen, "%s", b);
}
return 0;
#else
return strerror_r(err, buf, buflen);
#endif
return os_strerror(err, buf, buflen);
}
uintmax_t