11 Commits
2.1.1 ... 2.1.3

Author SHA1 Message Date
Jason Evans
ad11ee6a34 Merge branch 'dev' 2011-03-14 16:42:26 -07:00
Jason Evans
0e4d0d13f9 Update ChangeLog for 2.1.3. 2011-03-14 16:41:03 -07:00
Jason Evans
a8118233ec Fix a thread cache stats merging bug.
When a thread cache flushes objects to their arenas due to an abundance
of cached objects, it merges the allocation request count for the
associated size class, and increments a flush counter.  If none of the
flushed objects came from the thread's assigned arena, then the merging
wouldn't happen (though the counter would typically eventually be
merged), nor would the flush counter be incremented (a hard bug).  Fix
this via extra conditional code just after the flush loop.
2011-03-14 12:56:51 -07:00
Jason Evans
a7153a0d7d Fix a "thread.arena" mallctl bug.
Fix a variable reversal bug in mallctl("thread.arena", ...).
2011-03-14 11:43:54 -07:00
Jason Evans
814b9bda7f Fix a cpp logic regression.
Fix a cpp logic error that was introduced by the recent commit:
	Fix "thread.{de,}allocatedp" mallctl.
2011-03-06 23:03:33 -08:00
Jason Evans
e27d134efc Merge branch 'dev' 2011-03-02 12:19:58 -08:00
je
6e56e5ec6a Update ChangeLog for 2.1.2. 2011-03-02 11:23:41 -08:00
Arun Sharma
af5d6987f8 Build both PIC and no PIC static libraries
When jemalloc is linked into an executable (as opposed to a shared
library), compiling with -fno-pic can have significant advantages,
mainly because we don't have to go throught the GOT (global offset
table).

Users who want to link jemalloc into a shared library that could
be dlopened need to link with libjemalloc_pic.a or libjemalloc.so.
2011-03-02 11:14:50 -08:00
Jason Evans
655f04a5a4 Fix style nits. 2011-02-13 18:44:59 -08:00
Jason Evans
9dcad2dfd1 Fix "thread.{de,}allocatedp" mallctl.
For the non-TLS case (as on OS X), if the "thread.{de,}allocatedp"
mallctl was called before any allocation occurred for that thread, the
TSD was still NULL, thus putting the application at risk of
dereferencing NULL.  Fix this by refactoring the initialization code,
and making it part of the conditional logic for all per thread
allocation counter accesses.
2011-02-13 18:11:54 -08:00
Jason Evans
6369286f83 Add release dates to ChangeLog. 2011-02-07 22:48:35 -08:00
10 changed files with 195 additions and 75 deletions

View File

