21 Commits
2.2.1 ... 2.2.3

Author SHA1 Message Date
Jason Evans
5bdbae57ee Merge branch 'dev' 2011-08-31 16:18:38 -07:00
Jason Evans
c67e4fdc71 Update ChangeLog for 2.2.3. 2011-08-31 15:19:13 -07:00
Jason Evans
a9076c9483 Fix a prof-related race condition.
Fix prof_lookup() to artificially raise curobjs for all paths through
the code that creates a new entry in the per thread bt2cnt hash table.
This fixes a race condition that could corrupt memory if prof_accum were
false, and a non-default lg_prof_tcmax were used and/or threads were
destroyed.
2011-08-30 23:40:11 -07:00
Jason Evans
46405e670f Fix a prof-related bug in realloc().
Fix realloc() such that it only records the object passed in as freed if
no OOM error occurs.
2011-08-30 23:37:29 -07:00
Jason Evans
749c2a0ab6 Add missing prof_malloc() call in allocm().
Add a missing prof_malloc() call in allocm().  Before this fix, negative
object/byte counts could be observed in heap profiles for applications
that use allocm().
2011-08-12 18:37:54 -07:00
Jason Evans
a507004d29 Fix off-by-one backtracing issues.
Rewrite prof_alloc_prep() as a cpp macro, PROF_ALLOC_PREP(), in order to
remove any doubt as to whether an additional stack frame is created.
Prior to this change, it was assumed that inlining would reduce the
total number of frames in the backtrace, but in practice behavior wasn't
completely predictable.

Create imemalign() and call it from posix_memalign(), memalign(), and
valloc(), so that all entry points require the same number of stack
frames to be ignored during backtracing.
2011-08-12 13:48:27 -07:00
Jason Evans
745e30b157 Document swap.fds mallctl as read-write.
Fix the manual page to document the swap.fds mallctl as read-write,
rather than read-only.
2011-08-12 11:40:55 -07:00
Jason Evans
b493ce22a4 Conditionalize an isalloc() call in rallocm().
Conditionalize an isalloc() call in rallocm() that be unnecessary.
2011-08-12 11:28:47 -07:00
Jason Evans
183ba50c19 Fix two prof-related bugs in rallocm().
Properly handle boundary conditions for sampled region promotion in
rallocm().  Prior to this fix, some combinations of 'size' and 'extra'
values could cause erroneous behavior.  Additionally, size class
recording for promoted regions was incorrect.
2011-08-11 23:00:25 -07:00
Jason Evans
0cdd42eb32 Clean up prof-related comments.
Clean up some prof-related comments to more accurately reflect how the
code works.

Simplify OOM handling code in a couple of prof-related error paths.
2011-08-09 19:06:06 -07:00
Jason Evans
41b954ed36 Use prof_tdata_cleanup() argument.
Use the argument to prof_tdata_cleanup(), rather than calling
PROF_TCACHE_GET().  This fixes a bug in the NO_TLS case.
2011-08-08 17:10:07 -07:00
Jason Evans
04ca1efe35 Adjust relative #include for private_namespace.h. 2011-07-30 17:58:07 -07:00
Jason Evans
446c3b22f1 Merge branch 'dev' 2011-07-30 17:27:02 -07:00
Jason Evans
4c48481e7c Update ChangeLog for 2.2.2. 2011-07-30 16:59:13 -07:00
Jason Evans
746e77a06b Add the --with-private-namespace option.
Add the --with-private-namespace option to make it possible to work
around library-private symbols being exposed in static libraries.
2011-07-30 16:40:52 -07:00
Jason Evans
f9a8edbb50 Fix assertions in arena_purge().
Fix assertions in arena_purge() to accurately reflect the constraints in
arena_maybe_purge().  There were two bugs here, one of which merely
weakened the assertion, and the other of which referred to an
uninitialized variable (typo; used npurgatory instead of
arena->npurgatory).
2011-06-12 17:13:39 -07:00
Jason Evans
f0b22cf932 Use LLU suffix for all 64-bit constants.
Add the LLU suffix for all 0x... 64-bit constants.

Reported by Jakob Blomer.
2011-05-22 10:49:44 -07:00
Nathan McSween
408ade6545 Makefile.in - test/allocated requires pthread 2011-05-10 21:38:07 -07:00
Jason Evans
955851f384 Adjust repo path dependencies.
Update .gitignore and configure.ac to deal with the recent directory
restructuring.
2011-03-31 22:38:51 -07:00
Jason Evans
7427525c28 Move repo contents in jemalloc/ to top level. 2011-03-31 20:36:17 -07:00
Jason Evans
64ba3d7cd9 Fix a build error for --disable-tcache.
Add a missing #ifdef to conditionally exclude code that is relevant only
to the tcache feature.
2011-03-30 16:02:25 -07:00
81 changed files with 443 additions and 174 deletions

46
.gitignore vendored
View File

