From 768b5b35976e3f55d091928e41b0d78bd40ad04e Mon Sep 17 00:00:00 2001 From: Samy Al Bahra Date: Tue, 16 Jul 2013 01:28:31 -0400 Subject: [PATCH] ck_rwlock: Add adaptive elision and unit tests. --- include/ck_rwlock.h | 8 +++ regressions/ck_rwlock/benchmark/Makefile | 4 +- regressions/ck_rwlock/benchmark/latency.c | 43 +++++++++++++-- regressions/ck_rwlock/validate/Makefile | 2 +- regressions/ck_rwlock/validate/validate.c | 65 +++++++++++++++++++++++ 5 files changed, 114 insertions(+), 8 deletions(-) diff --git a/include/ck_rwlock.h b/include/ck_rwlock.h index e75d350..4adebf6 100644 --- a/include/ck_rwlock.h +++ b/include/ck_rwlock.h @@ -127,6 +127,10 @@ CK_ELIDE_PROTOTYPE(ck_rwlock_write, ck_rwlock_t, ck_rwlock_locked, ck_rwlock_write_lock, ck_rwlock_locked_writer, ck_rwlock_write_unlock) +CK_ELIDE_ADAPTIVE_PROTOTYPE(ck_rwlock_write, ck_rwlock_t, + ck_rwlock_locked, ck_rwlock_write_lock, + ck_rwlock_locked_writer, ck_rwlock_write_unlock) + CK_CC_INLINE static bool ck_rwlock_read_trylock(ck_rwlock_t *rw) { @@ -202,6 +206,10 @@ CK_ELIDE_PROTOTYPE(ck_rwlock_read, ck_rwlock_t, ck_rwlock_locked_writer, ck_rwlock_read_lock, ck_rwlock_locked_reader, ck_rwlock_read_unlock) +CK_ELIDE_ADAPTIVE_PROTOTYPE(ck_rwlock_read, ck_rwlock_t, + ck_rwlock_locked_writer, ck_rwlock_read_lock, + ck_rwlock_locked_reader, ck_rwlock_read_unlock) + /* * Recursive writer reader-writer lock implementation. */ diff --git a/regressions/ck_rwlock/benchmark/Makefile b/regressions/ck_rwlock/benchmark/Makefile index 6f739d9..ed63504 100644 --- a/regressions/ck_rwlock/benchmark/Makefile +++ b/regressions/ck_rwlock/benchmark/Makefile @@ -4,10 +4,10 @@ OBJECTS=latency throughput all: $(OBJECTS) -latency: latency.c ../../../include/ck_rwlock.h +latency: latency.c ../../../include/ck_rwlock.h ../../../include/ck_elide.h $(CC) $(CFLAGS) -o latency latency.c -throughput: throughput.c ../../../include/ck_rwlock.h +throughput: throughput.c ../../../include/ck_rwlock.h ../../../include/ck_elide.h $(CC) $(CFLAGS) -o throughput throughput.c clean: diff --git a/regressions/ck_rwlock/benchmark/latency.c b/regressions/ck_rwlock/benchmark/latency.c index 00971ab..bfcf5b8 100644 --- a/regressions/ck_rwlock/benchmark/latency.c +++ b/regressions/ck_rwlock/benchmark/latency.c @@ -30,8 +30,10 @@ #include "../../common.h" +#define CK_F_PR_RTM + #ifndef STEPS -#define STEPS 1000000 +#define STEPS 2000000 #endif int @@ -51,9 +53,12 @@ main(void) ck_rwlock_write_unlock(&rwlock); } e_b = rdtsc(); - printf(" WRITE: rwlock %15" PRIu64 "\n", (e_b - s_b) / STEPS); + printf(" WRITE: rwlock %15" PRIu64 "\n", (e_b - s_b) / STEPS); #ifdef CK_F_PR_RTM + struct ck_elide_config config = CK_ELIDE_CONFIG_DEFAULT_INITIALIZER; + struct ck_elide_stat st = CK_ELIDE_STAT_INITIALIZER; + for (i = 0; i < STEPS; i++) { CK_ELIDE_LOCK(ck_rwlock_write, &rwlock); CK_ELIDE_UNLOCK(ck_rwlock_write, &rwlock); @@ -65,7 +70,20 @@ main(void) CK_ELIDE_UNLOCK(ck_rwlock_write, &rwlock); } e_b = rdtsc(); - printf(" (rtm) WRITE: rwlock %15" PRIu64 "\n", (e_b - s_b) / STEPS); + printf(" (rtm) WRITE: rwlock %15" PRIu64 "\n", (e_b - s_b) / STEPS); + + for (i = 0; i < STEPS; i++) { + CK_ELIDE_LOCK_ADAPTIVE(ck_rwlock_write, &st, &config, &rwlock); + CK_ELIDE_UNLOCK_ADAPTIVE(ck_rwlock_write, &st, &rwlock); + } + + s_b = rdtsc(); + for (i = 0; i < STEPS; i++) { + CK_ELIDE_LOCK_ADAPTIVE(ck_rwlock_write, &st, &config, &rwlock); + CK_ELIDE_UNLOCK_ADAPTIVE(ck_rwlock_write, &st, &rwlock); + } + e_b = rdtsc(); + printf(" (rtm-adaptive) WRITE: rwlock %15" PRIu64 "\n", (e_b - s_b) / STEPS); #endif /* CK_F_PR_RTM */ for (i = 0; i < STEPS; i++) { @@ -79,9 +97,11 @@ main(void) ck_rwlock_read_unlock(&rwlock); } e_b = rdtsc(); - printf(" READ: rwlock %15" PRIu64 "\n", (e_b - s_b) / STEPS); + printf(" READ: rwlock %15" PRIu64 "\n", (e_b - s_b) / STEPS); #ifdef CK_F_PR_RTM + ck_elide_stat_init(&st); + for (i = 0; i < STEPS; i++) { CK_ELIDE_LOCK(ck_rwlock_read, &rwlock); CK_ELIDE_UNLOCK(ck_rwlock_read, &rwlock); @@ -93,7 +113,20 @@ main(void) CK_ELIDE_UNLOCK(ck_rwlock_read, &rwlock); } e_b = rdtsc(); - printf(" (rtm) READ: rwlock %15" PRIu64 "\n", (e_b - s_b) / STEPS); + printf(" (rtm) READ: rwlock %15" PRIu64 "\n", (e_b - s_b) / STEPS); + + for (i = 0; i < STEPS; i++) { + CK_ELIDE_LOCK_ADAPTIVE(ck_rwlock_read, &st, &config, &rwlock); + CK_ELIDE_UNLOCK_ADAPTIVE(ck_rwlock_read, &st, &rwlock); + } + + s_b = rdtsc(); + for (i = 0; i < STEPS; i++) { + CK_ELIDE_LOCK_ADAPTIVE(ck_rwlock_read, &st, &config, &rwlock); + CK_ELIDE_UNLOCK_ADAPTIVE(ck_rwlock_read, &st, &rwlock); + } + e_b = rdtsc(); + printf(" (rtm-adaptive) READ: rwlock %15" PRIu64 "\n", (e_b - s_b) / STEPS); #endif /* CK_F_PR_RTM */ return 0; diff --git a/regressions/ck_rwlock/validate/Makefile b/regressions/ck_rwlock/validate/Makefile index eeab170..2c2116b 100644 --- a/regressions/ck_rwlock/validate/Makefile +++ b/regressions/ck_rwlock/validate/Makefile @@ -4,7 +4,7 @@ OBJECTS=validate all: $(OBJECTS) -validate: validate.c ../../../include/ck_rwlock.h +validate: validate.c ../../../include/ck_rwlock.h ../../../include/ck_elide.h $(CC) $(CFLAGS) -o validate validate.c check: all diff --git a/regressions/ck_rwlock/validate/validate.c b/regressions/ck_rwlock/validate/validate.c index 1f22ba4..14ec3d8 100644 --- a/regressions/ck_rwlock/validate/validate.c +++ b/regressions/ck_rwlock/validate/validate.c @@ -124,6 +124,70 @@ thread_recursive(void *null CK_CC_UNUSED) } #ifdef CK_F_PR_RTM +static void * +thread_rtm_adaptive(void *null CK_CC_UNUSED) +{ + unsigned int i = ITERATE; + unsigned int l; + struct ck_elide_config config = CK_ELIDE_CONFIG_DEFAULT_INITIALIZER; + struct ck_elide_stat st = CK_ELIDE_STAT_INITIALIZER; + + if (aff_iterate(&a)) { + perror("ERROR: Could not affine thread"); + exit(EXIT_FAILURE); + } + + while (i--) { + CK_ELIDE_LOCK_ADAPTIVE(ck_rwlock_write, &st, &config, &lock); + { + l = ck_pr_load_uint(&locked); + if (l != 0) { + ck_error("ERROR [WR:%d]: %u != 0\n", __LINE__, l); + } + + ck_pr_inc_uint(&locked); + ck_pr_inc_uint(&locked); + ck_pr_inc_uint(&locked); + ck_pr_inc_uint(&locked); + ck_pr_inc_uint(&locked); + ck_pr_inc_uint(&locked); + ck_pr_inc_uint(&locked); + ck_pr_inc_uint(&locked); + + l = ck_pr_load_uint(&locked); + if (l != 8) { + ck_error("ERROR [WR:%d]: %u != 2\n", __LINE__, l); + } + + ck_pr_dec_uint(&locked); + ck_pr_dec_uint(&locked); + ck_pr_dec_uint(&locked); + ck_pr_dec_uint(&locked); + ck_pr_dec_uint(&locked); + ck_pr_dec_uint(&locked); + ck_pr_dec_uint(&locked); + ck_pr_dec_uint(&locked); + + l = ck_pr_load_uint(&locked); + if (l != 0) { + ck_error("ERROR [WR:%d]: %u != 0\n", __LINE__, l); + } + } + CK_ELIDE_UNLOCK_ADAPTIVE(ck_rwlock_write, &st, &lock); + + CK_ELIDE_LOCK(ck_rwlock_read, &lock); + { + l = ck_pr_load_uint(&locked); + if (l != 0) { + ck_error("ERROR [RD:%d]: %u != 0\n", __LINE__, l); + } + } + CK_ELIDE_UNLOCK(ck_rwlock_read, &lock); + } + + return NULL; +} + static void * thread_rtm_mix(void *null CK_CC_UNUSED) { @@ -375,6 +439,7 @@ main(int argc, char *argv[]) #ifdef CK_F_PR_RTM rwlock_test(threads, thread_rtm, "rtm"); rwlock_test(threads, thread_rtm_mix, "rtm-mix"); + rwlock_test(threads, thread_rtm_adaptive, "rtm-adaptive"); #endif rwlock_test(threads, thread_recursive, "recursive"); return 0;