41b6afb834
Use FreeBSD-specific functions (_pthread_mutex_init_calloc_cb(), _malloc_{pre,post}fork()) to avoid bootstrapping issues due to allocation in libc and libthr. Add malloc_strtoumax() and use it instead of strtoul(). Disable validation code in malloc_vsnprintf() and malloc_strtoumax() until jemalloc is initialized. This is necessary because locale initialization causes allocation for both vsnprintf() and strtoumax(). Force the lazy-lock feature on in order to avoid pthread_self(), because it causes allocation. Use syscall(SYS_write, ...) rather than write(...), because libthr wraps write() and causes allocation. Without this workaround, it would not be possible to print error messages in malloc_conf_init() without substantially reworking bootstrapping. Fix choose_arena_hard() to look at how many threads are assigned to the candidate choice, rather than checking whether the arena is uninitialized. This bug potentially caused more arenas to be initialized than necessary.
148 lines
3.8 KiB
C
148 lines
3.8 KiB
C
/******************************************************************************/
|
|
#ifdef JEMALLOC_H_TYPES
|
|
|
|
/* Size of stack-allocated buffer passed to buferror(). */
|
|
#define BUFERROR_BUF 64
|
|
|
|
/*
|
|
* Size of stack-allocated buffer used by malloc_{,v,vc}printf(). This must be
|
|
* large enough for all possible uses within jemalloc.
|
|
*/
|
|
#define MALLOC_PRINTF_BUFSIZE 4096
|
|
|
|
/*
|
|
* Wrap a cpp argument that contains commas such that it isn't broken up into
|
|
* multiple arguments.
|
|
*/
|
|
#define JEMALLOC_CONCAT(...) __VA_ARGS__
|
|
|
|
/*
|
|
* Silence compiler warnings due to uninitialized values. This is used
|
|
* wherever the compiler fails to recognize that the variable is never used
|
|
* uninitialized.
|
|
*/
|
|
#ifdef JEMALLOC_CC_SILENCE
|
|
# define JEMALLOC_CC_SILENCE_INIT(v) = v
|
|
#else
|
|
# define JEMALLOC_CC_SILENCE_INIT(v)
|
|
#endif
|
|
|
|
/*
|
|
* Define a custom assert() in order to reduce the chances of deadlock during
|
|
* assertion failure.
|
|
*/
|
|
#ifndef assert
|
|
#define assert(e) do { \
|
|
if (config_debug && !(e)) { \
|
|
malloc_printf( \
|
|
"<jemalloc>: %s:%d: Failed assertion: \"%s\"\n", \
|
|
__FILE__, __LINE__, #e); \
|
|
abort(); \
|
|
} \
|
|
} while (0)
|
|
#endif
|
|
|
|
/* Use to assert a particular configuration, e.g., cassert(config_debug). */
|
|
#define cassert(c) do { \
|
|
if ((c) == false) \
|
|
assert(false); \
|
|
} while (0)
|
|
|
|
#ifndef not_reached
|
|
#define not_reached() do { \
|
|
if (config_debug) { \
|
|
malloc_printf( \
|
|
"<jemalloc>: %s:%d: Unreachable code reached\n", \
|
|
__FILE__, __LINE__); \
|
|
abort(); \
|
|
} \
|
|
} while (0)
|
|
#endif
|
|
|
|
#ifndef not_implemented
|
|
#define not_implemented() do { \
|
|
if (config_debug) { \
|
|
malloc_printf("<jemalloc>: %s:%d: Not implemented\n", \
|
|
__FILE__, __LINE__); \
|
|
abort(); \
|
|
} \
|
|
} while (0)
|
|
#endif
|
|
|
|
#define assert_not_implemented(e) do { \
|
|
if (config_debug && !(e)) \
|
|
not_implemented(); \
|
|
} while (0)
|
|
|
|
#endif /* JEMALLOC_H_TYPES */
|
|
/******************************************************************************/
|
|
#ifdef JEMALLOC_H_STRUCTS
|
|
|
|
#endif /* JEMALLOC_H_STRUCTS */
|
|
/******************************************************************************/
|
|
#ifdef JEMALLOC_H_EXTERNS
|
|
|
|
extern void (*je_malloc_message)(void *wcbopaque, const char *s);
|
|
|
|
int buferror(int errnum, char *buf, size_t buflen);
|
|
uintmax_t malloc_strtoumax(const char *nptr, char **endptr, int base);
|
|
|
|
/*
|
|
* malloc_vsnprintf() supports a subset of snprintf(3) that avoids floating
|
|
* point math.
|
|
*/
|
|
int malloc_vsnprintf(char *str, size_t size, const char *format,
|
|
va_list ap);
|
|
int malloc_snprintf(char *str, size_t size, const char *format, ...)
|
|
JEMALLOC_ATTR(format(printf, 3, 4));
|
|
void malloc_vcprintf(void (*write_cb)(void *, const char *), void *cbopaque,
|
|
const char *format, va_list ap);
|
|
void malloc_cprintf(void (*write)(void *, const char *), void *cbopaque,
|
|
const char *format, ...) JEMALLOC_ATTR(format(printf, 3, 4));
|
|
void malloc_printf(const char *format, ...)
|
|
JEMALLOC_ATTR(format(printf, 1, 2));
|
|
|
|
#endif /* JEMALLOC_H_EXTERNS */
|
|
/******************************************************************************/
|
|
#ifdef JEMALLOC_H_INLINES
|
|
|
|
#ifndef JEMALLOC_ENABLE_INLINE
|
|
size_t pow2_ceil(size_t x);
|
|
void malloc_write(const char *s);
|
|
#endif
|
|
|
|
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_UTIL_C_))
|
|
/* Compute the smallest power of 2 that is >= x. */
|
|
JEMALLOC_INLINE size_t
|
|
pow2_ceil(size_t x)
|
|
{
|
|
|
|
x--;
|
|
x |= x >> 1;
|
|
x |= x >> 2;
|
|
x |= x >> 4;
|
|
x |= x >> 8;
|
|
x |= x >> 16;
|
|
#if (LG_SIZEOF_PTR == 3)
|
|
x |= x >> 32;
|
|
#endif
|
|
x++;
|
|
return (x);
|
|
}
|
|
|
|
/*
|
|
* Wrapper around malloc_message() that avoids the need for
|
|
* je_malloc_message(...) throughout the code.
|
|
*/
|
|
JEMALLOC_INLINE void
|
|
malloc_write(const char *s)
|
|
{
|
|
|
|
je_malloc_message(NULL, s);
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif /* JEMALLOC_H_INLINES */
|
|
/******************************************************************************/
|