void* test(void *data) { int unext, last = -1; val_t val = 0; pval_t pval = 0; thread_data_t *d = (thread_data_t *)data; /* Create transaction */ TM_THREAD_ENTER(d->id); set_cpu(the_cores[d->id]); /* Wait on barrier */ ssalloc_init(); PF_CORRECTION; seeds = seed_rand(); #ifdef PIN int id = d->id; int cpu = 40*(id/40) + 4*(id%10) + (id%40)/10; // printf("Pinning %d to %d\n",id,cpu); pin(pthread_self(), cpu); // pin(pthread_self(), id); #endif #ifdef PAPI if (PAPI_OK != PAPI_start_counters(g_events, G_EVENT_COUNT)) { printf("Problem starting counters 1."); } #endif barrier_cross(d->barrier); /* Is the first op an update? */ unext = (rand_range_re(&d->seed, 100) - 1 < d->update); #ifdef DISTRIBUTION_EXPERIMENT while (1) #else while (*running) #endif { if (d->es) { // event simulator experiment if (d->lin) { if (!empty(d->linden_set)) { d->nb_remove++; pval_t pval = deletemin(d->linden_set, d); d->nb_removed++; // printf("%d %d\n", pval, deps[pval][0]); int i = 0; val_t dep; while ((dep = deps[pval][i]) != -1 && i < MAX_DEPS) { d->nb_add++; if (insert(d->linden_set, dep, dep)) { d->nb_added++; } i++; } } } else { if (d->set->head->next[0]->next[0] != NULL) {// set not empty d->nb_remove++; if (d->sl) { // spray list if (spray_delete_min(d->set, &val, d)) { d->nb_removed++; } else { continue; } } else if (d->pq) { // lotan_shavit pq if (lotan_shavit_delete_min(d->set, &val, d)) { d->nb_removed++; // continue; // TODO: maybe try remove this to simulate task handling (dependency checks still occur) } else { continue; } } // struct timespec ten_usec; // ten_usec.tv_sec = 0; // ten_usec.tv_nsec = 10000; // nanosleep(&ten_usec, NULL); // dependency handling int i = 0; val_t dep; while ((dep = deps[val][i]) != -1 && i < MAX_DEPS) { if (!sl_contains(d->set, dep, TRANSACTIONAL)) { // dependent has been removed, need to add it again if (sl_add(d->set, dep, TRANSACTIONAL)) { // check if insert actually succeeded (otherwise someone else did it first) d->nb_added++; } d->nb_add++; } i++; } } } } else { // not event simulator if (unext) { // update if (last < 0) { // add val = rand_range_re(&d->seed, d->range); if (d->lin) { pval = val; insert(d->linden_set, pval, pval); d->nb_added++; last = pval; } else { // not linden if (sl_add(d->set, val, TRANSACTIONAL)) { d->nb_added++; last = val; } } d->nb_add++; } else { // remove if (d->pq) { if (lotan_shavit_delete_min(d->set, &val, d)) { d->nb_removed++; if (d->first_remove == -1) { d->first_remove = val; } } last = -1; } else if (d->sl) { if (spray_delete_min(d->set, &val, d)) { d->nb_removed++; if (d->first_remove == -1) { d->first_remove = val; } last = -1; } } else if (d->lin) { if ((pval = deletemin(d->linden_set, d))) { d->nb_removed++; if (d->first_remove == -1) { d->first_remove = pval; } last = -1; } } else if (d->alternate) { // alternate mode (default) if (sl_remove(d->set, last, TRANSACTIONAL)) { d->nb_removed++; if (d->first_remove == -1) { d->first_remove = val; } } last = -1; } else { /* Random computation only in non-alternated cases */ val = rand_range_re(&d->seed, d->range); /* Remove one random value */ if (sl_remove_succ(d->set, val, TRANSACTIONAL)) { d->nb_removed++; if (d->first_remove == -1) { d->first_remove = val; } /* Repeat until successful, to avoid size variations */ last = -1; } } d->nb_remove++; } } else { // read if (d->alternate) { if (d->update == 0) { if (last < 0) { val = d->first; last = val; } else { // last >= 0 val = rand_range_re(&d->seed, d->range); last = -1; } } else { // update != 0 if (last < 0) { val = rand_range_re(&d->seed, d->range); //last = val; } else { val = last; } } } else val = rand_range_re(&d->seed, d->range); PF_START(2); if (sl_contains(d->set, val, TRANSACTIONAL)) d->nb_found++; PF_STOP(2); d->nb_contains++; } /* Is the next op an update? */ if (d->effective) { // a failed remove/add is a read-only tx unext = ((100 * (d->nb_added + d->nb_removed)) < (d->update * (d->nb_add + d->nb_remove + d->nb_contains))); } else { // remove/add (even failed) is considered as an update unext = (rand_range_re(&d->seed, 100) - 1 < d->update); } } #ifdef DISTRIBUTION_EXPERIMENT if (d->first_remove != -1) { break; //only one run } #endif } #ifdef PAPI if (PAPI_OK != PAPI_read_counters(g_values[d->id], G_EVENT_COUNT)) { printf("Problem reading counters 2."); } #endif /* Free transaction */ TM_THREAD_EXIT(); PF_PRINT; return NULL; }
int main(int argc, char **argv) { set_cpu(the_cores[0]); ssalloc_init(); seeds = seed_rand(); #ifdef PAPI if (PAPI_VER_CURRENT != PAPI_library_init(PAPI_VER_CURRENT)) { printf("PAPI_library_init error.\n"); return 0; } else { printf("PAPI_library_init success.\n"); } if (PAPI_OK != PAPI_query_event(PAPI_L1_DCM)) { printf("Cannot count PAPI_L1_DCM."); } printf("PAPI_query_event: PAPI_L1_DCM OK.\n"); if (PAPI_OK != PAPI_query_event(PAPI_L2_DCM)) { printf("Cannot count PAPI_L2_DCM."); } printf("PAPI_query_event: PAPI_L2_DCM OK.\n"); #endif struct option long_options[] = { // These options don't set a flag {"help", no_argument, NULL, 'h'}, {"duration", required_argument, NULL, 'd'}, {"priority-queue", required_argument, NULL, 'p'}, {"linden", required_argument, NULL, 'L'}, {"spray-list", required_argument, NULL, 'l'}, {"event-simulator", required_argument, NULL, 'e'}, {"initial-size", required_argument, NULL, 'i'}, {"num-threads", required_argument, NULL, 'n'}, {"range", required_argument, NULL, 'r'}, {"seed", required_argument, NULL, 's'}, {"update-rate", required_argument, NULL, 'u'}, {"elasticity", required_argument, NULL, 'x'}, {"nothing", required_argument, NULL, 'l'}, {NULL, 0, NULL, 0} }; sl_intset_t *set; pq_t *linden_set; int i, c, size; val_t last = 0; val_t val = 0; pval_t pval = 0; unsigned long reads, effreads, updates, collisions, effupds, aborts, aborts_locked_read, aborts_locked_write, aborts_validate_read, aborts_validate_write, aborts_validate_commit, add, added, remove, removed, aborts_invalid_memory, aborts_double_write, max_retries, failures_because_contention, depdist; thread_data_t *data; pthread_t *threads; pthread_attr_t attr; barrier_t barrier; struct timeval start, end; struct timespec timeout; int duration = DEFAULT_DURATION; int initial = DEFAULT_INITIAL; int nb_threads = DEFAULT_NB_THREADS; long range = DEFAULT_RANGE; int seed = DEFAULT_SEED; int seed2 = DEFAULT_SEED; int update = DEFAULT_UPDATE; int unit_tx = DEFAULT_ELASTICITY; int alternate = DEFAULT_ALTERNATE; int pq = DEFAULT_PQ; int sl = DEFAULT_SL; int es = DEFAULT_ES; int lin = DEFAULT_LIN; int effective = DEFAULT_EFFECTIVE; sigset_t block_set; while(1) { i = 0; c = getopt_long(argc, argv, "hAplLe:f:d:i:n:r:s:u:x:l:", long_options, &i); if(c == -1) break; if(c == 0 && long_options[i].flag == 0) c = long_options[i].val; switch(c) { case 0: break; case 'h': printf("intset -- STM stress test " "(skip list)\n" "\n" "Usage:\n" " intset [options...]\n" "\n" "Options:\n" " -h, --help\n" " Print this message\n" " -A, --Alternate\n" " Consecutive insert/remove target the same value\n" " -l, --spray-list\n" " Remove via delete_min operations using a spray list\n" " -p, --priority-queue\n" " Remove via delete_min operations using a skip list\n" " -e, --event-simulator\n" " Descrete event simulator experiment, parameter = dependency distance\n" " -L, --linden\n" " Use Linden's priority queue\n" " -f, --effective <int>\n" " update txs must effectively write (0=trial, 1=effective, default=" XSTR(DEFAULT_EFFECTIVE) ")\n" " -d, --duration <int>\n" " Test duration in milliseconds (0=infinite, default=" XSTR(DEFAULT_DURATION) ")\n" " -i, --initial-size <int>\n" " Number of elements to insert before test (default=" XSTR(DEFAULT_INITIAL) ")\n" " -n, --num-threads <int>\n" " Number of threads (default=" XSTR(DEFAULT_NB_THREADS) ")\n" " -r, --range <int>\n" " Range of integer values inserted in set (default=" XSTR(DEFAULT_RANGE) ")\n" " -s, --seed <int>\n" " RNG seed (0=time-based, default=" XSTR(DEFAULT_SEED) ")\n" " -u, --update-rate <int>\n" " Percentage of update transactions (default=" XSTR(DEFAULT_UPDATE) ")\n" " -x, --elasticity (default=4)\n" " Use elastic transactions\n" " 0 = non-protected,\n" " 1 = normal transaction,\n" " 2 = read elastic-tx,\n" " 3 = read/add elastic-tx,\n" " 4 = read/add/rem elastic-tx,\n" " 5 = fraser lock-free\n" ); exit(0); case 'A': alternate = 1; break; case 'l': sl = 1; break; case 'p': pq = 1; break; case 'e': es = 1; depdist = atoi(optarg); break; case 'L': lin = 1; break; case 'f': effective = atoi(optarg); break; case 'd': duration = atoi(optarg); break; case 'i': initial = atoi(optarg); break; case 'n': nb_threads = atoi(optarg); break; case 'r': range = atol(optarg); break; case 's': seed = atoi(optarg); break; case 'u': update = atoi(optarg); break; case 'x': unit_tx = atoi(optarg); break; case '?': printf("Use -h or --help for help\n"); exit(0); default: exit(1); } } assert(duration >= 0); assert(initial >= 0); assert(nb_threads > 0); assert(range > 0); assert(update >= 0 && update <= 100); // if (range < initial) // { range = 100000000; // } printf("Set type : skip list\n"); printf("Duration : %d\n", duration); printf("Initial size : %u\n", initial); printf("Nb threads : %d\n", nb_threads); printf("Value range : %ld\n", range); printf("Seed : %d\n", seed); printf("Update rate : %d\n", update); printf("Elasticity : %d\n", unit_tx); printf("Alternate : %d\n", alternate); printf("Priority Q : %d\n", pq); printf("Spray List : %d\n", sl); printf("Linden : %d\n", lin); printf("Efffective : %d\n", effective); printf("Type sizes : int=%d/long=%d/ptr=%d/word=%d\n", (int)sizeof(int), (int)sizeof(long), (int)sizeof(void *), (int)sizeof(uintptr_t)); timeout.tv_sec = duration / 1000; timeout.tv_nsec = (duration % 1000) * 1000000; if ((data = (thread_data_t *)malloc(nb_threads * sizeof(thread_data_t))) == NULL) { perror("malloc"); exit(1); } if ((threads = (pthread_t *)malloc(nb_threads * sizeof(pthread_t))) == NULL) { perror("malloc"); exit(1); } if (seed == 0) srand((int)time(0)); else srand(seed); *levelmax = floor_log_2((unsigned int) initial); set = sl_set_new(); /* stop = 0; */ *running = 1; // Init STM printf("Initializing STM\n"); TM_STARTUP(); // Populate set printf("Adding %d entries to set\n", initial); i = 0; if (lin) { int offset = 32; // not sure what this does _init_gc_subsystem(); linden_set = pq_init(offset); } if (es) { // event simulator has event ids 1..m // no timeout in ES, finishes when list is empty // timeout.tv_sec = 0; // timeout.tv_nsec = 0; if ((nb_deps = (int *)malloc(initial * sizeof(int))) == NULL) { perror("malloc"); exit(1); } if ((deps = (val_t **)malloc(initial * sizeof(val_t*))) == NULL) { perror("malloc"); exit(1); } while (i < initial) { if ((deps[i] = (val_t*)malloc(MAX_DEPS * sizeof(val_t))) == NULL) { perror("malloc"); exit(1); } int num_deps = 0; nb_deps[i] = 0; if (lin) { insert(linden_set, i, i); } else { sl_add(set, (val_t)i, 0); } while (i < initial-1 && num_deps < MAX_DEPS && rand_range_re(NULL, 3) % 2) { // Add geometrically distributed # of deps TODO: parametrize '2' val_t dep = ((val_t)i)+1; int dep_var = sqrt(depdist); dep += depdist + rand_range_re(NULL,2*dep_var) - dep_var; if (dep >= initial) dep = initial-1; // while (dep < initial-1 && rand_range_re(NULL, 11) % 10) { // dep should be i+GEO(10) TODO: parametrize '10' // dep++; // } deps[i][num_deps] = dep; num_deps++; } nb_deps[i] = num_deps; if (num_deps < MAX_DEPS) { deps[i][num_deps] = -1; // marks last dep } i++; } } else if (lin) { while (i < initial) { #ifdef DISTRIBUTION_EXPERIMENT pval = i; #else pval = rand_range_re(NULL, range); #endif insert(linden_set, pval, pval); last = pval; i++; } } else { while (i < initial) { #ifdef DISTRIBUTION_EXPERIMENT val = i; #else val = rand_range_re(NULL, range); #endif if (sl_add(set, val, 0)) { last = val; i++; } } } #ifdef PRINT_LIST print_skiplist(set); #endif size = sl_set_size(set); printf("Set size : %d\n", size); printf("Level max : %d\n", *levelmax); // Access set from all threads barrier_init(&barrier, nb_threads + 1); pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); printf("Creating threads: "); for (i = 0; i < nb_threads; i++) { printf("%d, ", i); data[i].first = last; data[i].range = range; data[i].update = update; data[i].unit_tx = unit_tx; data[i].alternate = alternate; data[i].pq = pq; data[i].sl = sl; data[i].es = es; data[i].effective = effective; data[i].first_remove = -1; data[i].nb_collisions = 0; data[i].nb_add = 0; data[i].nb_clean = 0; data[i].nb_added = 0; data[i].nb_remove = 0; data[i].nb_removed = 0; data[i].nb_contains = 0; data[i].nb_found = 0; data[i].nb_aborts = 0; data[i].nb_aborts_locked_read = 0; data[i].nb_aborts_locked_write = 0; data[i].nb_aborts_validate_read = 0; data[i].nb_aborts_validate_write = 0; data[i].nb_aborts_validate_commit = 0; data[i].nb_aborts_invalid_memory = 0; data[i].nb_aborts_double_write = 0; data[i].max_retries = 0; data[i].nb_threads = nb_threads; data[i].seed = rand(); data[i].seed2 = rand(); data[i].set = set; data[i].barrier = &barrier; data[i].failures_because_contention = 0; data[i].id = i; /* LINDEN */ data[i].lin = lin; data[i].linden_set = linden_set; if (pthread_create(&threads[i], &attr, test, (void *)(&data[i])) != 0) { fprintf(stderr, "Error creating thread\n"); exit(1); } } pthread_attr_destroy(&attr); // Catch some signals if (signal(SIGHUP, catcher) == SIG_ERR || //signal(SIGINT, catcher) == SIG_ERR || signal(SIGTERM, catcher) == SIG_ERR) { perror("signal"); exit(1); } // Start threads barrier_cross(&barrier); printf("STARTING...\n"); gettimeofday(&start, NULL); #ifndef DISTRIBUTION_EXPERIMENT // don't sleep if doing distro experiment if (duration > 0) { nanosleep(&timeout, NULL); } else { sigemptyset(&block_set); sigsuspend(&block_set); } #endif /* AO_store_full(&stop, 1); */ *running = 0; // if (!es) { gettimeofday(&end, NULL); // } printf("STOPPING...\n"); // Wait for thread completion for (i = 0; i < nb_threads; i++) { if (pthread_join(threads[i], NULL) != 0) { fprintf(stderr, "Error waiting for thread completion\n"); exit(1); } } // if (es) { // gettimeofday(&end, NULL); // time when all threads finish // } printf ("duration = %d\n", duration); duration = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000); printf ("duration = %d\n", duration); aborts = 0; aborts_locked_read = 0; aborts_locked_write = 0; aborts_validate_read = 0; aborts_validate_write = 0; aborts_validate_commit = 0; aborts_invalid_memory = 0; aborts_double_write = 0; failures_because_contention = 0; reads = 0; effreads = 0; updates = 0; collisions = 0; add = 0; added = 0; remove = 0; removed = 0; effupds = 0; max_retries = 0; for (i = 0; i < nb_threads; i++) { printf("Thread %d\n", i); printf(" #add : %lu\n", data[i].nb_add); printf(" #added : %lu\n", data[i].nb_added); printf(" #remove : %lu\n", data[i].nb_remove); printf(" #removed : %lu\n", data[i].nb_removed); printf(" #cleaned : %lu\n", data[i].nb_clean); printf("first remove : %d\n", data[i].first_remove); printf(" #collisions : %lu\n", data[i].nb_collisions); printf(" #contains : %lu\n", data[i].nb_contains); printf(" #found : %lu\n", data[i].nb_found); printf(" #aborts : %lu\n", data[i].nb_aborts); printf(" #lock-r : %lu\n", data[i].nb_aborts_locked_read); printf(" #lock-w : %lu\n", data[i].nb_aborts_locked_write); printf(" #val-r : %lu\n", data[i].nb_aborts_validate_read); printf(" #val-w : %lu\n", data[i].nb_aborts_validate_write); printf(" #val-c : %lu\n", data[i].nb_aborts_validate_commit); printf(" #inv-mem : %lu\n", data[i].nb_aborts_invalid_memory); printf(" #dup-w : %lu\n", data[i].nb_aborts_double_write); printf(" #failures : %lu\n", data[i].failures_because_contention); printf(" Max retries : %lu\n", data[i].max_retries); aborts += data[i].nb_aborts; aborts_locked_read += data[i].nb_aborts_locked_read; aborts_locked_write += data[i].nb_aborts_locked_write; aborts_validate_read += data[i].nb_aborts_validate_read; aborts_validate_write += data[i].nb_aborts_validate_write; aborts_validate_commit += data[i].nb_aborts_validate_commit; aborts_invalid_memory += data[i].nb_aborts_invalid_memory; aborts_double_write += data[i].nb_aborts_double_write; failures_because_contention += data[i].failures_because_contention; reads += data[i].nb_contains; effreads += data[i].nb_contains + (data[i].nb_add - data[i].nb_added) + (data[i].nb_remove - data[i].nb_removed); updates += (data[i].nb_add + data[i].nb_remove); collisions += data[i].nb_collisions; add += data[i].nb_add; added += data[i].nb_added; remove += data[i].nb_remove; removed += data[i].nb_removed; effupds += data[i].nb_removed + data[i].nb_added; size += data[i].nb_added - data[i].nb_removed; if (max_retries < data[i].max_retries) max_retries = data[i].max_retries; } printf("Set size : %d (expected: %d)\n", sl_set_size(set), size); printf("Duration : %d (ms)\n", duration); printf("#txs : %lu (%f / s)\n", reads + updates, (reads + updates) * 1000.0 / duration); printf("#read txs : "); if (effective) { printf("%lu (%f / s)\n", effreads, effreads * 1000.0 / duration); printf(" #contains : %lu (%f / s)\n", reads, reads * 1000.0 / duration); } else printf("%lu (%f / s)\n", reads, reads * 1000.0 / duration); printf("#eff. upd rate: %f \n", 100.0 * effupds / (effupds + effreads)); printf("#update txs : "); if (effective) { printf("%lu (%f / s)\n", effupds, effupds * 1000.0 / duration); printf(" #upd trials : %lu (%f / s)\n", updates, updates * 1000.0 / duration); } else printf("%lu (%f / s)\n", updates, updates * 1000.0 / duration); printf("#total_remove : %lu\n", remove); printf("#total_removed: %lu\n", removed); printf("#total_add : %lu\n", add); printf("#total_added : %lu\n", added); printf("#net (rem-add): %lu\n", removed-added); printf("#total_collide: %lu\n", collisions); printf("#norm_collide : %f\n", ((double)collisions)/removed); printf("#aborts : %lu (%f / s)\n", aborts, aborts * 1000.0 / duration); printf(" #lock-r : %lu (%f / s)\n", aborts_locked_read, aborts_locked_read * 1000.0 / duration); printf(" #lock-w : %lu (%f / s)\n", aborts_locked_write, aborts_locked_write * 1000.0 / duration); printf(" #val-r : %lu (%f / s)\n", aborts_validate_read, aborts_validate_read * 1000.0 / duration); printf(" #val-w : %lu (%f / s)\n", aborts_validate_write, aborts_validate_write * 1000.0 / duration); printf(" #val-c : %lu (%f / s)\n", aborts_validate_commit, aborts_validate_commit * 1000.0 / duration); printf(" #inv-mem : %lu (%f / s)\n", aborts_invalid_memory, aborts_invalid_memory * 1000.0 / duration); printf(" #dup-w : %lu (%f / s)\n", aborts_double_write, aborts_double_write * 1000.0 / duration); printf(" #failures : %lu\n", failures_because_contention); printf("Max retries : %lu\n", max_retries); #ifdef PRINT_END print_skiplist(set); #endif #ifdef PAPI long total_L1_miss = 0; unsigned k = 0; for (k = 0; k < nb_threads; k++) { total_L1_miss += g_values[k][0]; //printf("[Thread %d] L1_DCM: %lld\n", i, g_values[i][0]); //printf("[Thread %d] L2_DCM: %lld\n", i, g_values[i][1]); } printf("\n#L1 Cache Misses: %lld\n", total_L1_miss); printf("#Normalized Cache Misses: %f\n", ((double)total_L1_miss)/(reads+updates)); #endif // Delete set sl_set_delete(set); // Cleanup STM TM_SHUTDOWN(); free(threads); free(data); return 0; }
int main(int argc, char **argv) { struct option long_options[] = { // These options don't set a flag {"help", no_argument, NULL, 'h'}, {"duration", required_argument, NULL, 'd'}, {"initial-size", required_argument, NULL, 'i'}, {"thread-num", required_argument, NULL, 't'}, {"range", required_argument, NULL, 'r'}, {"seed", required_argument, NULL, 'S'}, {"update-rate", required_argument, NULL, 'u'}, {"elasticity", required_argument, NULL, 'x'}, {NULL, 0, NULL, 0} }; avl_intset_t *set; int i, j, c, size, tree_size; val_t last = 0; val_t val = 0; unsigned long reads, effreads, updates, effupds, aborts, aborts_locked_read, aborts_locked_write, aborts_validate_read, aborts_validate_write, aborts_validate_commit, aborts_invalid_memory, aborts_double_write, max_retries, failures_because_contention; thread_data_t *data; maintenance_thread_data_t *maintenance_data; pthread_t *threads; pthread_t *maintenance_threads; pthread_attr_t attr; barrier_t barrier; struct timeval start, end; struct timespec timeout; int duration = DEFAULT_DURATION; int initial = DEFAULT_INITIAL; int nb_threads = DEFAULT_NB_THREADS; int nb_maintenance_threads = DEFAULT_NB_MAINTENANCE_THREADS; long range = DEFAULT_RANGE; int seed = DEFAULT_SEED; int update = DEFAULT_UPDATE; int unit_tx = DEFAULT_ELASTICITY; int alternate = DEFAULT_ALTERNATE; int effective = DEFAULT_EFFECTIVE; sigset_t block_set; while(1) { i = 0; c = getopt_long(argc, argv, "hAf:d:i:t:r:S:u:x:" , long_options, &i); if(c == -1) break; if(c == 0 && long_options[i].flag == 0) c = long_options[i].val; switch(c) { case 0: break; case 'h': printf("intset -- STM stress test " "(avltree)\n" "\n" "Usage:\n" " intset [options...]\n" "\n" "Options:\n" " -h, --help\n" " Print this message\n" " -A, --Alternate\n" " Consecutive insert/remove target the same value\n" " -f, --effective <int>\n" " update txs must effectively write (0=trial, 1=effective, default=" XSTR(DEFAULT_EFFECTIVE) ")\n" " -d, --duration <int>\n" " Test duration in milliseconds (0=infinite, default=" XSTR(DEFAULT_DURATION) ")\n" " -i, --initial-size <int>\n" " Number of elements to insert before test (default=" XSTR(DEFAULT_INITIAL) ")\n" " -t, --thread-num <int>\n" " Number of threads (default=" XSTR(DEFAULT_NB_THREADS) ")\n" " -r, --range <int>\n" " Range of integer values inserted in set (default=" XSTR(DEFAULT_RANGE) ")\n" " -S, --seed <int>\n" " RNG seed (0=time-based, default=" XSTR(DEFAULT_SEED) ")\n" " -u, --update-rate <int>\n" " Percentage of update transactions (default=" XSTR(DEFAULT_UPDATE) ")\n" " -x, --elasticity (default=4)\n" " Use elastic transactions\n" " 0 = non-protected,\n" " 1 = normal transaction,\n" " 2 = read elastic-tx,\n" " 3 = read/add elastic-tx,\n" " 4 = read/add/rem elastic-tx,\n" " 5 = fraser lock-free\n" ); exit(0); case 'A': alternate = 1; break; case 'f': effective = atoi(optarg); break; case 'd': duration = atoi(optarg); break; case 'i': initial = atoi(optarg); break; case 't': nb_threads = atoi(optarg); break; case 'r': range = atol(optarg); break; case 'S': seed = atoi(optarg); break; case 'u': update = atoi(optarg); break; case 'x': unit_tx = atoi(optarg); break; case '?': printf("Use -h or --help for help\n"); exit(0); default: exit(1); } } assert(duration >= 0); assert(initial >= 0); assert(nb_threads > 0); assert(range > 0 && range >= initial); assert(update >= 0 && update <= 100); printf("Set type : avltree\n"); printf("Duration : %d\n", duration); printf("Initial size : %u\n", initial); printf("Nb threads : %d\n", nb_threads); printf("Nb mt threads: %d\n", nb_maintenance_threads); printf("Value range : %ld\n", range); printf("Seed : %d\n", seed); printf("Update rate : %d\n", update); printf("Elasticity : %d\n", unit_tx); printf("Alternate : %d\n", alternate); printf("Efffective : %d\n", effective); printf("Type sizes : int=%d/long=%d/ptr=%d/word=%d\n", (int)sizeof(int), (int)sizeof(long), (int)sizeof(void *), (int)sizeof(uintptr_t)); timeout.tv_sec = duration / 1000; timeout.tv_nsec = (duration % 1000) * 1000000; if ((data = (thread_data_t *)malloc(nb_threads * sizeof(thread_data_t))) == NULL) { perror("malloc"); exit(1); } if ((threads = (pthread_t *)malloc(nb_threads * sizeof(pthread_t))) == NULL) { perror("malloc"); exit(1); } if ((maintenance_data = (maintenance_thread_data_t *)malloc(nb_maintenance_threads * sizeof(maintenance_thread_data_t))) == NULL) { perror("malloc"); exit(1); } if ((maintenance_threads = (pthread_t *)malloc(nb_maintenance_threads * sizeof(pthread_t))) == NULL) { perror("malloc"); exit(1); } if (seed == 0) srand((int)time(0)); else srand(seed); //levelmax = floor_log_2((unsigned int) initial); //set = avl_set_new(); set = avl_set_new_alloc(0, nb_threads); //set->stop = &stop; //#endif stop = 0; global_seed = rand(); #ifdef TLS rng_seed = &global_seed; #else /* ! TLS */ if (pthread_key_create(&rng_seed_key, NULL) != 0) { fprintf(stderr, "Error creating thread local\n"); exit(1); } pthread_setspecific(rng_seed_key, &global_seed); #endif /* ! TLS */ // Init STM printf("Initializing STM\n"); TM_STARTUP(); // Populate set printf("Adding %d entries to set\n", initial); i = 0; while (i < initial) { val = rand_range_re(&global_seed, range); //printf("Adding %d\n", val); if (avl_add(set, val, 0, 0) > 0) { //printf("Added %d\n", val); //print_avltree(set); last = val; i++; } } size = avl_set_size(set); tree_size = avl_tree_size(set); printf("Set size : %d\n", size); printf("Tree size : %d\n", tree_size); //printf("Level max : %d\n", levelmax); // Access set from all threads barrier_init(&barrier, nb_threads + nb_maintenance_threads + 1); pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); for (i = 0; i < nb_threads; i++) { printf("Creating thread %d\n", i); data[i].id = i; data[i].first = last; data[i].range = range; data[i].update = update; data[i].unit_tx = unit_tx; data[i].alternate = alternate; data[i].effective = effective; data[i].nb_modifications = 0; data[i].nb_add = 0; data[i].nb_added = 0; data[i].nb_remove = 0; data[i].nb_removed = 0; data[i].nb_contains = 0; data[i].nb_found = 0; data[i].nb_aborts = 0; data[i].nb_aborts_locked_read = 0; data[i].nb_aborts_locked_write = 0; data[i].nb_aborts_validate_read = 0; data[i].nb_aborts_validate_write = 0; data[i].nb_aborts_validate_commit = 0; data[i].nb_aborts_invalid_memory = 0; data[i].nb_aborts_double_write = 0; data[i].max_retries = 0; data[i].seed = rand(); data[i].set = set; data[i].barrier = &barrier; data[i].failures_because_contention = 0; if (pthread_create(&threads[i], &attr, test, (void *)(&data[i])) != 0) { fprintf(stderr, "Error creating thread\n"); exit(1); } } for (i = 0; i < nb_maintenance_threads; i++) { maintenance_data[i].nb_maint = nb_maintenance_threads; maintenance_data[i].id = i; maintenance_data[i].nb_removed = 0; maintenance_data[i].nb_rotated = 0; maintenance_data[i].nb_suc_rotated = 0; maintenance_data[i].nb_propagated = 0; maintenance_data[i].nb_suc_propagated = 0; maintenance_data[i].nb_aborts = 0; maintenance_data[i].nb_aborts_locked_read = 0; maintenance_data[i].nb_aborts_locked_write = 0; maintenance_data[i].nb_aborts_validate_read = 0; maintenance_data[i].nb_aborts_validate_write = 0; maintenance_data[i].nb_aborts_validate_commit = 0; maintenance_data[i].nb_aborts_invalid_memory = 0; maintenance_data[i].nb_aborts_double_write = 0; maintenance_data[i].max_retries = 0; maintenance_data[i].t_data = data; maintenance_data[i].nb_threads = nb_threads; maintenance_data[i].set = set; maintenance_data[i].barrier = &barrier; if ((maintenance_data[i].t_nb_trans = (unsigned long *)malloc(nb_threads * sizeof(unsigned long))) == NULL) { perror("malloc"); exit(1); } for(j = 0; j < nb_threads; j++) { maintenance_data[i].t_nb_trans[j] = 0; } if ((maintenance_data[i].t_nb_trans_old = (unsigned long *)malloc(nb_threads * sizeof(unsigned long))) == NULL) { perror("malloc"); exit(1); } for(j = 0; j < nb_threads; j++) { maintenance_data[i].t_nb_trans_old[j] = 0; } printf("Creating maintenance thread %d\n", i); if (pthread_create(&maintenance_threads[i], &attr, test_maintenance, (void *)(&maintenance_data[i])) != 0) { fprintf(stderr, "Error creating thread\n"); exit(1); } } pthread_attr_destroy(&attr); // Catch some signals if (signal(SIGHUP, catcher) == SIG_ERR || //signal(SIGINT, catcher) == SIG_ERR || signal(SIGTERM, catcher) == SIG_ERR) { perror("signal"); exit(1); } // Start threads barrier_cross(&barrier); printf("STARTING...\n"); gettimeofday(&start, NULL); if (duration > 0) { nanosleep(&timeout, NULL); } else { sigemptyset(&block_set); sigsuspend(&block_set); } #ifdef ICC stop = 1; #else AO_store_full(&stop, 1); #endif /* ICC */ gettimeofday(&end, NULL); printf("STOPPING...\n"); // Wait for thread completion for (i = 0; i < nb_threads; i++) { if (pthread_join(threads[i], NULL) != 0) { fprintf(stderr, "Error waiting for thread completion\n"); exit(1); } } // Wait for maintenance thread completion for (i = 0; i < nb_maintenance_threads; i++) { if (pthread_join(maintenance_threads[i], NULL) != 0) { fprintf(stderr, "Error waiting for maintenance thread completion\n"); exit(1); } } duration = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000); aborts = 0; aborts_locked_read = 0; aborts_locked_write = 0; aborts_validate_read = 0; aborts_validate_write = 0; aborts_validate_commit = 0; aborts_invalid_memory = 0; aborts_double_write = 0; failures_because_contention = 0; reads = 0; effreads = 0; updates = 0; effupds = 0; max_retries = 0; for (i = 0; i < nb_threads; i++) { printf("Thread %d\n", i); printf(" #add : %lu\n", data[i].nb_add); printf(" #added : %lu\n", data[i].nb_added); printf(" #remove : %lu\n", data[i].nb_remove); printf(" #removed : %lu\n", data[i].nb_removed); printf(" #contains : %lu\n", data[i].nb_contains); printf(" #found : %lu\n", data[i].nb_found); printf(" #aborts : %lu\n", data[i].nb_aborts); printf(" #lock-r : %lu\n", data[i].nb_aborts_locked_read); printf(" #lock-w : %lu\n", data[i].nb_aborts_locked_write); printf(" #val-r : %lu\n", data[i].nb_aborts_validate_read); printf(" #val-w : %lu\n", data[i].nb_aborts_validate_write); printf(" #val-c : %lu\n", data[i].nb_aborts_validate_commit); printf(" #inv-mem : %lu\n", data[i].nb_aborts_invalid_memory); printf(" #dup-w : %lu\n", data[i].nb_aborts_double_write); printf(" #failures : %lu\n", data[i].failures_because_contention); printf(" Max retries : %lu\n", data[i].max_retries); printf(" #set read trans reads: %lu\n", data[i].set_read_reads); printf(" #set write trans reads: %lu\n", data[i].set_write_reads); printf(" #set write trans writes: %lu\n", data[i].set_write_writes); printf(" #set trans reads: %lu\n", data[i].set_reads); printf(" #set trans writes: %lu\n", data[i].set_writes); printf(" set max reads: %lu\n", data[i].set_max_reads); printf(" set max writes: %lu\n", data[i].set_max_writes); printf(" #read trans reads: %lu\n", data[i].read_reads); printf(" #write trans reads: %lu\n", data[i].write_reads); printf(" #write trans writes: %lu\n", data[i].write_writes); printf(" #trans reads: %lu\n", data[i].reads); printf(" #trans writes: %lu\n", data[i].writes); printf(" max reads: %lu\n", data[i].max_reads); printf(" max writes: %lu\n", data[i].max_writes); aborts += data[i].nb_aborts; aborts_locked_read += data[i].nb_aborts_locked_read; aborts_locked_write += data[i].nb_aborts_locked_write; aborts_validate_read += data[i].nb_aborts_validate_read; aborts_validate_write += data[i].nb_aborts_validate_write; aborts_validate_commit += data[i].nb_aborts_validate_commit; aborts_invalid_memory += data[i].nb_aborts_invalid_memory; aborts_double_write += data[i].nb_aborts_double_write; failures_because_contention += data[i].failures_because_contention; reads += data[i].nb_contains; effreads += data[i].nb_contains + (data[i].nb_add - data[i].nb_added) + (data[i].nb_remove - data[i].nb_removed); updates += (data[i].nb_add + data[i].nb_remove); effupds += data[i].nb_removed + data[i].nb_added; size += data[i].nb_added - data[i].nb_removed; if (max_retries < data[i].max_retries) max_retries = data[i].max_retries; } for (i = 0; i < nb_maintenance_threads; i++) { printf("Maintenance thread %d\n", i); printf(" #removed %lu\n", set->nb_removed); printf(" #rotated %lu\n", set->nb_rotated); printf(" #rotated sucs %lu\n", set->nb_suc_rotated); printf(" #propogated %lu\n", set->nb_propogated); printf(" #propogated sucs %lu\n", set->nb_suc_propogated); printf(" #aborts : %lu\n", maintenance_data[i].nb_aborts); printf(" #lock-r : %lu\n", maintenance_data[i].nb_aborts_locked_read); printf(" #lock-w : %lu\n", maintenance_data[i].nb_aborts_locked_write); printf(" #val-r : %lu\n", maintenance_data[i].nb_aborts_validate_read); printf(" #val-w : %lu\n", maintenance_data[i].nb_aborts_validate_write); printf(" #val-c : %lu\n", maintenance_data[i].nb_aborts_validate_commit); printf(" #inv-mem : %lu\n", maintenance_data[i].nb_aborts_invalid_memory); printf(" #dup-w : %lu\n", maintenance_data[i].nb_aborts_double_write); //printf(" #failures : %lu\n", maintenance_data[i].failures_because_contention); printf(" Max retries : %lu\n", maintenance_data[i].max_retries); } printf("Set size : %d (expected: %d)\n", avl_set_size(set), size); printf("Tree size : %d\n", avl_tree_size(set)); printf("Duration : %d (ms)\n", duration); printf("#txs : %lu (%f / s)\n", reads + updates, (reads + updates) * 1000.0 / duration); printf("#read txs : "); if (effective) { printf("%lu (%f / s)\n", effreads, effreads * 1000.0 / duration); printf(" #contains : %lu (%f / s)\n", reads, reads * 1000.0 / duration); } else printf("%lu (%f / s)\n", reads, reads * 1000.0 / duration); printf("#eff. upd rate: %f \n", 100.0 * effupds / (effupds + effreads)); printf("#update txs : "); if (effective) { printf("%lu (%f / s)\n", effupds, effupds * 1000.0 / duration); printf(" #upd trials : %lu (%f / s)\n", updates, updates * 1000.0 / duration); } else printf("%lu (%f / s)\n", updates, updates * 1000.0 / duration); printf("#aborts : %lu (%f / s)\n", aborts, aborts * 1000.0 / duration); printf(" #lock-r : %lu (%f / s)\n", aborts_locked_read, aborts_locked_read * 1000.0 / duration); printf(" #lock-w : %lu (%f / s)\n", aborts_locked_write, aborts_locked_write * 1000.0 / duration); printf(" #val-r : %lu (%f / s)\n", aborts_validate_read, aborts_validate_read * 1000.0 / duration); printf(" #val-w : %lu (%f / s)\n", aborts_validate_write, aborts_validate_write * 1000.0 / duration); printf(" #val-c : %lu (%f / s)\n", aborts_validate_commit, aborts_validate_commit * 1000.0 / duration); printf(" #inv-mem : %lu (%f / s)\n", aborts_invalid_memory, aborts_invalid_memory * 1000.0 / duration); printf(" #dup-w : %lu (%f / s)\n", aborts_double_write, aborts_double_write * 1000.0 / duration); printf(" #failures : %lu\n", failures_because_contention); printf("Max retries : %lu\n", max_retries); //print_avltree(set); // Delete set avl_set_delete(set); // Cleanup STM TM_SHUTDOWN(); #ifndef TLS pthread_key_delete(rng_seed_key); #endif /* ! TLS */ free(threads); free(data); free(maintenance_threads); free(maintenance_data); return 0; }
void *test(void *data) { int val2, numtx, r, last = -1; val_t val = 0; int unext, mnext, cnext; thread_data_t *d = (thread_data_t *)data; /* Create transaction */ TM_THREAD_ENTER(); /* Wait on barrier */ barrier_cross(d->barrier); /* Is the first op an update, a move? */ r = rand_range_re(&d->seed, 100) - 1; unext = (r < d->update); mnext = (r < d->move); cnext = (r >= d->update + d->snapshot); #ifdef ICC while (stop == 0) { #else while (AO_load_full(&stop) == 0) { #endif /* ICC */ if (unext) { // update if (mnext) { // move if (last == -1) val = rand_range_re(&d->seed, d->range); val2 = rand_range_re(&d->seed, d->range); if (ht_move(d->set, val, val2, TRANSACTIONAL)) { d->nb_moved++; last = val2; } d->nb_move++; } else if (last < 0) { // add val = rand_range_re(&d->seed, d->range); if (ht_add(d->set, val, TRANSACTIONAL)) { d->nb_added++; last = val; } d->nb_add++; } else { // remove if (d->alternate) { // alternate mode if (ht_remove(d->set, last, TRANSACTIONAL)) { d->nb_removed++; last = -1; } } else { /* Random computation only in non-alternated cases */ val = rand_range_re(&d->seed, d->range); /* Remove one random value */ if (ht_remove(d->set, val, TRANSACTIONAL)) { d->nb_removed++; /* Repeat until successful, to avoid size variations */ last = -1; } } d->nb_remove++; } } else { // reads if (cnext) { // contains (no snapshot) if (d->alternate) { if (d->update == 0) { if (last < 0) { val = d->first; last = val; } else { // last >= 0 val = rand_range_re(&d->seed, d->range); last = -1; } } else { // update != 0 if (last < 0) { val = rand_range_re(&d->seed, d->range); //last = val; } else { val = last; } } } else val = rand_range_re(&d->seed, d->range); if (ht_contains(d->set, val, TRANSACTIONAL)) d->nb_found++; d->nb_contains++; } else { // snapshot if (ht_snapshot(d->set, TRANSACTIONAL)) d->nb_snapshoted++; d->nb_snapshot++; } } /* Is the next op an update, a move, a contains? */ if (d->effective) { // a failed remove/add is a read-only tx numtx = d->nb_contains + d->nb_add + d->nb_remove + d->nb_move + d->nb_snapshot; unext = ((100.0 * (d->nb_added + d->nb_removed + d->nb_moved)) < (d->update * numtx)); mnext = ((100.0 * d->nb_moved) < (d->move * numtx)); cnext = !((100.0 * d->nb_snapshoted) < (d->snapshot * numtx)); } else { // remove/add (even failed) is considered as an update r = rand_range_re(&d->seed, 100) - 1; unext = (r < d->update); mnext = (r < d->move); cnext = (r >= d->update + d->snapshot); } #ifdef ICC } #else } #endif /* ICC */ /* Free transaction */ TM_THREAD_EXIT(); return NULL; }
void *test(void *data) { int unext, last = -1; val_t val = 0; int result; int id; ulong *tloc; #ifdef BIAS_RANGE val_t increase; #endif thread_data_t *d = (thread_data_t *)data; id = d->id; tloc = d->set->nb_committed; #ifdef BIAS_RANGE increase = d->range; #endif /* Create transaction */ TM_THREAD_ENTER(); /* Wait on barrier */ barrier_cross(d->barrier); /* Is the first op an update? */ unext = (rand_range_re(&d->seed, 100) - 1 < d->update); #ifdef ICC while (stop == 0) { #else while (AO_load_full(&stop) == 0) { #endif /* ICC */ if (unext) { // update if (last < 0) { // add val = rand_range_re(&d->seed, d->range); #ifdef BIAS_RANGE if(rand_range_re(&d->seed, 1000) < 50) { increase += rand_range_re(&d->seed, 10); if(increase > d->range * 20) { increase = d->range; } val = increase; } #endif if ((result = avl_add(d->set, val, TRANSACTIONAL, id)) > 0) { d->nb_added++; if(result > 1) { d->nb_modifications++; } last = val; } d->nb_trans++; tloc[id]++; d->nb_add++; } else { // remove if (d->alternate) { // alternate mode (default) #ifdef TINY10B if ((result = avl_remove(d->set, last, TRANSACTIONAL, id)) > 0) { #else if ((result = avl_remove(d->set, last, TRANSACTIONAL, 0)) > 0) { #endif d->nb_removed++; #ifdef REMOVE_LATER finish_removal(d->set, id); #endif if(result > 1) { d->nb_modifications++; } } last = -1; } else { /* Random computation only in non-alternated cases */ val = rand_range_re(&d->seed, d->range); /* Remove one random value */ #ifdef BIAS_RANGE if(rand_range_re(&d->seed, 1000) < 300) { //val = d->range + rand_range_re(&d->seed, increase - d->range); val = increase - rand_range_re(&d->seed, 10); } #endif #ifdef TINY10B if ((result = avl_remove(d->set, val, TRANSACTIONAL, id)) > 0) { #else if ((result = avl_remove(d->set, val, TRANSACTIONAL, 0)) > 0) { #endif d->nb_removed++; #ifdef REMOVE_LATER finish_removal(d->set, id); #endif if(result > 1) { d->nb_modifications++; } /* Repeat until successful, to avoid size variations */ last = -1; } } d->nb_trans++; tloc[id]++; d->nb_remove++; } } else { // read if (d->alternate) { if (d->update == 0) { if (last < 0) { val = d->first; last = val; } else { // last >= 0 val = rand_range_re(&d->seed, d->range); last = -1; } } else { // update != 0 if (last < 0) { val = rand_range_re(&d->seed, d->range); //last = val; } else { val = last; } } } else val = rand_range_re(&d->seed, d->range); #ifdef BIAS_RANGE if(rand_range_re(&d->seed, 1000) < 100) { val = increase; } #endif if (avl_contains(d->set, val, TRANSACTIONAL, id)) d->nb_found++; d->nb_trans++; tloc[id]++; d->nb_contains++; } /* Is the next op an update? */ if (d->effective) { // a failed remove/add is a read-only tx unext = ((100 * (d->nb_added + d->nb_removed)) < (d->update * (d->nb_add + d->nb_remove + d->nb_contains))); } else { // remove/add (even failed) is considered as an update unext = (rand_range_re(&d->seed, 100) - 1 < d->update); } #ifdef ICC } #else } #endif /* ICC */ /* Free transaction */ TM_THREAD_EXIT(); return NULL; } void *test_maintenance(void *data) { #ifdef TINY10B int i; free_list_item **t_list_items; #endif maintenance_thread_data_t *d = (maintenance_thread_data_t *)data; #ifdef TINY10B t_list_items = (free_list_item **)malloc(d->nb_threads * sizeof(free_list_item *)); for(i = 0; i < d->nb_threads; i++) { t_list_items[i] = d->set->t_free_list[i]; } #endif /* Create transaction */ TM_THREAD_ENTER(); /* Wait on barrier */ barrier_cross(d->barrier); /* Is the first op an update? */ //unext = (rand_range_re(&d->seed, 100) - 1 < d->update); #ifdef ICC while (stop == 0) { #else while (AO_load_full(&stop) == 0) { #endif /* ICC */ #ifdef TINY10B do_maintenance_thread(d->set, d->id, d->nb_maint); #endif #ifdef ICC } #else } #endif /* ICC */ /* Free transaction */ TM_THREAD_EXIT(); return NULL; } void catcher(int sig) { printf("CAUGHT SIGNAL %d\n", sig); }
void *test(void *data) { int unext, last = -1; val_t val = 0; thread_data_t *d = (thread_data_t *)data; /* Wait on barrier */ barrier_cross(d->barrier); /* Is the first op an update? */ unext = (rand_range_re(&d->seed, 100) - 1 < d->update); while (stop == 0) { if (unext) { // update if (last < 0) { // add val = rand_range_re(&d->seed, d->range); if (set_add_l(d->set, val, TRANSACTIONAL)) { d->nb_added++; last = val; } d->nb_add++; } else { // remove if (d->alternate) { // alternate mode if (set_remove_l(d->set, last, TRANSACTIONAL)) { d->nb_removed++; } last = -1; } else { val = rand_range_re(&d->seed, d->range); if (set_remove_l(d->set, val, TRANSACTIONAL)) { d->nb_removed++; last = -1; } } d->nb_remove++; } } else { // read if (d->alternate) { if (d->update == 0) { if (last < 0) { val = d->first; last = val; } else { // last >= 0 val = rand_range_re(&d->seed, d->range); last = -1; } } else { // update != 0 if (last < 0) { val = rand_range_re(&d->seed, d->range); //last = val; } else { val = last; } } } else val = rand_range_re(&d->seed, d->range); if (set_contains_l(d->set, val, TRANSACTIONAL)) d->nb_found++; d->nb_contains++; } /* Is the next op an update? */ if (d->effective) { // a failed remove/add is a read-only tx unext = ((100 * (d->nb_added + d->nb_removed)) < (d->update * (d->nb_add + d->nb_remove + d->nb_contains))); } else { // remove/add (even failed) is considered an update unext = (rand_range_re(&d->seed, 100) - 1 < d->update); } } return NULL; }
void* test(void* data, double duration) { int unext, last = -1; val_t val = 0; thread_data_t* d = (thread_data_t*) data; srand_core(); /* Create transaction */ /* Is the first op an update? */ unext = (rand_range(100) < d->update); signal (SIGALRM, alarm_handler); alarm(duration); BARRIER; while(work) { if (unext) { // update if (last < 0) { // add val = rand_range_re(&d->seed, d->range); if (set_add(d->set, val, TRANSACTIONAL)) { d->nb_added++; last = val; } d->nb_add++; } else { // remove if (d->alternate) { // alternate mode (default) if (set_remove(d->set, last, TRANSACTIONAL)) { d->nb_removed++; } last = -1; } else { /* Random computation only in non-alternated cases */ val = rand_range_re(&d->seed, d->range); /* Remove one random value */ if (set_remove(d->set, val, TRANSACTIONAL)) { d->nb_removed++; /* Repeat until successful, to avoid size variations */ last = -1; } } d->nb_remove++; } } else { // read if (d->alternate) { if (d->update == 0) { if (last < 0) { val = d->first; last = val; } else { // last >= 0 val = rand_range_re(&d->seed, d->range); last = -1; } } else { // update != 0 if (last < 0) { val = rand_range_re(&d->seed, d->range); //last = val; } else { val = last; } } } else val = rand_range_re(&d->seed, d->range); if (set_contains(d->set, val, TRANSACTIONAL)) d->nb_found++; d->nb_contains++; } /* Is the next op an update? */ if (d->effective) { // a failed remove/add is a read-only tx unext = ((100 * (d->nb_added + d->nb_removed)) < (d->update * (d->nb_add + d->nb_remove + d->nb_contains))); } else { // remove/add (even failed) is considered as an update unext = (rand_range_re(&d->seed, 100) < d->update); } } duration__ = duration; return NULL; }
void *test2(void *data) { int val, newval, last, flag = 1; int id; ulong *tloc; thread_data_t *d = (thread_data_t *)data; id = d->id; tloc = d->set->nb_committed; /* Create transaction */ TM_THREAD_ENTER(); /* Wait on barrier */ barrier_cross(d->barrier); last = 0; // to avoid warning while (stop == 0) { val = rand_range_re(&d->seed, 100) - 1; /* added for HashTables */ if (val < d->update) { if (val >= d->move) { /* update without move */ if (flag) { /* Add random value */ val = (rand_r(&d->seed) % d->range) + 1; if (avl_add(d->set, val, TRANSACTIONAL, id)) { d->nb_added++; last = val; flag = 0; } d->nb_trans++; tloc[id]++; d->nb_add++; } else { if (d->alternate) { /* Remove last value */ if (avl_remove(d->set, last, TRANSACTIONAL, id)) d->nb_removed++; d->nb_trans++; tloc[id]++; d->nb_remove++; flag = 1; } else { /* Random computation only in non-alternated cases */ newval = rand_range_re(&d->seed, d->range); if (avl_remove(d->set, newval, TRANSACTIONAL, id)) { d->nb_removed++; /* Repeat until successful, to avoid size variations */ flag = 1; } d->nb_trans++; tloc[id]++; d->nb_remove++; } } } else { /* move */ val = rand_range_re(&d->seed, d->range); if (avl_move(d->set, last, val, TRANSACTIONAL, id)) { d->nb_moved++; last = val; } d->nb_trans++; tloc[id]++; d->nb_move++; } } else { if (val >= d->update + d->snapshot) { /* read-only without snapshot */ /* Look for random value */ val = rand_range_re(&d->seed, d->range); if (avl_contains(d->set, val, TRANSACTIONAL, id)) d->nb_found++; d->nb_trans++; tloc[id]++; d->nb_contains++; } else { /* snapshot */ if (avl_snapshot(d->set, TRANSACTIONAL, id)) d->nb_snapshoted++; d->nb_trans++; tloc[id]++; d->nb_snapshot++; } } } /* Free transaction */ TM_THREAD_EXIT(); return NULL; }
void *test(void *data) { // Read this locally to prevent possible cache effects. thread_data_t d = *(thread_data_t *)data; // Wait for all threads to become ready. barrier_cross(d.barrier); // Last value to be inserted, or -ve if last action was remove. // Start -ve here so that alternate mode will not hang. int last = -1; // If we're in bias mode, should start positive so that something // gets removed. if (d.bias_enabled) last = d.bias_offset; while (atomic_load(&stop) == 0) { // Is the next op an update? int do_update; if (d.effective) do_update = (100 * (d.nb_added + d.nb_removed)) < (d.update * (d.nb_add + d.nb_remove + d.nb_contains)); else do_update = rand_range_re(&d.seed, 100) - 1 < d.update; // Value on which to operate. (may be modified later, // if in alternate mode or bias mode) int value = rand_range_re(&d.seed, d.range); // If we're in bias mode, restrict the range, and just choose adding or removing at random if (d.bias_enabled) { value = d.bias_offset + rand_range_re(&d.seed, d.bias_range) - 1; last = (rand_range_re(&d.seed, 2) == 1) ? -1 : value; } if (do_update && last < 0) { // Add if (set_insert(d.set, value)) { d.nb_added++; last = value; } d.nb_add++; } else if (do_update && last >= 0) { // Remove // If in alternate mode, remove the last item added. if (d.alternate) { if (set_remove(d.set, last)) d.nb_removed++; last = -1; } else { if (set_remove(d.set, value)) { d.nb_removed++; last = -1; } } d.nb_remove++; } else { // Read if (d.alternate) { if (d.update == 0) { if (last < 0) last = value = d.first; else last = -1; } else { // update != 0 if (last >= 0) value = last; } } if (set_contains(d.set, value)) d.nb_found++; d.nb_contains++; } } *(thread_data_t *)data = d; return NULL; }