Commit a9951b1b authored by antirez's avatar antirez
Browse files

Jemalloc updated to 4.0.3.

parent e3ded027
#include "jemalloc/internal/jemalloc_internal.h"
#ifndef JEMALLOC_VALGRIND
# error "This source file is for Valgrind integration."
#endif
#include <valgrind/memcheck.h>
void
valgrind_make_mem_noaccess(void *ptr, size_t usize)
{
VALGRIND_MAKE_MEM_NOACCESS(ptr, usize);
}
void
valgrind_make_mem_undefined(void *ptr, size_t usize)
{
VALGRIND_MAKE_MEM_UNDEFINED(ptr, usize);
}
void
valgrind_make_mem_defined(void *ptr, size_t usize)
{
VALGRIND_MAKE_MEM_DEFINED(ptr, usize);
}
void
valgrind_freelike_block(void *ptr, size_t usize)
{
VALGRIND_FREELIKE_BLOCK(ptr, usize);
}
......@@ -176,6 +176,7 @@ register_zone(void)
* register jemalloc's.
*/
malloc_zone_t *default_zone = malloc_default_zone();
malloc_zone_t *purgeable_zone = NULL;
if (!default_zone->zone_name ||
strcmp(default_zone->zone_name, "DefaultMallocZone") != 0) {
return;
......@@ -237,22 +238,37 @@ register_zone(void)
* run time.
*/
if (malloc_default_purgeable_zone != NULL)
malloc_default_purgeable_zone();
purgeable_zone = malloc_default_purgeable_zone();
/* Register the custom zone. At this point it won't be the default. */
malloc_zone_register(&zone);
/*
* Unregister and reregister the default zone. On OSX >= 10.6,
* unregistering takes the last registered zone and places it at the
* location of the specified zone. Unregistering the default zone thus
* makes the last registered one the default. On OSX < 10.6,
* unregistering shifts all registered zones. The first registered zone
* then becomes the default.
*/
do {
default_zone = malloc_default_zone();
/*
* Unregister and reregister the default zone. On OSX >= 10.6,
* unregistering takes the last registered zone and places it
* at the location of the specified zone. Unregistering the
* default zone thus makes the last registered one the default.
* On OSX < 10.6, unregistering shifts all registered zones.
* The first registered zone then becomes the default.
*/
malloc_zone_unregister(default_zone);
malloc_zone_register(default_zone);
/*
* On OSX 10.6, having the default purgeable zone appear before
* the default zone makes some things crash because it thinks it
* owns the default zone allocated pointers. We thus
* unregister/re-register it in order to ensure it's always
* after the default zone. On OSX < 10.6, there is no purgeable
* zone, so this does nothing. On OSX >= 10.6, unregistering
* replaces the purgeable zone with the last registered zone
* above, i.e. the default zone. Registering it again then puts
* it at the end, obviously after the default zone.
*/
if (purgeable_zone) {
malloc_zone_unregister(purgeable_zone);
malloc_zone_register(purgeable_zone);
}
} while (malloc_default_zone() != &zone);
}
#include "test/jemalloc_test.h"
/* btalloc() provides a mechanism for allocating via permuted backtraces. */
void *btalloc(size_t size, unsigned bits);
#define NTHREADS 4
#define NALLOCS_PER_THREAD 50
#define DUMP_INTERVAL 1
#define BT_COUNT_CHECK_INTERVAL 5
#define btalloc_n_proto(n) \
void *btalloc_##n(size_t size, unsigned bits);
btalloc_n_proto(0)
btalloc_n_proto(1)
#define alloc_n_proto(n) \
void *alloc_##n(unsigned bits);
alloc_n_proto(0)
alloc_n_proto(1)
#define alloc_n_gen(n) \
#define btalloc_n_gen(n) \
void * \
alloc_##n(unsigned bits) \
btalloc_##n(size_t size, unsigned bits) \
{ \
void *p; \
\
if (bits == 0) \
p = mallocx(1, 0); \
p = mallocx(size, 0); \
else { \
switch (bits & 0x1U) { \
case 0: \
p = (alloc_0(bits >> 1)); \
p = (btalloc_0(size, bits >> 1)); \
break; \
case 1: \
p = (alloc_1(bits >> 1)); \
p = (btalloc_1(size, bits >> 1)); \
break; \
default: not_reached(); \
} \
......
#include <limits.h>
#ifndef SIZE_T_MAX
# define SIZE_T_MAX SIZE_MAX
#endif
#include <stdlib.h>
#include <stdarg.h>
#include <stdbool.h>
#include <errno.h>
#include <inttypes.h>
#include <math.h>
#include <string.h>
#ifdef _WIN32
# include "msvc_compat/strings.h"
#endif
#include <sys/time.h>
#ifdef _WIN32
# include <windows.h>
# include "msvc_compat/windows_extra.h"
#else
# include <pthread.h>
#endif
......@@ -132,10 +140,12 @@
/*
* Common test utilities.
*/
#include "test/btalloc.h"
#include "test/math.h"
#include "test/mtx.h"
#include "test/mq.h"
#include "test/test.h"
#include "test/timer.h"
#include "test/thd.h"
#define MEXP 19937
#include "test/SFMT.h"
#include "jemalloc/internal/jemalloc_internal_defs.h"
#include "jemalloc/internal/jemalloc_internal_decls.h"
/* For use by SFMT. */
/*
* For use by SFMT. configure.ac doesn't actually define HAVE_SSE2 because its
* dependencies are notoriously unportable in practice.
*/
#undef HAVE_SSE2
#undef HAVE_ALTIVEC
......@@ -299,7 +299,7 @@ pt_chi2(double p, double df, double ln_gamma_df_2)
/*
* Given a value p in [0..1] and Gamma distribution shape and scale parameters,
* compute the upper limit on the definite integeral from [0..z] that satisfies
* compute the upper limit on the definite integral from [0..z] that satisfies
* p.
*/
JEMALLOC_INLINE double
......
void mq_nanosleep(unsigned ns);
/*
* Simple templated message queue implementation that relies on only mutexes for
* synchronization (which reduces portability issues). Given the following
......@@ -75,26 +77,23 @@ a_attr a_mq_msg_type * \
a_prefix##get(a_mq_type *mq) \
{ \
a_mq_msg_type *msg; \
struct timespec timeout; \
unsigned ns; \
\
msg = a_prefix##tryget(mq); \
if (msg != NULL) \
return (msg); \
\
timeout.tv_sec = 0; \
timeout.tv_nsec = 1; \
ns = 1; \
while (true) { \
nanosleep(&timeout, NULL); \
mq_nanosleep(ns); \
msg = a_prefix##tryget(mq); \
if (msg != NULL) \
return (msg); \
if (timeout.tv_sec == 0) { \
if (ns < 1000*1000*1000) { \
/* Double sleep time, up to max 1 second. */ \
timeout.tv_nsec <<= 1; \
if (timeout.tv_nsec >= 1000*1000*1000) { \
timeout.tv_sec = 1; \
timeout.tv_nsec = 0; \
} \
ns <<= 1; \
if (ns > 1000*1000*1000) \
ns = 1000*1000*1000; \
} \
} \
} \
......
#define ASSERT_BUFSIZE 256
#define assert_cmp(t, a, b, cmp, neg_cmp, pri, fmt...) do { \
#define assert_cmp(t, a, b, cmp, neg_cmp, pri, ...) do { \
t a_ = (a); \
t b_ = (b); \
if (!(a_ cmp b_)) { \
......@@ -12,205 +12,205 @@
"%"pri" "#neg_cmp" %"pri": ", \
__func__, __FILE__, __LINE__, \
#a, #b, a_, b_); \
malloc_snprintf(message, sizeof(message), fmt); \
malloc_snprintf(message, sizeof(message), __VA_ARGS__); \
p_test_fail(prefix, message); \
} \
} while (0)
#define assert_ptr_eq(a, b, fmt...) assert_cmp(void *, a, b, ==, \
!=, "p", fmt)
#define assert_ptr_ne(a, b, fmt...) assert_cmp(void *, a, b, !=, \
==, "p", fmt)
#define assert_ptr_null(a, fmt...) assert_cmp(void *, a, NULL, ==, \
!=, "p", fmt)
#define assert_ptr_not_null(a, fmt...) assert_cmp(void *, a, NULL, !=, \
==, "p", fmt)
#define assert_ptr_eq(a, b, ...) assert_cmp(void *, a, b, ==, \
!=, "p", __VA_ARGS__)
#define assert_ptr_ne(a, b, ...) assert_cmp(void *, a, b, !=, \
==, "p", __VA_ARGS__)
#define assert_ptr_null(a, ...) assert_cmp(void *, a, NULL, ==, \
!=, "p", __VA_ARGS__)
#define assert_ptr_not_null(a, ...) assert_cmp(void *, a, NULL, !=, \
==, "p", __VA_ARGS__)
#define assert_c_eq(a, b, fmt...) assert_cmp(char, a, b, ==, !=, "c", fmt)
#define assert_c_ne(a, b, fmt...) assert_cmp(char, a, b, !=, ==, "c", fmt)
#define assert_c_lt(a, b, fmt...) assert_cmp(char, a, b, <, >=, "c", fmt)
#define assert_c_le(a, b, fmt...) assert_cmp(char, a, b, <=, >, "c", fmt)
#define assert_c_ge(a, b, fmt...) assert_cmp(char, a, b, >=, <, "c", fmt)
#define assert_c_gt(a, b, fmt...) assert_cmp(char, a, b, >, <=, "c", fmt)
#define assert_c_eq(a, b, ...) assert_cmp(char, a, b, ==, !=, "c", __VA_ARGS__)
#define assert_c_ne(a, b, ...) assert_cmp(char, a, b, !=, ==, "c", __VA_ARGS__)
#define assert_c_lt(a, b, ...) assert_cmp(char, a, b, <, >=, "c", __VA_ARGS__)
#define assert_c_le(a, b, ...) assert_cmp(char, a, b, <=, >, "c", __VA_ARGS__)
#define assert_c_ge(a, b, ...) assert_cmp(char, a, b, >=, <, "c", __VA_ARGS__)
#define assert_c_gt(a, b, ...) assert_cmp(char, a, b, >, <=, "c", __VA_ARGS__)
#define assert_x_eq(a, b, fmt...) assert_cmp(int, a, b, ==, !=, "#x", fmt)
#define assert_x_ne(a, b, fmt...) assert_cmp(int, a, b, !=, ==, "#x", fmt)
#define assert_x_lt(a, b, fmt...) assert_cmp(int, a, b, <, >=, "#x", fmt)
#define assert_x_le(a, b, fmt...) assert_cmp(int, a, b, <=, >, "#x", fmt)
#define assert_x_ge(a, b, fmt...) assert_cmp(int, a, b, >=, <, "#x", fmt)
#define assert_x_gt(a, b, fmt...) assert_cmp(int, a, b, >, <=, "#x", fmt)
#define assert_x_eq(a, b, ...) assert_cmp(int, a, b, ==, !=, "#x", __VA_ARGS__)
#define assert_x_ne(a, b, ...) assert_cmp(int, a, b, !=, ==, "#x", __VA_ARGS__)
#define assert_x_lt(a, b, ...) assert_cmp(int, a, b, <, >=, "#x", __VA_ARGS__)
#define assert_x_le(a, b, ...) assert_cmp(int, a, b, <=, >, "#x", __VA_ARGS__)
#define assert_x_ge(a, b, ...) assert_cmp(int, a, b, >=, <, "#x", __VA_ARGS__)
#define assert_x_gt(a, b, ...) assert_cmp(int, a, b, >, <=, "#x", __VA_ARGS__)
#define assert_d_eq(a, b, fmt...) assert_cmp(int, a, b, ==, !=, "d", fmt)
#define assert_d_ne(a, b, fmt...) assert_cmp(int, a, b, !=, ==, "d", fmt)
#define assert_d_lt(a, b, fmt...) assert_cmp(int, a, b, <, >=, "d", fmt)
#define assert_d_le(a, b, fmt...) assert_cmp(int, a, b, <=, >, "d", fmt)
#define assert_d_ge(a, b, fmt...) assert_cmp(int, a, b, >=, <, "d", fmt)
#define assert_d_gt(a, b, fmt...) assert_cmp(int, a, b, >, <=, "d", fmt)
#define assert_d_eq(a, b, ...) assert_cmp(int, a, b, ==, !=, "d", __VA_ARGS__)
#define assert_d_ne(a, b, ...) assert_cmp(int, a, b, !=, ==, "d", __VA_ARGS__)
#define assert_d_lt(a, b, ...) assert_cmp(int, a, b, <, >=, "d", __VA_ARGS__)
#define assert_d_le(a, b, ...) assert_cmp(int, a, b, <=, >, "d", __VA_ARGS__)
#define assert_d_ge(a, b, ...) assert_cmp(int, a, b, >=, <, "d", __VA_ARGS__)
#define assert_d_gt(a, b, ...) assert_cmp(int, a, b, >, <=, "d", __VA_ARGS__)
#define assert_u_eq(a, b, fmt...) assert_cmp(int, a, b, ==, !=, "u", fmt)
#define assert_u_ne(a, b, fmt...) assert_cmp(int, a, b, !=, ==, "u", fmt)
#define assert_u_lt(a, b, fmt...) assert_cmp(int, a, b, <, >=, "u", fmt)
#define assert_u_le(a, b, fmt...) assert_cmp(int, a, b, <=, >, "u", fmt)
#define assert_u_ge(a, b, fmt...) assert_cmp(int, a, b, >=, <, "u", fmt)
#define assert_u_gt(a, b, fmt...) assert_cmp(int, a, b, >, <=, "u", fmt)
#define assert_u_eq(a, b, ...) assert_cmp(int, a, b, ==, !=, "u", __VA_ARGS__)
#define assert_u_ne(a, b, ...) assert_cmp(int, a, b, !=, ==, "u", __VA_ARGS__)
#define assert_u_lt(a, b, ...) assert_cmp(int, a, b, <, >=, "u", __VA_ARGS__)
#define assert_u_le(a, b, ...) assert_cmp(int, a, b, <=, >, "u", __VA_ARGS__)
#define assert_u_ge(a, b, ...) assert_cmp(int, a, b, >=, <, "u", __VA_ARGS__)
#define assert_u_gt(a, b, ...) assert_cmp(int, a, b, >, <=, "u", __VA_ARGS__)
#define assert_ld_eq(a, b, fmt...) assert_cmp(long, a, b, ==, \
!=, "ld", fmt)
#define assert_ld_ne(a, b, fmt...) assert_cmp(long, a, b, !=, \
==, "ld", fmt)
#define assert_ld_lt(a, b, fmt...) assert_cmp(long, a, b, <, \
>=, "ld", fmt)
#define assert_ld_le(a, b, fmt...) assert_cmp(long, a, b, <=, \
>, "ld", fmt)
#define assert_ld_ge(a, b, fmt...) assert_cmp(long, a, b, >=, \
<, "ld", fmt)
#define assert_ld_gt(a, b, fmt...) assert_cmp(long, a, b, >, \
<=, "ld", fmt)
#define assert_ld_eq(a, b, ...) assert_cmp(long, a, b, ==, \
!=, "ld", __VA_ARGS__)
#define assert_ld_ne(a, b, ...) assert_cmp(long, a, b, !=, \
==, "ld", __VA_ARGS__)
#define assert_ld_lt(a, b, ...) assert_cmp(long, a, b, <, \
>=, "ld", __VA_ARGS__)
#define assert_ld_le(a, b, ...) assert_cmp(long, a, b, <=, \
>, "ld", __VA_ARGS__)
#define assert_ld_ge(a, b, ...) assert_cmp(long, a, b, >=, \
<, "ld", __VA_ARGS__)
#define assert_ld_gt(a, b, ...) assert_cmp(long, a, b, >, \
<=, "ld", __VA_ARGS__)
#define assert_lu_eq(a, b, fmt...) assert_cmp(unsigned long, \
a, b, ==, !=, "lu", fmt)
#define assert_lu_ne(a, b, fmt...) assert_cmp(unsigned long, \
a, b, !=, ==, "lu", fmt)
#define assert_lu_lt(a, b, fmt...) assert_cmp(unsigned long, \
a, b, <, >=, "lu", fmt)
#define assert_lu_le(a, b, fmt...) assert_cmp(unsigned long, \
a, b, <=, >, "lu", fmt)
#define assert_lu_ge(a, b, fmt...) assert_cmp(unsigned long, \
a, b, >=, <, "lu", fmt)
#define assert_lu_gt(a, b, fmt...) assert_cmp(unsigned long, \
a, b, >, <=, "lu", fmt)
#define assert_lu_eq(a, b, ...) assert_cmp(unsigned long, \
a, b, ==, !=, "lu", __VA_ARGS__)
#define assert_lu_ne(a, b, ...) assert_cmp(unsigned long, \
a, b, !=, ==, "lu", __VA_ARGS__)
#define assert_lu_lt(a, b, ...) assert_cmp(unsigned long, \
a, b, <, >=, "lu", __VA_ARGS__)
#define assert_lu_le(a, b, ...) assert_cmp(unsigned long, \
a, b, <=, >, "lu", __VA_ARGS__)
#define assert_lu_ge(a, b, ...) assert_cmp(unsigned long, \
a, b, >=, <, "lu", __VA_ARGS__)
#define assert_lu_gt(a, b, ...) assert_cmp(unsigned long, \
a, b, >, <=, "lu", __VA_ARGS__)
#define assert_qd_eq(a, b, fmt...) assert_cmp(long long, a, b, ==, \
!=, "qd", fmt)
#define assert_qd_ne(a, b, fmt...) assert_cmp(long long, a, b, !=, \
==, "qd", fmt)
#define assert_qd_lt(a, b, fmt...) assert_cmp(long long, a, b, <, \
>=, "qd", fmt)
#define assert_qd_le(a, b, fmt...) assert_cmp(long long, a, b, <=, \
>, "qd", fmt)
#define assert_qd_ge(a, b, fmt...) assert_cmp(long long, a, b, >=, \
<, "qd", fmt)
#define assert_qd_gt(a, b, fmt...) assert_cmp(long long, a, b, >, \
<=, "qd", fmt)
#define assert_qd_eq(a, b, ...) assert_cmp(long long, a, b, ==, \
!=, "qd", __VA_ARGS__)
#define assert_qd_ne(a, b, ...) assert_cmp(long long, a, b, !=, \
==, "qd", __VA_ARGS__)
#define assert_qd_lt(a, b, ...) assert_cmp(long long, a, b, <, \
>=, "qd", __VA_ARGS__)
#define assert_qd_le(a, b, ...) assert_cmp(long long, a, b, <=, \
>, "qd", __VA_ARGS__)
#define assert_qd_ge(a, b, ...) assert_cmp(long long, a, b, >=, \
<, "qd", __VA_ARGS__)
#define assert_qd_gt(a, b, ...) assert_cmp(long long, a, b, >, \
<=, "qd", __VA_ARGS__)
#define assert_qu_eq(a, b, fmt...) assert_cmp(unsigned long long, \
a, b, ==, !=, "qu", fmt)
#define assert_qu_ne(a, b, fmt...) assert_cmp(unsigned long long, \
a, b, !=, ==, "qu", fmt)
#define assert_qu_lt(a, b, fmt...) assert_cmp(unsigned long long, \
a, b, <, >=, "qu", fmt)
#define assert_qu_le(a, b, fmt...) assert_cmp(unsigned long long, \
a, b, <=, >, "qu", fmt)
#define assert_qu_ge(a, b, fmt...) assert_cmp(unsigned long long, \
a, b, >=, <, "qu", fmt)
#define assert_qu_gt(a, b, fmt...) assert_cmp(unsigned long long, \
a, b, >, <=, "qu", fmt)
#define assert_qu_eq(a, b, ...) assert_cmp(unsigned long long, \
a, b, ==, !=, "qu", __VA_ARGS__)
#define assert_qu_ne(a, b, ...) assert_cmp(unsigned long long, \
a, b, !=, ==, "qu", __VA_ARGS__)
#define assert_qu_lt(a, b, ...) assert_cmp(unsigned long long, \
a, b, <, >=, "qu", __VA_ARGS__)
#define assert_qu_le(a, b, ...) assert_cmp(unsigned long long, \
a, b, <=, >, "qu", __VA_ARGS__)
#define assert_qu_ge(a, b, ...) assert_cmp(unsigned long long, \
a, b, >=, <, "qu", __VA_ARGS__)
#define assert_qu_gt(a, b, ...) assert_cmp(unsigned long long, \
a, b, >, <=, "qu", __VA_ARGS__)
#define assert_jd_eq(a, b, fmt...) assert_cmp(intmax_t, a, b, ==, \
!=, "jd", fmt)
#define assert_jd_ne(a, b, fmt...) assert_cmp(intmax_t, a, b, !=, \
==, "jd", fmt)
#define assert_jd_lt(a, b, fmt...) assert_cmp(intmax_t, a, b, <, \
>=, "jd", fmt)
#define assert_jd_le(a, b, fmt...) assert_cmp(intmax_t, a, b, <=, \
>, "jd", fmt)
#define assert_jd_ge(a, b, fmt...) assert_cmp(intmax_t, a, b, >=, \
<, "jd", fmt)
#define assert_jd_gt(a, b, fmt...) assert_cmp(intmax_t, a, b, >, \
<=, "jd", fmt)
#define assert_jd_eq(a, b, ...) assert_cmp(intmax_t, a, b, ==, \
!=, "jd", __VA_ARGS__)
#define assert_jd_ne(a, b, ...) assert_cmp(intmax_t, a, b, !=, \
==, "jd", __VA_ARGS__)
#define assert_jd_lt(a, b, ...) assert_cmp(intmax_t, a, b, <, \
>=, "jd", __VA_ARGS__)
#define assert_jd_le(a, b, ...) assert_cmp(intmax_t, a, b, <=, \
>, "jd", __VA_ARGS__)
#define assert_jd_ge(a, b, ...) assert_cmp(intmax_t, a, b, >=, \
<, "jd", __VA_ARGS__)
#define assert_jd_gt(a, b, ...) assert_cmp(intmax_t, a, b, >, \
<=, "jd", __VA_ARGS__)
#define assert_ju_eq(a, b, fmt...) assert_cmp(uintmax_t, a, b, ==, \
!=, "ju", fmt)
#define assert_ju_ne(a, b, fmt...) assert_cmp(uintmax_t, a, b, !=, \
==, "ju", fmt)
#define assert_ju_lt(a, b, fmt...) assert_cmp(uintmax_t, a, b, <, \
>=, "ju", fmt)
#define assert_ju_le(a, b, fmt...) assert_cmp(uintmax_t, a, b, <=, \
>, "ju", fmt)
#define assert_ju_ge(a, b, fmt...) assert_cmp(uintmax_t, a, b, >=, \
<, "ju", fmt)
#define assert_ju_gt(a, b, fmt...) assert_cmp(uintmax_t, a, b, >, \
<=, "ju", fmt)
#define assert_ju_eq(a, b, ...) assert_cmp(uintmax_t, a, b, ==, \
!=, "ju", __VA_ARGS__)
#define assert_ju_ne(a, b, ...) assert_cmp(uintmax_t, a, b, !=, \
==, "ju", __VA_ARGS__)
#define assert_ju_lt(a, b, ...) assert_cmp(uintmax_t, a, b, <, \
>=, "ju", __VA_ARGS__)
#define assert_ju_le(a, b, ...) assert_cmp(uintmax_t, a, b, <=, \
>, "ju", __VA_ARGS__)
#define assert_ju_ge(a, b, ...) assert_cmp(uintmax_t, a, b, >=, \
<, "ju", __VA_ARGS__)
#define assert_ju_gt(a, b, ...) assert_cmp(uintmax_t, a, b, >, \
<=, "ju", __VA_ARGS__)
#define assert_zd_eq(a, b, fmt...) assert_cmp(ssize_t, a, b, ==, \
!=, "zd", fmt)
#define assert_zd_ne(a, b, fmt...) assert_cmp(ssize_t, a, b, !=, \
==, "zd", fmt)
#define assert_zd_lt(a, b, fmt...) assert_cmp(ssize_t, a, b, <, \
>=, "zd", fmt)
#define assert_zd_le(a, b, fmt...) assert_cmp(ssize_t, a, b, <=, \
>, "zd", fmt)
#define assert_zd_ge(a, b, fmt...) assert_cmp(ssize_t, a, b, >=, \
<, "zd", fmt)
#define assert_zd_gt(a, b, fmt...) assert_cmp(ssize_t, a, b, >, \
<=, "zd", fmt)
#define assert_zd_eq(a, b, ...) assert_cmp(ssize_t, a, b, ==, \
!=, "zd", __VA_ARGS__)
#define assert_zd_ne(a, b, ...) assert_cmp(ssize_t, a, b, !=, \
==, "zd", __VA_ARGS__)
#define assert_zd_lt(a, b, ...) assert_cmp(ssize_t, a, b, <, \
>=, "zd", __VA_ARGS__)
#define assert_zd_le(a, b, ...) assert_cmp(ssize_t, a, b, <=, \
>, "zd", __VA_ARGS__)
#define assert_zd_ge(a, b, ...) assert_cmp(ssize_t, a, b, >=, \
<, "zd", __VA_ARGS__)
#define assert_zd_gt(a, b, ...) assert_cmp(ssize_t, a, b, >, \
<=, "zd", __VA_ARGS__)
#define assert_zu_eq(a, b, fmt...) assert_cmp(size_t, a, b, ==, \
!=, "zu", fmt)
#define assert_zu_ne(a, b, fmt...) assert_cmp(size_t, a, b, !=, \
==, "zu", fmt)
#define assert_zu_lt(a, b, fmt...) assert_cmp(size_t, a, b, <, \
>=, "zu", fmt)
#define assert_zu_le(a, b, fmt...) assert_cmp(size_t, a, b, <=, \
>, "zu", fmt)
#define assert_zu_ge(a, b, fmt...) assert_cmp(size_t, a, b, >=, \
<, "zu", fmt)
#define assert_zu_gt(a, b, fmt...) assert_cmp(size_t, a, b, >, \
<=, "zu", fmt)
#define assert_zu_eq(a, b, ...) assert_cmp(size_t, a, b, ==, \
!=, "zu", __VA_ARGS__)
#define assert_zu_ne(a, b, ...) assert_cmp(size_t, a, b, !=, \
==, "zu", __VA_ARGS__)
#define assert_zu_lt(a, b, ...) assert_cmp(size_t, a, b, <, \
>=, "zu", __VA_ARGS__)
#define assert_zu_le(a, b, ...) assert_cmp(size_t, a, b, <=, \
>, "zu", __VA_ARGS__)
#define assert_zu_ge(a, b, ...) assert_cmp(size_t, a, b, >=, \
<, "zu", __VA_ARGS__)
#define assert_zu_gt(a, b, ...) assert_cmp(size_t, a, b, >, \
<=, "zu", __VA_ARGS__)
#define assert_d32_eq(a, b, fmt...) assert_cmp(int32_t, a, b, ==, \
!=, PRId32, fmt)
#define assert_d32_ne(a, b, fmt...) assert_cmp(int32_t, a, b, !=, \
==, PRId32, fmt)
#define assert_d32_lt(a, b, fmt...) assert_cmp(int32_t, a, b, <, \
>=, PRId32, fmt)
#define assert_d32_le(a, b, fmt...) assert_cmp(int32_t, a, b, <=, \
>, PRId32, fmt)
#define assert_d32_ge(a, b, fmt...) assert_cmp(int32_t, a, b, >=, \
<, PRId32, fmt)
#define assert_d32_gt(a, b, fmt...) assert_cmp(int32_t, a, b, >, \
<=, PRId32, fmt)
#define assert_d32_eq(a, b, ...) assert_cmp(int32_t, a, b, ==, \
!=, FMTd32, __VA_ARGS__)
#define assert_d32_ne(a, b, ...) assert_cmp(int32_t, a, b, !=, \
==, FMTd32, __VA_ARGS__)
#define assert_d32_lt(a, b, ...) assert_cmp(int32_t, a, b, <, \
>=, FMTd32, __VA_ARGS__)
#define assert_d32_le(a, b, ...) assert_cmp(int32_t, a, b, <=, \
>, FMTd32, __VA_ARGS__)
#define assert_d32_ge(a, b, ...) assert_cmp(int32_t, a, b, >=, \
<, FMTd32, __VA_ARGS__)
#define assert_d32_gt(a, b, ...) assert_cmp(int32_t, a, b, >, \
<=, FMTd32, __VA_ARGS__)
#define assert_u32_eq(a, b, fmt...) assert_cmp(uint32_t, a, b, ==, \
!=, PRIu32, fmt)
#define assert_u32_ne(a, b, fmt...) assert_cmp(uint32_t, a, b, !=, \
==, PRIu32, fmt)
#define assert_u32_lt(a, b, fmt...) assert_cmp(uint32_t, a, b, <, \
>=, PRIu32, fmt)
#define assert_u32_le(a, b, fmt...) assert_cmp(uint32_t, a, b, <=, \
>, PRIu32, fmt)
#define assert_u32_ge(a, b, fmt...) assert_cmp(uint32_t, a, b, >=, \
<, PRIu32, fmt)
#define assert_u32_gt(a, b, fmt...) assert_cmp(uint32_t, a, b, >, \
<=, PRIu32, fmt)
#define assert_u32_eq(a, b, ...) assert_cmp(uint32_t, a, b, ==, \
!=, FMTu32, __VA_ARGS__)
#define assert_u32_ne(a, b, ...) assert_cmp(uint32_t, a, b, !=, \
==, FMTu32, __VA_ARGS__)
#define assert_u32_lt(a, b, ...) assert_cmp(uint32_t, a, b, <, \
>=, FMTu32, __VA_ARGS__)
#define assert_u32_le(a, b, ...) assert_cmp(uint32_t, a, b, <=, \
>, FMTu32, __VA_ARGS__)
#define assert_u32_ge(a, b, ...) assert_cmp(uint32_t, a, b, >=, \
<, FMTu32, __VA_ARGS__)
#define assert_u32_gt(a, b, ...) assert_cmp(uint32_t, a, b, >, \
<=, FMTu32, __VA_ARGS__)
#define assert_d64_eq(a, b, fmt...) assert_cmp(int64_t, a, b, ==, \
!=, PRId64, fmt)
#define assert_d64_ne(a, b, fmt...) assert_cmp(int64_t, a, b, !=, \
==, PRId64, fmt)
#define assert_d64_lt(a, b, fmt...) assert_cmp(int64_t, a, b, <, \
>=, PRId64, fmt)
#define assert_d64_le(a, b, fmt...) assert_cmp(int64_t, a, b, <=, \
>, PRId64, fmt)
#define assert_d64_ge(a, b, fmt...) assert_cmp(int64_t, a, b, >=, \
<, PRId64, fmt)
#define assert_d64_gt(a, b, fmt...) assert_cmp(int64_t, a, b, >, \
<=, PRId64, fmt)
#define assert_d64_eq(a, b, ...) assert_cmp(int64_t, a, b, ==, \
!=, FMTd64, __VA_ARGS__)
#define assert_d64_ne(a, b, ...) assert_cmp(int64_t, a, b, !=, \
==, FMTd64, __VA_ARGS__)
#define assert_d64_lt(a, b, ...) assert_cmp(int64_t, a, b, <, \
>=, FMTd64, __VA_ARGS__)
#define assert_d64_le(a, b, ...) assert_cmp(int64_t, a, b, <=, \
>, FMTd64, __VA_ARGS__)
#define assert_d64_ge(a, b, ...) assert_cmp(int64_t, a, b, >=, \
<, FMTd64, __VA_ARGS__)
#define assert_d64_gt(a, b, ...) assert_cmp(int64_t, a, b, >, \
<=, FMTd64, __VA_ARGS__)
#define assert_u64_eq(a, b, fmt...) assert_cmp(uint64_t, a, b, ==, \
!=, PRIu64, fmt)
#define assert_u64_ne(a, b, fmt...) assert_cmp(uint64_t, a, b, !=, \
==, PRIu64, fmt)
#define assert_u64_lt(a, b, fmt...) assert_cmp(uint64_t, a, b, <, \
>=, PRIu64, fmt)
#define assert_u64_le(a, b, fmt...) assert_cmp(uint64_t, a, b, <=, \
>, PRIu64, fmt)
#define assert_u64_ge(a, b, fmt...) assert_cmp(uint64_t, a, b, >=, \
<, PRIu64, fmt)
#define assert_u64_gt(a, b, fmt...) assert_cmp(uint64_t, a, b, >, \
<=, PRIu64, fmt)
#define assert_u64_eq(a, b, ...) assert_cmp(uint64_t, a, b, ==, \
!=, FMTu64, __VA_ARGS__)
#define assert_u64_ne(a, b, ...) assert_cmp(uint64_t, a, b, !=, \
==, FMTu64, __VA_ARGS__)
#define assert_u64_lt(a, b, ...) assert_cmp(uint64_t, a, b, <, \
>=, FMTu64, __VA_ARGS__)
#define assert_u64_le(a, b, ...) assert_cmp(uint64_t, a, b, <=, \
>, FMTu64, __VA_ARGS__)
#define assert_u64_ge(a, b, ...) assert_cmp(uint64_t, a, b, >=, \
<, FMTu64, __VA_ARGS__)
#define assert_u64_gt(a, b, ...) assert_cmp(uint64_t, a, b, >, \
<=, FMTu64, __VA_ARGS__)
#define assert_b_eq(a, b, fmt...) do { \
#define assert_b_eq(a, b, ...) do { \
bool a_ = (a); \
bool b_ = (b); \
if (!(a_ == b_)) { \
......@@ -222,11 +222,11 @@
__func__, __FILE__, __LINE__, \
#a, #b, a_ ? "true" : "false", \
b_ ? "true" : "false"); \
malloc_snprintf(message, sizeof(message), fmt); \
malloc_snprintf(message, sizeof(message), __VA_ARGS__); \
p_test_fail(prefix, message); \
} \
} while (0)
#define assert_b_ne(a, b, fmt...) do { \
#define assert_b_ne(a, b, ...) do { \
bool a_ = (a); \
bool b_ = (b); \
if (!(a_ != b_)) { \
......@@ -238,14 +238,14 @@
__func__, __FILE__, __LINE__, \
#a, #b, a_ ? "true" : "false", \
b_ ? "true" : "false"); \
malloc_snprintf(message, sizeof(message), fmt); \
malloc_snprintf(message, sizeof(message), __VA_ARGS__); \
p_test_fail(prefix, message); \
} \
} while (0)
#define assert_true(a, fmt...) assert_b_eq(a, true, fmt)
#define assert_false(a, fmt...) assert_b_eq(a, false, fmt)
#define assert_true(a, ...) assert_b_eq(a, true, __VA_ARGS__)
#define assert_false(a, ...) assert_b_eq(a, false, __VA_ARGS__)
#define assert_str_eq(a, b, fmt...) do { \
#define assert_str_eq(a, b, ...) do { \
if (strcmp((a), (b))) { \
char prefix[ASSERT_BUFSIZE]; \
char message[ASSERT_BUFSIZE]; \
......@@ -254,11 +254,11 @@
"(%s) same as (%s) --> " \
"\"%s\" differs from \"%s\": ", \
__func__, __FILE__, __LINE__, #a, #b, a, b); \
malloc_snprintf(message, sizeof(message), fmt); \
malloc_snprintf(message, sizeof(message), __VA_ARGS__); \
p_test_fail(prefix, message); \
} \
} while (0)
#define assert_str_ne(a, b, fmt...) do { \
#define assert_str_ne(a, b, ...) do { \
if (!strcmp((a), (b))) { \
char prefix[ASSERT_BUFSIZE]; \
char message[ASSERT_BUFSIZE]; \
......@@ -267,18 +267,18 @@
"(%s) differs from (%s) --> " \
"\"%s\" same as \"%s\": ", \
__func__, __FILE__, __LINE__, #a, #b, a, b); \
malloc_snprintf(message, sizeof(message), fmt); \
malloc_snprintf(message, sizeof(message), __VA_ARGS__); \
p_test_fail(prefix, message); \
} \
} while (0)
#define assert_not_reached(fmt...) do { \
#define assert_not_reached(...) do { \
char prefix[ASSERT_BUFSIZE]; \
char message[ASSERT_BUFSIZE]; \
malloc_snprintf(prefix, sizeof(prefix), \
"%s:%s:%d: Unreachable code reached: ", \
__func__, __FILE__, __LINE__); \
malloc_snprintf(message, sizeof(message), fmt); \
malloc_snprintf(message, sizeof(message), __VA_ARGS__); \
p_test_fail(prefix, message); \
} while (0)
......@@ -308,8 +308,8 @@ label_test_end: \
p_test_fini(); \
}
#define test(tests...) \
p_test(tests, NULL)
#define test(...) \
p_test(__VA_ARGS__, NULL)
#define test_skip_if(e) do { \
if (e) { \
......@@ -319,11 +319,11 @@ label_test_end: \
} \
} while (0)
void test_skip(const char *format, ...) JEMALLOC_ATTR(format(printf, 1, 2));
void test_fail(const char *format, ...) JEMALLOC_ATTR(format(printf, 1, 2));
void test_skip(const char *format, ...) JEMALLOC_FORMAT_PRINTF(1, 2);
void test_fail(const char *format, ...) JEMALLOC_FORMAT_PRINTF(1, 2);
/* For private use by macros. */
test_status_t p_test(test_t* t, ...);
test_status_t p_test(test_t *t, ...);
void p_test_init(const char *name);
void p_test_fini(void);
void p_test_fail(const char *prefix, const char *message);
/* Abstraction layer for threading in tests */
/* Abstraction layer for threading in tests. */
#ifdef _WIN32
typedef HANDLE thd_t;
#else
......
/* Simple timer, for use in benchmark reporting. */
#include <unistd.h>
#include <sys/time.h>
#define JEMALLOC_CLOCK_GETTIME defined(_POSIX_MONOTONIC_CLOCK) \
&& _POSIX_MONOTONIC_CLOCK >= 0
typedef struct {
#ifdef _WIN32
FILETIME ft0;
FILETIME ft1;
#elif JEMALLOC_CLOCK_GETTIME
struct timespec ts0;
struct timespec ts1;
int clock_id;
#else
struct timeval tv0;
struct timeval tv1;
#endif
} timedelta_t;
void timer_start(timedelta_t *timer);
void timer_stop(timedelta_t *timer);
uint64_t timer_usec(const timedelta_t *timer);
void timer_ratio(timedelta_t *a, timedelta_t *b, char *buf, size_t buflen);
......@@ -2,6 +2,14 @@
#define NTHREADS 10
static bool have_dss =
#ifdef JEMALLOC_DSS
true
#else
false
#endif
;
void *
thd_start(void *arg)
{
......@@ -18,13 +26,16 @@ thd_start(void *arg)
size_t mib[3];
size_t miblen = sizeof(mib) / sizeof(size_t);
const char *dss_precs[] = {"disabled", "primary", "secondary"};
const char *dss = dss_precs[thread_ind %
(sizeof(dss_precs)/sizeof(char*))];
unsigned prec_ind = thread_ind %
(sizeof(dss_precs)/sizeof(char*));
const char *dss = dss_precs[prec_ind];
int expected_err = (have_dss || prec_ind == 0) ? 0 : EFAULT;
assert_d_eq(mallctlnametomib("arena.0.dss", mib, &miblen), 0,
"Error in mallctlnametomib()");
mib[1] = arena_ind;
assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, (void *)&dss,
sizeof(const char *)), 0, "Error in mallctlbymib()");
sizeof(const char *)), expected_err,
"Error in mallctlbymib()");
}
p = mallocx(1, MALLOCX_ARENA(arena_ind));
......@@ -34,7 +45,7 @@ thd_start(void *arg)
return (NULL);
}
TEST_BEGIN(test_ALLOCM_ARENA)
TEST_BEGIN(test_MALLOCX_ARENA)
{
thd_t thds[NTHREADS];
unsigned i;
......@@ -54,5 +65,5 @@ main(void)
{
return (test(
test_ALLOCM_ARENA));
test_MALLOCX_ARENA));
}
#include "test/jemalloc_test.h"
#define CHUNK 0x400000
#define MAXALIGN (((size_t)1) << 25)
#define NITER 4
TEST_BEGIN(test_basic)
{
size_t nsz, rsz, sz;
void *p;
sz = 42;
nsz = 0;
assert_d_eq(nallocm(&nsz, sz, 0), ALLOCM_SUCCESS,
"Unexpected nallocm() error");
rsz = 0;
assert_d_eq(allocm(&p, &rsz, sz, 0), ALLOCM_SUCCESS,
"Unexpected allocm() error");
assert_zu_ge(rsz, sz, "Real size smaller than expected");
assert_zu_eq(nsz, rsz, "nallocm()/allocm() rsize mismatch");
assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,
"Unexpected dallocm() error");
assert_d_eq(allocm(&p, NULL, sz, 0), ALLOCM_SUCCESS,
"Unexpected allocm() error");
assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,
"Unexpected dallocm() error");
nsz = 0;
assert_d_eq(nallocm(&nsz, sz, ALLOCM_ZERO), ALLOCM_SUCCESS,
"Unexpected nallocm() error");
rsz = 0;
assert_d_eq(allocm(&p, &rsz, sz, ALLOCM_ZERO), ALLOCM_SUCCESS,
"Unexpected allocm() error");
assert_zu_eq(nsz, rsz, "nallocm()/allocm() rsize mismatch");
assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,
"Unexpected dallocm() error");
}
TEST_END
TEST_BEGIN(test_alignment_and_size)
{
int r;
size_t nsz, rsz, sz, alignment, total;
unsigned i;
void *ps[NITER];
for (i = 0; i < NITER; i++)
ps[i] = NULL;
for (alignment = 8;
alignment <= MAXALIGN;
alignment <<= 1) {
total = 0;
for (sz = 1;
sz < 3 * alignment && sz < (1U << 31);
sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {
for (i = 0; i < NITER; i++) {
nsz = 0;
r = nallocm(&nsz, sz, ALLOCM_ALIGN(alignment) |
ALLOCM_ZERO);
assert_d_eq(r, ALLOCM_SUCCESS,
"nallocm() error for alignment=%zu, "
"size=%zu (%#zx): %d",
alignment, sz, sz, r);
rsz = 0;
r = allocm(&ps[i], &rsz, sz,
ALLOCM_ALIGN(alignment) | ALLOCM_ZERO);
assert_d_eq(r, ALLOCM_SUCCESS,
"allocm() error for alignment=%zu, "
"size=%zu (%#zx): %d",
alignment, sz, sz, r);
assert_zu_ge(rsz, sz,
"Real size smaller than expected for "
"alignment=%zu, size=%zu", alignment, sz);
assert_zu_eq(nsz, rsz,
"nallocm()/allocm() rsize mismatch for "
"alignment=%zu, size=%zu", alignment, sz);
assert_ptr_null(
(void *)((uintptr_t)ps[i] & (alignment-1)),
"%p inadequately aligned for"
" alignment=%zu, size=%zu", ps[i],
alignment, sz);
sallocm(ps[i], &rsz, 0);
total += rsz;
if (total >= (MAXALIGN << 1))
break;
}
for (i = 0; i < NITER; i++) {
if (ps[i] != NULL) {
dallocm(ps[i], 0);
ps[i] = NULL;
}
}
}
}
}
TEST_END
int
main(void)
{
return (test(
test_basic,
test_alignment_and_size));
}
#include "test/jemalloc_test.h"
#ifdef JEMALLOC_FILL
const char *malloc_conf = "junk:false";
#endif
static chunk_hooks_t orig_hooks;
static chunk_hooks_t old_hooks;
static bool do_dalloc = true;
static bool do_decommit;
static bool did_alloc;
static bool did_dalloc;
static bool did_commit;
static bool did_decommit;
static bool did_purge;
static bool did_split;
static bool did_merge;
#if 0
# define TRACE_HOOK(fmt, ...) malloc_printf(fmt, __VA_ARGS__)
#else
# define TRACE_HOOK(fmt, ...)
#endif
void *
chunk_alloc(void *new_addr, size_t size, size_t alignment, bool *zero,
bool *commit, unsigned arena_ind)
{
TRACE_HOOK("%s(new_addr=%p, size=%zu, alignment=%zu, *zero=%s, "
"*commit=%s, arena_ind=%u)\n", __func__, new_addr, size, alignment,
*zero ? "true" : "false", *commit ? "true" : "false", arena_ind);
did_alloc = true;
return (old_hooks.alloc(new_addr, size, alignment, zero, commit,
arena_ind));
}
bool
chunk_dalloc(void *chunk, size_t size, bool committed, unsigned arena_ind)
{
TRACE_HOOK("%s(chunk=%p, size=%zu, committed=%s, arena_ind=%u)\n",
__func__, chunk, size, committed ? "true" : "false", arena_ind);
did_dalloc = true;
if (!do_dalloc)
return (true);
return (old_hooks.dalloc(chunk, size, committed, arena_ind));
}
bool
chunk_commit(void *chunk, size_t size, size_t offset, size_t length,
unsigned arena_ind)
{
bool err;
TRACE_HOOK("%s(chunk=%p, size=%zu, offset=%zu, length=%zu, "
"arena_ind=%u)\n", __func__, chunk, size, offset, length,
arena_ind);
err = old_hooks.commit(chunk, size, offset, length, arena_ind);
did_commit = !err;
return (err);
}
bool
chunk_decommit(void *chunk, size_t size, size_t offset, size_t length,
unsigned arena_ind)
{
bool err;
TRACE_HOOK("%s(chunk=%p, size=%zu, offset=%zu, length=%zu, "
"arena_ind=%u)\n", __func__, chunk, size, offset, length,
arena_ind);
if (!do_decommit)
return (true);
err = old_hooks.decommit(chunk, size, offset, length, arena_ind);
did_decommit = !err;
return (err);
}
bool
chunk_purge(void *chunk, size_t size, size_t offset, size_t length,
unsigned arena_ind)
{
TRACE_HOOK("%s(chunk=%p, size=%zu, offset=%zu, length=%zu "
"arena_ind=%u)\n", __func__, chunk, size, offset, length,
arena_ind);
did_purge = true;
return (old_hooks.purge(chunk, size, offset, length, arena_ind));
}
bool
chunk_split(void *chunk, size_t size, size_t size_a, size_t size_b,
bool committed, unsigned arena_ind)
{
TRACE_HOOK("%s(chunk=%p, size=%zu, size_a=%zu, size_b=%zu, "
"committed=%s, arena_ind=%u)\n", __func__, chunk, size, size_a,
size_b, committed ? "true" : "false", arena_ind);
did_split = true;
return (old_hooks.split(chunk, size, size_a, size_b, committed,
arena_ind));
}
bool
chunk_merge(void *chunk_a, size_t size_a, void *chunk_b, size_t size_b,
bool committed, unsigned arena_ind)
{
TRACE_HOOK("%s(chunk_a=%p, size_a=%zu, chunk_b=%p size_b=%zu, "
"committed=%s, arena_ind=%u)\n", __func__, chunk_a, size_a, chunk_b,
size_b, committed ? "true" : "false", arena_ind);
did_merge = true;
return (old_hooks.merge(chunk_a, size_a, chunk_b, size_b,
committed, arena_ind));
}
TEST_BEGIN(test_chunk)
{
void *p;
size_t old_size, new_size, large0, large1, huge0, huge1, huge2, sz;
chunk_hooks_t new_hooks = {
chunk_alloc,
chunk_dalloc,
chunk_commit,
chunk_decommit,
chunk_purge,
chunk_split,
chunk_merge
};
bool xallocx_success_a, xallocx_success_b, xallocx_success_c;
/* Install custom chunk hooks. */
old_size = sizeof(chunk_hooks_t);
new_size = sizeof(chunk_hooks_t);
assert_d_eq(mallctl("arena.0.chunk_hooks", &old_hooks, &old_size,
&new_hooks, new_size), 0, "Unexpected chunk_hooks error");
orig_hooks = old_hooks;
assert_ptr_ne(old_hooks.alloc, chunk_alloc, "Unexpected alloc error");
assert_ptr_ne(old_hooks.dalloc, chunk_dalloc,
"Unexpected dalloc error");
assert_ptr_ne(old_hooks.commit, chunk_commit,
"Unexpected commit error");
assert_ptr_ne(old_hooks.decommit, chunk_decommit,
"Unexpected decommit error");
assert_ptr_ne(old_hooks.purge, chunk_purge, "Unexpected purge error");
assert_ptr_ne(old_hooks.split, chunk_split, "Unexpected split error");
assert_ptr_ne(old_hooks.merge, chunk_merge, "Unexpected merge error");
/* Get large size classes. */
sz = sizeof(size_t);
assert_d_eq(mallctl("arenas.lrun.0.size", &large0, &sz, NULL, 0), 0,
"Unexpected arenas.lrun.0.size failure");
assert_d_eq(mallctl("arenas.lrun.1.size", &large1, &sz, NULL, 0), 0,
"Unexpected arenas.lrun.1.size failure");
/* Get huge size classes. */
assert_d_eq(mallctl("arenas.hchunk.0.size", &huge0, &sz, NULL, 0), 0,
"Unexpected arenas.hchunk.0.size failure");
assert_d_eq(mallctl("arenas.hchunk.1.size", &huge1, &sz, NULL, 0), 0,
"Unexpected arenas.hchunk.1.size failure");
assert_d_eq(mallctl("arenas.hchunk.2.size", &huge2, &sz, NULL, 0), 0,
"Unexpected arenas.hchunk.2.size failure");
/* Test dalloc/decommit/purge cascade. */
do_dalloc = false;
do_decommit = false;
p = mallocx(huge0 * 2, 0);
assert_ptr_not_null(p, "Unexpected mallocx() error");
did_dalloc = false;
did_decommit = false;
did_purge = false;
did_split = false;
xallocx_success_a = (xallocx(p, huge0, 0, 0) == huge0);
assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
"Unexpected arena.0.purge error");
if (xallocx_success_a) {
assert_true(did_dalloc, "Expected dalloc");
assert_false(did_decommit, "Unexpected decommit");
assert_true(did_purge, "Expected purge");
}
assert_true(did_split, "Expected split");
dallocx(p, 0);
do_dalloc = true;
/* Test decommit/commit and observe split/merge. */
do_dalloc = false;
do_decommit = true;
p = mallocx(huge0 * 2, 0);
assert_ptr_not_null(p, "Unexpected mallocx() error");
did_decommit = false;
did_commit = false;
did_split = false;
did_merge = false;
xallocx_success_b = (xallocx(p, huge0, 0, 0) == huge0);
assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
"Unexpected arena.0.purge error");
if (xallocx_success_b)
assert_true(did_split, "Expected split");
xallocx_success_c = (xallocx(p, huge0 * 2, 0, 0) == huge0 * 2);
assert_b_eq(did_decommit, did_commit, "Expected decommit/commit match");
if (xallocx_success_b && xallocx_success_c)
assert_true(did_merge, "Expected merge");
dallocx(p, 0);
do_dalloc = true;
do_decommit = false;
/* Test purge for partial-chunk huge allocations. */
if (huge0 * 2 > huge2) {
/*
* There are at least four size classes per doubling, so a
* successful xallocx() from size=huge2 to size=huge1 is
* guaranteed to leave trailing purgeable memory.
*/
p = mallocx(huge2, 0);
assert_ptr_not_null(p, "Unexpected mallocx() error");
did_purge = false;
assert_zu_eq(xallocx(p, huge1, 0, 0), huge1,
"Unexpected xallocx() failure");
assert_true(did_purge, "Expected purge");
dallocx(p, 0);
}
/* Test decommit for large allocations. */
do_decommit = true;
p = mallocx(large1, 0);
assert_ptr_not_null(p, "Unexpected mallocx() error");
assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
"Unexpected arena.0.purge error");
did_decommit = false;
assert_zu_eq(xallocx(p, large0, 0, 0), large0,
"Unexpected xallocx() failure");
assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
"Unexpected arena.0.purge error");
did_commit = false;
assert_zu_eq(xallocx(p, large1, 0, 0), large1,
"Unexpected xallocx() failure");
assert_b_eq(did_decommit, did_commit, "Expected decommit/commit match");
dallocx(p, 0);
do_decommit = false;
/* Make sure non-huge allocation succeeds. */
p = mallocx(42, 0);
assert_ptr_not_null(p, "Unexpected mallocx() error");
dallocx(p, 0);
/* Restore chunk hooks. */
assert_d_eq(mallctl("arena.0.chunk_hooks", NULL, NULL, &old_hooks,
new_size), 0, "Unexpected chunk_hooks error");
assert_d_eq(mallctl("arena.0.chunk_hooks", &old_hooks, &old_size,
NULL, 0), 0, "Unexpected chunk_hooks error");
assert_ptr_eq(old_hooks.alloc, orig_hooks.alloc,
"Unexpected alloc error");
assert_ptr_eq(old_hooks.dalloc, orig_hooks.dalloc,
"Unexpected dalloc error");
assert_ptr_eq(old_hooks.commit, orig_hooks.commit,
"Unexpected commit error");
assert_ptr_eq(old_hooks.decommit, orig_hooks.decommit,
"Unexpected decommit error");
assert_ptr_eq(old_hooks.purge, orig_hooks.purge,
"Unexpected purge error");
assert_ptr_eq(old_hooks.split, orig_hooks.split,
"Unexpected split error");
assert_ptr_eq(old_hooks.merge, orig_hooks.merge,
"Unexpected merge error");
}
TEST_END
int
main(void)
{
return (test(test_chunk));
}
#include "test/jemalloc_test.h"
#define CHUNK 0x400000
#define MAXALIGN (((size_t)1) << 25)
#define NITER 4
static unsigned
get_nsizes_impl(const char *cmd)
{
unsigned ret;
size_t z;
z = sizeof(unsigned);
assert_d_eq(mallctl(cmd, &ret, &z, NULL, 0), 0,
"Unexpected mallctl(\"%s\", ...) failure", cmd);
return (ret);
}
static unsigned
get_nhuge(void)
{
return (get_nsizes_impl("arenas.nhchunks"));
}
static size_t
get_size_impl(const char *cmd, size_t ind)
{
size_t ret;
size_t z;
size_t mib[4];
size_t miblen = 4;
z = sizeof(size_t);
assert_d_eq(mallctlnametomib(cmd, mib, &miblen),
0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
mib[2] = ind;
z = sizeof(size_t);
assert_d_eq(mallctlbymib(mib, miblen, &ret, &z, NULL, 0),
0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
return (ret);
}
static size_t
get_huge_size(size_t ind)
{
return (get_size_impl("arenas.hchunk.0.size", ind));
}
TEST_BEGIN(test_oom)
{
size_t hugemax, size, alignment;
hugemax = get_huge_size(get_nhuge()-1);
/*
* It should be impossible to allocate two objects that each consume
* more than half the virtual address space.
*/
{
void *p;
p = mallocx(hugemax, 0);
if (p != NULL) {
assert_ptr_null(mallocx(hugemax, 0),
"Expected OOM for mallocx(size=%#zx, 0)", hugemax);
dallocx(p, 0);
}
}
#if LG_SIZEOF_PTR == 3
size = ZU(0x8000000000000000);
alignment = ZU(0x8000000000000000);
#else
size = ZU(0x80000000);
alignment = ZU(0x80000000);
#endif
assert_ptr_null(mallocx(size, MALLOCX_ALIGN(alignment)),
"Expected OOM for mallocx(size=%#zx, MALLOCX_ALIGN(%#zx)", size,
alignment);
}
TEST_END
TEST_BEGIN(test_basic)
{
size_t nsz, rsz, sz;
void *p;
sz = 42;
nsz = nallocx(sz, 0);
assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
p = mallocx(sz, 0);
assert_ptr_not_null(p, "Unexpected mallocx() error");
rsz = sallocx(p, 0);
assert_zu_ge(rsz, sz, "Real size smaller than expected");
assert_zu_eq(nsz, rsz, "nallocx()/sallocx() size mismatch");
dallocx(p, 0);
p = mallocx(sz, 0);
assert_ptr_not_null(p, "Unexpected mallocx() error");
dallocx(p, 0);
nsz = nallocx(sz, MALLOCX_ZERO);
assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
p = mallocx(sz, MALLOCX_ZERO);
assert_ptr_not_null(p, "Unexpected mallocx() error");
rsz = sallocx(p, 0);
assert_zu_eq(nsz, rsz, "nallocx()/sallocx() rsize mismatch");
dallocx(p, 0);
#define MAXSZ (((size_t)1) << 26)
size_t sz;
for (sz = 1; sz < MAXSZ; sz = nallocx(sz, 0) + 1) {
size_t nsz, rsz;
void *p;
nsz = nallocx(sz, 0);
assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
p = mallocx(sz, 0);
assert_ptr_not_null(p, "Unexpected mallocx() error");
rsz = sallocx(p, 0);
assert_zu_ge(rsz, sz, "Real size smaller than expected");
assert_zu_eq(nsz, rsz, "nallocx()/sallocx() size mismatch");
dallocx(p, 0);
p = mallocx(sz, 0);
assert_ptr_not_null(p, "Unexpected mallocx() error");
dallocx(p, 0);
nsz = nallocx(sz, MALLOCX_ZERO);
assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
p = mallocx(sz, MALLOCX_ZERO);
assert_ptr_not_null(p, "Unexpected mallocx() error");
rsz = sallocx(p, 0);
assert_zu_eq(nsz, rsz, "nallocx()/sallocx() rsize mismatch");
dallocx(p, 0);
}
#undef MAXSZ
}
TEST_END
TEST_BEGIN(test_alignment_and_size)
{
#define MAXALIGN (((size_t)1) << 25)
#define NITER 4
size_t nsz, rsz, sz, alignment, total;
unsigned i;
void *ps[NITER];
......@@ -84,6 +166,8 @@ TEST_BEGIN(test_alignment_and_size)
}
}
}
#undef MAXALIGN
#undef NITER
}
TEST_END
......@@ -92,6 +176,7 @@ main(void)
{
return (test(
test_oom,
test_basic,
test_alignment_and_size));
}
#include "test/jemalloc_test.h"
TEST_BEGIN(test_mremap)
{
int err;
size_t sz, lg_chunk, chunksize, i;
char *p, *q;
sz = sizeof(lg_chunk);
err = mallctl("opt.lg_chunk", &lg_chunk, &sz, NULL, 0);
assert_d_eq(err, 0, "Error in mallctl(): %s", strerror(err));
chunksize = ((size_t)1U) << lg_chunk;
p = (char *)malloc(chunksize);
assert_ptr_not_null(p, "malloc(%zu) --> %p", chunksize, p);
memset(p, 'a', chunksize);
q = (char *)realloc(p, chunksize * 2);
assert_ptr_not_null(q, "realloc(%p, %zu) --> %p", p, chunksize * 2,
q);
for (i = 0; i < chunksize; i++) {
assert_c_eq(q[i], 'a',
"realloc() should preserve existing bytes across copies");
}
p = q;
q = (char *)realloc(p, chunksize);
assert_ptr_not_null(q, "realloc(%p, %zu) --> %p", p, chunksize, q);
for (i = 0; i < chunksize; i++) {
assert_c_eq(q[i], 'a',
"realloc() should preserve existing bytes across copies");
}
free(q);
}
TEST_END
int
main(void)
{
return (test(
test_mremap));
}
#include "test/jemalloc_test.h"
TEST_BEGIN(test_overflow)
{
unsigned nhchunks;
size_t mib[4];
size_t sz, miblen, max_size_class;
void *p;
sz = sizeof(unsigned);
assert_d_eq(mallctl("arenas.nhchunks", &nhchunks, &sz, NULL, 0), 0,
"Unexpected mallctl() error");
miblen = sizeof(mib) / sizeof(size_t);
assert_d_eq(mallctlnametomib("arenas.hchunk.0.size", mib, &miblen), 0,
"Unexpected mallctlnametomib() error");
mib[2] = nhchunks - 1;
sz = sizeof(size_t);
assert_d_eq(mallctlbymib(mib, miblen, &max_size_class, &sz, NULL, 0), 0,
"Unexpected mallctlbymib() error");
assert_ptr_null(malloc(max_size_class + 1),
"Expected OOM due to over-sized allocation request");
assert_ptr_null(malloc(SIZE_T_MAX),
"Expected OOM due to over-sized allocation request");
assert_ptr_null(calloc(1, max_size_class + 1),
"Expected OOM due to over-sized allocation request");
assert_ptr_null(calloc(1, SIZE_T_MAX),
"Expected OOM due to over-sized allocation request");
p = malloc(1);
assert_ptr_not_null(p, "Unexpected malloc() OOM");
assert_ptr_null(realloc(p, max_size_class + 1),
"Expected OOM due to over-sized allocation request");
assert_ptr_null(realloc(p, SIZE_T_MAX),
"Expected OOM due to over-sized allocation request");
free(p);
}
TEST_END
int
main(void)
{
return (test(
test_overflow));
}
#include "test/jemalloc_test.h"
TEST_BEGIN(test_same_size)
{
void *p, *q;
size_t sz, tsz;
assert_d_eq(allocm(&p, &sz, 42, 0), ALLOCM_SUCCESS,
"Unexpected allocm() error");
q = p;
assert_d_eq(rallocm(&q, &tsz, sz, 0, ALLOCM_NO_MOVE), ALLOCM_SUCCESS,
"Unexpected rallocm() error");
assert_ptr_eq(q, p, "Unexpected object move");
assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz);
assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,
"Unexpected dallocm() error");
}
TEST_END
TEST_BEGIN(test_extra_no_move)
{
void *p, *q;
size_t sz, tsz;
assert_d_eq(allocm(&p, &sz, 42, 0), ALLOCM_SUCCESS,
"Unexpected allocm() error");
q = p;
assert_d_eq(rallocm(&q, &tsz, sz, sz-42, ALLOCM_NO_MOVE),
ALLOCM_SUCCESS, "Unexpected rallocm() error");
assert_ptr_eq(q, p, "Unexpected object move");
assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz);
assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,
"Unexpected dallocm() error");
}
TEST_END
TEST_BEGIN(test_no_move_fail)
{
void *p, *q;
size_t sz, tsz;
assert_d_eq(allocm(&p, &sz, 42, 0), ALLOCM_SUCCESS,
"Unexpected allocm() error");
q = p;
assert_d_eq(rallocm(&q, &tsz, sz + 5, 0, ALLOCM_NO_MOVE),
ALLOCM_ERR_NOT_MOVED, "Unexpected rallocm() result");
assert_ptr_eq(q, p, "Unexpected object move");
assert_zu_eq(tsz, sz, "Unexpected size change: %zu --> %zu", sz, tsz);
assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,
"Unexpected dallocm() error");
}
TEST_END
TEST_BEGIN(test_grow_and_shrink)
{
void *p, *q;
size_t tsz;
#define NCYCLES 3
unsigned i, j;
#define NSZS 2500
size_t szs[NSZS];
#define MAXSZ ZU(12 * 1024 * 1024)
assert_d_eq(allocm(&p, &szs[0], 1, 0), ALLOCM_SUCCESS,
"Unexpected allocm() error");
for (i = 0; i < NCYCLES; i++) {
for (j = 1; j < NSZS && szs[j-1] < MAXSZ; j++) {
q = p;
assert_d_eq(rallocm(&q, &szs[j], szs[j-1]+1, 0, 0),
ALLOCM_SUCCESS,
"Unexpected rallocm() error for size=%zu-->%zu",
szs[j-1], szs[j-1]+1);
assert_zu_ne(szs[j], szs[j-1]+1,
"Expected size to at least: %zu", szs[j-1]+1);
p = q;
}
for (j--; j > 0; j--) {
q = p;
assert_d_eq(rallocm(&q, &tsz, szs[j-1], 0, 0),
ALLOCM_SUCCESS,
"Unexpected rallocm() error for size=%zu-->%zu",
szs[j], szs[j-1]);
assert_zu_eq(tsz, szs[j-1],
"Expected size=%zu, got size=%zu", szs[j-1], tsz);
p = q;
}
}
assert_d_eq(dallocm(p, 0), ALLOCM_SUCCESS,
"Unexpected dallocm() error");
}
TEST_END
int
main(void)
{
return (test(
test_same_size,
test_extra_no_move,
test_no_move_fail,
test_grow_and_shrink));
}
......@@ -22,7 +22,7 @@ TEST_BEGIN(test_grow_and_shrink)
szs[j-1], szs[j-1]+1);
szs[j] = sallocx(q, 0);
assert_zu_ne(szs[j], szs[j-1]+1,
"Expected size to at least: %zu", szs[j-1]+1);
"Expected size to be at least: %zu", szs[j-1]+1);
p = q;
}
......@@ -55,8 +55,9 @@ validate_fill(const void *p, uint8_t c, size_t offset, size_t len)
for (i = 0; i < len; i++) {
uint8_t b = buf[offset+i];
if (b != c) {
test_fail("Allocation at %p contains %#x rather than "
"%#x at offset %zu", p, b, c, offset+i);
test_fail("Allocation at %p (len=%zu) contains %#x "
"rather than %#x at offset %zu", p, len, b, c,
offset+i);
ret = true;
}
}
......@@ -95,7 +96,8 @@ TEST_BEGIN(test_zero)
"Expected zeroed memory");
}
if (psz != qsz) {
memset(q+psz, FILL_BYTE, qsz-psz);
memset((void *)((uintptr_t)q+psz), FILL_BYTE,
qsz-psz);
psz = qsz;
}
p = q;
......@@ -159,8 +161,9 @@ TEST_BEGIN(test_lg_align_and_zero)
} else {
assert_false(validate_fill(q, 0, 0, MAX_VALIDATE),
"Expected zeroed memory");
assert_false(validate_fill(q+sz-MAX_VALIDATE, 0, 0,
MAX_VALIDATE), "Expected zeroed memory");
assert_false(validate_fill(
(void *)((uintptr_t)q+sz-MAX_VALIDATE),
0, 0, MAX_VALIDATE), "Expected zeroed memory");
}
p = q;
}
......
#include "test/jemalloc_test.h"
#define MAXALIGN (((size_t)1) << 25)
#define NITER 4
TEST_BEGIN(test_basic)
{
void *ptr = mallocx(64, 0);
sdallocx(ptr, 64, 0);
}
TEST_END
TEST_BEGIN(test_alignment_and_size)
{
size_t nsz, sz, alignment, total;
unsigned i;
void *ps[NITER];
for (i = 0; i < NITER; i++)
ps[i] = NULL;
for (alignment = 8;
alignment <= MAXALIGN;
alignment <<= 1) {
total = 0;
for (sz = 1;
sz < 3 * alignment && sz < (1U << 31);
sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {
for (i = 0; i < NITER; i++) {
nsz = nallocx(sz, MALLOCX_ALIGN(alignment) |
MALLOCX_ZERO);
ps[i] = mallocx(sz, MALLOCX_ALIGN(alignment) |
MALLOCX_ZERO);
total += nsz;
if (total >= (MAXALIGN << 1))
break;
}
for (i = 0; i < NITER; i++) {
if (ps[i] != NULL) {
sdallocx(ps[i], sz,
MALLOCX_ALIGN(alignment));
ps[i] = NULL;
}
}
}
}
}
TEST_END
int
main(void)
{
return (test(
test_basic,
test_alignment_and_size));
}
......@@ -48,6 +48,411 @@ TEST_BEGIN(test_no_move_fail)
}
TEST_END
static unsigned
get_nsizes_impl(const char *cmd)
{
unsigned ret;
size_t z;
z = sizeof(unsigned);
assert_d_eq(mallctl(cmd, &ret, &z, NULL, 0), 0,
"Unexpected mallctl(\"%s\", ...) failure", cmd);
return (ret);
}
static unsigned
get_nsmall(void)
{
return (get_nsizes_impl("arenas.nbins"));
}
static unsigned
get_nlarge(void)
{
return (get_nsizes_impl("arenas.nlruns"));
}
static unsigned
get_nhuge(void)
{
return (get_nsizes_impl("arenas.nhchunks"));
}
static size_t
get_size_impl(const char *cmd, size_t ind)
{
size_t ret;
size_t z;
size_t mib[4];
size_t miblen = 4;
z = sizeof(size_t);
assert_d_eq(mallctlnametomib(cmd, mib, &miblen),
0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
mib[2] = ind;
z = sizeof(size_t);
assert_d_eq(mallctlbymib(mib, miblen, &ret, &z, NULL, 0),
0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
return (ret);
}
static size_t
get_small_size(size_t ind)
{
return (get_size_impl("arenas.bin.0.size", ind));
}
static size_t
get_large_size(size_t ind)
{
return (get_size_impl("arenas.lrun.0.size", ind));
}
static size_t
get_huge_size(size_t ind)
{
return (get_size_impl("arenas.hchunk.0.size", ind));
}
TEST_BEGIN(test_size)
{
size_t small0, hugemax;
void *p;
/* Get size classes. */
small0 = get_small_size(0);
hugemax = get_huge_size(get_nhuge()-1);
p = mallocx(small0, 0);
assert_ptr_not_null(p, "Unexpected mallocx() error");
/* Test smallest supported size. */
assert_zu_eq(xallocx(p, 1, 0, 0), small0,
"Unexpected xallocx() behavior");
/* Test largest supported size. */
assert_zu_le(xallocx(p, hugemax, 0, 0), hugemax,
"Unexpected xallocx() behavior");
/* Test size overflow. */
assert_zu_le(xallocx(p, hugemax+1, 0, 0), hugemax,
"Unexpected xallocx() behavior");
assert_zu_le(xallocx(p, SIZE_T_MAX, 0, 0), hugemax,
"Unexpected xallocx() behavior");
dallocx(p, 0);
}
TEST_END
TEST_BEGIN(test_size_extra_overflow)
{
size_t small0, hugemax;
void *p;
/* Get size classes. */
small0 = get_small_size(0);
hugemax = get_huge_size(get_nhuge()-1);
p = mallocx(small0, 0);
assert_ptr_not_null(p, "Unexpected mallocx() error");
/* Test overflows that can be resolved by clamping extra. */
assert_zu_le(xallocx(p, hugemax-1, 2, 0), hugemax,
"Unexpected xallocx() behavior");
assert_zu_le(xallocx(p, hugemax, 1, 0), hugemax,
"Unexpected xallocx() behavior");
/* Test overflow such that hugemax-size underflows. */
assert_zu_le(xallocx(p, hugemax+1, 2, 0), hugemax,
"Unexpected xallocx() behavior");
assert_zu_le(xallocx(p, hugemax+2, 3, 0), hugemax,
"Unexpected xallocx() behavior");
assert_zu_le(xallocx(p, SIZE_T_MAX-2, 2, 0), hugemax,
"Unexpected xallocx() behavior");
assert_zu_le(xallocx(p, SIZE_T_MAX-1, 1, 0), hugemax,
"Unexpected xallocx() behavior");
dallocx(p, 0);
}
TEST_END
TEST_BEGIN(test_extra_small)
{
size_t small0, small1, hugemax;
void *p;
/* Get size classes. */
small0 = get_small_size(0);
small1 = get_small_size(1);
hugemax = get_huge_size(get_nhuge()-1);
p = mallocx(small0, 0);
assert_ptr_not_null(p, "Unexpected mallocx() error");
assert_zu_eq(xallocx(p, small1, 0, 0), small0,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, small1, 0, 0), small0,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, small0, small1 - small0, 0), small0,
"Unexpected xallocx() behavior");
/* Test size+extra overflow. */
assert_zu_eq(xallocx(p, small0, hugemax - small0 + 1, 0), small0,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, small0, SIZE_T_MAX - small0, 0), small0,
"Unexpected xallocx() behavior");
dallocx(p, 0);
}
TEST_END
TEST_BEGIN(test_extra_large)
{
size_t smallmax, large0, large1, large2, huge0, hugemax;
void *p;
/* Get size classes. */
smallmax = get_small_size(get_nsmall()-1);
large0 = get_large_size(0);
large1 = get_large_size(1);
large2 = get_large_size(2);
huge0 = get_huge_size(0);
hugemax = get_huge_size(get_nhuge()-1);
p = mallocx(large2, 0);
assert_ptr_not_null(p, "Unexpected mallocx() error");
assert_zu_eq(xallocx(p, large2, 0, 0), large2,
"Unexpected xallocx() behavior");
/* Test size decrease with zero extra. */
assert_zu_eq(xallocx(p, large0, 0, 0), large0,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, smallmax, 0, 0), large0,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, large2, 0, 0), large2,
"Unexpected xallocx() behavior");
/* Test size decrease with non-zero extra. */
assert_zu_eq(xallocx(p, large0, large2 - large0, 0), large2,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, large1, large2 - large1, 0), large2,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, large0, large1 - large0, 0), large1,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, smallmax, large0 - smallmax, 0), large0,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, large0, 0, 0), large0,
"Unexpected xallocx() behavior");
/* Test size increase with zero extra. */
assert_zu_eq(xallocx(p, large2, 0, 0), large2,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, huge0, 0, 0), large2,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, large0, 0, 0), large0,
"Unexpected xallocx() behavior");
/* Test size increase with non-zero extra. */
assert_zu_lt(xallocx(p, large0, huge0 - large0, 0), huge0,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, large0, 0, 0), large0,
"Unexpected xallocx() behavior");
/* Test size increase with non-zero extra. */
assert_zu_eq(xallocx(p, large0, large2 - large0, 0), large2,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, large2, 0, 0), large2,
"Unexpected xallocx() behavior");
/* Test size+extra overflow. */
assert_zu_lt(xallocx(p, large2, hugemax - large2 + 1, 0), huge0,
"Unexpected xallocx() behavior");
dallocx(p, 0);
}
TEST_END
TEST_BEGIN(test_extra_huge)
{
size_t largemax, huge0, huge1, huge2, hugemax;
void *p;
/* Get size classes. */
largemax = get_large_size(get_nlarge()-1);
huge0 = get_huge_size(0);
huge1 = get_huge_size(1);
huge2 = get_huge_size(2);
hugemax = get_huge_size(get_nhuge()-1);
p = mallocx(huge2, 0);
assert_ptr_not_null(p, "Unexpected mallocx() error");
assert_zu_eq(xallocx(p, huge2, 0, 0), huge2,
"Unexpected xallocx() behavior");
/* Test size decrease with zero extra. */
assert_zu_ge(xallocx(p, huge0, 0, 0), huge0,
"Unexpected xallocx() behavior");
assert_zu_ge(xallocx(p, largemax, 0, 0), huge0,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, huge2, 0, 0), huge2,
"Unexpected xallocx() behavior");
/* Test size decrease with non-zero extra. */
assert_zu_eq(xallocx(p, huge0, huge2 - huge0, 0), huge2,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, huge1, huge2 - huge1, 0), huge2,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, huge0, huge1 - huge0, 0), huge1,
"Unexpected xallocx() behavior");
assert_zu_ge(xallocx(p, largemax, huge0 - largemax, 0), huge0,
"Unexpected xallocx() behavior");
assert_zu_ge(xallocx(p, huge0, 0, 0), huge0,
"Unexpected xallocx() behavior");
/* Test size increase with zero extra. */
assert_zu_le(xallocx(p, huge2, 0, 0), huge2,
"Unexpected xallocx() behavior");
assert_zu_le(xallocx(p, hugemax+1, 0, 0), huge2,
"Unexpected xallocx() behavior");
assert_zu_ge(xallocx(p, huge0, 0, 0), huge0,
"Unexpected xallocx() behavior");
/* Test size increase with non-zero extra. */
assert_zu_le(xallocx(p, huge0, SIZE_T_MAX - huge0, 0), hugemax,
"Unexpected xallocx() behavior");
assert_zu_ge(xallocx(p, huge0, 0, 0), huge0,
"Unexpected xallocx() behavior");
/* Test size increase with non-zero extra. */
assert_zu_le(xallocx(p, huge0, huge2 - huge0, 0), huge2,
"Unexpected xallocx() behavior");
assert_zu_eq(xallocx(p, huge2, 0, 0), huge2,
"Unexpected xallocx() behavior");
/* Test size+extra overflow. */
assert_zu_le(xallocx(p, huge2, hugemax - huge2 + 1, 0), hugemax,
"Unexpected xallocx() behavior");
dallocx(p, 0);
}
TEST_END
static void
print_filled_extents(const void *p, uint8_t c, size_t len)
{
const uint8_t *pc = (const uint8_t *)p;
size_t i, range0;
uint8_t c0;
malloc_printf(" p=%p, c=%#x, len=%zu:", p, c, len);
range0 = 0;
c0 = pc[0];
for (i = 0; i < len; i++) {
if (pc[i] != c0) {
malloc_printf(" %#x[%zu..%zu)", c0, range0, i);
range0 = i;
c0 = pc[i];
}
}
malloc_printf(" %#x[%zu..%zu)\n", c0, range0, i);
}
static bool
validate_fill(const void *p, uint8_t c, size_t offset, size_t len)
{
const uint8_t *pc = (const uint8_t *)p;
bool err;
size_t i;
for (i = offset, err = false; i < offset+len; i++) {
if (pc[i] != c)
err = true;
}
if (err)
print_filled_extents(p, c, offset + len);
return (err);
}
static void
test_zero(size_t szmin, size_t szmax)
{
size_t sz, nsz;
void *p;
#define FILL_BYTE 0x7aU
sz = szmax;
p = mallocx(sz, MALLOCX_ZERO);
assert_ptr_not_null(p, "Unexpected mallocx() error");
assert_false(validate_fill(p, 0x00, 0, sz), "Memory not filled: sz=%zu",
sz);
/*
* Fill with non-zero so that non-debug builds are more likely to detect
* errors.
*/
memset(p, FILL_BYTE, sz);
assert_false(validate_fill(p, FILL_BYTE, 0, sz),
"Memory not filled: sz=%zu", sz);
/* Shrink in place so that we can expect growing in place to succeed. */
sz = szmin;
assert_zu_eq(xallocx(p, sz, 0, MALLOCX_ZERO), sz,
"Unexpected xallocx() error");
assert_false(validate_fill(p, FILL_BYTE, 0, sz),
"Memory not filled: sz=%zu", sz);
for (sz = szmin; sz < szmax; sz = nsz) {
nsz = nallocx(sz+1, MALLOCX_ZERO);
assert_zu_eq(xallocx(p, sz+1, 0, MALLOCX_ZERO), nsz,
"Unexpected xallocx() failure");
assert_false(validate_fill(p, FILL_BYTE, 0, sz),
"Memory not filled: sz=%zu", sz);
assert_false(validate_fill(p, 0x00, sz, nsz-sz),
"Memory not filled: sz=%zu, nsz-sz=%zu", sz, nsz-sz);
memset((void *)((uintptr_t)p + sz), FILL_BYTE, nsz-sz);
assert_false(validate_fill(p, FILL_BYTE, 0, nsz),
"Memory not filled: nsz=%zu", nsz);
}
dallocx(p, 0);
}
TEST_BEGIN(test_zero_large)
{
size_t large0, largemax;
/* Get size classes. */
large0 = get_large_size(0);
largemax = get_large_size(get_nlarge()-1);
test_zero(large0, largemax);
}
TEST_END
TEST_BEGIN(test_zero_huge)
{
size_t huge0, huge1;
/* Get size classes. */
huge0 = get_huge_size(0);
huge1 = get_huge_size(1);
test_zero(huge1, huge0 * 2);
}
TEST_END
int
main(void)
{
......@@ -55,5 +460,12 @@ main(void)
return (test(
test_same_size,
test_extra_no_move,
test_no_move_fail));
test_no_move_fail,
test_size,
test_size_extra_overflow,
test_extra_small,
test_extra_large,
test_extra_huge,
test_zero_large,
test_zero_huge));
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment