void *memblock_test(void *arg) { long cnt = 0; long cntfail = 0; int i; int runlength = (int)(long)arg; struct memblock *p[MAX_RUN]; if (runlength > MAX_RUN) runlength = MAX_RUN; while (goflag) { for (i = 0; i < runlength; i++) p[i] = memblock_alloc(); for (i = 0; i < runlength; i++) { if (p[i] == NULL) { cntfail++; } else { memblock_free(p[i]); cnt++; } } } __get_thread_var(results) += cnt; __get_thread_var(failures) += cntfail; return NULL; }
void *init_test(void *arg) { while (goflag != GOFLAG_STOP) { while (goflag == GOFLAG_INIT) poll(NULL, 0, 1); if (goflag == GOFLAG_STOP) break; atomic_inc(&start_count); while (atomic_read(&start_count) != nkids) continue; /* --- Lock-free checked initialization --- */ if (!initialized) { spin_lock(&mutex); initialized = 1; atomic_inc(&counter); spin_unlock(&mutex); } /* --- End of lock-free checked initialization --- */ __get_thread_var(doneflag) = 1; while (goflag == GOFLAG_START) poll(NULL, 0, 1); atomic_inc(&counter); } return NULL; }
void *seqlock_read_test(void *arg) { int i; int j; int me = (long)arg; long long n_errs_local = 0LL; long long n_reads_local = 0LL; long long n_retries_local = 0LL; long long n_retries_local_cur = 0LL; unsigned long old; unsigned long seq; run_on(me); atomic_inc(&nthreadsrunning); while (ACCESS_ONCE(goflag) == GOFLAG_INIT) poll(NULL, 0, 1); while (ACCESS_ONCE(goflag) == GOFLAG_RUN) { for (i = COUNT_READ_RUN; i > 0; i--) { n_retries_local_cur = -1; do { seq = read_seqbegin(&test_seqlock); old = testarray[0]; n_errs_local = 0; n_retries_local_cur++; for (j = 1; j < n_elems; j++) { if (old + 1 != testarray[j]) n_errs_local++; old = testarray[j]; } } while (read_seqretry(&test_seqlock, seq)); n_retries_local += n_retries_local_cur; barrier(); } n_reads_local += COUNT_READ_RUN; } __get_thread_var(n_reads_pt) += n_reads_local; __get_thread_var(n_read_retries_pt) += n_retries_local; __get_thread_var(n_read_errs_pt) += n_errs_local; return (NULL); }
void memblock_free(struct memblock *p) { int i; struct perthreadmempool *pcpp = &__get_thread_var(perthreadmem); if (pcpp->cur >= 2 * TARGET_POOL_SIZE - 1) { spin_lock(&globalmem.mutex); for (i = pcpp->cur; i >= TARGET_POOL_SIZE; i--) { globalmem.pool[++globalmem.cur] = pcpp->pool[i]; pcpp->pool[i] = NULL; } pcpp->cur = i; spin_unlock(&globalmem.mutex); } pcpp->pool[++pcpp->cur] = p; }
struct memblock *memblock_alloc(void) { int i; struct memblock *p; struct perthreadmempool *pcpp = &__get_thread_var(perthreadmem); if (pcpp->cur < 0) { spin_lock(&globalmem.mutex); for (i = 0; i < TARGET_POOL_SIZE && globalmem.cur >= 0; i++) { pcpp->pool[i] = globalmem.pool[globalmem.cur]; globalmem.pool[globalmem.cur--] = NULL; } pcpp->cur = i - 1; spin_unlock(&globalmem.mutex); } if (pcpp->cur >= 0) { p = pcpp->pool[pcpp->cur]; pcpp->pool[pcpp->cur--] = NULL; return p; } return NULL; }
void *seqlock_write_test(void *arg) { int i; int j; int me = (long)arg; long long n_writes_local = 0LL; run_on(me); atomic_inc(&nthreadsrunning); while (ACCESS_ONCE(goflag) == GOFLAG_INIT) poll(NULL, 0, 1); while (ACCESS_ONCE(goflag) == GOFLAG_RUN) { for (i = COUNT_UPDATE_RUN; i > 0; i--) { write_seqlock(&test_seqlock); for (j = 0; j < n_elems; j++) testarray[j]++; write_sequnlock(&test_seqlock); barrier(); } n_writes_local += COUNT_UPDATE_RUN; } __get_thread_var(n_writes_pt) += n_writes_local; return NULL; }
void inc_count(void) { ACCESS_ONCE(__get_thread_var(counter))++; }
void inc_count(void) { atomic_inc(&__get_thread_var(counter)); }
void inc_count(void) { __get_thread_var(counter)++; }
int main(int argc, char *argv[]) { int done; int i; int iter; smp_init(); if (argc > 1) { nkids = strtoul(argv[1], NULL, 0); if (nkids > NR_THREADS) { fprintf(stderr, "nkids = %d too large, max = %d\n", nkids, NR_THREADS); usage(argv[0]); } } printf("Number of threads: %d\n", nkids); spin_lock_init(&mutex); goflag = GOFLAG_INIT; for (i = 0; i < nkids; i++) create_thread(init_test, NULL); for (iter = 0; iter < 100; iter++) { spin_lock(&mutex); for_each_thread(i) { per_thread(doneflag, i) = 0; } __get_thread_var(doneflag) = 1; atomic_set(&counter, 0); atomic_set(&start_count, 0); initialized = 0; spin_unlock(&mutex); spin_lock(&mutex); goflag = GOFLAG_START; spin_unlock(&mutex); poll(NULL, 0, 1); done = 0; while (!done) { done = 1; for (i = 0; i < nkids; i++) if (!per_thread(doneflag, i)) { done = 0; break; } poll(NULL, 0, 1); } if (atomic_read(&counter) != 1) { printf("Double initialization, counter = %d\n", atomic_read(&counter)); exit(-1); } else { printf("Iteration %d succeeded\n", iter); } spin_lock(&mutex); atomic_set(&counter, 0); spin_unlock(&mutex); spin_lock(&mutex); goflag = GOFLAG_INIT; while (atomic_read(&counter) < nkids) poll(NULL, 0, 1); spin_unlock(&mutex); spin_lock(&mutex); atomic_set(&counter, 0); spin_unlock(&mutex); } goflag = GOFLAG_STOP; wait_all_threads(); exit(0); }