void *test_hash_rw_thr_reader(void *_count) { unsigned long long *count = _count; struct lfht_test_node *node; struct cds_lfht_iter iter; printf_verbose("thread_begin %s, tid %lu\n", "reader", urcu_get_thread_id()); URCU_TLS(rand_lookup) = urcu_get_thread_id() ^ time(NULL); set_affinity(); rcu_register_thread(); while (!test_go) { } cmm_smp_mb(); for (;;) { rcu_read_lock(); cds_lfht_test_lookup(test_ht, (void *)(((unsigned long) rand_r(&URCU_TLS(rand_lookup)) % lookup_pool_size) + lookup_pool_offset), sizeof(void *), &iter); node = cds_lfht_iter_get_test_node(&iter); if (node == NULL) { if (validate_lookup) { printf("[ERROR] Lookup cannot find initial node.\n"); exit(-1); } URCU_TLS(lookup_fail)++; } else { URCU_TLS(lookup_ok)++; } rcu_debug_yield_read(); if (caa_unlikely(rduration)) loop_sleep(rduration); rcu_read_unlock(); URCU_TLS(nr_reads)++; if (caa_unlikely(!test_duration_read())) break; if (caa_unlikely((URCU_TLS(nr_reads) & ((1 << 10) - 1)) == 0)) rcu_quiescent_state(); } rcu_unregister_thread(); *count = URCU_TLS(nr_reads); printf_verbose("thread_end %s, tid %lu\n", "reader", urcu_get_thread_id()); printf_verbose("read tid : %lx, lookupfail %lu, lookupok %lu\n", urcu_get_thread_id(), URCU_TLS(lookup_fail), URCU_TLS(lookup_ok)); return ((void*)1); }
void* run(void* arg) { unsigned long i; char iamreader; int key; long t = (long) arg; long nbn;//same cache line for the best rand! double start, end; node_t **hd; lock_t *lck; set_affinity(t); /************ init *****************/ thd_ins = 0; thd_del = 0; thd_sea = 0; nbmallocs = 0; nbretry = 0; nbrelink = 0; nbreprev = 0; nbfl = 0; thread=t; thd_nbupdaters=nbupdaters; setsignals(); iamreader = t >= nbupdaters ? 1 : 0; if(!iamreader) prealloc(); mysrand(t^time(NULL)); /************** init done **************/ /************** barrier ****************/ atomic_xadd4(&ready, 1); while(!go) memory_barrier(); /******************* START ****************/ start = d_gettimeofday(); #ifdef RCU rcu_register_thread(); #endif i=0; do{ key = myrand()%nbkeys; //key = rand_r(&thd_seed)%nbthreads; //key = (t+key)%nbkeys; //key = random() % nbkeys; //if(i%100000) printf("%d %d\n", thread, key); get_buckets(key, &hd, &lck); if(iamreader) { thd_sea += search(key, hd, lck); if(i>= NB_TEST) break; } else { if(i%2) thd_ins += insert(key, hd, lck); else thd_del += delete(key, hd, lck); if(done) { //printf("writer stopped\n"); break; } } //if(!(i%10000)) //printf("%d loop %d\n", t, i); #ifdef RCU_QSBR #if ((defined RCU_QSBR_ACCELERATE) || (defined RCU_Q10)) #ifdef RCU_Q10 if(!(i%10)) #else if(!(i%100)) #endif #endif rcu_quiescent_state(); #endif }while(++i); #ifdef RCU //if(!iamreader) rcu_barrier(); //printf("iamreader %d, ops %d\n", iamreader, i); rcu_unregister_thread(); #endif end = d_gettimeofday(); /******************* END ****************/ //number of ops done thd_ops[t] = i; //printf("nbmallocs %g\n", nbmallocs); thd_mallocs[t] = nbmallocs; thd_retry[t] = nbretry; thd_relink[t] = nbrelink; thd_reprev[t] = nbreprev; //if(t==0) printf("%lu | nbblocked %g\n", t, nbblockeds); #ifdef RCU thd_blockeds[t] = atomic_read_ptr(&rcublockeds); #else thd_blockeds[t] = nbblockeds; #endif //average time per ops avg_time[t] = (((end - start))/i); //total time thd_time[t] = (end - start); suc_ins[t] = thd_ins; suc_sea[t] = thd_sea; suc_del[t] = thd_del; return NULL; }
void *test_hash_rw_thr_writer(void *_count) { struct lfht_test_node *node; struct cds_lfht_node *ret_node; struct cds_lfht_iter iter; struct wr_count *count = _count; int ret; printf_verbose("thread_begin %s, tid %lu\n", "writer", urcu_get_thread_id()); URCU_TLS(rand_lookup) = urcu_get_thread_id() ^ time(NULL); set_affinity(); rcu_register_thread(); while (!test_go) { } cmm_smp_mb(); for (;;) { if ((addremove == AR_ADD || add_only) || (addremove == AR_RANDOM && rand_r(&URCU_TLS(rand_lookup)) & 1)) { node = malloc(sizeof(struct lfht_test_node)); lfht_test_node_init(node, (void *)(((unsigned long) rand_r(&URCU_TLS(rand_lookup)) % write_pool_size) + write_pool_offset), sizeof(void *)); rcu_read_lock(); if (add_unique) { ret_node = cds_lfht_add_unique(test_ht, test_hash(node->key, node->key_len, TEST_HASH_SEED), test_match, node->key, &node->node); } else { if (add_replace) ret_node = cds_lfht_add_replace(test_ht, test_hash(node->key, node->key_len, TEST_HASH_SEED), test_match, node->key, &node->node); else cds_lfht_add(test_ht, test_hash(node->key, node->key_len, TEST_HASH_SEED), &node->node); } rcu_read_unlock(); if (add_unique && ret_node != &node->node) { free(node); URCU_TLS(nr_addexist)++; } else { if (add_replace && ret_node) { call_rcu(&to_test_node(ret_node)->head, free_node_cb); URCU_TLS(nr_addexist)++; } else { URCU_TLS(nr_add)++; } } } else { /* May delete */ rcu_read_lock(); cds_lfht_test_lookup(test_ht, (void *)(((unsigned long) rand_r(&URCU_TLS(rand_lookup)) % write_pool_size) + write_pool_offset), sizeof(void *), &iter); ret = cds_lfht_del(test_ht, cds_lfht_iter_get_node(&iter)); rcu_read_unlock(); if (ret == 0) { node = cds_lfht_iter_get_test_node(&iter); call_rcu(&node->head, free_node_cb); URCU_TLS(nr_del)++; } else URCU_TLS(nr_delnoent)++; } #if 0 //if (URCU_TLS(nr_writes) % 100000 == 0) { if (URCU_TLS(nr_writes) % 1000 == 0) { rcu_read_lock(); if (rand_r(&URCU_TLS(rand_lookup)) & 1) { ht_resize(test_ht, 1); } else { ht_resize(test_ht, -1); } rcu_read_unlock(); } #endif //0 URCU_TLS(nr_writes)++; if (caa_unlikely(!test_duration_write())) break; if (caa_unlikely(wdelay)) loop_sleep(wdelay); if (caa_unlikely((URCU_TLS(nr_writes) & ((1 << 10) - 1)) == 0)) rcu_quiescent_state(); } rcu_unregister_thread(); printf_verbose("thread_end %s, tid %lu\n", "writer", urcu_get_thread_id()); printf_verbose("info tid %lu: nr_add %lu, nr_addexist %lu, nr_del %lu, " "nr_delnoent %lu\n", urcu_get_thread_id(), URCU_TLS(nr_add), URCU_TLS(nr_addexist), URCU_TLS(nr_del), URCU_TLS(nr_delnoent)); count->update_ops = URCU_TLS(nr_writes); count->add = URCU_TLS(nr_add); count->add_exist = URCU_TLS(nr_addexist); count->remove = URCU_TLS(nr_del); return ((void*)2); }