summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Evans <je@fb.com>2013-12-12 22:41:02 (GMT)
committerJason Evans <je@fb.com>2013-12-12 22:41:02 (GMT)
commit0f4f1efd94d33a4bbf766d3d4e7e349fa7c0d3b9 (patch)
tree8880cd7c807260d0e585ca1b1c263342758d9574
parent19609724f9dce1ac644b6cbf89acb740319eb498 (diff)
downloadjemalloc-0f4f1efd94d33a4bbf766d3d4e7e349fa7c0d3b9.zip
jemalloc-0f4f1efd94d33a4bbf766d3d4e7e349fa7c0d3b9.tar.gz
jemalloc-0f4f1efd94d33a4bbf766d3d4e7e349fa7c0d3b9.tar.bz2
Add mq (message queue) to test infrastructure.
Add mtx (mutex) to test infrastructure, in order to avoid bootstrapping complications that would result from directly using malloc_mutex. Rename test infrastructure's thread abstraction from je_thread to thd. Fix some header ordering issues.
-rw-r--r--Makefile.in6
-rw-r--r--include/jemalloc/internal/hash.h10
-rw-r--r--include/jemalloc/internal/jemalloc_internal_defs.h.in4
-rw-r--r--include/jemalloc/internal/tsd.h2
-rw-r--r--test/include/test/jemalloc_test.h.in16
-rw-r--r--test/include/test/jemalloc_test_defs.h.in2
-rw-r--r--test/include/test/mq.h110
-rw-r--r--test/include/test/mtx.h21
-rw-r--r--test/include/test/thd.h9
-rw-r--r--test/include/test/thread.h9
-rw-r--r--test/integration/ALLOCM_ARENA.c8
-rw-r--r--test/integration/allocated.c10
-rw-r--r--test/integration/jemalloc_integration.h.in50
-rw-r--r--test/integration/thread_arena.c8
-rw-r--r--test/integration/thread_tcache_enabled.c10
-rw-r--r--test/src/mtx.c62
-rw-r--r--test/src/thd.c35
-rw-r--r--test/src/thread.c35
-rw-r--r--test/unit/mq.c91
-rw-r--r--test/unit/mtx.c60
-rw-r--r--test/unit/tsd.c14
21 files changed, 441 insertions, 131 deletions
diff --git a/Makefile.in b/Makefile.in
index 7855443..cd137fd 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -103,10 +103,12 @@ DOCS_XML := $(objroot)doc/jemalloc$(install_suffix).xml
DOCS_HTML := $(DOCS_XML:$(objroot)%.xml=$(srcroot)%.html)
DOCS_MAN3 := $(DOCS_XML:$(objroot)%.xml=$(srcroot)%.3)
DOCS := $(DOCS_HTML) $(DOCS_MAN3)
-C_TESTLIB_SRCS := $(srcroot)test/src/math.c $(srcroot)test/src/SFMT.c \
- $(srcroot)test/src/test.c $(srcroot)test/src/thread.c
+C_TESTLIB_SRCS := $(srcroot)test/src/math.c $(srcroot)test/src/mtx.c \
+ $(srcroot)test/src/SFMT.c $(srcroot)test/src/test.c \
+ $(srcroot)test/src/thd.c
C_UTIL_INTEGRATION_SRCS := $(srcroot)src/util.c
TESTS_UNIT := $(srcroot)test/unit/bitmap.c $(srcroot)test/unit/math.c \
+ $(srcroot)test/unit/mq.c $(srcroot)test/unit/mtx.c \
$(srcroot)test/unit/SFMT.c $(srcroot)test/unit/tsd.c
TESTS_INTEGRATION := $(srcroot)test/integration/aligned_alloc.c \
$(srcroot)test/integration/allocated.c \
diff --git a/include/jemalloc/internal/hash.h b/include/jemalloc/internal/hash.h
index 56ecc79..6b8d9cd 100644
--- a/include/jemalloc/internal/hash.h
+++ b/include/jemalloc/internal/hash.h
@@ -43,14 +43,14 @@ JEMALLOC_INLINE uint32_t
hash_get_block_32(const uint32_t *p, int i)
{
- return p[i];
+ return (p[i]);
}
JEMALLOC_INLINE uint64_t
hash_get_block_64(const uint64_t *p, int i)
{
- return p[i];
+ return (p[i]);
}
JEMALLOC_INLINE uint32_t
@@ -63,7 +63,7 @@ hash_fmix_32(uint32_t h)
h *= 0xc2b2ae35;
h ^= h >> 16;
- return h;
+ return (h);
}
JEMALLOC_INLINE uint64_t
@@ -76,7 +76,7 @@ hash_fmix_64(uint64_t k)
k *= QU(0xc4ceb9fe1a85ec53LLU);
k ^= k >> 33;
- return k;
+ return (k);
}
JEMALLOC_INLINE uint32_t
@@ -127,7 +127,7 @@ hash_x86_32(const void *key, int len, uint32_t seed)
h1 = hash_fmix_32(h1);
- return h1;
+ return (h1);
}
UNUSED JEMALLOC_INLINE void
diff --git a/include/jemalloc/internal/jemalloc_internal_defs.h.in b/include/jemalloc/internal/jemalloc_internal_defs.h.in
index 3b72b35..752bb10 100644
--- a/include/jemalloc/internal/jemalloc_internal_defs.h.in
+++ b/include/jemalloc/internal/jemalloc_internal_defs.h.in
@@ -1,3 +1,5 @@
+#ifndef JEMALLOC_INTERNAL_DEFS_H_
+#define JEMALLOC_INTERNAL_DEFS_H_
/*
* If JEMALLOC_PREFIX is defined via --with-jemalloc-prefix, it will cause all
* public APIs to be prefixed. This makes it possible, with some care, to use
@@ -193,3 +195,5 @@
/* sizeof(intmax_t) == 2^LG_SIZEOF_INTMAX_T. */
#undef LG_SIZEOF_INTMAX_T
+
+#endif /* JEMALLOC_INTERNAL_DEFS_H_ */
diff --git a/include/jemalloc/internal/tsd.h b/include/jemalloc/internal/tsd.h
index 5f7ad1c..9fb4a23 100644
--- a/include/jemalloc/internal/tsd.h
+++ b/include/jemalloc/internal/tsd.h
@@ -348,7 +348,7 @@ a_name##_tsd_get_wrapper(void) \
wrapper = tsd_init_check_recursion( \
&a_name##_tsd_init_head, &block); \
if (wrapper) \
- return wrapper; \
+ return (wrapper); \
wrapper = (a_name##_tsd_wrapper_t *) \
malloc_tsd_malloc(sizeof(a_name##_tsd_wrapper_t)); \
block.data = wrapper; \
diff --git a/test/include/test/jemalloc_test.h.in b/test/include/test/jemalloc_test.h.in
index 9743cd5..9f7dfa4 100644
--- a/test/include/test/jemalloc_test.h.in
+++ b/test/include/test/jemalloc_test.h.in
@@ -1,8 +1,10 @@
#include <stdlib.h>
+#include <stdarg.h>
#include <stdbool.h>
-#include <string.h>
+#include <errno.h>
#include <inttypes.h>
#include <math.h>
+#include <string.h>
#ifdef _WIN32
# include <windows.h>
@@ -45,6 +47,10 @@
#include "test/jemalloc_test_defs.h"
+#ifdef JEMALLOC_OSSPIN
+# include <libkern/OSAtomic.h>
+#endif
+
#if defined(HAVE_ALTIVEC) && !defined(__APPLE__)
# include <altivec.h>
#endif
@@ -75,13 +81,13 @@
# define JEMALLOC_N(n) @private_namespace@##n
# include "jemalloc/internal/private_namespace.h"
-# include <stdarg.h>
-# include <errno.h>
# define JEMALLOC_H_TYPES
# define JEMALLOC_H_STRUCTS
# define JEMALLOC_H_EXTERNS
# define JEMALLOC_H_INLINES
# include "jemalloc/internal/util.h"
+# include "jemalloc/internal/qr.h"
+# include "jemalloc/internal/ql.h"
# undef JEMALLOC_H_TYPES
# undef JEMALLOC_H_STRUCTS
# undef JEMALLOC_H_EXTERNS
@@ -124,7 +130,9 @@
* Common test utilities.
*/
#include "test/math.h"
+#include "test/mtx.h"
+#include "test/mq.h"
#include "test/test.h"
-#include "test/thread.h"
+#include "test/thd.h"
#define MEXP 19937
#include "test/SFMT.h"
diff --git a/test/include/test/jemalloc_test_defs.h.in b/test/include/test/jemalloc_test_defs.h.in
index 093e2f2..18a9773 100644
--- a/test/include/test/jemalloc_test_defs.h.in
+++ b/test/include/test/jemalloc_test_defs.h.in
@@ -1,3 +1,5 @@
+#include "jemalloc/internal/jemalloc_internal_defs.h"
+
/* For use by SFMT. */
#undef HAVE_SSE2
#undef HAVE_ALTIVEC
diff --git a/test/include/test/mq.h b/test/include/test/mq.h
new file mode 100644
index 0000000..1118865
--- /dev/null
+++ b/test/include/test/mq.h
@@ -0,0 +1,110 @@
+/*
+ * Simple templated message queue implementation that relies on only mutexes for
+ * synchronization (which reduces portability issues). Given the following
+ * setup:
+ *
+ * typedef struct mq_msg_s mq_msg_t;
+ * struct mq_msg_s {
+ * mq_msg(mq_msg_t) link;
+ * [message data]
+ * };
+ * mq_gen(, mq_, mq_t, mq_msg_t, link)
+ *
+ * The API is as follows:
+ *
+ * bool mq_init(mq_t *mq);
+ * void mq_fini(mq_t *mq);
+ * unsigned mq_count(mq_t *mq);
+ * mq_msg_t *mq_tryget(mq_t *mq);
+ * mq_msg_t *mq_get(mq_t *mq);
+ * void mq_put(mq_t *mq, mq_msg_t *msg);
+ *
+ * The message queue linkage embedded in each message is to be treated as
+ * externally opaque (no need to initialize or clean up externally). mq_fini()
+ * does not perform any cleanup of messages, since it knows nothing of their
+ * payloads.
+ */
+#define mq_msg(a_mq_msg_type) ql_elm(a_mq_msg_type)
+
+#define mq_gen(a_attr, a_prefix, a_mq_type, a_mq_msg_type, a_field) \
+typedef struct { \
+ mtx_t lock; \
+ ql_head(a_mq_msg_type) msgs; \
+ unsigned count; \
+} a_mq_type; \
+a_attr bool \
+a_prefix##init(a_mq_type *mq) { \
+ \
+ if (mtx_init(&mq->lock)) \
+ return (true); \
+ ql_new(&mq->msgs); \
+ mq->count = 0; \
+ return (false); \
+} \
+a_attr void \
+a_prefix##fini(a_mq_type *mq) \
+{ \
+ \
+ mtx_fini(&mq->lock); \
+} \
+a_attr unsigned \
+a_prefix##count(a_mq_type *mq) \
+{ \
+ unsigned count; \
+ \
+ mtx_lock(&mq->lock); \
+ count = mq->count; \
+ mtx_unlock(&mq->lock); \
+ return (count); \
+} \
+a_attr a_mq_msg_type * \
+a_prefix##tryget(a_mq_type *mq) \
+{ \
+ a_mq_msg_type *msg; \
+ \
+ mtx_lock(&mq->lock); \
+ msg = ql_first(&mq->msgs); \
+ if (msg != NULL) { \
+ ql_head_remove(&mq->msgs, a_mq_msg_type, a_field); \
+ mq->count--; \
+ } \
+ mtx_unlock(&mq->lock); \
+ return (msg); \
+} \
+a_attr a_mq_msg_type * \
+a_prefix##get(a_mq_type *mq) \
+{ \
+ a_mq_msg_type *msg; \
+ struct timespec timeout; \
+ \
+ msg = a_prefix##tryget(mq); \
+ if (msg != NULL) \
+ return (msg); \
+ \
+ timeout.tv_sec = 0; \
+ timeout.tv_nsec = 1; \
+ while (true) { \
+ nanosleep(&timeout, NULL); \
+ msg = a_prefix##tryget(mq); \
+ if (msg != NULL) \
+ return (msg); \
+ if (timeout.tv_sec == 0) { \
+ /* 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; \
+ } \
+ } \
+ } \
+} \
+a_attr void \
+a_prefix##put(a_mq_type *mq, a_mq_msg_type *msg) \
+{ \
+ \
+ mtx_lock(&mq->lock); \
+ ql_elm_new(msg, a_field); \
+ ql_tail_insert(&mq->msgs, msg, a_field); \
+ mq->count++; \
+ mtx_unlock(&mq->lock); \
+}
diff --git a/test/include/test/mtx.h b/test/include/test/mtx.h
new file mode 100644
index 0000000..bbe822f
--- /dev/null
+++ b/test/include/test/mtx.h
@@ -0,0 +1,21 @@
+/*
+ * mtx is a slightly simplified version of malloc_mutex. This code duplication
+ * is unfortunate, but there are allocator bootstrapping considerations that
+ * would leak into the test infrastructure if malloc_mutex were used directly
+ * in tests.
+ */
+
+typedef struct {
+#ifdef _WIN32
+ CRITICAL_SECTION lock;
+#elif (defined(JEMALLOC_OSSPIN))
+ OSSpinLock lock;
+#else
+ pthread_mutex_t lock;
+#endif
+} mtx_t;
+
+bool mtx_init(mtx_t *mtx);
+void mtx_fini(mtx_t *mtx);
+void mtx_lock(mtx_t *mtx);
+void mtx_unlock(mtx_t *mtx);
diff --git a/test/include/test/thd.h b/test/include/test/thd.h
new file mode 100644
index 0000000..f941d7a
--- /dev/null
+++ b/test/include/test/thd.h
@@ -0,0 +1,9 @@
+/* Abstraction layer for threading in tests */
+#ifdef _WIN32
+typedef HANDLE thd_t;
+#else
+typedef pthread_t thd_t;
+#endif
+
+void thd_create(thd_t *thd, void *(*proc)(void *), void *arg);
+void thd_join(thd_t thd, void **ret);
diff --git a/test/include/test/thread.h b/test/include/test/thread.h
deleted file mode 100644
index 3b02a01..0000000
--- a/test/include/test/thread.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* Abstraction layer for threading in tests */
-#ifdef _WIN32
-typedef HANDLE je_thread_t;
-#else
-typedef pthread_t je_thread_t;
-#endif
-
-void je_thread_create(je_thread_t *thread, void *(*proc)(void *), void *arg);
-void je_thread_join(je_thread_t thread, void **ret);
diff --git a/test/integration/ALLOCM_ARENA.c b/test/integration/ALLOCM_ARENA.c
index ec91c59..5bf3c4a 100644
--- a/test/integration/ALLOCM_ARENA.c
+++ b/test/integration/ALLOCM_ARENA.c
@@ -3,7 +3,7 @@
#define NTHREADS 10
void *
-je_thread_start(void *arg)
+thd_start(void *arg)
{
unsigned thread_ind = (unsigned)(uintptr_t)arg;
unsigned arena_ind;
@@ -36,16 +36,16 @@ je_thread_start(void *arg)
TEST_BEGIN(test_ALLOCM_ARENA)
{
- je_thread_t threads[NTHREADS];
+ thd_t thds[NTHREADS];
unsigned i;
for (i = 0; i < NTHREADS; i++) {
- je_thread_create(&threads[i], je_thread_start,
+ thd_create(&thds[i], thd_start,
(void *)(uintptr_t)i);
}
for (i = 0; i < NTHREADS; i++)
- je_thread_join(threads[i], NULL);
+ thd_join(thds[i], NULL);
}
TEST_END
diff --git a/test/integration/allocated.c b/test/integration/allocated.c
index 156451d..3630e80 100644
--- a/test/integration/allocated.c
+++ b/test/integration/allocated.c
@@ -9,7 +9,7 @@ static const bool config_stats =
;
void *
-je_thread_start(void *arg)
+thd_start(void *arg)
{
int err;
void *p;
@@ -98,16 +98,16 @@ label_ENOENT:
TEST_BEGIN(test_main_thread)
{
- je_thread_start(NULL);
+ thd_start(NULL);
}
TEST_END
TEST_BEGIN(test_subthread)
{
- je_thread_t thread;
+ thd_t thd;
- je_thread_create(&thread, je_thread_start, NULL);
- je_thread_join(thread, NULL);
+ thd_create(&thd, thd_start, NULL);
+ thd_join(thd, NULL);
}
TEST_END
diff --git a/test/integration/jemalloc_integration.h.in b/test/integration/jemalloc_integration.h.in
deleted file mode 100644
index 4730aab..0000000
--- a/test/integration/jemalloc_integration.h.in
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * This header should be included by tests, rather than directly including
- * jemalloc/jemalloc.h, because --with-install-suffix may cause the header to
- * have a different name.
- */
-#include "jemalloc/jemalloc@install_suffix@.h"
-#include "jemalloc/internal/jemalloc_internal.h"
-
-/* Abstraction layer for threading in tests. */
-#ifdef _WIN32
-#include <windows.h>
-
-typedef HANDLE je_thread_t;
-
-void
-je_thread_create(je_thread_t *thread, void *(*proc)(void *), void *arg)
-{
- LPTHREAD_START_ROUTINE routine = (LPTHREAD_START_ROUTINE)proc;
- *thread = CreateThread(NULL, 0, routine, arg, 0, NULL);
- if (*thread == NULL)
- test_fail("Error in CreateThread()\n");
-}
-
-void
-je_thread_join(je_thread_t thread, void **ret)
-{
-
- WaitForSingleObject(thread, INFINITE);
-}
-
-#else
-#include <pthread.h>
-
-typedef pthread_t je_thread_t;
-
-void
-je_thread_create(je_thread_t *thread, void *(*proc)(void *), void *arg)
-{
-
- if (pthread_create(thread, NULL, proc, arg) != 0)
- test_fail("Error in pthread_create()\n");
-}
-
-void
-je_thread_join(je_thread_t thread, void **ret)
-{
-
- pthread_join(thread, ret);
-}
-#endif
diff --git a/test/integration/thread_arena.c b/test/integration/thread_arena.c
index cf0aad7..67be535 100644
--- a/test/integration/thread_arena.c
+++ b/test/integration/thread_arena.c
@@ -3,7 +3,7 @@
#define NTHREADS 10
void *
-je_thread_start(void *arg)
+thd_start(void *arg)
{
unsigned main_arena_ind = *(unsigned *)arg;
void *p;
@@ -43,7 +43,7 @@ TEST_BEGIN(test_thread_arena)
unsigned arena_ind;
size_t size;
int err;
- je_thread_t threads[NTHREADS];
+ thd_t thds[NTHREADS];
unsigned i;
p = malloc(1);
@@ -58,13 +58,13 @@ TEST_BEGIN(test_thread_arena)
}
for (i = 0; i < NTHREADS; i++) {
- je_thread_create(&threads[i], je_thread_start,
+ thd_create(&thds[i], thd_start,
(void *)&arena_ind);
}
for (i = 0; i < NTHREADS; i++) {
intptr_t join_ret;
- je_thread_join(threads[i], (void *)&join_ret);
+ thd_join(thds[i], (void *)&join_ret);
assert_zd_eq(join_ret, 0, "Unexpected thread join error");
}
}
diff --git a/test/integration/thread_tcache_enabled.c b/test/integration/thread_tcache_enabled.c
index 52e8a11..f4e89c6 100644
--- a/test/integration/thread_tcache_enabled.c
+++ b/test/integration/thread_tcache_enabled.c
@@ -9,7 +9,7 @@ static const bool config_tcache =
;
void *
-je_thread_start(void *arg)
+thd_start(void *arg)
{
int err;
size_t sz;
@@ -86,16 +86,16 @@ label_ENOENT:
TEST_BEGIN(test_main_thread)
{
- je_thread_start(NULL);
+ thd_start(NULL);
}
TEST_END
TEST_BEGIN(test_subthread)
{
- je_thread_t thread;
+ thd_t thd;
- je_thread_create(&thread, je_thread_start, NULL);
- je_thread_join(thread, NULL);
+ thd_create(&thd, thd_start, NULL);
+ thd_join(thd, NULL);
}
TEST_END
diff --git a/test/src/mtx.c b/test/src/mtx.c
new file mode 100644
index 0000000..8d9e0ca
--- /dev/null
+++ b/test/src/mtx.c
@@ -0,0 +1,62 @@
+#include "test/jemalloc_test.h"
+
+bool
+mtx_init(mtx_t *mtx)
+{
+
+#ifdef _WIN32
+ if (!InitializeCriticalSectionAndSpinCount(&mtx->lock, _CRT_SPINCOUNT))
+ return (true);
+#elif (defined(JEMALLOC_OSSPIN))
+ mtx->lock = 0;
+#else
+ pthread_mutexattr_t attr;
+
+ if (pthread_mutexattr_init(&attr) != 0)
+ return (true);
+ pthread_mutexattr_settype(&attr, MALLOC_MUTEX_TYPE);
+ if (pthread_mutex_init(&mtx->lock, &attr) != 0) {
+ pthread_mutexattr_destroy(&attr);
+ return (true);
+ }
+ pthread_mutexattr_destroy(&attr);
+#endif
+ return (false);
+}
+
+void
+mtx_fini(mtx_t *mtx)
+{
+
+#ifdef _WIN32
+#elif (defined(JEMALLOC_OSSPIN))
+#else
+ pthread_mutex_destroy(&mtx->lock);
+#endif
+}
+
+void
+mtx_lock(mtx_t *mtx)
+{
+
+#ifdef _WIN32
+ EnterCriticalSection(&mtx->lock);
+#elif (defined(JEMALLOC_OSSPIN))
+ OSSpinLockLock(&mtx->lock);
+#else
+ pthread_mutex_lock(&mtx->lock);
+#endif
+}
+
+void
+mtx_unlock(mtx_t *mtx)
+{
+
+#ifdef _WIN32
+ LeaveCriticalSection(&mtx->lock);
+#elif (defined(JEMALLOC_OSSPIN))
+ OSSpinLockUnlock(&mtx->lock);
+#else
+ pthread_mutex_unlock(&mtx->lock);
+#endif
+}
diff --git a/test/src/thd.c b/test/src/thd.c
new file mode 100644
index 0000000..233242a
--- /dev/null
+++ b/test/src/thd.c
@@ -0,0 +1,35 @@
+#include "test/jemalloc_test.h"
+
+#ifdef _WIN32
+void
+thd_create(thd_t *thd, void *(*proc)(void *), void *arg)
+{
+ LPTHREAD_START_ROUTINE routine = (LPTHREAD_START_ROUTINE)proc;
+ *thd = CreateThread(NULL, 0, routine, arg, 0, NULL);
+ if (*thd == NULL)
+ test_fail("Error in CreateThread()\n");
+}
+
+void
+thd_join(thd_t thd, void **ret)
+{
+
+ WaitForSingleObject(thd, INFINITE);
+}
+
+#else
+void
+thd_create(thd_t *thd, void *(*proc)(void *), void *arg)
+{
+
+ if (pthread_create(thd, NULL, proc, arg) != 0)
+ test_fail("Error in pthread_create()\n");
+}
+
+void
+thd_join(thd_t thd, void **ret)
+{
+
+ pthread_join(thd, ret);
+}
+#endif
diff --git a/test/src/thread.c b/test/src/thread.c
deleted file mode 100644
index 5a91e27..0000000
--- a/test/src/thread.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include "test/jemalloc_test.h"
-
-#ifdef _WIN32
-void
-je_thread_create(je_thread_t *thread, void *(*proc)(void *), void *arg)
-{
- LPTHREAD_START_ROUTINE routine = (LPTHREAD_START_ROUTINE)proc;
- *thread = CreateThread(NULL, 0, routine, arg, 0, NULL);
- if (*thread == NULL)
- test_fail("Error in CreateThread()\n");
-}
-
-void
-je_thread_join(je_thread_t thread, void **ret)
-{
-
- WaitForSingleObject(thread, INFINITE);
-}
-
-#else
-void
-je_thread_create(je_thread_t *thread, void *(*proc)(void *), void *arg)
-{
-
- if (pthread_create(thread, NULL, proc, arg) != 0)
- test_fail("Error in pthread_create()\n");
-}
-
-void
-je_thread_join(je_thread_t thread, void **ret)
-{
-
- pthread_join(thread, ret);
-}
-#endif
diff --git a/test/unit/mq.c b/test/unit/mq.c
new file mode 100644
index 0000000..f0f4990
--- /dev/null
+++ b/test/unit/mq.c
@@ -0,0 +1,91 @@
+#include "test/jemalloc_test.h"
+
+#define NSENDERS 3
+#define NMSGS 100000
+
+typedef struct mq_msg_s mq_msg_t;
+struct mq_msg_s {
+ mq_msg(mq_msg_t) link;
+};
+mq_gen(static, mq_, mq_t, mq_msg_t, link)
+
+TEST_BEGIN(test_mq_basic)
+{
+ mq_t mq;
+ mq_msg_t msg;
+
+ assert_false(mq_init(&mq), "Unexpected mq_init() failure");
+ assert_u_eq(mq_count(&mq), 0, "mq should be empty");
+ assert_ptr_null(mq_tryget(&mq),
+ "mq_tryget() should fail when the queue is empty");
+
+ mq_put(&mq, &msg);
+ assert_u_eq(mq_count(&mq), 1, "mq should contain one message");
+ assert_ptr_eq(mq_tryget(&mq), &msg, "mq_tryget() should return msg");
+
+ mq_put(&mq, &msg);
+ assert_ptr_eq(mq_get(&mq), &msg, "mq_get() should return msg");
+
+ mq_fini(&mq);
+}
+TEST_END
+
+static void *
+thd_receiver_start(void *arg)
+{
+ mq_t *mq = (mq_t *)arg;
+ unsigned i;
+
+ for (i = 0; i < (NSENDERS * NMSGS); i++) {
+ mq_msg_t *msg = mq_get(mq);
+ assert_ptr_not_null(msg, "mq_get() should never return NULL");
+ assert_d_eq(jet_dallocm(msg, 0), ALLOCM_SUCCESS,
+ "Unexpected dallocm() failure");
+ }
+ return (NULL);
+}
+
+static void *
+thd_sender_start(void *arg)
+{
+ mq_t *mq = (mq_t *)arg;
+ unsigned i;
+
+ for (i = 0; i < NMSGS; i++) {
+ mq_msg_t *msg;
+ assert_d_eq(jet_allocm((void **)&msg, NULL, sizeof(mq_msg_t),
+ 0), ALLOCM_SUCCESS, "Unexpected allocm() failure");
+ mq_put(mq, msg);
+ }
+ return (NULL);
+}
+
+TEST_BEGIN(test_mq_threaded)
+{
+ mq_t mq;
+ thd_t receiver;
+ thd_t senders[NSENDERS];
+ unsigned i;
+
+ assert_false(mq_init(&mq), "Unexpected mq_init() failure");
+
+ thd_create(&receiver, thd_receiver_start, (void *)&mq);
+ for (i = 0; i < NSENDERS; i++)
+ thd_create(&senders[i], thd_sender_start, (void *)&mq);
+
+ thd_join(receiver, NULL);
+ for (i = 0; i < NSENDERS; i++)
+ thd_join(senders[i], NULL);
+
+ mq_fini(&mq);
+}
+TEST_END
+
+int
+main(void)
+{
+ return (test(
+ test_mq_basic,
+ test_mq_threaded));
+}
+
diff --git a/test/unit/mtx.c b/test/unit/mtx.c
new file mode 100644
index 0000000..96ff694
--- /dev/null
+++ b/test/unit/mtx.c
@@ -0,0 +1,60 @@
+#include "test/jemalloc_test.h"
+
+#define NTHREADS 2
+#define NINCRS 2000000
+
+TEST_BEGIN(test_mtx_basic)
+{
+ mtx_t mtx;
+
+ assert_false(mtx_init(&mtx), "Unexpected mtx_init() failure");
+ mtx_lock(&mtx);
+ mtx_unlock(&mtx);
+ mtx_fini(&mtx);
+}
+TEST_END
+
+typedef struct {
+ mtx_t mtx;
+ unsigned x;
+} thd_start_arg_t;
+
+static void *
+thd_start(void *varg)
+{
+ thd_start_arg_t *arg = (thd_start_arg_t *)varg;
+ unsigned i;
+
+ for (i = 0; i < NINCRS; i++) {
+ mtx_lock(&arg->mtx);
+ arg->x++;
+ mtx_unlock(&arg->mtx);
+ }
+ return (NULL);
+}
+
+TEST_BEGIN(test_mtx_race)
+{
+ thd_start_arg_t arg;
+ thd_t thds[NTHREADS];
+ unsigned i;
+
+ assert_false(mtx_init(&arg.mtx), "Unexpected mtx_init() failure");
+ arg.x = 0;
+ for (i = 0; i < NTHREADS; i++)
+ thd_create(&thds[i], thd_start, (void *)&arg);
+ for (i = 0; i < NTHREADS; i++)
+ thd_join(thds[i], NULL);
+ assert_u_eq(arg.x, NTHREADS * NINCRS,
+ "Race-related counter corruption");
+}
+TEST_END
+
+int
+main(void)
+{
+
+ return (test(
+ test_mtx_basic,
+ test_mtx_race));
+}
diff --git a/test/unit/tsd.c b/test/unit/tsd.c
index 71feb84..f421c1a 100644
--- a/test/unit/tsd.c
+++ b/test/unit/tsd.c
@@ -22,8 +22,8 @@ malloc_tsd_externs(data, data_t)
malloc_tsd_data(, data, data_t, DATA_INIT)
malloc_tsd_funcs(, data, data_t, DATA_INIT, data_cleanup)
-void *
-je_thread_start(void *arg)
+static void *
+thd_start(void *arg)
{
data_t d = (data_t)(uintptr_t)arg;
assert_x_eq(*data_tsd_get(), DATA_INIT,
@@ -37,23 +37,23 @@ je_thread_start(void *arg)
assert_x_eq(*data_tsd_get(), (data_t)(uintptr_t)arg,
"Resetting local data should have no effect on tsd");
- return NULL;
+ return (NULL);
}
TEST_BEGIN(test_tsd_main_thread)
{
- je_thread_start((void *) 0xa5f3e329);
+ thd_start((void *) 0xa5f3e329);
}
TEST_END
TEST_BEGIN(test_tsd_sub_thread)
{
- je_thread_t thread;
+ thd_t thd;
data_cleanup_executed = false;
- je_thread_create(&thread, je_thread_start, (void *) THREAD_DATA);
- je_thread_join(thread, NULL);
+ thd_create(&thd, thd_start, (void *)THREAD_DATA);
+ thd_join(thd, NULL);
assert_true(data_cleanup_executed,
"Cleanup function should have executed");
}