@@ -6,15 +6,29 @@ 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.1.1 * 2.1.3 (March 14, 2011)
Bug Fixes: Bug fixes:
- Fix a cpp logic regression (due to the "thread.{de,}allocatedp" mallctl fix
for OS X in 2.1.2).
- Fix a "thread.arena" mallctl bug.
- Fix a thread cache stats merging bug.
* 2.1.2 (March 2, 2011)
Bug fixes:
- Fix "thread.{de,}allocatedp" mallctl for OS X.
- Add missing jemalloc.a to build system.
* 2.1.1 (January 31, 2011)
Bug fixes:
- Fix aligned huge reallocation (affected allocm()). - Fix aligned huge reallocation (affected allocm()).
- Fix the ALLOCM_LG_ALIGN macro definition. - Fix the ALLOCM_LG_ALIGN macro definition.
- Fix a heap dumping deadlock. - Fix a heap dumping deadlock.
- Fix a "thread.arena" mallctl bug. - Fix a "thread.arena" mallctl bug.
* 2.1.0 * 2.1.0 (December 3, 2010)
This version incorporates some optimizations that can't quite be considered This version incorporates some optimizations that can't quite be considered
bug fixes. bug fixes.
@@ -31,7 +45,7 @@ found in the git revision history:
--enable-debug --enable-dss configurations. --enable-debug --enable-dss configurations.
- Fix a minor statistics bug for mallctl("swap.avail", ...). - Fix a minor statistics bug for mallctl("swap.avail", ...).
* 2.0.1 * 2.0.1 (October 29, 2010)
Bug fixes: Bug fixes:
- Fix a race condition in heap profiling that could cause undefined behavior - Fix a race condition in heap profiling that could cause undefined behavior
@@ -40,7 +54,7 @@ found in the git revision history:
code. code.
- Fix a compilation error for non-C99 builds. - Fix a compilation error for non-C99 builds.
* 2.0.0 * 2.0.0 (October 24, 2010)
This version focuses on the experimental *allocm() API, and on improved This version focuses on the experimental *allocm() API, and on improved
run-time configuration/introspection. Nonetheless, numerous performance run-time configuration/introspection. Nonetheless, numerous performance
@@ -92,7 +106,7 @@ found in the git revision history:
- Fix a heap profiling bug due to sometimes losing track of requested object - Fix a heap profiling bug due to sometimes losing track of requested object
size for sampled objects. size for sampled objects.
* 1.0.3 * 1.0.3 (August 12, 2010)
Bug fixes: Bug fixes:
- Fix the libunwind-based implementation of stack backtracing (used for heap - Fix the libunwind-based implementation of stack backtracing (used for heap
@@ -101,7 +115,7 @@ found in the git revision history:
threads raced to initialize malloc, some of them could end up permanently threads raced to initialize malloc, some of them could end up permanently
blocked. blocked.
* 1.0.2 * 1.0.2 (May 11, 2010)
Bug fixes: Bug fixes:
- Fix junk filling of large objects, which could cause memory corruption. - Fix junk filling of large objects, which could cause memory corruption.
@@ -109,7 +123,7 @@ found in the git revision history:
memory limits could cause swap file configuration to fail. Contributed by memory limits could cause swap file configuration to fail. Contributed by
Jordan DeLong. Jordan DeLong.
* 1.0.1 * 1.0.1 (April 14, 2010)
Bug fixes: Bug fixes:
- Fix compilation when --enable-fill is specified. - Fix compilation when --enable-fill is specified.
@@ -118,7 +132,7 @@ found in the git revision history:
- Fix dirty page purging race conditions that could cause crashes. - Fix dirty page purging race conditions that could cause crashes.
- Fix crash in tcache flushing code during thread destruction. - Fix crash in tcache flushing code during thread destruction.
* 1.0.0 * 1.0.0 (April 11, 2010)
This release focuses on speed and run-time introspection. Numerous This release focuses on speed and run-time introspection. Numerous
algorithmic improvements make this release substantially faster than its algorithmic improvements make this release substantially faster than its
@@ -154,7 +168,7 @@ found in the git revision history:
- Fix a chunk leak. The leaked chunks were never touched, so this impacted - Fix a chunk leak. The leaked chunks were never touched, so this impacted
virtual memory usage, but not physical memory usage. virtual memory usage, but not physical memory usage.
* linux_20080828a, linux_20080827a * linux_2008082[78]a (August 27/28, 2008)
These snapshot releases are the simple result of incorporating Linux-specific These snapshot releases are the simple result of incorporating Linux-specific
support into the FreeBSD malloc sources. support into the FreeBSD malloc sources.

View File

@@ -20,7 +20,7 @@ MANDIR := $(DESTDIR)@MANDIR@
# Build parameters. # Build parameters.
CPPFLAGS := @CPPFLAGS@ -I@srcroot@include -I@objroot@include CPPFLAGS := @CPPFLAGS@ -I@srcroot@include -I@objroot@include
CFLAGS := @CFLAGS@ -fPIC -DPIC CFLAGS := @CFLAGS@
ifeq (macho, @abi@) ifeq (macho, @abi@)
CFLAGS += -dynamic CFLAGS += -dynamic
endif endif
@@ -55,6 +55,7 @@ CSRCS := @srcroot@src/jemalloc.c @srcroot@src/arena.c @srcroot@src/base.c \
ifeq (macho, @abi@) ifeq (macho, @abi@)
CSRCS += @srcroot@src/zone.c CSRCS += @srcroot@src/zone.c
endif endif
STATIC_LIBS := @objroot@lib/libjemalloc@install_suffix@.a
DSOS := @objroot@lib/libjemalloc@install_suffix@.$(SO).$(REV) \ DSOS := @objroot@lib/libjemalloc@install_suffix@.$(SO).$(REV) \
@objroot@lib/libjemalloc@install_suffix@.$(SO) \ @objroot@lib/libjemalloc@install_suffix@.$(SO) \
@objroot@lib/libjemalloc@install_suffix@_pic.a @objroot@lib/libjemalloc@install_suffix@_pic.a
@@ -72,8 +73,10 @@ CTESTS := @srcroot@test/allocated.c @srcroot@test/allocm.c \
.PHONY: install_html install_man install_doc install .PHONY: install_html install_man install_doc install
.PHONY: tests check clean distclean relclean .PHONY: tests check clean distclean relclean
.SECONDARY : $(CTESTS:@srcroot@%.c=@objroot@%.o)
# Default target. # Default target.
all: $(DSOS) all: $(DSOS) $(STATIC_LIBS)
dist: doc dist: doc
@@ -97,15 +100,24 @@ doc: $(DOCS)
$(CC) $(CFLAGS) -c $(CPPFLAGS) -o $@ $< $(CC) $(CFLAGS) -c $(CPPFLAGS) -o $@ $<
@$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)" @$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)"
@objroot@src/%.pic.o: @srcroot@src/%.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) -fPIC -DPIC -c $(CPPFLAGS) -o $@ $<
@$(SHELL) -ec "$(CC) -MM $(CPPFLAGS) $< | sed \"s/\($(subst /,\/,$(notdir $(basename $@)))\)\.o\([ :]*\)/$(subst /,\/,$(strip $(dir $@)))\1.o \2/g\" > $(@:%.o=%.d)"
%.$(SO) : %.$(SO).$(REV) %.$(SO) : %.$(SO).$(REV)
@mkdir -p $(@D) @mkdir -p $(@D)
ln -sf $(<F) $@ ln -sf $(<F) $@
@objroot@lib/libjemalloc@install_suffix@.$(SO).$(REV) : $(CSRCS:@srcroot@%.c=@objroot@%.o) @objroot@lib/libjemalloc@install_suffix@.$(SO).$(REV) : $(CSRCS:@srcroot@%.c=@objroot@%.pic.o)
@mkdir -p $(@D) @mkdir -p $(@D)
$(CC) -shared -Wl,-$(WL_SONAME),$(@F) $(RPATH_EXTRA:%=@RPATH@%) -o $@ $+ $(LDFLAGS) $(LIBS) $(CC) -shared -Wl,-$(WL_SONAME),$(@F) $(RPATH_EXTRA:%=@RPATH@%) -o $@ $+ $(LDFLAGS) $(LIBS)
@objroot@lib/libjemalloc@install_suffix@_pic.a : $(CSRCS:@srcroot@%.c=@objroot@%.o) @objroot@lib/libjemalloc@install_suffix@_pic.a : $(CSRCS:@srcroot@%.c=@objroot@%.pic.o)
@mkdir -p $(@D)
ar crus $@ $+
@objroot@lib/libjemalloc@install_suffix@.a : $(CSRCS:@srcroot@%.c=@objroot@%.o)
@mkdir -p $(@D) @mkdir -p $(@D)
ar crus $@ $+ ar crus $@ $+
@@ -137,11 +149,12 @@ install_include:
install -m 644 $$h $(INCLUDEDIR)/jemalloc; \ install -m 644 $$h $(INCLUDEDIR)/jemalloc; \
done done
install_lib: $(DSOS) install_lib: $(DSOS) $(STATIC_LIBS)
install -d $(LIBDIR) install -d $(LIBDIR)
install -m 755 @objroot@lib/libjemalloc@install_suffix@.$(SO).$(REV) $(LIBDIR) install -m 755 @objroot@lib/libjemalloc@install_suffix@.$(SO).$(REV) $(LIBDIR)
ln -sf libjemalloc@install_suffix@.$(SO).$(REV) $(LIBDIR)/libjemalloc@install_suffix@.$(SO) ln -sf libjemalloc@install_suffix@.$(SO).$(REV) $(LIBDIR)/libjemalloc@install_suffix@.$(SO)
install -m 755 @objroot@lib/libjemalloc@install_suffix@_pic.a $(LIBDIR) install -m 755 @objroot@lib/libjemalloc@install_suffix@_pic.a $(LIBDIR)
install -m 755 @objroot@lib/libjemalloc@install_suffix@.a $(LIBDIR)
install_html: install_html:
install -d $(DATADIR)/doc/jemalloc@install_suffix@ install -d $(DATADIR)/doc/jemalloc@install_suffix@
@@ -193,12 +206,14 @@ check: tests
clean: clean:
rm -f $(CSRCS:@srcroot@%.c=@objroot@%.o) rm -f $(CSRCS:@srcroot@%.c=@objroot@%.o)
rm -f $(CSRCS:@srcroot@%.c=@objroot@%.pic.o)
rm -f $(CSRCS:@srcroot@%.c=@objroot@%.d) rm -f $(CSRCS:@srcroot@%.c=@objroot@%.d)
rm -f $(CSRCS:@srcroot@%.c=@objroot@%.pic.d)
rm -f $(CTESTS:@srcroot@%.c=@objroot@%) rm -f $(CTESTS:@srcroot@%.c=@objroot@%)
rm -f $(CTESTS:@srcroot@%.c=@objroot@%.o) rm -f $(CTESTS:@srcroot@%.c=@objroot@%.o)
rm -f $(CTESTS:@srcroot@%.c=@objroot@%.d) rm -f $(CTESTS:@srcroot@%.c=@objroot@%.d)
rm -f $(CTESTS:@srcroot@%.c=@objroot@%.out) rm -f $(CTESTS:@srcroot@%.c=@objroot@%.out)
rm -f $(DSOS) rm -f $(DSOS) $(STATIC_LIBS)
distclean: clean distclean: clean
rm -rf @objroot@autom4te.cache rm -rf @objroot@autom4te.cache

