ck_hp_fifo: Add try{enqueue,dequeue} variants.

Regression test has been updated and passes.
ck_pring
Samy Al Bahra 13 years ago
parent a90b402c0c
commit 402c31ca9a

@ -97,6 +97,35 @@ ck_hp_fifo_enqueue_mpmc(ck_hp_record_t *record,
return; 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_CC_INLINE static struct ck_hp_fifo_entry *
ck_hp_fifo_dequeue_mpmc(ck_hp_record_t *record, ck_hp_fifo_dequeue_mpmc(ck_hp_record_t *record,
struct ck_hp_fifo *fifo, struct ck_hp_fifo *fifo,
@ -133,6 +162,39 @@ ck_hp_fifo_dequeue_mpmc(ck_hp_record_t *record,
return (head); 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_ISEMPTY(f) ((f)->head->next == NULL)
#define CK_HP_FIFO_FIRST(f) ((f)->head->next) #define CK_HP_FIFO_FIRST(f) ((f)->head->next)
#define CK_HP_FIFO_NEXT(m) ((m)->next) #define CK_HP_FIFO_NEXT(m) ((m)->next)

@ -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); ck_pr_inc_uint(&e_barrier);
while (ck_pr_load_uint(&e_barrier) < (unsigned int)nthr); while (ck_pr_load_uint(&e_barrier) < (unsigned int)nthr);

Loading…
Cancel
Save