From 402c31ca9a818748b87553e91e9a7b1c0f9e4261 Mon Sep 17 00:00:00 2001 From: Samy Al Bahra Date: Sun, 1 Jul 2012 19:19:56 -0400 Subject: [PATCH] ck_hp_fifo: Add try{enqueue,dequeue} variants. Regression test has been updated and passes. --- include/ck_hp_fifo.h | 62 +++++++++++++++++++++++++ regressions/ck_hp/validate/ck_hp_fifo.c | 21 +++++++++ 2 files changed, 83 insertions(+) diff --git a/include/ck_hp_fifo.h b/include/ck_hp_fifo.h index 68423ee..3a6dd47 100644 --- a/include/ck_hp_fifo.h +++ b/include/ck_hp_fifo.h @@ -97,6 +97,35 @@ ck_hp_fifo_enqueue_mpmc(ck_hp_record_t *record, return; } +CK_CC_INLINE static bool +ck_hp_fifo_tryenqueue_mpmc(ck_hp_record_t *record, + struct ck_hp_fifo *fifo, + struct ck_hp_fifo_entry *entry, + void *value) +{ + struct ck_hp_fifo_entry *tail, *next; + + entry->value = value; + entry->next = NULL; + ck_pr_fence_store(); + + tail = ck_pr_load_ptr(&fifo->tail); + ck_hp_set(record, 0, tail); + ck_pr_fence_memory(); + if (tail != ck_pr_load_ptr(&fifo->tail)) + return false; + + next = ck_pr_load_ptr(&tail->next); + if (next != NULL) { + ck_pr_cas_ptr(&fifo->tail, tail, next); + return false; + } else if (ck_pr_cas_ptr(&fifo->tail->next, next, entry) == false) + return false; + + ck_pr_cas_ptr(&fifo->tail, tail, entry); + return true; +} + CK_CC_INLINE static struct ck_hp_fifo_entry * ck_hp_fifo_dequeue_mpmc(ck_hp_record_t *record, struct ck_hp_fifo *fifo, @@ -133,6 +162,39 @@ ck_hp_fifo_dequeue_mpmc(ck_hp_record_t *record, return (head); } +CK_CC_INLINE static struct ck_hp_fifo_entry * +ck_hp_fifo_trydequeue_mpmc(ck_hp_record_t *record, + struct ck_hp_fifo *fifo, + void *value) +{ + struct ck_hp_fifo_entry *head, *tail, *next; + + tail = ck_pr_load_ptr(&fifo->tail); + head = ck_pr_load_ptr(&fifo->head); + ck_hp_set(record, 0, head); + ck_pr_fence_memory(); + if (head != ck_pr_load_ptr(&fifo->head)) + return NULL; + + next = ck_pr_load_ptr(&head->next); + ck_hp_set(record, 1, next); + ck_pr_fence_memory(); + if (head != ck_pr_load_ptr(&fifo->head)) + return NULL; + + if (head == tail) { + if (next == NULL) + return NULL; + + ck_pr_cas_ptr(&fifo->tail, tail, next); + return NULL; + } else if (ck_pr_cas_ptr(&fifo->head, head, next) == false) + return NULL; + + ck_pr_store_ptr(value, next->value); + return head; +} + #define CK_HP_FIFO_ISEMPTY(f) ((f)->head->next == NULL) #define CK_HP_FIFO_FIRST(f) ((f)->head->next) #define CK_HP_FIFO_NEXT(m) ((m)->next) diff --git a/regressions/ck_hp/validate/ck_hp_fifo.c b/regressions/ck_hp/validate/ck_hp_fifo.c index f324993..87cfdc9 100644 --- a/regressions/ck_hp/validate/ck_hp_fifo.c +++ b/regressions/ck_hp/validate/ck_hp_fifo.c @@ -96,6 +96,27 @@ test(void *c) } } + for (i = 0; i < ITERATIONS; i++) { + for (j = 0; j < size; j++) { + fifo_entry = malloc(sizeof(ck_hp_fifo_entry_t)); + entry = malloc(sizeof(struct entry)); + entry->tid = context->tid; + + while (ck_hp_fifo_tryenqueue_mpmc(&record, &fifo, fifo_entry, entry) == false) + ck_pr_stall(); + + while (fifo_entry = ck_hp_fifo_trydequeue_mpmc(&record, &fifo, &entry), fifo_entry == NULL) + ck_pr_stall(); + + if (entry->tid < 0 || entry->tid >= nthr) { + fprintf(stderr, "ERROR [%u] Incorrect value in entry.\n", entry->tid); + exit(EXIT_FAILURE); + } + + ck_hp_free(&record, &fifo_entry->hazard, fifo_entry, fifo_entry); + } + } + ck_pr_inc_uint(&e_barrier); while (ck_pr_load_uint(&e_barrier) < (unsigned int)nthr);