View File

@@ -62,7 +62,7 @@ hash(const void *key, size_t len, uint64_t seed)
h *= m; h *= m;
h ^= h >> r; h ^= h >> r;
return h; return (h);
} }
#endif #endif

View File

@@ -148,11 +148,6 @@ extern void (*JEMALLOC_P(malloc_message))(void *wcbopaque, const char *s);
#define SIZEOF_PTR (1U << LG_SIZEOF_PTR) #define SIZEOF_PTR (1U << LG_SIZEOF_PTR)
/* We can't use TLS in non-PIC programs, since TLS relies on loader magic. */
#if (!defined(PIC) && !defined(NO_TLS))
# define NO_TLS
#endif
/* /*
* Maximum size of L1 cache line. This is used to avoid cache line aliasing. * Maximum size of L1 cache line. This is used to avoid cache line aliasing.
* In addition, this controls the spacing of cacheline-spaced size classes. * In addition, this controls the spacing of cacheline-spaced size classes.
@@ -240,6 +235,13 @@ extern void (*JEMALLOC_P(malloc_message))(void *wcbopaque, const char *s);
#endif #endif
#include "jemalloc/internal/prof.h" #include "jemalloc/internal/prof.h"
#ifdef JEMALLOC_STATS
typedef struct {
uint64_t allocated;
uint64_t deallocated;
} thread_allocated_t;
#endif
#undef JEMALLOC_H_STRUCTS #undef JEMALLOC_H_STRUCTS
/******************************************************************************/ /******************************************************************************/
#define JEMALLOC_H_EXTERNS #define JEMALLOC_H_EXTERNS
@@ -295,45 +297,28 @@ extern arena_t **arenas;
extern unsigned narenas; extern unsigned narenas;
#ifdef JEMALLOC_STATS #ifdef JEMALLOC_STATS
typedef struct {
uint64_t allocated;
uint64_t deallocated;
} thread_allocated_t;
# ifndef NO_TLS # ifndef NO_TLS
extern __thread thread_allocated_t thread_allocated_tls; extern __thread thread_allocated_t thread_allocated_tls;
# define ALLOCATED_GET() thread_allocated_tls.allocated # define ALLOCATED_GET() (thread_allocated_tls.allocated)
# define DEALLOCATED_GET() thread_allocated_tls.deallocated # define ALLOCATEDP_GET() (&thread_allocated_tls.allocated)
# define DEALLOCATED_GET() (thread_allocated_tls.deallocated)
# define DEALLOCATEDP_GET() (&thread_allocated_tls.deallocated)
# define ALLOCATED_ADD(a, d) do { \ # define ALLOCATED_ADD(a, d) do { \
thread_allocated_tls.allocated += a; \ thread_allocated_tls.allocated += a; \
thread_allocated_tls.deallocated += d; \ thread_allocated_tls.deallocated += d; \
} while (0) } while (0)
# else # else
extern pthread_key_t thread_allocated_tsd; extern pthread_key_t thread_allocated_tsd;
# define ALLOCATED_GET() \ thread_allocated_t *thread_allocated_get_hard(void);
(uint64_t)((pthread_getspecific(thread_allocated_tsd) != NULL) \
? ((thread_allocated_t *) \ # define ALLOCATED_GET() (thread_allocated_get()->allocated)
pthread_getspecific(thread_allocated_tsd))->allocated : 0) # define ALLOCATEDP_GET() (&thread_allocated_get()->allocated)
# define DEALLOCATED_GET() \ # define DEALLOCATED_GET() (thread_allocated_get()->deallocated)
(uint64_t)((pthread_getspecific(thread_allocated_tsd) != NULL) \ # define DEALLOCATEDP_GET() (&thread_allocated_get()->deallocated)
? ((thread_allocated_t \
*)pthread_getspecific(thread_allocated_tsd))->deallocated : \
0)
# define ALLOCATED_ADD(a, d) do { \ # define ALLOCATED_ADD(a, d) do { \
thread_allocated_t *thread_allocated = (thread_allocated_t *) \ thread_allocated_t *thread_allocated = thread_allocated_get(); \
pthread_getspecific(thread_allocated_tsd); \ thread_allocated->allocated += (a); \
if (thread_allocated != NULL) { \ thread_allocated->deallocated += (d); \
thread_allocated->allocated += (a); \
thread_allocated->deallocated += (d); \
} else { \
thread_allocated = (thread_allocated_t *) \
imalloc(sizeof(thread_allocated_t)); \
if (thread_allocated != NULL) { \
pthread_setspecific(thread_allocated_tsd, \
thread_allocated); \
thread_allocated->allocated = (a); \
thread_allocated->deallocated = (d); \
} \
} \
} while (0) } while (0)
# endif # endif
#endif #endif
@@ -384,6 +369,9 @@ size_t s2u(size_t size);
size_t sa2u(size_t size, size_t alignment, size_t *run_size_p); size_t sa2u(size_t size, size_t alignment, size_t *run_size_p);
void malloc_write(const char *s); void malloc_write(const char *s);
arena_t *choose_arena(void); arena_t *choose_arena(void);
# if (defined(JEMALLOC_STATS) && defined(NO_TLS))
thread_allocated_t *thread_allocated_get(void);
# endif
#endif #endif
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_)) #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))
@@ -414,10 +402,10 @@ s2u(size_t size)
{ {
if (size <= small_maxclass) if (size <= small_maxclass)
return arenas[0]->bins[small_size2bin[size]].reg_size; return (arenas[0]->bins[small_size2bin[size]].reg_size);
if (size <= arena_maxclass) if (size <= arena_maxclass)
return PAGE_CEILING(size); return (PAGE_CEILING(size));
return CHUNK_CEILING(size); return (CHUNK_CEILING(size));
} }
/* /*
@@ -544,6 +532,19 @@ choose_arena(void)
return (ret); return (ret);
} }
#if (defined(JEMALLOC_STATS) && defined(NO_TLS))
JEMALLOC_INLINE thread_allocated_t *
thread_allocated_get(void)
{
thread_allocated_t *thread_allocated = (thread_allocated_t *)
pthread_getspecific(thread_allocated_tsd);
if (thread_allocated == NULL)
return (thread_allocated_get_hard());
return (thread_allocated);
}
#endif
#endif #endif
#include "jemalloc/internal/rtree.h" #include "jemalloc/internal/rtree.h"

View File

@@ -206,13 +206,15 @@ chunk_alloc_mmap_internal(size_t size, bool noreserve)
void * void *
chunk_alloc_mmap(size_t size) chunk_alloc_mmap(size_t size)
{ {
return chunk_alloc_mmap_internal(size, false);
return (chunk_alloc_mmap_internal(size, false));
} }
void * void *
chunk_alloc_mmap_noreserve(size_t size) chunk_alloc_mmap_noreserve(size_t size)
{ {
return chunk_alloc_mmap_internal(size, true);
return (chunk_alloc_mmap_internal(size, true));
} }
void void

View File

@@ -1114,8 +1114,8 @@ thread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
unsigned newind, oldind; unsigned newind, oldind;
newind = oldind = choose_arena()->ind; newind = oldind = choose_arena()->ind;
WRITE(oldind, unsigned); WRITE(newind, unsigned);
READ(newind, unsigned); READ(oldind, unsigned);
if (newind != oldind) { if (newind != oldind) {
arena_t *arena; arena_t *arena;
@@ -1151,9 +1151,9 @@ RETURN:
#ifdef JEMALLOC_STATS #ifdef JEMALLOC_STATS
CTL_RO_NL_GEN(thread_allocated, ALLOCATED_GET(), uint64_t); CTL_RO_NL_GEN(thread_allocated, ALLOCATED_GET(), uint64_t);
CTL_RO_NL_GEN(thread_allocatedp, &ALLOCATED_GET(), uint64_t *); CTL_RO_NL_GEN(thread_allocatedp, ALLOCATEDP_GET(), uint64_t *);
CTL_RO_NL_GEN(thread_deallocated, DEALLOCATED_GET(), uint64_t); CTL_RO_NL_GEN(thread_deallocated, DEALLOCATED_GET(), uint64_t);
CTL_RO_NL_GEN(thread_deallocatedp, &DEALLOCATED_GET(), uint64_t *); CTL_RO_NL_GEN(thread_deallocatedp, DEALLOCATEDP_GET(), uint64_t *);
#endif #endif
/******************************************************************************/ /******************************************************************************/

