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.
This commit is contained 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"
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#include "jemalloc/internal/jemalloc_internal_defs.h"
|
||||
|
||||
/* For use by SFMT. */
|
||||
#undef HAVE_SSE2
|
||||
#undef HAVE_ALTIVEC
|
||||
|
110
test/include/test/mq.h
Normal file
110
test/include/test/mq.h
Normal file
@@ -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); \
|
||||
}
|
21
test/include/test/mtx.h
Normal file
21
test/include/test/mtx.h
Normal file
@@ -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);
|
9
test/include/test/thd.h
Normal file
9
test/include/test/thd.h
Normal file
@@ -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);
|
@@ -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);
|
Reference in New Issue
Block a user