static void queue_jlog_enqueue(fqd_queue_impl_data f, fq_msg *m) { struct queue_jlog *d = (struct queue_jlog *)f; size_t wlen; wlen = offsetof(fq_msg, payload) + m->payload_len; if(jlog_ctx_write(d->writer, m, wlen) != 0) { ck_pr_inc_uint(&d->errors); } ck_pr_inc_uint(&d->nenqueued); }
static void * fq_data_worker(void *u) { int backoff = 0; bool zero; fq_conn_s *conn_s = (fq_conn_s *)u; ck_pr_inc_uint(&conn_s->thrcnt); while(conn_s->stop == 0) { if(conn_s->data_ready) { if(fq_client_data_connect_internal(conn_s) == 0) { backoff = 0; /* we're good, restart our backoff */ } fq_debug(FQ_DEBUG_IO, "[data] connected\n"); fq_data_worker_loop(conn_s); fq_debug(FQ_DEBUG_IO, "[data] connection failed: %s\n", conn_s->error); } if(backoff) usleep(backoff + (4096 - (lrand48()%8192))); /* +/- 4ms */ else backoff = 16384; if(backoff < 1000000) backoff += (backoff >> 4); } if(conn_s->data_fd >= 0) { int toclose = conn_s->data_fd; conn_s->data_fd = -1; fq_debug(FQ_DEBUG_CONN, "close(data_fd)\n"); close(toclose); } ck_pr_dec_uint_zero(&conn_s->thrcnt, &zero); if(zero) fq_conn_free(conn_s); return (void *)NULL; }
static void * test(void *c) { struct context *context = c; struct entry *entry; ck_fifo_spsc_entry_t *fifo_entry; int i, j; if (aff_iterate(&a)) { perror("ERROR: Could not affine thread"); exit(EXIT_FAILURE); } #ifdef DEBUG fprintf(stderr, "%p %u: %u -> %u\n", fifo+context->tid, context->tid, context->previous, context->tid); #endif if (context->tid == 0) { struct entry *entries; entries = malloc(sizeof(struct entry) * size); assert(entries != NULL); for (i = 0; i < size; i++) { entries[i].value = i; entries[i].tid = 0; fifo_entry = malloc(sizeof(ck_fifo_spsc_entry_t)); ck_fifo_spsc_enqueue(fifo + context->tid, fifo_entry, entries + i); } } 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++) { while (ck_fifo_spsc_dequeue(fifo + context->previous, &entry) == false); if (context->previous != (unsigned int)entry->tid) { ck_error("T [%u:%p] %u != %u\n", context->tid, (void *)entry, entry->tid, context->previous); } if (entry->value != j) { ck_error("V [%u:%p] %u != %u\n", context->tid, (void *)entry, entry->value, j); } entry->tid = context->tid; fifo_entry = ck_fifo_spsc_recycle(fifo + context->tid); if (fifo_entry == NULL) fifo_entry = malloc(sizeof(ck_fifo_spsc_entry_t)); ck_fifo_spsc_enqueue(fifo + context->tid, fifo_entry, entry); } } return (NULL); }
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); }
static void * writer_thread(void *unused) { unsigned int i; unsigned int iteration = 0; (void)unused; for (;;) { iteration++; ck_epoch_write_begin(&epoch_wr); for (i = 1; i <= writer_max; i++) { if (ck_bag_put_spmc(&bag, (void *)(uintptr_t)i) == false) { perror("ck_bag_put_spmc"); exit(EXIT_FAILURE); } if (ck_bag_member_spmc(&bag, (void *)(uintptr_t)i) == false) { fprintf(stderr, "ck_bag_put_spmc [%u]: %u\n", iteration, i); exit(EXIT_FAILURE); } } if (ck_pr_load_int(&leave) == 1) break; for (i = 1; i < writer_max; i++) { void *replace = (void *)(uintptr_t)i; if (ck_bag_set_spmc(&bag, (void *)(uintptr_t)i, replace) == false) { fprintf(stderr, "ERROR: set %ju != %ju", (uintmax_t)(uintptr_t)replace, (uintmax_t)i); exit(EXIT_FAILURE); } } for (i = writer_max; i > 0; i--) { if (ck_bag_member_spmc(&bag, (void *)(uintptr_t)i) == false) { fprintf(stderr, "ck_bag_member_spmc [%u]: %u\n", iteration, i); exit(EXIT_FAILURE); } if (ck_bag_remove_spmc(&bag, (void *)(uintptr_t)i) == false) { fprintf(stderr, "ck_bag_remove_spmc [%u]: %u\n", iteration, i); exit(EXIT_FAILURE); } } ck_epoch_write_end(&epoch_wr); } fprintf(stderr, "Writer %u iterations, %u writes per iteration.\n", iteration, writer_max); while (ck_pr_load_uint(&barrier) != NUM_READER_THREADS) ck_pr_stall(); ck_pr_inc_uint(&barrier); return NULL; }
static void * test(void *c) { #ifdef CK_F_FIFO_MPMC struct context *context = c; struct entry *entry; ck_fifo_mpmc_entry_t *fifo_entry, *garbage; int i, j; if (aff_iterate(&a)) { perror("ERROR: Could not affine thread"); exit(EXIT_FAILURE); } 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_fifo_mpmc_entry_t)); entry = malloc(sizeof(struct entry)); entry->tid = context->tid; ck_fifo_mpmc_enqueue(&fifo, fifo_entry, entry); if (ck_fifo_mpmc_dequeue(&fifo, &entry, &garbage) == false) { 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); } } } for (i = 0; i < ITERATIONS; i++) { for (j = 0; j < size; j++) { fifo_entry = malloc(sizeof(ck_fifo_mpmc_entry_t)); entry = malloc(sizeof(struct entry)); entry->tid = context->tid; while (ck_fifo_mpmc_tryenqueue(&fifo, fifo_entry, entry) == false) ck_pr_stall(); while (ck_fifo_mpmc_trydequeue(&fifo, &entry, &garbage) == false) ck_pr_stall(); if (entry->tid < 0 || entry->tid >= nthr) { fprintf(stderr, "ERROR [%u] Incorrect value in entry when using try interface.\n", entry->tid); exit(EXIT_FAILURE); } } } #endif return (NULL); }
void fq_client_publish(fq_client conn, fq_msg *msg) { fq_conn_s *conn_s = conn; ck_fifo_mpmc_entry_t *fifo_entry; while(conn_s->qlen > conn_s->qmaxlen) { if(conn_s->q_stall_time > 0) usleep(conn_s->q_stall_time); else ck_pr_stall(); } fifo_entry = malloc(sizeof(ck_fifo_mpmc_entry_t)); fq_msg_ref(msg); ck_fifo_mpmc_enqueue(&conn_s->q, fifo_entry, msg); ck_pr_inc_uint(&conn_s->qlen); }
static CK_CC_INLINE void rwlock_read_lock(rwlock_t *rw) { for (;;) { while (ck_pr_load_uint(&rw->writer.value) != 0) ck_pr_stall(); ck_pr_inc_uint(&rw->readers); if (ck_pr_load_uint(&rw->writer.value) == 0) break; ck_pr_dec_uint(&rw->readers); } return; }
static void * fairness(void *null) { struct block *context = null; unsigned int i = context->tid; volatile int j; long int base; unsigned int core; CK_COHORT_INSTANCE(basic) *cohort; if (aff_iterate_core(&a, &core)) { perror("ERROR: Could not affine thread"); exit(EXIT_FAILURE); } cohort = &((cohorts + (core / (int)(a.delta)) % n_cohorts)->cohort); while (ck_pr_load_uint(&ready) == 0); ck_pr_inc_uint(&barrier); while (ck_pr_load_uint(&barrier) != nthr); while (ready) { CK_COHORT_LOCK(basic, cohort, NULL, NULL); count[i].value++; if (critical) { base = common_lrand48() % critical; for (j = 0; j < base; j++); } CK_COHORT_UNLOCK(basic, cohort, NULL, NULL); } return NULL; }
static void * fq_conn_worker(void *u) { int backoff = 0, i; bool zero; fq_conn_s *conn_s = (fq_conn_s *)u; cmd_instr *last_entries[MAX_PENDING] = { NULL }; int last_entry_idx = 0; int next_entry_idx = 0; #define SAVE_ENTRY(e) do { \ if(last_entries[next_entry_idx] != NULL) { \ CONNERR(conn_s, "exceed max cmd pipeline"); \ goto restart; \ } \ last_entries[next_entry_idx++] = e; \ next_entry_idx = next_entry_idx % MAX_PENDING; \ } while(0) #define last_entry last_entries[last_entry_idx] #define PROCESS_ENTRY(e, should_free) do { \ fq_assert(last_entries[last_entry_idx] == e); \ if(should_free) free(last_entries[last_entry_idx]); \ last_entries[last_entry_idx++] = NULL; \ last_entry_idx = last_entry_idx % MAX_PENDING; \ } while(0) cmd_instr *entry; ck_pr_inc_uint(&conn_s->thrcnt); while(conn_s->stop == 0) { int wait_ms = 50; if(fq_client_connect_internal(conn_s) == 0) { backoff = 0; /* we're good, restart our backoff */ } while(conn_s->data_ready && conn_s->stop == 0) { hrtime_t t; unsigned long long hb_us; struct timeval tv; int rv; ck_fifo_spsc_dequeue_lock(&conn_s->cmdq); while(ck_fifo_spsc_dequeue(&conn_s->cmdq, &entry) == true) { #ifdef DEBUG fq_debug(FQ_DEBUG_CONN, "client acting on user req 0x%04x\n", entry->cmd); #endif switch(entry->cmd) { case FQ_PROTO_STATUSREQ: fq_debug(FQ_DEBUG_CONN, "sending status request\n"); if(fq_write_uint16(conn_s->cmd_fd, entry->cmd)) { free(entry); CONNERR(conn_s, "write failed (statusreq)"); goto restart; } SAVE_ENTRY(entry); break; case FQ_PROTO_HBREQ: fq_debug(FQ_DEBUG_CONN, "sending heartbeat request\n"); if(fq_write_uint16(conn_s->cmd_fd, entry->cmd) || fq_write_uint16(conn_s->cmd_fd, entry->data.heartbeat.ms)) { free(entry); CONNERR(conn_s, "write failed (hbreq)"); goto restart; } conn_s->cmd_hb_ms = entry->data.heartbeat.ms; tv.tv_sec = (unsigned long)entry->data.heartbeat.ms / 1000; tv.tv_usec = 1000UL * (entry->data.heartbeat.ms % 1000); if(setsockopt(conn_s->cmd_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) CONNERR(conn_s, strerror(errno)); tv.tv_sec = (unsigned long)entry->data.heartbeat.ms / 1000; tv.tv_usec = 1000UL * (entry->data.heartbeat.ms % 1000); if(setsockopt(conn_s->cmd_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv))) CONNERR(conn_s, strerror(errno)); conn_s->cmd_hb_last = fq_gethrtime(); free(entry); break; case FQ_PROTO_BINDREQ: { unsigned short flags = entry->data.bind->flags; if(fq_write_uint16(conn_s->cmd_fd, entry->cmd) || fq_write_uint16(conn_s->cmd_fd, flags) || fq_write_short_cmd(conn_s->cmd_fd, entry->data.bind->exchange.len, entry->data.bind->exchange.name) < 0 || fq_write_short_cmd(conn_s->cmd_fd, strlen(entry->data.bind->program), entry->data.bind->program) < 0) { CONNERR(conn_s, "write failed (bindreq)"); goto restart; } SAVE_ENTRY(entry); } break; case FQ_PROTO_UNBINDREQ: { if(fq_write_uint16(conn_s->cmd_fd, entry->cmd) || fq_write_uint32(conn_s->cmd_fd, entry->data.unbind->route_id) || fq_write_short_cmd(conn_s->cmd_fd, entry->data.unbind->exchange.len, entry->data.unbind->exchange.name) < 0) { CONNERR(conn_s, "write failed (unbindreq)"); goto restart; } SAVE_ENTRY(entry); } break; default: CONNERR(conn_s, "unknown user-side cmd"); free(entry); } } ck_fifo_spsc_dequeue_unlock(&conn_s->cmdq); if(conn_s->cmd_hb_needed) { #ifdef DEBUG fq_debug(FQ_DEBUG_CONN, "-> heartbeat\n"); #endif if(fq_write_uint16(conn_s->cmd_fd, FQ_PROTO_HB)) { CONNERR(conn_s, "write failed (hb)"); break; } conn_s->cmd_hb_needed = 0; } rv = fq_client_wfrw_internal(conn_s->cmd_fd, 1, 0, wait_ms, NULL); if(rv == 0) { wait_ms = (wait_ms >> 2) + wait_ms; if(conn_s->cmd_hb_ms && wait_ms > conn_s->cmd_hb_ms) wait_ms = conn_s->cmd_hb_ms; if(wait_ms > 1000) wait_ms = 1000; } else wait_ms = 50; fq_debug(FQ_DEBUG_CONN, "fq_client_wfrw_internal(cmd:%d) -> %d\n", conn_s->cmd_fd, rv); t = fq_gethrtime(); hb_us = (unsigned long long)conn_s->cmd_hb_ms * 3 * 1000000ULL; if(conn_s->cmd_hb_last && hb_us && conn_s->cmd_hb_last < (unsigned int) (t - hb_us)) { char errbuf[256]; snprintf(errbuf, sizeof(errbuf), "heartbeat failed [%llu - %llu = %llu]", (unsigned long long)t, (unsigned long long)conn_s->cmd_hb_last, (unsigned long long)(t - conn_s->cmd_hb_last)); CONNERR(conn_s, errbuf); break; } if(rv < 0) { CONNERR(conn_s, strerror(errno)); break; } if(rv > 0) { bool handled = false; uint16_t hb; if(fq_read_uint16(conn_s->cmd_fd, &hb)) break; switch(hb) { case FQ_PROTO_HB: #ifdef DEBUG fq_debug(FQ_DEBUG_CONN, "<- heartbeat\n"); #endif conn_s->cmd_hb_last = fq_gethrtime(); conn_s->cmd_hb_needed = 1; break; case FQ_PROTO_STATUS: if(!last_entry || last_entry->cmd != FQ_PROTO_STATUSREQ) { CONNERR(conn_s, "protocol violation (status unexpected)"); goto restart; } if(fq_read_status(conn_s->cmd_fd, last_entry->data.status.callback, last_entry->data.status.closure)) goto restart; PROCESS_ENTRY(last_entry, 1); break; case FQ_PROTO_BIND: if(!last_entry || last_entry->cmd != FQ_PROTO_BINDREQ) { CONNERR(conn_s, "protocol violation (bind unexpected)"); goto restart; } if(fq_read_uint32(conn_s->cmd_fd, &last_entry->data.bind->out__route_id)) { if(conn_s->bind_hook) { if(conn_s->sync_hooks) { enqueue_cmd_hook_req(conn_s, last_entry); PROCESS_ENTRY(last_entry, 0); handled = true; } else conn_s->bind_hook((fq_client)conn_s, last_entry->data.bind); } CONNERR(conn_s, "read failed (bind)"); goto restart; } if(conn_s->bind_hook) { if(conn_s->sync_hooks) { enqueue_cmd_hook_req(conn_s, last_entry); PROCESS_ENTRY(last_entry, 0); handled = true; } else conn_s->bind_hook((fq_client)conn_s, last_entry->data.bind); } if(!handled) PROCESS_ENTRY(last_entry, 1); break; case FQ_PROTO_UNBIND: if(!last_entry || last_entry->cmd != FQ_PROTO_UNBINDREQ) { CONNERR(conn_s, "protocol violation (unbind unexpected)"); goto restart; } if(fq_read_uint32(conn_s->cmd_fd, &last_entry->data.unbind->out__success)) { if(conn_s->unbind_hook) { if(conn_s->sync_hooks) { enqueue_cmd_hook_req(conn_s, last_entry); PROCESS_ENTRY(last_entry, 0); handled = true; } conn_s->unbind_hook((fq_client)conn_s, last_entry->data.unbind); } CONNERR(conn_s, "read failed (unbind)"); goto restart; } if(conn_s->unbind_hook) { if(conn_s->sync_hooks) { enqueue_cmd_hook_req(conn_s, last_entry); PROCESS_ENTRY(last_entry, 0); handled = true; last_entry = NULL; } conn_s->unbind_hook((fq_client)conn_s, last_entry->data.unbind); } if(!handled) PROCESS_ENTRY(last_entry,1); break; default: CONNERR(conn_s, "protocol violation"); goto restart; break; } } }
static void * thread(void *null) { struct block *context = null; int i = ITERATE; unsigned int l; if (aff_iterate(&a)) { perror("ERROR: Could not affine thread"); exit(EXIT_FAILURE); } if (context->tid == (unsigned int)nthr - 1) context->tid = sizeof(lock.readers) + 1; while (i--) { ck_bytelock_write_lock(&lock, context->tid); { 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_bytelock_write_unlock(&lock); ck_bytelock_read_lock(&lock, context->tid); { l = ck_pr_load_uint(&locked); if (l != 0) { ck_error("ERROR [RD:%d]: %u != 0\n", __LINE__, l); } } ck_bytelock_read_unlock(&lock, context->tid); } return (NULL); }
void fqd_remote_client_ref(remote_client *r) { ck_pr_inc_uint(&r->refcnt); }
int main(int argc, char** argv) { ck_hp_fifo_entry_t *stub; unsigned long element_count, i; pthread_t *thr; if (argc != 3) { ck_error("Usage: cktest <thread_count> <element_count>\n"); } /* Get element count from argument */ element_count = atoi(argv[2]); /* Get element count from argument */ thread_count = atoi(argv[1]); /* pthread handles */ thr = malloc(sizeof(pthread_t) * thread_count); /* array for local operation count */ count = malloc(sizeof(unsigned long *) * thread_count); /* * Initialize global hazard pointer safe memory reclamation to execute free() * when a fifo_entry is safe to be deleted. * Hazard pointer scan routine will be called when the thread local intern plist's * size exceed 100 entries. */ /* FIFO queue needs 2 hazard pointers */ ck_hp_init(&fifo_hp, CK_HP_FIFO_SLOTS_COUNT, 100, destructor); /* The FIFO requires one stub entry on initialization. */ stub = malloc(sizeof(ck_hp_fifo_entry_t)); /* Behavior is undefined if stub is NULL. */ if (stub == NULL) { exit(EXIT_FAILURE); } /* This is called once to initialize the fifo. */ ck_hp_fifo_init(&fifo, stub); /* Create threads */ for (i = 0; i < thread_count; i++) { count[i] = (element_count + i) / thread_count; if (pthread_create(&thr[i], NULL, queue_50_50, (void *) &count[i]) != 0) { exit(EXIT_FAILURE); } } /* start barrier */ ck_pr_inc_uint(&start_barrier); while (ck_pr_load_uint(&start_barrier) < thread_count + 1); /* end barrier */ ck_pr_inc_uint(&end_barrier); while (ck_pr_load_uint(&end_barrier) < thread_count + 1); /* Join threads */ for (i = 0; i < thread_count; i++) pthread_join(thr[i], NULL); return 0; }
static void * reader(void *arg) { void *curr_ptr; intptr_t curr, prev, curr_max, prev_max; unsigned long long n_entries = 0, iterations = 0; ck_epoch_record_t epoch_record; ck_bag_iterator_t iterator; struct ck_bag_block *block = NULL; (void)arg; ck_epoch_register(&epoch_bag, &epoch_record); /* * Check if entries within a block are sequential. Since ck_bag inserts * newly occupied blocks at the beginning of the list, there is no ordering * guarantee across the bag. */ for (;;) { ck_epoch_read_begin(&epoch_record); ck_bag_iterator_init(&iterator, &bag); curr_max = prev_max = prev = -1; block = NULL; while (ck_bag_next(&iterator, &curr_ptr) == true) { if (block != iterator.block) { prev = -1; curr = 0; prev_max = curr_max; curr_max = 0; block = iterator.block; } curr = (uintptr_t)(curr_ptr); if (curr < prev) { /* Ascending order within block violated */ fprintf(stderr, "%p: %p: %ju\n", (void *)&epoch_record, (void *)iterator.block, (uintmax_t)curr); fprintf(stderr, "ERROR: %ju < %ju \n", (uintmax_t)curr, (uintmax_t)prev); exit(EXIT_FAILURE); } else if (prev_max != -1 && curr > prev_max) { /* Max of prev block > max of current block */ fprintf(stderr, "%p: %p: %ju\n", (void *)&epoch_record, (void *)iterator.block, (uintmax_t)curr); fprintf(stderr, "ERROR: %ju > prev_max: %ju\n", (uintmax_t)curr, (uintmax_t)prev_max); exit(EXIT_FAILURE); } curr_max = curr; prev = curr; n_entries++; } ck_epoch_read_end(&epoch_record); iterations++; if (ck_pr_load_int(&leave) == 1) break; } fprintf(stderr, "Read %llu entries in %llu iterations.\n", n_entries, iterations); ck_pr_inc_uint(&barrier); while (ck_pr_load_uint(&barrier) != NUM_READER_THREADS + 1) ck_pr_stall(); return NULL; }
void fq_msg_ref(fq_msg *msg) { ck_pr_inc_uint(&msg->refcnt); }
static fq_msg *queue_jlog_dequeue(fqd_queue_impl_data f) { struct queue_jlog *d = (struct queue_jlog *)f; jlog_message msg; fq_msg *m; if(d->count == 0 && d->last_seen_nenqueued == d->nenqueued) return NULL; retry: if(d->count <= 0) { d->count = jlog_ctx_read_interval(d->reader, &d->start, &d->finish); fq_debug(FQ_DEBUG_IO, "jlog read batch count -> %d\n", d->count); if(d->count < 0) { char idxfile[PATH_MAX]; fq_debug(FQ_DEBUG_IO, "jlog_ctx_read_interval: %s\n", jlog_ctx_err_string(d->reader)); switch (jlog_ctx_err(d->reader)) { case JLOG_ERR_FILE_CORRUPT: case JLOG_ERR_IDX_CORRUPT: jlog_repair_datafile(d->reader, d->start.log); jlog_repair_datafile(d->reader, d->start.log + 1); fq_debug(FQ_DEBUG_IO, "jlog reconstructed, deleting corresponding index.\n"); STRSETDATAFILE(d->reader, idxfile, d->start.log); strncpy(idxfile + strlen(idxfile), INDEX_EXT, sizeof(idxfile) - strlen(idxfile)); unlink(idxfile); STRSETDATAFILE(d->reader, idxfile, d->start.log + 1); strncpy(idxfile + strlen(idxfile), INDEX_EXT, sizeof(idxfile) - strlen(idxfile)); unlink(idxfile); break; default: break; } } if(d->count <= 0) return NULL; } if(jlog_ctx_read_message(d->reader, &d->start, &msg) == -1) { d->count = 0; return NULL; } if(d->last_dequeued.log > d->start.log || (d->last_dequeued.log == d->start.log && d->last_dequeued.marker > d->start.marker)) { d->count--; JLOG_ID_ADVANCE(&d->start); goto retry; } if(msg.mess_len < sizeof(fq_msg)-1) m = NULL; else { off_t expected_len; uint32_t payload_len; m = (fq_msg *)msg.mess; memcpy(&payload_len, &m->payload_len, sizeof(m->payload_len)); expected_len = offsetof(fq_msg, payload) + payload_len; if(expected_len != msg.mess_len) m = NULL; else { m = malloc(expected_len); memcpy(m, msg.mess, expected_len); m->sender_msgid.id.u32.p3 = d->start.log; m->sender_msgid.id.u32.p4 = d->start.marker; } } d->count--; fq_debug(FQ_DEBUG_IO, "jlog batch count -> %d\n", d->count); if(d->count == 0) { if(d->auto_chkpt) { jlog_ctx_read_checkpoint(d->reader, &d->start); } } d->last_dequeued = d->start; JLOG_ID_ADVANCE(&d->start); ck_pr_inc_uint(&d->last_seen_nenqueued); return m; }
/* 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; }