View File

@@ -213,6 +213,28 @@ stats_print_atexit(void)
JEMALLOC_P(malloc_stats_print)(NULL, NULL, NULL); JEMALLOC_P(malloc_stats_print)(NULL, NULL, NULL);
} }
#if (defined(JEMALLOC_STATS) && defined(NO_TLS))
thread_allocated_t *
thread_allocated_get_hard(void)
{
thread_allocated_t *thread_allocated = (thread_allocated_t *)
imalloc(sizeof(thread_allocated_t));
if (thread_allocated == NULL) {
static thread_allocated_t static_thread_allocated = {0, 0};
malloc_write("<jemalloc>: Error allocating TSD;"
" mallctl(\"thread.{de,}allocated[p]\", ...)"
" will be inaccurate\n");
if (opt_abort)
abort();
return (&static_thread_allocated);
}
pthread_setspecific(thread_allocated_tsd, thread_allocated);
thread_allocated->allocated = 0;
thread_allocated->deallocated = 0;
return (thread_allocated);
}
#endif
/* /*
* End miscellaneous support functions. * End miscellaneous support functions.
*/ */

View File

@@ -58,6 +58,9 @@ tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem
void *flush, *deferred, *ptr; void *flush, *deferred, *ptr;
unsigned i, nflush, ndeferred; unsigned i, nflush, ndeferred;
bool first_pass; bool first_pass;
#ifdef JEMALLOC_STATS
bool merged_stats = false;
#endif
assert(binind < nbins); assert(binind < nbins);
assert(rem <= tbin->ncached); assert(rem <= tbin->ncached);
@@ -82,6 +85,8 @@ tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem
malloc_mutex_lock(&bin->lock); malloc_mutex_lock(&bin->lock);
#ifdef JEMALLOC_STATS #ifdef JEMALLOC_STATS
if (arena == tcache->arena) { if (arena == tcache->arena) {
assert(merged_stats == false);
merged_stats = true;
bin->stats.nflushes++; bin->stats.nflushes++;
bin->stats.nrequests += tbin->tstats.nrequests; bin->stats.nrequests += tbin->tstats.nrequests;
tbin->tstats.nrequests = 0; tbin->tstats.nrequests = 0;
@@ -119,6 +124,20 @@ tcache_bin_flush_small(tcache_bin_t *tbin, size_t binind, unsigned rem
first_pass = false; first_pass = false;
} }
} }
#ifdef JEMALLOC_STATS
if (merged_stats == false) {
/*
* The flush loop didn't happen to flush to this thread's
* arena, so the stats didn't get merged. Manually do so now.
*/
arena_bin_t *bin = &tcache->arena->bins[binind];
malloc_mutex_lock(&bin->lock);
bin->stats.nflushes++;
bin->stats.nrequests += tbin->tstats.nrequests;
tbin->tstats.nrequests = 0;
malloc_mutex_unlock(&bin->lock);
}
#endif
tbin->ncached = rem; tbin->ncached = rem;
if (tbin->ncached < tbin->low_water) if (tbin->ncached < tbin->low_water)

