summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--jemalloc/Makefile.in50
-rw-r--r--jemalloc/configure.ac5
-rw-r--r--jemalloc/doc/jemalloc.3.in13
-rw-r--r--jemalloc/src/ctl.c52
-rw-r--r--jemalloc/test/thread_arena.c69
-rw-r--r--jemalloc/test/thread_arena.exp2
7 files changed, 191 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index d9e49f8..8e95c7a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,4 +12,6 @@
/jemalloc/src/jemalloc\.h
/jemalloc/src/jemalloc_defs\.h
/jemalloc/src/*.[od]
+/jemalloc/test/*.[od]
+/jemalloc/test/*.out
/jemalloc/VERSION
diff --git a/jemalloc/Makefile.in b/jemalloc/Makefile.in
index ac9b782..a7acc96 100644
--- a/jemalloc/Makefile.in
+++ b/jemalloc/Makefile.in
@@ -47,6 +47,10 @@ DSOS := @objroot@lib/libjemalloc@install_suffix@.so.$(REV) \
@objroot@lib/libjemalloc@install_suffix@.so \
@objroot@lib/libjemalloc@install_suffix@_pic.a
MAN3 := @objroot@doc/jemalloc@install_suffix@.3
+CTESTS :=
+ifeq (1, @enable_tls@)
+CTESTS += @srcroot@test/thread_arena.c
+endif
.PHONY: all dist install check clean distclean relclean
@@ -69,12 +73,22 @@ all: $(DSOS)
@objroot@lib/libjemalloc@install_suffix@.so.$(REV) : $(CSRCS:@srcroot@%.c=@objroot@%.o)
@mkdir -p $(@D)
- $(CC) -shared -Wl,-soname,$(@F) -o $@ $+ $(LDFLAGS) $(LIBS)
+ $(CC) -shared -Wl,-soname,$(@F) $(RPATH_EXTRA:%=@RPATH@%) -o $@ $+ $(LDFLAGS) $(LIBS)
@objroot@lib/libjemalloc@install_suffix@_pic.a : $(CSRCS:@srcroot@%.c=@objroot@%.o)
@mkdir -p $(@D)
ar crus $@ $+
+@objroot@test/%.o: @srcroot@test/%.c
+ @mkdir -p $(@D)
+ $(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)"
+
+@objroot@test/%: @objroot@test/%.o \
+ @objroot@lib/libjemalloc@install_suffix@.so
+ @mkdir -p $(@D)
+ $(CC) -o $@ $< @RPATH@@objroot@lib -L@objroot@lib -ljemalloc
+
install_bin:
install -d $(BINDIR)
@for b in $(BINS); do \
@@ -104,11 +118,43 @@ done
install: install_bin install_include install_lib install_man
-check:
+tests: $(CTESTS:@srcroot@%.c=@objroot@%)
+
+check: tests
+ @mkdir -p @objroot@test
+ @$(SHELL) -c 'total=0; \
+ failures=0; \
+ echo "========================================="; \
+ for t in $(CTESTS:@srcroot@%.c=@objroot@%); do \
+ total=`expr $$total + 1`; \
+ /bin/echo -n "$${t} ... "; \
+ $${t} @abs_srcroot@ @abs_objroot@ \
+ > @objroot@$${t}.out 2>&1; \
+ if test -e "@srcroot@$${t}.exp"; then \
+ diff -u @srcroot@$${t}.exp \
+ @objroot@$${t}.out >/dev/null 2>&1; \
+ fail=$$?; \
+ if test "$${fail}" -eq "1" ; then \
+ failures=`expr $${failures} + 1`; \
+ echo "*** FAIL ***"; \
+ else \
+ echo "pass"; \
+ fi; \
+ else \
+ echo "*** FAIL *** (.exp file is missing)"; \
+ failures=`expr $${failures} + 1`; \
+ fi; \
+ done; \
+ echo "========================================="; \
+ echo "Failures: $${failures}/$${total}"'
clean:
rm -f $(CSRCS:@srcroot@%.c=@objroot@%.o)
rm -f $(CSRCS:@srcroot@%.c=@objroot@%.d)
+ rm -f $(CTESTS:@srcroot@%.c=@objroot@%)
+ rm -f $(CTESTS:@srcroot@%.c=@objroot@%.o)
+ rm -f $(CTESTS:@srcroot@%.c=@objroot@%.d)
+ rm -f $(CTESTS:@srcroot@%.c=@objroot@%.out)
rm -f $(DSOS)
distclean: clean
diff --git a/jemalloc/configure.ac b/jemalloc/configure.ac
index ce6e679..bf16596 100644
--- a/jemalloc/configure.ac
+++ b/jemalloc/configure.ac
@@ -647,9 +647,14 @@ AC_RUN_IFELSE([AC_LANG_PROGRAM(
AC_MSG_RESULT([no])
enable_tls="0")
fi
+AC_SUBST([enable_tls])
if test "x${enable_tls}" = "x0" ; then
AC_DEFINE_UNQUOTED([NO_TLS], [ ])
+ roff_tls=".\\\" "
+else
+ roff_tls=""
fi
+AC_SUBST([roff_tls])
dnl Finish tcache-related definitions, now that TLS configuration is done.
if test "x$enable_tls" = "x0" ; then
diff --git a/jemalloc/doc/jemalloc.3.in b/jemalloc/doc/jemalloc.3.in
index cf5cb5e..d2d5b77 100644
--- a/jemalloc/doc/jemalloc.3.in
+++ b/jemalloc/doc/jemalloc.3.in
@@ -669,6 +669,19 @@ This is useful for detecting whether another thread caused a refresh.
@roff_tcache@find manual flushing useful.
.Ed
.\"-----------------------------------------------------------------------------
+@roff_tls@.It Sy "thread.arena (unsigned) rw"
+@roff_tls@.Bd -ragged -offset indent -compact
+@roff_tls@Get or set the arena associated with the calling thread.
+@roff_tls@The arena index must be less than the maximum number of arenas (see
+@roff_tls@the
+@roff_tls@.Dq arenas.narenas
+@roff_tls@mallctl).
+@roff_tls@If the specified arena was not initialized beforehand (see the
+@roff_tls@.Dq arenas.initialized
+@roff_tls@mallctl), it will be automatically initialized as a side effect of
+@roff_tls@calling this interface.
+@roff_tls@.Ed
+.\"-----------------------------------------------------------------------------
.It Sy "config.debug (bool) r-"
.Bd -ragged -offset indent -compact
--enable-debug was specified during build configuration.
diff --git a/jemalloc/src/ctl.c b/jemalloc/src/ctl.c
index ffb732d..128883f 100644
--- a/jemalloc/src/ctl.c
+++ b/jemalloc/src/ctl.c
@@ -41,6 +41,9 @@ CTL_PROTO(epoch)
#ifdef JEMALLOC_TCACHE
CTL_PROTO(tcache_flush)
#endif
+#ifndef NO_TLS
+CTL_PROTO(thread_arena)
+#endif
CTL_PROTO(config_debug)
CTL_PROTO(config_dss)
CTL_PROTO(config_dynamic_page_shift)
@@ -210,6 +213,12 @@ static const ctl_node_t tcache_node[] = {
};
#endif
+#ifndef NO_TLS
+static const ctl_node_t thread_node[] = {
+ {NAME("arena"), CTL(thread_arena)}
+};
+#endif
+
static const ctl_node_t config_node[] = {
{NAME("debug"), CTL(config_debug)},
{NAME("dss"), CTL(config_dss)},
@@ -448,6 +457,9 @@ static const ctl_node_t root_node[] = {
#ifdef JEMALLOC_TCACHE
{NAME("tcache"), CHILD(tcache)},
#endif
+#ifndef NO_TLS
+ {NAME("thread"), CHILD(thread)},
+#endif
{NAME("config"), CHILD(config)},
{NAME("opt"), CHILD(opt)},
{NAME("arenas"), CHILD(arenas)},
@@ -1042,6 +1054,46 @@ RETURN:
}
#endif
+#ifndef NO_TLS
+static int
+thread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
+ void *newp, size_t newlen)
+{
+ int ret;
+ unsigned newind, oldind;
+
+ newind = oldind = choose_arena()->ind;
+ WRITE(oldind, unsigned);
+ READ(newind, unsigned);
+ if (newind != oldind) {
+ arena_t *arena;
+
+ if (newind >= narenas) {
+ /* New arena index is out of range. */
+ ret = EFAULT;
+ goto RETURN;
+ }
+
+ /* Initialize arena if necessary. */
+ malloc_mutex_lock(&arenas_lock);
+ if ((arena = arenas[newind]) == NULL)
+ arena = arenas_extend(newind);
+ malloc_mutex_unlock(&arenas_lock);
+ if (arena == NULL) {
+ ret = EAGAIN;
+ goto RETURN;
+ }
+
+ /* Set new arena association. */
+ arenas_map = arena;
+ }
+
+ ret = 0;
+RETURN:
+ return (ret);
+}
+#endif
+
/******************************************************************************/
#ifdef JEMALLOC_DEBUG
diff --git a/jemalloc/test/thread_arena.c b/jemalloc/test/thread_arena.c
new file mode 100644
index 0000000..99e9669
--- /dev/null
+++ b/jemalloc/test/thread_arena.c
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <string.h>
+
+#include "jemalloc/jemalloc.h"
+
+void *
+thread_start(void *arg)
+{
+ unsigned main_arena_ind = *(unsigned *)arg;
+ unsigned arena_ind;
+ size_t size;
+ int err;
+
+ malloc(1);
+
+ size = sizeof(arena_ind);
+ if ((err = mallctl("thread.arena", &arena_ind, &size,
+ &main_arena_ind, sizeof(main_arena_ind)))) {
+ fprintf(stderr, "%s(): Error in mallctl(): %s\n", __func__,
+ strerror(err));
+ return (void *)1;
+ }
+
+ return (NULL);
+}
+
+int
+main(void)
+{
+ int ret = 0;
+ unsigned arena_ind;
+ size_t size;
+ int err;
+ pthread_t thread;
+
+ fprintf(stderr, "Test begin\n");
+
+ malloc(1);
+
+ size = sizeof(arena_ind);
+ if ((err = mallctl("thread.arena", &arena_ind, &size, NULL, 0))) {
+ fprintf(stderr, "%s(): Error in mallctl(): %s\n", __func__,
+ strerror(err));
+ ret = 1;
+ goto RETURN;
+ }
+
+ if (pthread_create(&thread, NULL, thread_start, (void *)&arena_ind)
+ != 0) {
+ fprintf(stderr, "%s(): Error in pthread_create()\n", __func__);
+ ret = 1;
+ goto RETURN;
+ }
+ pthread_join(thread, (void *)&ret);
+
+ if (pthread_create(&thread, NULL, thread_start, (void *)&arena_ind)
+ != 0) {
+ fprintf(stderr, "%s(): Error in pthread_create()\n", __func__);
+ ret = 1;
+ goto RETURN;
+ }
+ pthread_join(thread, (void *)&ret);
+
+RETURN:
+ fprintf(stderr, "Test end\n");
+ return (ret);
+}
diff --git a/jemalloc/test/thread_arena.exp b/jemalloc/test/thread_arena.exp
new file mode 100644
index 0000000..369a88d
--- /dev/null
+++ b/jemalloc/test/thread_arena.exp
@@ -0,0 +1,2 @@
+Test begin
+Test end