@@ -1,23 +1,23 @@
/jemalloc/autom4te.cache/ /autom4te.cache/
/jemalloc/config.stamp /config.stamp
/jemalloc/config.log /config.log
/jemalloc/config.status /config.status
/jemalloc/configure /configure
/jemalloc/doc/html.xsl /doc/html.xsl
/jemalloc/doc/manpages.xsl /doc/manpages.xsl
/jemalloc/doc/jemalloc.xml /doc/jemalloc.xml
/jemalloc/doc/jemalloc.html /doc/jemalloc.html
/jemalloc/doc/jemalloc.3 /doc/jemalloc.3
/jemalloc/lib/ /lib/
/jemalloc/Makefile /Makefile
/jemalloc/include/jemalloc/internal/jemalloc_internal\.h /include/jemalloc/internal/jemalloc_internal\.h
/jemalloc/include/jemalloc/jemalloc\.h /include/jemalloc/jemalloc\.h
/jemalloc/include/jemalloc/jemalloc_defs\.h /include/jemalloc/jemalloc_defs\.h
/jemalloc/test/jemalloc_test\.h /test/jemalloc_test\.h
/jemalloc/src/*.[od] /src/*.[od]
/jemalloc/test/*.[od] /test/*.[od]
/jemalloc/test/*.out /test/*.out
/jemalloc/test/[a-z]* /test/[a-z]*
!/jemalloc/test/*.c !test/*.c
!/jemalloc/test/*.exp !test/*.exp
/jemalloc/VERSION /VERSION

View File

@@ -6,6 +6,28 @@ found in the git revision history:
http://www.canonware.com/cgi-bin/gitweb.cgi?p=jemalloc.git http://www.canonware.com/cgi-bin/gitweb.cgi?p=jemalloc.git
git://canonware.com/jemalloc.git git://canonware.com/jemalloc.git
* 2.2.3 (August 31, 2011)
This version fixes numerous bugs related to heap profiling.
Bug fixes:
- Fix a prof-related race condition. This bug could cause memory corruption,
but only occurred in non-default configurations (prof_accum:false).
- Fix off-by-one backtracing issues (make sure that prof_alloc_prep() is
excluded from backtraces).
- Fix a prof-related bug in realloc() (only triggered by OOM errors).
- Fix prof-related bugs in allocm() and rallocm().
- Fix prof_tdata_cleanup() for --disable-tls builds.
- Fix a relative include path, to fix objdir builds.
* 2.2.2 (July 30, 2011)
Bug fixes:
- Fix a build error for --disable-tcache.
- Fix assertions in arena_purge() (for real this time).
- Add the --with-private-namespace option. This is a workaround for symbol
conflicts that can inadvertently arise when using static libraries.
* 2.2.1 (March 30, 2011) * 2.2.1 (March 30, 2011)
Bug fixes: Bug fixes:

View File

@@ -42,6 +42,12 @@ any of the following arguments (not a definitive list) to 'configure':
jemalloc overlays the default malloc zone, but makes no attempt to actually jemalloc overlays the default malloc zone, but makes no attempt to actually
replace the "malloc", "calloc", etc. symbols. replace the "malloc", "calloc", etc. symbols.
--with-private-namespace=<prefix>
Prefix all library-private APIs with <prefix>. For shared libraries,
symbol visibility mechanisms prevent these symbols from being exported, but
for static libraries, naming collisions are a real possibility. By
default, the prefix is "" (empty string).
--with-install-suffix=<suffix> --with-install-suffix=<suffix>
Append <suffix> to the base name of all installed files, such that multiple Append <suffix> to the base name of all installed files, such that multiple
versions of jemalloc can coexist in the same installation directory. For versions of jemalloc can coexist in the same installation directory. For

View File

@@ -136,9 +136,9 @@ doc: $(DOCS)
@objroot@lib/libjemalloc@install_suffix@.$(SO) @objroot@lib/libjemalloc@install_suffix@.$(SO)
@mkdir -p $(@D) @mkdir -p $(@D)
ifneq (@RPATH@, ) ifneq (@RPATH@, )
$(CC) -o $@ $< @RPATH@@objroot@lib -L@objroot@lib -ljemalloc@install_suffix@ $(CC) -o $@ $< @RPATH@@objroot@lib -L@objroot@lib -ljemalloc@install_suffix@ -lpthread
else else
$(CC) -o $@ $< -L@objroot@lib -ljemalloc@install_suffix@ $(CC) -o $@ $< -L@objroot@lib -ljemalloc@install_suffix@ -lpthread
endif endif
install_bin: install_bin:

View File

View File

@@ -292,13 +292,22 @@ if test "x$JEMALLOC_PREFIX" != "x" ; then
JEMALLOC_CPREFIX=`echo ${JEMALLOC_PREFIX} | tr "a-z" "A-Z"` JEMALLOC_CPREFIX=`echo ${JEMALLOC_PREFIX} | tr "a-z" "A-Z"`
AC_DEFINE_UNQUOTED([JEMALLOC_PREFIX], ["$JEMALLOC_PREFIX"]) AC_DEFINE_UNQUOTED([JEMALLOC_PREFIX], ["$JEMALLOC_PREFIX"])
AC_DEFINE_UNQUOTED([JEMALLOC_CPREFIX], ["$JEMALLOC_CPREFIX"]) AC_DEFINE_UNQUOTED([JEMALLOC_CPREFIX], ["$JEMALLOC_CPREFIX"])
jemalloc_prefix="$JEMALLOC_PREFIX"
jemalloc_cprefix="$JEMALLOC_CPREFIX"
AC_SUBST([jemalloc_prefix])
AC_SUBST([jemalloc_cprefix])
AC_DEFINE_UNQUOTED([JEMALLOC_P(string_that_no_one_should_want_to_use_as_a_jemalloc_API_prefix)], [${JEMALLOC_PREFIX}##string_that_no_one_should_want_to_use_as_a_jemalloc_API_prefix]) AC_DEFINE_UNQUOTED([JEMALLOC_P(string_that_no_one_should_want_to_use_as_a_jemalloc_API_prefix)], [${JEMALLOC_PREFIX}##string_that_no_one_should_want_to_use_as_a_jemalloc_API_prefix])
fi fi
dnl Do not mangle library-private APIs by default.
AC_ARG_WITH([private_namespace],
[AS_HELP_STRING([--with-private-namespace=<prefix>], [Prefix to prepend to all library-private APIs])],
[JEMALLOC_PRIVATE_NAMESPACE="$with_private_namespace"],
[JEMALLOC_PRIVATE_NAMESPACE=""]
)
AC_DEFINE_UNQUOTED([JEMALLOC_PRIVATE_NAMESPACE], ["$JEMALLOC_PRIVATE_NAMESPACE"])
if test "x$JEMALLOC_PRIVATE_NAMESPACE" != "x" ; then
AC_DEFINE_UNQUOTED([JEMALLOC_N(string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix)], [${JEMALLOC_PRIVATE_NAMESPACE}##string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix])
else
AC_DEFINE_UNQUOTED([JEMALLOC_N(string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix)], [string_that_no_one_should_want_to_use_as_a_jemalloc_private_namespace_prefix])
fi
dnl Do not add suffix to installed files by default. dnl Do not add suffix to installed files by default.
AC_ARG_WITH([install_suffix], AC_ARG_WITH([install_suffix],
[AS_HELP_STRING([--with-install-suffix=<suffix>], [Suffix to append to all installed files])], [AS_HELP_STRING([--with-install-suffix=<suffix>], [Suffix to append to all installed files])],
@@ -688,7 +697,7 @@ dnl jemalloc configuration.
dnl dnl
dnl Set VERSION if source directory has an embedded git repository. dnl Set VERSION if source directory has an embedded git repository.
if test -d "${srcroot}../.git" ; then if test -d "${srcroot}.git" ; then
git describe --long --abbrev=40 > ${srcroot}VERSION git describe --long --abbrev=40 > ${srcroot}VERSION
fi fi
jemalloc_version=`cat ${srcroot}VERSION` jemalloc_version=`cat ${srcroot}VERSION`
@@ -905,6 +914,8 @@ AC_MSG_RESULT([objroot : ${objroot}])
AC_MSG_RESULT([abs_objroot : ${abs_objroot}]) AC_MSG_RESULT([abs_objroot : ${abs_objroot}])
AC_MSG_RESULT([]) AC_MSG_RESULT([])
AC_MSG_RESULT([JEMALLOC_PREFIX : ${JEMALLOC_PREFIX}]) AC_MSG_RESULT([JEMALLOC_PREFIX : ${JEMALLOC_PREFIX}])
AC_MSG_RESULT([JEMALLOC_PRIVATE_NAMESPACE])
AC_MSG_RESULT([ : ${JEMALLOC_PRIVATE_NAMESPACE}])
AC_MSG_RESULT([install_suffix : ${install_suffix}]) AC_MSG_RESULT([install_suffix : ${install_suffix}])
AC_MSG_RESULT([autogen : ${enable_autogen}]) AC_MSG_RESULT([autogen : ${enable_autogen}])
AC_MSG_RESULT([cc-silence : ${enable_cc_silence}]) AC_MSG_RESULT([cc-silence : ${enable_cc_silence}])

View File

@@ -2025,7 +2025,7 @@ malloc_conf = "xmalloc:true";]]></programlisting>
<term> <term>
<mallctl>swap.fds</mallctl> <mallctl>swap.fds</mallctl>
(<type>int *</type>) (<type>int *</type>)
<literal>r-</literal> <literal>rw</literal>
[<option>--enable-swap</option>] [<option>--enable-swap</option>]
</term> </term>
<listitem><para>When written to, the files associated with the <listitem><para>When written to, the files associated with the

View File

@@ -26,7 +26,7 @@ uint64_t hash(const void *key, size_t len, uint64_t seed);
JEMALLOC_INLINE uint64_t JEMALLOC_INLINE uint64_t
hash(const void *key, size_t len, uint64_t seed) hash(const void *key, size_t len, uint64_t seed)
{ {
const uint64_t m = 0xc6a4a7935bd1e995; const uint64_t m = 0xc6a4a7935bd1e995LLU;
const int r = 47; const int r = 47;
uint64_t h = seed ^ (len * m); uint64_t h = seed ^ (len * m);
const uint64_t *data = (const uint64_t *)key; const uint64_t *data = (const uint64_t *)key;

View File

@@ -33,6 +33,8 @@
#define JEMALLOC_MANGLE #define JEMALLOC_MANGLE
#include "../jemalloc@install_suffix@.h" #include "../jemalloc@install_suffix@.h"
#include "jemalloc/internal/private_namespace.h"
#if (defined(JEMALLOC_OSATOMIC) || defined(JEMALLOC_OSSPIN)) #if (defined(JEMALLOC_OSATOMIC) || defined(JEMALLOC_OSSPIN))
#include <libkern/OSAtomic.h> #include <libkern/OSAtomic.h>
#endif #endif

View File

@@ -0,0 +1,195 @@
#define arena_bin_index JEMALLOC_N(arena_bin_index)
#define arena_boot JEMALLOC_N(arena_boot)
#define arena_dalloc JEMALLOC_N(arena_dalloc)
#define arena_dalloc_bin JEMALLOC_N(arena_dalloc_bin)
#define arena_dalloc_large JEMALLOC_N(arena_dalloc_large)
#define arena_malloc JEMALLOC_N(arena_malloc)
#define arena_malloc_large JEMALLOC_N(arena_malloc_large)
#define arena_malloc_small JEMALLOC_N(arena_malloc_small)
#define arena_new JEMALLOC_N(arena_new)
#define arena_palloc JEMALLOC_N(arena_palloc)
#define arena_prof_accum JEMALLOC_N(arena_prof_accum)
#define arena_prof_ctx_get JEMALLOC_N(arena_prof_ctx_get)
#define arena_prof_ctx_set JEMALLOC_N(arena_prof_ctx_set)
#define arena_prof_promoted JEMALLOC_N(arena_prof_promoted)
#define arena_purge_all JEMALLOC_N(arena_purge_all)
#define arena_ralloc JEMALLOC_N(arena_ralloc)
#define arena_ralloc_no_move JEMALLOC_N(arena_ralloc_no_move)
#define arena_run_regind JEMALLOC_N(arena_run_regind)
#define arena_salloc JEMALLOC_N(arena_salloc)
#define arena_salloc_demote JEMALLOC_N(arena_salloc_demote)
#define arena_stats_merge JEMALLOC_N(arena_stats_merge)
#define arena_tcache_fill_small JEMALLOC_N(arena_tcache_fill_small)
#define arenas_bin_i_index JEMALLOC_N(arenas_bin_i_index)
#define arenas_extend JEMALLOC_N(arenas_extend)
#define arenas_lrun_i_index JEMALLOC_N(arenas_lrun_i_index)
#define atomic_add_uint32 JEMALLOC_N(atomic_add_uint32)
#define atomic_add_uint64 JEMALLOC_N(atomic_add_uint64)
#define atomic_sub_uint32 JEMALLOC_N(atomic_sub_uint32)
#define atomic_sub_uint64 JEMALLOC_N(atomic_sub_uint64)
#define base_alloc JEMALLOC_N(base_alloc)
#define base_boot JEMALLOC_N(base_boot)
#define base_node_alloc JEMALLOC_N(base_node_alloc)
#define base_node_dealloc JEMALLOC_N(base_node_dealloc)
#define bitmap_full JEMALLOC_N(bitmap_full)
#define bitmap_get JEMALLOC_N(bitmap_get)
#define bitmap_info_init JEMALLOC_N(bitmap_info_init)
#define bitmap_info_ngroups JEMALLOC_N(bitmap_info_ngroups)
#define bitmap_init JEMALLOC_N(bitmap_init)
#define bitmap_set JEMALLOC_N(bitmap_set)
#define bitmap_sfu JEMALLOC_N(bitmap_sfu)
#define bitmap_size JEMALLOC_N(bitmap_size)
#define bitmap_unset JEMALLOC_N(bitmap_unset)
#define bt_init JEMALLOC_N(bt_init)
#define buferror JEMALLOC_N(buferror)
#define choose_arena JEMALLOC_N(choose_arena)
#define choose_arena_hard JEMALLOC_N(choose_arena_hard)
#define chunk_alloc JEMALLOC_N(chunk_alloc)
#define chunk_alloc_dss JEMALLOC_N(chunk_alloc_dss)
#define chunk_alloc_mmap JEMALLOC_N(chunk_alloc_mmap)
#define chunk_alloc_mmap_noreserve JEMALLOC_N(chunk_alloc_mmap_noreserve)
#define chunk_alloc_swap JEMALLOC_N(chunk_alloc_swap)
#define chunk_boot JEMALLOC_N(chunk_boot)
#define chunk_dealloc JEMALLOC_N(chunk_dealloc)
#define chunk_dealloc_dss JEMALLOC_N(chunk_dealloc_dss)
#define chunk_dealloc_mmap JEMALLOC_N(chunk_dealloc_mmap)
#define chunk_dealloc_swap JEMALLOC_N(chunk_dealloc_swap)
#define chunk_dss_boot JEMALLOC_N(chunk_dss_boot)
#define chunk_in_dss JEMALLOC_N(chunk_in_dss)
#define chunk_in_swap JEMALLOC_N(chunk_in_swap)
#define chunk_mmap_boot JEMALLOC_N(chunk_mmap_boot)
#define chunk_swap_boot JEMALLOC_N(chunk_swap_boot)
#define chunk_swap_enable JEMALLOC_N(chunk_swap_enable)
#define ckh_bucket_search JEMALLOC_N(ckh_bucket_search)
#define ckh_count JEMALLOC_N(ckh_count)
#define ckh_delete JEMALLOC_N(ckh_delete)
#define ckh_evict_reloc_insert JEMALLOC_N(ckh_evict_reloc_insert)
#define ckh_insert JEMALLOC_N(ckh_insert)
#define ckh_isearch JEMALLOC_N(ckh_isearch)
#define ckh_iter JEMALLOC_N(ckh_iter)
#define ckh_new JEMALLOC_N(ckh_new)
#define ckh_pointer_hash JEMALLOC_N(ckh_pointer_hash)
#define ckh_pointer_keycomp JEMALLOC_N(ckh_pointer_keycomp)
#define ckh_rebuild JEMALLOC_N(ckh_rebuild)
#define ckh_remove JEMALLOC_N(ckh_remove)
#define ckh_search JEMALLOC_N(ckh_search)
#define ckh_string_hash JEMALLOC_N(ckh_string_hash)
#define ckh_string_keycomp JEMALLOC_N(ckh_string_keycomp)
#define ckh_try_bucket_insert JEMALLOC_N(ckh_try_bucket_insert)
#define ckh_try_insert JEMALLOC_N(ckh_try_insert)
#define create_zone JEMALLOC_N(create_zone)
#define ctl_boot JEMALLOC_N(ctl_boot)
#define ctl_bymib JEMALLOC_N(ctl_bymib)
#define ctl_byname JEMALLOC_N(ctl_byname)
#define ctl_nametomib JEMALLOC_N(ctl_nametomib)
#define extent_tree_ad_first JEMALLOC_N(extent_tree_ad_first)
#define extent_tree_ad_insert JEMALLOC_N(extent_tree_ad_insert)
#define extent_tree_ad_iter JEMALLOC_N(extent_tree_ad_iter)
#define extent_tree_ad_iter_recurse JEMALLOC_N(extent_tree_ad_iter_recurse)
#define extent_tree_ad_iter_start JEMALLOC_N(extent_tree_ad_iter_start)
#define extent_tree_ad_last JEMALLOC_N(extent_tree_ad_last)
#define extent_tree_ad_new JEMALLOC_N(extent_tree_ad_new)
#define extent_tree_ad_next JEMALLOC_N(extent_tree_ad_next)
#define extent_tree_ad_nsearch JEMALLOC_N(extent_tree_ad_nsearch)
#define extent_tree_ad_prev JEMALLOC_N(extent_tree_ad_prev)
#define extent_tree_ad_psearch JEMALLOC_N(extent_tree_ad_psearch)
#define extent_tree_ad_remove JEMALLOC_N(extent_tree_ad_remove)
#define extent_tree_ad_reverse_iter JEMALLOC_N(extent_tree_ad_reverse_iter)
#define extent_tree_ad_reverse_iter_recurse JEMALLOC_N(extent_tree_ad_reverse_iter_recurse)
#define extent_tree_ad_reverse_iter_start JEMALLOC_N(extent_tree_ad_reverse_iter_start)
#define extent_tree_ad_search JEMALLOC_N(extent_tree_ad_search)
#define extent_tree_szad_first JEMALLOC_N(extent_tree_szad_first)
#define extent_tree_szad_insert JEMALLOC_N(extent_tree_szad_insert)
#define extent_tree_szad_iter JEMALLOC_N(extent_tree_szad_iter)
#define extent_tree_szad_iter_recurse JEMALLOC_N(extent_tree_szad_iter_recurse)
#define extent_tree_szad_iter_start JEMALLOC_N(extent_tree_szad_iter_start)
#define extent_tree_szad_last JEMALLOC_N(extent_tree_szad_last)
#define extent_tree_szad_new JEMALLOC_N(extent_tree_szad_new)
#define extent_tree_szad_next JEMALLOC_N(extent_tree_szad_next)
#define extent_tree_szad_nsearch JEMALLOC_N(extent_tree_szad_nsearch)
#define extent_tree_szad_prev JEMALLOC_N(extent_tree_szad_prev)
#define extent_tree_szad_psearch JEMALLOC_N(extent_tree_szad_psearch)
#define extent_tree_szad_remove JEMALLOC_N(extent_tree_szad_remove)
#define extent_tree_szad_reverse_iter JEMALLOC_N(extent_tree_szad_reverse_iter)
#define extent_tree_szad_reverse_iter_recurse JEMALLOC_N(extent_tree_szad_reverse_iter_recurse)
#define extent_tree_szad_reverse_iter_start JEMALLOC_N(extent_tree_szad_reverse_iter_start)
#define extent_tree_szad_search JEMALLOC_N(extent_tree_szad_search)
#define hash JEMALLOC_N(hash)
#define huge_boot JEMALLOC_N(huge_boot)
#define huge_dalloc JEMALLOC_N(huge_dalloc)
#define huge_malloc JEMALLOC_N(huge_malloc)
#define huge_palloc JEMALLOC_N(huge_palloc)
#define huge_prof_ctx_get JEMALLOC_N(huge_prof_ctx_get)
#define huge_prof_ctx_set JEMALLOC_N(huge_prof_ctx_set)
#define huge_ralloc JEMALLOC_N(huge_ralloc)
#define huge_ralloc_no_move JEMALLOC_N(huge_ralloc_no_move)
#define huge_salloc JEMALLOC_N(huge_salloc)
#define iallocm JEMALLOC_N(iallocm)
#define icalloc JEMALLOC_N(icalloc)
#define idalloc JEMALLOC_N(idalloc)
#define imalloc JEMALLOC_N(imalloc)
#define ipalloc JEMALLOC_N(ipalloc)
#define iralloc JEMALLOC_N(iralloc)
#define isalloc JEMALLOC_N(isalloc)
#define ivsalloc JEMALLOC_N(ivsalloc)
#define jemalloc_darwin_init JEMALLOC_N(jemalloc_darwin_init)
#define jemalloc_postfork JEMALLOC_N(jemalloc_postfork)
#define jemalloc_prefork JEMALLOC_N(jemalloc_prefork)
#define malloc_cprintf JEMALLOC_N(malloc_cprintf)
#define malloc_mutex_destroy JEMALLOC_N(malloc_mutex_destroy)
#define malloc_mutex_init JEMALLOC_N(malloc_mutex_init)
#define malloc_mutex_lock JEMALLOC_N(malloc_mutex_lock)
#define malloc_mutex_trylock JEMALLOC_N(malloc_mutex_trylock)
#define malloc_mutex_unlock JEMALLOC_N(malloc_mutex_unlock)
#define malloc_printf JEMALLOC_N(malloc_printf)
#define malloc_write JEMALLOC_N(malloc_write)
#define mb_write JEMALLOC_N(mb_write)
#define pow2_ceil JEMALLOC_N(pow2_ceil)
#define prof_backtrace JEMALLOC_N(prof_backtrace)
#define prof_boot0 JEMALLOC_N(prof_boot0)
#define prof_boot1 JEMALLOC_N(prof_boot1)
#define prof_boot2 JEMALLOC_N(prof_boot2)
#define prof_ctx_get JEMALLOC_N(prof_ctx_get)
#define prof_ctx_set JEMALLOC_N(prof_ctx_set)
#define prof_free JEMALLOC_N(prof_free)
#define prof_gdump JEMALLOC_N(prof_gdump)
#define prof_idump JEMALLOC_N(prof_idump)
#define prof_lookup JEMALLOC_N(prof_lookup)
#define prof_malloc JEMALLOC_N(prof_malloc)
#define prof_mdump JEMALLOC_N(prof_mdump)
#define prof_realloc JEMALLOC_N(prof_realloc)
#define prof_sample_accum_update JEMALLOC_N(prof_sample_accum_update)
#define prof_sample_threshold_update JEMALLOC_N(prof_sample_threshold_update)
#define prof_tdata_init JEMALLOC_N(prof_tdata_init)
#define pthread_create JEMALLOC_N(pthread_create)
#define rtree_get JEMALLOC_N(rtree_get)
#define rtree_get_locked JEMALLOC_N(rtree_get_locked)
#define rtree_new JEMALLOC_N(rtree_new)
#define rtree_set JEMALLOC_N(rtree_set)
#define s2u JEMALLOC_N(s2u)
#define sa2u JEMALLOC_N(sa2u)
#define stats_arenas_i_bins_j_index JEMALLOC_N(stats_arenas_i_bins_j_index)
#define stats_arenas_i_index JEMALLOC_N(stats_arenas_i_index)
#define stats_arenas_i_lruns_j_index JEMALLOC_N(stats_arenas_i_lruns_j_index)
#define stats_cactive_add JEMALLOC_N(stats_cactive_add)
#define stats_cactive_get JEMALLOC_N(stats_cactive_get)
#define stats_cactive_sub JEMALLOC_N(stats_cactive_sub)
#define stats_print JEMALLOC_N(stats_print)
#define szone2ozone JEMALLOC_N(szone2ozone)
#define tcache_alloc_easy JEMALLOC_N(tcache_alloc_easy)
#define tcache_alloc_large JEMALLOC_N(tcache_alloc_large)
#define tcache_alloc_small JEMALLOC_N(tcache_alloc_small)
#define tcache_alloc_small_hard JEMALLOC_N(tcache_alloc_small_hard)
#define tcache_bin_flush_large JEMALLOC_N(tcache_bin_flush_large)
#define tcache_bin_flush_small JEMALLOC_N(tcache_bin_flush_small)
#define tcache_boot JEMALLOC_N(tcache_boot)
#define tcache_create JEMALLOC_N(tcache_create)
#define tcache_dalloc_large JEMALLOC_N(tcache_dalloc_large)
#define tcache_dalloc_small JEMALLOC_N(tcache_dalloc_small)
#define tcache_destroy JEMALLOC_N(tcache_destroy)
#define tcache_event JEMALLOC_N(tcache_event)
#define tcache_get JEMALLOC_N(tcache_get)
#define tcache_stats_merge JEMALLOC_N(tcache_stats_merge)
#define thread_allocated_get JEMALLOC_N(thread_allocated_get)
#define thread_allocated_get_hard JEMALLOC_N(thread_allocated_get_hard)
#define u2s JEMALLOC_N(u2s)

View File

@@ -227,9 +227,60 @@ bool prof_boot2(void);
/******************************************************************************/ /******************************************************************************/
#ifdef JEMALLOC_H_INLINES #ifdef JEMALLOC_H_INLINES
#define PROF_ALLOC_PREP(nignore, size, ret) do { \
prof_tdata_t *prof_tdata; \
prof_bt_t bt; \
\
assert(size == s2u(size)); \
\
prof_tdata = PROF_TCACHE_GET(); \
if (prof_tdata == NULL) { \
prof_tdata = prof_tdata_init(); \
if (prof_tdata == NULL) { \
ret = NULL; \
break; \
} \
} \
\
if (opt_prof_active == false) { \
/* Sampling is currently inactive, so avoid sampling. */\
ret = (prof_thr_cnt_t *)(uintptr_t)1U; \
} else if (opt_lg_prof_sample == 0) { \
/* Don't bother with sampling logic, since sampling */\
/* interval is 1. */\
bt_init(&bt, prof_tdata->vec); \
prof_backtrace(&bt, nignore, prof_bt_max); \
ret = prof_lookup(&bt); \
} else { \
if (prof_tdata->threshold == 0) { \
/* Initialize. Seed the prng differently for */\
/* each thread. */\
prof_tdata->prn_state = \
(uint64_t)(uintptr_t)&size; \
prof_sample_threshold_update(prof_tdata); \
} \
\
/* Determine whether to capture a backtrace based on */\
/* whether size is enough for prof_accum to reach */\
/* prof_tdata->threshold. However, delay updating */\
/* these variables until prof_{m,re}alloc(), because */\
/* we don't know for sure that the allocation will */\
/* succeed. */\
/* */\
/* Use subtraction rather than addition to avoid */\
/* potential integer overflow. */\
if (size >= prof_tdata->threshold - \
prof_tdata->accum) { \
bt_init(&bt, prof_tdata->vec); \
prof_backtrace(&bt, nignore, prof_bt_max); \
ret = prof_lookup(&bt); \
} else \
ret = (prof_thr_cnt_t *)(uintptr_t)1U; \
} \
} while (0)
#ifndef JEMALLOC_ENABLE_INLINE #ifndef JEMALLOC_ENABLE_INLINE
void prof_sample_threshold_update(prof_tdata_t *prof_tdata); void prof_sample_threshold_update(prof_tdata_t *prof_tdata);
prof_thr_cnt_t *prof_alloc_prep(size_t size);
prof_ctx_t *prof_ctx_get(const void *ptr); prof_ctx_t *prof_ctx_get(const void *ptr);
void prof_ctx_set(const void *ptr, prof_ctx_t *ctx); void prof_ctx_set(const void *ptr, prof_ctx_t *ctx);
bool prof_sample_accum_update(size_t size); bool prof_sample_accum_update(size_t size);
@@ -272,71 +323,6 @@ prof_sample_threshold_update(prof_tdata_t *prof_tdata)
+ (uint64_t)1U; + (uint64_t)1U;
} }
JEMALLOC_INLINE prof_thr_cnt_t *
prof_alloc_prep(size_t size)
{
#ifdef JEMALLOC_ENABLE_INLINE
/* This function does not have its own stack frame, because it is inlined. */
# define NIGNORE 1
#else
# define NIGNORE 2
#endif
prof_thr_cnt_t *ret;
prof_tdata_t *prof_tdata;
prof_bt_t bt;
assert(size == s2u(size));
prof_tdata = PROF_TCACHE_GET();
if (prof_tdata == NULL) {
prof_tdata = prof_tdata_init();
if (prof_tdata == NULL)
return (NULL);
}
if (opt_prof_active == false) {
/* Sampling is currently inactive, so avoid sampling. */
ret = (prof_thr_cnt_t *)(uintptr_t)1U;
} else if (opt_lg_prof_sample == 0) {
/*
* Don't bother with sampling logic, since sampling interval is
* 1.
*/
bt_init(&bt, prof_tdata->vec);
prof_backtrace(&bt, NIGNORE, prof_bt_max);
ret = prof_lookup(&bt);
} else {
if (prof_tdata->threshold == 0) {
/*
* Initialize. Seed the prng differently for each
* thread.
*/
prof_tdata->prn_state = (uint64_t)(uintptr_t)&size;
prof_sample_threshold_update(prof_tdata);
}
/*
* Determine whether to capture a backtrace based on whether
* size is enough for prof_accum to reach
* prof_tdata->threshold. However, delay updating these
* variables until prof_{m,re}alloc(), because we don't know
* for sure that the allocation will succeed.
*
* Use subtraction rather than addition to avoid potential
* integer overflow.
*/
if (size >= prof_tdata->threshold - prof_tdata->accum) {
bt_init(&bt, prof_tdata->vec);
prof_backtrace(&bt, NIGNORE, prof_bt_max);
ret = prof_lookup(&bt);
} else
ret = (prof_thr_cnt_t *)(uintptr_t)1U;
}
return (ret);
#undef NIGNORE
}
JEMALLOC_INLINE prof_ctx_t * JEMALLOC_INLINE prof_ctx_t *
prof_ctx_get(const void *ptr) prof_ctx_get(const void *ptr)
{ {
@@ -415,7 +401,7 @@ prof_malloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt)
* always possible to tell in advance how large an * always possible to tell in advance how large an
* object's usable size will be, so there should never * object's usable size will be, so there should never
* be a difference between the size passed to * be a difference between the size passed to
* prof_alloc_prep() and prof_malloc(). * PROF_ALLOC_PREP() and prof_malloc().
*/ */
assert((uintptr_t)cnt == (uintptr_t)1U); assert((uintptr_t)cnt == (uintptr_t)1U);
} }
@@ -459,7 +445,7 @@ prof_realloc(const void *ptr, size_t size, prof_thr_cnt_t *cnt,
if (prof_sample_accum_update(size)) { if (prof_sample_accum_update(size)) {
/* /*
* Don't sample. The size passed to * Don't sample. The size passed to
* prof_alloc_prep() was larger than what * PROF_ALLOC_PREP() was larger than what
* actually got allocated, so a backtrace was * actually got allocated, so a backtrace was
* captured for this allocation, even though * captured for this allocation, even though
* its actual size was insufficient to cross * its actual size was insufficient to cross

View File

@@ -18,6 +18,15 @@
#undef JEMALLOC_P #undef JEMALLOC_P
#endif #endif
/*
* JEMALLOC_PRIVATE_NAMESPACE is used as a prefix for all library-private APIs.
* For shared libraries, symbol visibility mechanisms prevent these symbols
* from being exported, but for static libraries, naming collisions are a real
* possibility.
*/
#undef JEMALLOC_PRIVATE_NAMESPACE
#undef JEMALLOC_N
/* /*
* Hyper-threaded CPUs may need a special instruction inside spin loops in * Hyper-threaded CPUs may need a special instruction inside spin loops in
* order to yield to another virtual CPU. * order to yield to another virtual CPU.

View File

@@ -869,9 +869,9 @@ arena_purge(arena_t *arena, bool all)
assert(ndirty == arena->ndirty); assert(ndirty == arena->ndirty);
#endif #endif
assert(arena->ndirty > arena->npurgatory || all); assert(arena->ndirty > arena->npurgatory || all);
assert(arena->ndirty > chunk_npages || all); assert(arena->ndirty - arena->npurgatory > chunk_npages || all);
assert((arena->nactive >> opt_lg_dirty_mult) < (arena->ndirty - assert((arena->nactive >> opt_lg_dirty_mult) < (arena->ndirty -
npurgatory) || all); arena->npurgatory) || all);
#ifdef JEMALLOC_STATS #ifdef JEMALLOC_STATS
arena->stats.npurge++; arena->stats.npurge++;
@@ -1657,6 +1657,7 @@ arena_prof_promoted(const void *ptr, size_t size)
assert(ptr != NULL); assert(ptr != NULL);
assert(CHUNK_ADDR2BASE(ptr) != ptr); assert(CHUNK_ADDR2BASE(ptr) != ptr);
assert(isalloc(ptr) == PAGE_SIZE); assert(isalloc(ptr) == PAGE_SIZE);
assert(size <= small_maxclass);
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT;

View File

@@ -556,7 +556,7 @@ ckh_string_hash(const void *key, unsigned minbits, size_t *hash1, size_t *hash2)
} else { } else {
ret1 = h; ret1 = h;
ret2 = hash(key, strlen((const char *)key), ret2 = hash(key, strlen((const char *)key),
0x8432a476666bbc13U); 0x8432a476666bbc13LLU);
} }
*hash1 = ret1; *hash1 = ret1;

View File

@@ -1151,11 +1151,13 @@ thread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
/* Set new arena association. */ /* Set new arena association. */
ARENA_SET(arena); ARENA_SET(arena);
#ifdef JEMALLOC_TCACHE
{ {
tcache_t *tcache = TCACHE_GET(); tcache_t *tcache = TCACHE_GET();
if (tcache != NULL) if (tcache != NULL)
tcache->arena = arena; tcache->arena = arena;
} }
#endif
} }
ret = 0; ret = 0;

View File

@@ -84,6 +84,7 @@ static void malloc_conf_error(const char *msg, const char *k, size_t klen,
const char *v, size_t vlen); const char *v, size_t vlen);
static void malloc_conf_init(void); static void malloc_conf_init(void);
static bool malloc_init_hard(void); static bool malloc_init_hard(void);
static int imemalign(void **memptr, size_t alignment, size_t size);
/******************************************************************************/ /******************************************************************************/
/* malloc_message() setup. */ /* malloc_message() setup. */
@@ -939,7 +940,8 @@ JEMALLOC_P(malloc)(size_t size)
#ifdef JEMALLOC_PROF #ifdef JEMALLOC_PROF
if (opt_prof) { if (opt_prof) {
usize = s2u(size); usize = s2u(size);
if ((cnt = prof_alloc_prep(usize)) == NULL) { PROF_ALLOC_PREP(1, usize, cnt);
if (cnt == NULL) {
ret = NULL; ret = NULL;
goto OOM; goto OOM;
} }
@@ -988,9 +990,15 @@ RETURN:
} }
JEMALLOC_ATTR(nonnull(1)) JEMALLOC_ATTR(nonnull(1))
JEMALLOC_ATTR(visibility("default")) #ifdef JEMALLOC_PROF
int /*
JEMALLOC_P(posix_memalign)(void **memptr, size_t alignment, size_t size) * Avoid any uncertainty as to how many backtrace frames to ignore in
* PROF_ALLOC_PREP().
*/
JEMALLOC_ATTR(noinline)
#endif
static int
imemalign(void **memptr, size_t alignment, size_t size)
{ {
int ret; int ret;
size_t usize size_t usize
@@ -1057,7 +1065,8 @@ JEMALLOC_P(posix_memalign)(void **memptr, size_t alignment, size_t size)
#ifdef JEMALLOC_PROF #ifdef JEMALLOC_PROF
if (opt_prof) { if (opt_prof) {
if ((cnt = prof_alloc_prep(usize)) == NULL) { PROF_ALLOC_PREP(2, usize, cnt);
if (cnt == NULL) {
result = NULL; result = NULL;
ret = EINVAL; ret = EINVAL;
} else { } else {
@@ -1110,6 +1119,15 @@ RETURN:
return (ret); return (ret);
} }
JEMALLOC_ATTR(nonnull(1))
JEMALLOC_ATTR(visibility("default"))
int
JEMALLOC_P(posix_memalign)(void **memptr, size_t alignment, size_t size)
{
return imemalign(memptr, alignment, size);
}
JEMALLOC_ATTR(malloc) JEMALLOC_ATTR(malloc)
JEMALLOC_ATTR(visibility("default")) JEMALLOC_ATTR(visibility("default"))
void * void *
@@ -1165,7 +1183,8 @@ JEMALLOC_P(calloc)(size_t num, size_t size)
#ifdef JEMALLOC_PROF #ifdef JEMALLOC_PROF
if (opt_prof) { if (opt_prof) {
usize = s2u(num_size); usize = s2u(num_size);
if ((cnt = prof_alloc_prep(usize)) == NULL) { PROF_ALLOC_PREP(1, usize, cnt);
if (cnt == NULL) {
ret = NULL; ret = NULL;
goto RETURN; goto RETURN;
} }
@@ -1278,7 +1297,9 @@ JEMALLOC_P(realloc)(void *ptr, size_t size)
if (opt_prof) { if (opt_prof) {
usize = s2u(size); usize = s2u(size);
old_ctx = prof_ctx_get(ptr); old_ctx = prof_ctx_get(ptr);
if ((cnt = prof_alloc_prep(usize)) == NULL) { PROF_ALLOC_PREP(1, usize, cnt);
if (cnt == NULL) {
old_ctx = NULL;
ret = NULL; ret = NULL;
goto OOM; goto OOM;
} }
@@ -1288,8 +1309,13 @@ JEMALLOC_P(realloc)(void *ptr, size_t size)
false, false); false, false);
if (ret != NULL) if (ret != NULL)
arena_prof_promoted(ret, usize); arena_prof_promoted(ret, usize);
} else else
old_ctx = NULL;
} else {
ret = iralloc(ptr, size, 0, 0, false, false); ret = iralloc(ptr, size, 0, 0, false, false);
if (ret == NULL)
old_ctx = NULL;
}
} else } else
#endif #endif
{ {
@@ -1327,7 +1353,8 @@ OOM:
#ifdef JEMALLOC_PROF #ifdef JEMALLOC_PROF
if (opt_prof) { if (opt_prof) {
usize = s2u(size); usize = s2u(size);
if ((cnt = prof_alloc_prep(usize)) == NULL) PROF_ALLOC_PREP(1, usize, cnt);
if (cnt == NULL)
ret = NULL; ret = NULL;
else { else {
if (prof_promote && (uintptr_t)cnt != if (prof_promote && (uintptr_t)cnt !=
@@ -1432,7 +1459,7 @@ JEMALLOC_P(memalign)(size_t alignment, size_t size)
#ifdef JEMALLOC_CC_SILENCE #ifdef JEMALLOC_CC_SILENCE
int result = int result =
#endif #endif
JEMALLOC_P(posix_memalign)(&ret, alignment, size); imemalign(&ret, alignment, size);
#ifdef JEMALLOC_CC_SILENCE #ifdef JEMALLOC_CC_SILENCE
if (result != 0) if (result != 0)
return (NULL); return (NULL);
@@ -1451,7 +1478,7 @@ JEMALLOC_P(valloc)(size_t size)
#ifdef JEMALLOC_CC_SILENCE #ifdef JEMALLOC_CC_SILENCE
int result = int result =
#endif #endif
JEMALLOC_P(posix_memalign)(&ret, PAGE_SIZE, size); imemalign(&ret, PAGE_SIZE, size);
#ifdef JEMALLOC_CC_SILENCE #ifdef JEMALLOC_CC_SILENCE
if (result != 0) if (result != 0)
return (NULL); return (NULL);
@@ -1566,14 +1593,14 @@ JEMALLOC_P(allocm)(void **ptr, size_t *rsize, size_t size, int flags)
if (malloc_init()) if (malloc_init())
goto OOM; goto OOM;
usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment, usize = (alignment == 0) ? s2u(size) : sa2u(size, alignment, NULL);
NULL);
if (usize == 0) if (usize == 0)
goto OOM; goto OOM;
#ifdef JEMALLOC_PROF #ifdef JEMALLOC_PROF
if (opt_prof) { if (opt_prof) {
if ((cnt = prof_alloc_prep(usize)) == NULL) PROF_ALLOC_PREP(1, usize, cnt);
if (cnt == NULL)
goto OOM; goto OOM;
if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize <= if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && usize <=
small_maxclass) { small_maxclass) {
@@ -1590,7 +1617,7 @@ JEMALLOC_P(allocm)(void **ptr, size_t *rsize, size_t size, int flags)
if (p == NULL) if (p == NULL)
goto OOM; goto OOM;
} }
prof_malloc(p, usize, cnt);
if (rsize != NULL) if (rsize != NULL)
*rsize = usize; *rsize = usize;
} else } else
@@ -1645,7 +1672,6 @@ JEMALLOC_P(rallocm)(void **ptr, size_t *rsize, size_t size, size_t extra,
bool no_move = flags & ALLOCM_NO_MOVE; bool no_move = flags & ALLOCM_NO_MOVE;
#ifdef JEMALLOC_PROF #ifdef JEMALLOC_PROF
prof_thr_cnt_t *cnt; prof_thr_cnt_t *cnt;
prof_ctx_t *old_ctx;
#endif #endif
assert(ptr != NULL); assert(ptr != NULL);
@@ -1660,25 +1686,33 @@ JEMALLOC_P(rallocm)(void **ptr, size_t *rsize, size_t size, size_t extra,
/* /*
* usize isn't knowable before iralloc() returns when extra is * usize isn't knowable before iralloc() returns when extra is
* non-zero. Therefore, compute its maximum possible value and * non-zero. Therefore, compute its maximum possible value and
* use that in prof_alloc_prep() to decide whether to capture a * use that in PROF_ALLOC_PREP() to decide whether to capture a
* backtrace. prof_realloc() will use the actual usize to * backtrace. prof_realloc() will use the actual usize to
* decide whether to sample. * decide whether to sample.
*/ */
size_t max_usize = (alignment == 0) ? s2u(size+extra) : size_t max_usize = (alignment == 0) ? s2u(size+extra) :
sa2u(size+extra, alignment, NULL); sa2u(size+extra, alignment, NULL);
prof_ctx_t *old_ctx = prof_ctx_get(p);
old_size = isalloc(p); old_size = isalloc(p);
old_ctx = prof_ctx_get(p); PROF_ALLOC_PREP(1, max_usize, cnt);
if ((cnt = prof_alloc_prep(max_usize)) == NULL) if (cnt == NULL)
goto OOM; goto OOM;
if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U && max_usize /*
<= small_maxclass) { * Use minimum usize to determine whether promotion may happen.
*/
if (prof_promote && (uintptr_t)cnt != (uintptr_t)1U
&& ((alignment == 0) ? s2u(size) : sa2u(size,
alignment, NULL)) <= small_maxclass) {
q = iralloc(p, small_maxclass+1, (small_maxclass+1 >= q = iralloc(p, small_maxclass+1, (small_maxclass+1 >=
size+extra) ? 0 : size+extra - (small_maxclass+1), size+extra) ? 0 : size+extra - (small_maxclass+1),
alignment, zero, no_move); alignment, zero, no_move);
if (q == NULL) if (q == NULL)
goto ERR; goto ERR;
usize = isalloc(q); if (max_usize < PAGE_SIZE) {
usize = max_usize;
arena_prof_promoted(q, usize); arena_prof_promoted(q, usize);
} else
usize = isalloc(q);
} else { } else {
q = iralloc(p, size, extra, alignment, zero, no_move); q = iralloc(p, size, extra, alignment, zero, no_move);
if (q == NULL) if (q == NULL)

View File

@@ -474,11 +474,23 @@ prof_lookup(prof_bt_t *bt)
/* /*
* Artificially raise curobjs, in order to avoid a race * Artificially raise curobjs, in order to avoid a race
* condition with prof_ctx_merge()/prof_ctx_destroy(). * condition with prof_ctx_merge()/prof_ctx_destroy().
*
* No locking is necessary for ctx here because no other
* threads have had the opportunity to fetch it from
* bt2ctx yet.
*/ */
ctx.p->cnt_merged.curobjs++; ctx.p->cnt_merged.curobjs++;
new_ctx = true; new_ctx = true;
} else } else {
/*
* Artificially raise curobjs, in order to avoid a race
* condition with prof_ctx_merge()/prof_ctx_destroy().
*/
malloc_mutex_lock(&ctx.p->lock);
ctx.p->cnt_merged.curobjs++;
malloc_mutex_unlock(&ctx.p->lock);
new_ctx = false; new_ctx = false;
}
prof_leave(); prof_leave();
/* Link a prof_thd_cnt_t into ctx for this thread. */ /* Link a prof_thd_cnt_t into ctx for this thread. */
@@ -491,8 +503,9 @@ prof_lookup(prof_bt_t *bt)
*/ */
ret.p = ql_last(&prof_tdata->lru_ql, lru_link); ret.p = ql_last(&prof_tdata->lru_ql, lru_link);
assert(ret.v != NULL); assert(ret.v != NULL);
ckh_remove(&prof_tdata->bt2cnt, ret.p->ctx->bt, NULL, if (ckh_remove(&prof_tdata->bt2cnt, ret.p->ctx->bt,
NULL); NULL, NULL))
assert(false);
ql_remove(&prof_tdata->lru_ql, ret.p, lru_link); ql_remove(&prof_tdata->lru_ql, ret.p, lru_link);
prof_ctx_merge(ret.p->ctx, ret.p); prof_ctx_merge(ret.p->ctx, ret.p);
/* ret can now be re-used. */ /* ret can now be re-used. */
@@ -503,11 +516,8 @@ prof_lookup(prof_bt_t *bt)
/* Allocate and partially initialize a new cnt. */ /* Allocate and partially initialize a new cnt. */
ret.v = imalloc(sizeof(prof_thr_cnt_t)); ret.v = imalloc(sizeof(prof_thr_cnt_t));
if (ret.p == NULL) { if (ret.p == NULL) {
if (new_ctx) { if (new_ctx)
malloc_mutex_lock(&ctx.p->lock); prof_ctx_destroy(ctx.p);
ctx.p->cnt_merged.curobjs--;
malloc_mutex_unlock(&ctx.p->lock);
}
return (NULL); return (NULL);
} }
ql_elm_new(ret.p, cnts_link); ql_elm_new(ret.p, cnts_link);
@@ -518,18 +528,14 @@ prof_lookup(prof_bt_t *bt)
ret.p->epoch = 0; ret.p->epoch = 0;
memset(&ret.p->cnts, 0, sizeof(prof_cnt_t)); memset(&ret.p->cnts, 0, sizeof(prof_cnt_t));
if (ckh_insert(&prof_tdata->bt2cnt, btkey.v, ret.v)) { if (ckh_insert(&prof_tdata->bt2cnt, btkey.v, ret.v)) {
if (new_ctx) { if (new_ctx)
malloc_mutex_lock(&ctx.p->lock); prof_ctx_destroy(ctx.p);
ctx.p->cnt_merged.curobjs--;
malloc_mutex_unlock(&ctx.p->lock);
}
idalloc(ret.v); idalloc(ret.v);
return (NULL); return (NULL);
} }
ql_head_insert(&prof_tdata->lru_ql, ret.p, lru_link); ql_head_insert(&prof_tdata->lru_ql, ret.p, lru_link);
malloc_mutex_lock(&ctx.p->lock); malloc_mutex_lock(&ctx.p->lock);
ql_tail_insert(&ctx.p->cnts_ql, ret.p, cnts_link); ql_tail_insert(&ctx.p->cnts_ql, ret.p, cnts_link);
if (new_ctx)
ctx.p->cnt_merged.curobjs--; ctx.p->cnt_merged.curobjs--;
malloc_mutex_unlock(&ctx.p->lock); malloc_mutex_unlock(&ctx.p->lock);
} else { } else {
@@ -644,11 +650,10 @@ prof_ctx_destroy(prof_ctx_t *ctx)
/* /*
* Check that ctx is still unused by any thread cache before destroying * Check that ctx is still unused by any thread cache before destroying
* it. prof_lookup() interlocks bt2ctx_mtx and ctx->lock in order to * it. prof_lookup() artificially raises ctx->cnt_merge.curobjs in
* avoid a race condition with this function, and prof_ctx_merge() * order to avoid a race condition with this function, as does
* artificially raises ctx->cnt_merged.curobjs in order to avoid a race * prof_ctx_merge() in order to avoid a race between the main body of
* between the main body of prof_ctx_merge() and entry into this * prof_ctx_merge() and entry into this function.
* function.
*/ */
prof_enter(); prof_enter();
malloc_mutex_lock(&ctx->lock); malloc_mutex_lock(&ctx->lock);
@@ -657,7 +662,8 @@ prof_ctx_destroy(prof_ctx_t *ctx)
assert(ctx->cnt_merged.accumobjs == 0); assert(ctx->cnt_merged.accumobjs == 0);
assert(ctx->cnt_merged.accumbytes == 0); assert(ctx->cnt_merged.accumbytes == 0);
/* Remove ctx from bt2ctx. */ /* Remove ctx from bt2ctx. */
ckh_remove(&bt2ctx, ctx->bt, NULL, NULL); if (ckh_remove(&bt2ctx, ctx->bt, NULL, NULL))
assert(false);
prof_leave(); prof_leave();
/* Destroy ctx. */ /* Destroy ctx. */
malloc_mutex_unlock(&ctx->lock); malloc_mutex_unlock(&ctx->lock);
@@ -665,7 +671,10 @@ prof_ctx_destroy(prof_ctx_t *ctx)
malloc_mutex_destroy(&ctx->lock); malloc_mutex_destroy(&ctx->lock);
idalloc(ctx); idalloc(ctx);
} else { } else {
/* Compensate for increment in prof_ctx_merge(). */ /*
* Compensate for increment in prof_ctx_merge() or
* prof_lookup().
*/
ctx->cnt_merged.curobjs--; ctx->cnt_merged.curobjs--;
malloc_mutex_unlock(&ctx->lock); malloc_mutex_unlock(&ctx->lock);
prof_leave(); prof_leave();
@@ -1072,7 +1081,7 @@ prof_bt_hash(const void *key, unsigned minbits, size_t *hash1, size_t *hash2)
} else { } else {
ret1 = h; ret1 = h;
ret2 = hash(bt->vec, bt->len * sizeof(void *), ret2 = hash(bt->vec, bt->len * sizeof(void *),
0x8432a476666bbc13U); 0x8432a476666bbc13LLU);
} }
*hash1 = ret1; *hash1 = ret1;
@@ -1109,7 +1118,6 @@ prof_tdata_init(void)
prof_tdata->vec = imalloc(sizeof(void *) * prof_bt_max); prof_tdata->vec = imalloc(sizeof(void *) * prof_bt_max);
if (prof_tdata->vec == NULL) { if (prof_tdata->vec == NULL) {
ckh_delete(&prof_tdata->bt2cnt); ckh_delete(&prof_tdata->bt2cnt);
idalloc(prof_tdata); idalloc(prof_tdata);
return (NULL); return (NULL);
@@ -1127,25 +1135,19 @@ prof_tdata_init(void)
static void static void
prof_tdata_cleanup(void *arg) prof_tdata_cleanup(void *arg)
{ {
prof_tdata_t *prof_tdata;
prof_tdata = PROF_TCACHE_GET();
if (prof_tdata != NULL) {
prof_thr_cnt_t *cnt; prof_thr_cnt_t *cnt;
prof_tdata_t *prof_tdata = (prof_tdata_t *)arg;
/* /*
* Delete the hash table. All of its contents can still be * Delete the hash table. All of its contents can still be iterated
* iterated over via the LRU. * over via the LRU.
*/ */
ckh_delete(&prof_tdata->bt2cnt); ckh_delete(&prof_tdata->bt2cnt);
/* /* Iteratively merge cnt's into the global stats and delete them. */
* Iteratively merge cnt's into the global stats and delete
* them.
*/
while ((cnt = ql_last(&prof_tdata->lru_ql, lru_link)) != NULL) { while ((cnt = ql_last(&prof_tdata->lru_ql, lru_link)) != NULL) {
prof_ctx_merge(cnt->ctx, cnt);
ql_remove(&prof_tdata->lru_ql, cnt, lru_link); ql_remove(&prof_tdata->lru_ql, cnt, lru_link);
prof_ctx_merge(cnt->ctx, cnt);
idalloc(cnt); idalloc(cnt);
} }
@@ -1153,7 +1155,6 @@ prof_tdata_cleanup(void *arg)
idalloc(prof_tdata); idalloc(prof_tdata);
PROF_TCACHE_SET(NULL); PROF_TCACHE_SET(NULL);
}
} }
void void