#ifndef JEMALLOC_INTERNAL_UTIL_H #define JEMALLOC_INTERNAL_UTIL_H #include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/jemalloc_internal_types.h" #define UTIL_INLINE static inline /* Junk fill patterns. */ #ifndef JEMALLOC_ALLOC_JUNK # define JEMALLOC_ALLOC_JUNK ((uint8_t)0xa5) #endif #ifndef JEMALLOC_FREE_JUNK # define JEMALLOC_FREE_JUNK ((uint8_t)0x5a) #endif /* * Wrap a cpp argument that contains commas such that it isn't broken up into * multiple arguments. */ #define JEMALLOC_ARG_CONCAT(...) __VA_ARGS__ /* cpp macro definition stringification. */ #define STRINGIFY_HELPER(x) #x #define STRINGIFY(x) STRINGIFY_HELPER(x) /* * Silence compiler warnings due to uninitialized values. This is used * wherever the compiler fails to recognize that the variable is never used * uninitialized. */ #define JEMALLOC_CC_SILENCE_INIT(v) = v #ifdef __GNUC__ # define likely(x) __builtin_expect(!!(x), 1) # define unlikely(x) __builtin_expect(!!(x), 0) #else # define likely(x) !!(x) # define unlikely(x) !!(x) #endif #if !defined(JEMALLOC_INTERNAL_UNREACHABLE) # error JEMALLOC_INTERNAL_UNREACHABLE should have been defined by configure #endif #define unreachable() JEMALLOC_INTERNAL_UNREACHABLE() /* Set error code. */ UTIL_INLINE void set_errno(int errnum) { #ifdef _WIN32 SetLastError(errnum); #else errno = errnum; #endif } /* Get last error code. */ UTIL_INLINE int get_errno(void) { #ifdef _WIN32 return GetLastError(); #else return errno; #endif } JEMALLOC_ALWAYS_INLINE void util_assume(bool b) { if (!b) { unreachable(); } } /* ptr should be valid. */ JEMALLOC_ALWAYS_INLINE void util_prefetch_read(void *ptr) { /* * This should arguably be a config check; but any version of GCC so old * that it doesn't support __builtin_prefetch is also too old to build * jemalloc. */ #ifdef __GNUC__ if (config_debug) { /* Enforce the "valid ptr" requirement. */ *(volatile char *)ptr; } __builtin_prefetch(ptr, /* read or write */ 0, /* locality hint */ 3); #else *(volatile char *)ptr; #endif } JEMALLOC_ALWAYS_INLINE void util_prefetch_write(void *ptr) { #ifdef __GNUC__ if (config_debug) { *(volatile char *)ptr; } /* * The only difference from the read variant is that this has a 1 as the * second argument (the write hint). */ __builtin_prefetch(ptr, 1, 3); #else *(volatile char *)ptr; #endif } JEMALLOC_ALWAYS_INLINE void util_prefetch_read_range(void *ptr, size_t sz) { for (size_t i = 0; i < sz; i += CACHELINE) { util_prefetch_read((void *)((uintptr_t)ptr + i)); } } JEMALLOC_ALWAYS_INLINE void util_prefetch_write_range(void *ptr, size_t sz) { for (size_t i = 0; i < sz; i += CACHELINE) { util_prefetch_write((void *)((uintptr_t)ptr + i)); } } #undef UTIL_INLINE #endif /* JEMALLOC_INTERNAL_UTIL_H */