View File

@@ -16,6 +16,7 @@ thread_start(void *arg)
int err; int err;
void *p; void *p;
uint64_t a0, a1, d0, d1; uint64_t a0, a1, d0, d1;
uint64_t *ap0, *ap1, *dp0, *dp1;
size_t sz, usize; size_t sz, usize;
sz = sizeof(a0); sz = sizeof(a0);
@@ -31,6 +32,20 @@ thread_start(void *arg)
strerror(err)); strerror(err));
exit(1); exit(1);
} }
sz = sizeof(ap0);
if ((err = JEMALLOC_P(mallctl)("thread.allocatedp", &ap0, &sz, NULL,
0))) {
if (err == ENOENT) {
#ifdef JEMALLOC_STATS
assert(false);
#endif
goto RETURN;
}
fprintf(stderr, "%s(): Error in mallctl(): %s\n", __func__,
strerror(err));
exit(1);
}
assert(*ap0 == a0);
sz = sizeof(d0); sz = sizeof(d0);
if ((err = JEMALLOC_P(mallctl)("thread.deallocated", &d0, &sz, NULL, if ((err = JEMALLOC_P(mallctl)("thread.deallocated", &d0, &sz, NULL,
@@ -45,6 +60,20 @@ thread_start(void *arg)
strerror(err)); strerror(err));
exit(1); exit(1);
} }
sz = sizeof(dp0);
if ((err = JEMALLOC_P(mallctl)("thread.deallocatedp", &dp0, &sz, NULL,
0))) {
if (err == ENOENT) {
#ifdef JEMALLOC_STATS
assert(false);
#endif
goto RETURN;
}
fprintf(stderr, "%s(): Error in mallctl(): %s\n", __func__,
strerror(err));
exit(1);
}
assert(*dp0 == d0);
p = JEMALLOC_P(malloc)(1); p = JEMALLOC_P(malloc)(1);
if (p == NULL) { if (p == NULL) {
@@ -54,6 +83,10 @@ thread_start(void *arg)
sz = sizeof(a1); sz = sizeof(a1);
JEMALLOC_P(mallctl)("thread.allocated", &a1, &sz, NULL, 0); JEMALLOC_P(mallctl)("thread.allocated", &a1, &sz, NULL, 0);
sz = sizeof(ap1);
JEMALLOC_P(mallctl)("thread.allocatedp", &ap1, &sz, NULL, 0);
assert(*ap1 == a1);
assert(ap0 == ap1);
usize = JEMALLOC_P(malloc_usable_size)(p); usize = JEMALLOC_P(malloc_usable_size)(p);
assert(a0 + usize <= a1); assert(a0 + usize <= a1);
@@ -62,6 +95,10 @@ thread_start(void *arg)
sz = sizeof(d1); sz = sizeof(d1);
JEMALLOC_P(mallctl)("thread.deallocated", &d1, &sz, NULL, 0); JEMALLOC_P(mallctl)("thread.deallocated", &d1, &sz, NULL, 0);
sz = sizeof(dp1);
JEMALLOC_P(mallctl)("thread.deallocatedp", &dp1, &sz, NULL, 0);
assert(*dp1 == d1);
assert(dp0 == dp1);
assert(d0 + usize <= d1); assert(d0 + usize <= d1);

View File

@@ -2,10 +2,13 @@
#include <stdlib.h> #include <stdlib.h>
#include <pthread.h> #include <pthread.h>
#include <string.h> #include <string.h>
#include <assert.h>
#define JEMALLOC_MANGLE #define JEMALLOC_MANGLE
#include "jemalloc_test.h" #include "jemalloc_test.h"
#define NTHREADS 10
void * void *
thread_start(void *arg) thread_start(void *arg)
{ {
@@ -29,6 +32,15 @@ thread_start(void *arg)
return (void *)1; return (void *)1;
} }
size = sizeof(arena_ind);
if ((err = JEMALLOC_P(mallctl)("thread.arena", &arena_ind, &size, NULL,
0))) {
fprintf(stderr, "%s(): Error in mallctl(): %s\n", __func__,
strerror(err));
return (void *)1;
}
assert(arena_ind == main_arena_ind);
return (NULL); return (NULL);
} }
@@ -40,7 +52,8 @@ main(void)
unsigned arena_ind; unsigned arena_ind;
size_t size; size_t size;
int err; int err;
pthread_t thread; pthread_t threads[NTHREADS];
unsigned i;
fprintf(stderr, "Test begin\n"); fprintf(stderr, "Test begin\n");
@@ -60,21 +73,18 @@ main(void)
goto RETURN; goto RETURN;
} }
if (pthread_create(&thread, NULL, thread_start, (void *)&arena_ind) for (i = 0; i < NTHREADS; i++) {
!= 0) { if (pthread_create(&threads[i], NULL, thread_start,
fprintf(stderr, "%s(): Error in pthread_create()\n", __func__); (void *)&arena_ind) != 0) {
ret = 1; fprintf(stderr, "%s(): Error in pthread_create()\n",
goto RETURN; __func__);
ret = 1;
goto RETURN;
}
} }
pthread_join(thread, (void *)&ret);
if (pthread_create(&thread, NULL, thread_start, (void *)&arena_ind) for (i = 0; i < NTHREADS; i++)
!= 0) { pthread_join(threads[i], (void *)&ret);
fprintf(stderr, "%s(): Error in pthread_create()\n", __func__);
ret = 1;
goto RETURN;
}
pthread_join(thread, (void *)&ret);
RETURN: RETURN:
fprintf(stderr, "Test end\n"); fprintf(stderr, "Test end\n");