From 07d753c02637b93d9b91afff979c64a401aabdbe Mon Sep 17 00:00:00 2001 From: Shintaro Iwasaki Date: Mon, 25 Mar 2019 14:37:32 -0500 Subject: [PATCH] test: add test for idsmsync --- test/regres/lock/Makefile.am | 6 +- test/regres/lock/idsm.c | 150 +++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 test/regres/lock/idsm.c diff --git a/test/regres/lock/Makefile.am b/test/regres/lock/Makefile.am index 03b17e0..b4d0bf2 100644 --- a/test/regres/lock/Makefile.am +++ b/test/regres/lock/Makefile.am @@ -17,7 +17,8 @@ TESTS = \ tryacq_imcs \ tryacq_tlp \ tryacq_hmcs \ - hmpr_thruput + hmpr_thruput \ + idsm XFAIL_TESTS = @@ -40,6 +41,7 @@ tryacq_imcs_SOURCES = cs_thruput.c tryacq_tlp_SOURCES = cs_thruput.c tryacq_hmcs_SOURCES = cs_thruput.c hmpr_thruput_SOURCES = hmpr_thruput.c +idsm_SOURCES = idsm.c cs_thruput_tkt_CFLAGS = -DZM_LOCK_IF=ZM_TICKET_IF -D_GNU_SOURCE cs_thruput_mcs_CFLAGS = -DZM_LOCK_IF=ZM_MCS_IF -D_GNU_SOURCE @@ -55,6 +57,7 @@ tryacq_imcs_CFLAGS = -DZM_LOCK_IF=ZM_IMCS_IF -D_GNU_SOURCE tryacq_tlp_CFLAGS = -DZM_LOCK_IF=ZM_TLP_IF -D_GNU_SOURCE tryacq_hmcs_CFLAGS = -DZM_LOCK_IF=ZM_HMCS_IF -D_GNU_SOURCE hmpr_thruput_CFLAGS = -D_GNU_SOURCE +idsm_CFLAGS = -D_GNU_SOURCE cs_thruput_tkt_LDFLAGS = -pthread cs_thruput_mcs_LDFLAGS = -pthread @@ -70,3 +73,4 @@ tryacq_imcs_LDFLAGS = -pthread tryacq_tlp_LDFLAGS = -pthread tryacq_hmcs_LDFLAGS = -pthread hmpr_thruput_LDFLAGS = -pthread +idsm_LDFLAGS = -pthread diff --git a/test/regres/lock/idsm.c b/test/regres/lock/idsm.c new file mode 100644 index 0000000..14408e6 --- /dev/null +++ b/test/regres/lock/idsm.c @@ -0,0 +1,150 @@ +/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */ +/* + * See COPYRIGHT in top-level directory. + */ +#include +#include +#include +#include "lock/zm_idsmsync.h" + +#define TEST_NTEST ((int64_t)10) +#define TEST_NTHREADS ((int64_t)8) +#define TEST_NITER ((int64_t)100000) +#define TEST_LOCAL_OFFSET ((int64_t)24) + +int64_t global_val; +int64_t local_vals[TEST_NTHREADS * TEST_LOCAL_OFFSET]; + +static inline void global_work(int64_t val) { + global_val += val; +} + +static inline void local_work(int64_t thread_id, int64_t val) { + local_vals[thread_id * TEST_LOCAL_OFFSET] += val; +} + +static void work(void *req) { + int64_t req_val = (intptr_t)(req); + int64_t thread_id = req_val / TEST_NITER; + int64_t val = req_val % TEST_NITER; + global_work(val); + local_work(thread_id, val); +} + +typedef struct { + pthread_t thread; + int64_t thread_id; + int64_t op_kind; + zm_dsm_t dsm; +} thread_arg_t; + +static void *run(void *_arg) { + thread_arg_t *arg = (thread_arg_t *)_arg; + + const int64_t thread_id = arg->thread_id; + const int64_t op_kind = arg->op_kind; + zm_dsm_t dsm = arg->dsm; + + /* Directly change the thread-local value in izem. Not good. */ + tid = thread_id; + + int64_t count; + for (count = 0; count < TEST_NITER; count++) { + void *req = (void *)((intptr_t)(arg->thread_id * TEST_NITER + count)); + switch (op_kind) { + case 0: + zm_idsm_acquire(dsm); + work(req); + zm_idsm_release(dsm); + break; + case 1: + zm_idsm_cacq(dsm, work); + work(req); + zm_idsm_release(dsm); + break; + case 2: + while (1) { + int success = 0; + zm_idsm_ctry(dsm, work, &success); + if (success == 1) { + work(req); + zm_idsm_release(dsm); + break; + } + } + break; + case 3: + default: + zm_idsm_sync(dsm, work, req); + break; + } + } + return NULL; +} + +/*------------------------------------------------------------------------- + * Function: test_idsm_lock + * + * Purpose: Test the correctness of idsm lock + * + * Return: Success: 0 + * Failure: 1 + *------------------------------------------------------------------------- + */ +static void test_idsm_lock() { + thread_arg_t args[TEST_NTHREADS]; + + int i; + for (i = 0; i < TEST_NTEST; i++) { + zm_dsm_t dsm; + zm_idsm_init(&dsm); + + global_val = 0; + memset(local_vals, 0, sizeof(int64_t) * TEST_NTHREADS + * TEST_LOCAL_OFFSET); + + int th; + for (th = 0; th < TEST_NTHREADS; th++) { + pthread_attr_t attr; + pthread_attr_init(&attr); + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(th, &cpuset); + pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset); + args[th].thread_id = th; + args[th].op_kind = th % 4; + args[th].dsm = dsm; + pthread_create(&args[th].thread, &attr, run, &args[th]); + } + for (th = 0; th < TEST_NTHREADS; th++) { + pthread_join(args[th].thread, NULL); + } + zm_idsm_destroy(&dsm); + + /* Examine the result. */ + const int64_t tmp = TEST_NITER * (TEST_NITER - 1) / 2; + const int64_t global_val_ans = tmp * TEST_NTHREADS; + if (global_val != global_val_ans) { + printf("[%d] Error: global_val = %llu (ans %llu)\n", i, + (unsigned long long) global_val, + (unsigned long long) global_val_ans); + return; + } + for (th = 0; th < TEST_NTHREADS; th++) { + const int64_t local_val_ans = tmp; + if (local_vals[th * TEST_LOCAL_OFFSET] != local_val_ans) { + printf("[%d] Error: local_vals[%d] = %llu (ans %llu)\n", i, th, + (unsigned long long) local_vals[th * TEST_LOCAL_OFFSET], + (unsigned long long) local_val_ans); + return; + } + } + } + printf("Pass\n"); +} /* end test_lock_thruput() */ + +int main(int argc, char **argv) +{ + test_idsm_lock(); +} /* end main() */ +