int main(void) { void *r; uint64_t s, e, a; unsigned int i; unsigned int j; ck_hp_fifo_entry_t hp_entry[ENTRIES]; ck_hp_fifo_entry_t hp_stub; ck_hp_record_t record; ck_hp_init(&fifo_hp, CK_HP_FIFO_SLOTS_COUNT, 1000000, NULL); r = malloc(CK_HP_FIFO_SLOTS_SIZE); if (r == NULL) { fprintf(stderr, "ERROR: Failed to allocate slots.\n"); exit(EXIT_FAILURE); } ck_hp_register(&fifo_hp, &record, r); a = 0; for (i = 0; i < STEPS; i++) { ck_hp_fifo_init(&fifo, &hp_stub); s = rdtsc(); for (j = 0; j < ENTRIES; j++) ck_hp_fifo_enqueue_mpmc(&record, &fifo, hp_entry + j, NULL); e = rdtsc(); a += e - s; } printf("ck_hp_fifo_enqueue_mpmc: %16" PRIu64 "\n", a / STEPS / ENTRIES); a = 0; for (i = 0; i < STEPS; i++) { ck_hp_fifo_init(&fifo, &hp_stub); for (j = 0; j < ENTRIES; j++) ck_hp_fifo_enqueue_mpmc(&record, &fifo, hp_entry + j, NULL); s = rdtsc(); for (j = 0; j < ENTRIES; j++) ck_hp_fifo_dequeue_mpmc(&record, &fifo, &r); e = rdtsc(); a += e - s; } printf("ck_hp_fifo_dequeue_mpmc: %16" PRIu64 "\n", a / STEPS / ENTRIES); return 0; }
int main(void) { ck_hp_record_t record; ck_stack_entry_t entry[ENTRIES]; uint64_t s, e, a; unsigned int i; unsigned int j; void *r; ck_hp_init(&stack_hp, CK_HP_STACK_SLOTS_COUNT, 1000000, NULL); r = malloc(CK_HP_STACK_SLOTS_SIZE); if (r == NULL) { ck_error("ERROR: Failed to allocate slots.\n"); } ck_hp_register(&stack_hp, &record, (void *)r); a = 0; for (i = 0; i < STEPS; i++) { ck_stack_init(&stack); s = rdtsc(); for (j = 0; j < ENTRIES; j++) ck_hp_stack_push_mpmc(&stack, entry + j); e = rdtsc(); a += e - s; } printf("ck_hp_stack_push_mpmc: %16" PRIu64 "\n", a / STEPS / ENTRIES); a = 0; for (i = 0; i < STEPS; i++) { ck_stack_init(&stack); for (j = 0; j < ENTRIES; j++) ck_hp_stack_push_mpmc(&stack, entry + j); s = rdtsc(); for (j = 0; j < ENTRIES; j++) { r = ck_hp_stack_pop_mpmc(&record, &stack); } e = rdtsc(); a += e - s; } printf(" ck_hp_stack_pop_mpmc: %16" PRIu64 "\n", a / STEPS / ENTRIES); return 0; }
static void * test(void *c) { struct context *context = c; struct entry *entry; ck_hp_fifo_entry_t *fifo_entry; ck_hp_record_t record; int i, j; if (aff_iterate(&a)) { perror("ERROR: Could not affine thread"); exit(EXIT_FAILURE); } ck_hp_register(&fifo_hp, &record, malloc(sizeof(void *) * 2)); ck_pr_inc_uint(&barrier); while (ck_pr_load_uint(&barrier) < (unsigned int)nthr); 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; ck_hp_fifo_enqueue_mpmc(&record, &fifo, fifo_entry, entry); fifo_entry = ck_hp_fifo_dequeue_mpmc(&record, &fifo, &entry); if (fifo_entry == NULL) { fprintf(stderr, "ERROR [%u] Queue should never be empty.\n", context->tid); exit(EXIT_FAILURE); } 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); return (NULL); }
/* function for thread */ static void * queue_50_50(void *elements) { struct entry *entry; ck_hp_fifo_entry_t *fifo_entry; ck_hp_record_t *record; void *slots; unsigned long j, element_count = *(unsigned long *)elements; unsigned int seed; record = malloc(sizeof(ck_hp_record_t)); assert(record); slots = malloc(CK_HP_FIFO_SLOTS_SIZE); assert(slots); /* different seed for each thread */ seed = 1337; /*(unsigned int) pthread_self(); */ /* * This subscribes the thread to the fifo_hp state using the thread-owned * record. * FIFO queue needs 2 hazard pointers. */ ck_hp_register(&fifo_hp, record, slots); /* start barrier */ ck_pr_inc_uint(&start_barrier); while (ck_pr_load_uint(&start_barrier) < thread_count + 1) ck_pr_stall(); /* 50/50 enqueue-dequeue */ for(j = 0; j < element_count; j++) { /* rand_r with thread local state should be thread safe */ if( 50 < (1+(int) (100.0*common_rand_r(&seed)/(RAND_MAX+1.0)))) { /* This is the container for the enqueued data. */ fifo_entry = malloc(sizeof(ck_hp_fifo_entry_t)); if (fifo_entry == NULL) { exit(EXIT_FAILURE); } /* This is the data. */ entry = malloc(sizeof(struct entry)); if (entry != NULL) { entry->value = j; } /* * Enqueue the value of the pointer entry into FIFO queue using the * container fifo_entry. */ ck_hp_fifo_enqueue_mpmc(record, &fifo, fifo_entry, entry); } else { /* * ck_hp_fifo_dequeue_mpmc will return a pointer to the first unused node and store * the value of the first pointer in the FIFO queue in entry. */ fifo_entry = ck_hp_fifo_dequeue_mpmc(record, &fifo, &entry); if (fifo_entry != NULL) { /* * Safely reclaim memory associated with fifo_entry. * This inserts garbage into a local list. Once the list (plist) reaches * a length of 100, ck_hp_free will attempt to reclaim all references * to objects on the list. */ ck_hp_free(record, &fifo_entry->hazard, fifo_entry, fifo_entry); } } } /* end barrier */ ck_pr_inc_uint(&end_barrier); while (ck_pr_load_uint(&end_barrier) < thread_count + 1) ck_pr_stall(); return NULL; }