/** * Show regions info * \param info Pointer to region information data */ static void _app_show_regions_info(struct regions_info *info) { uint32_t boot_region = info->boot_region; void *app_addr = (void *)(APP_START(boot_region)); bool app_valid = false; app_valid = region_check_valid(app_addr, info->length[ boot_region], info->signature[ boot_region]); dbg_print("==== Regions Information ====\r\n"); dbg_print(": trigger flag: %s\r\n", trigger_modes_str[info->trigger]); dbg_print(": source file : %s\r\n", info->boot_file_name); dbg_print(":----------------------------\r\n"); dbg_print(": region\t%8d\t%8d\r\n", 0, 1); dbg_print(": size \t%8d\t%8d\r\n", (int)info->length[0], (int)info->length[1]); dbg_print(": sign \t%8x\t%8x\r\n", (unsigned)info->signature[0], (unsigned)info->signature[1]); dbg_print(": boot \t %c\t %c\r\n", boot_region ? ' ' : 'Y', boot_region ? 'Y' : ' '); dbg_print(": App @ %d, %x - data %x ...\r\n", (int)boot_region, (unsigned)app_addr, (unsigned)*(uint32_t *)app_addr); dbg_print("bl: App valid: %c\r\n", app_valid ? 'Y' : 'N'); }
/** * Bootloader main entry */ int main(void) { uint8_t boot_region = 0; /* Real boot region at this time */ #ifdef DBG_USE_USART uint8_t load_region = 0; /* Real region to put loaded data */ #endif struct regions_info info; void *app_addr = NULL; uint32_t app_size = 0; enum trigger_modes trigger; bool app_valid = false; wdt_disable(WDT); sysclk_init(); board_init(); /* First turn on the led to indicate the bootloader run. */ ioport_set_pin_dir(DBG_LED_PIN, IOPORT_DIR_OUTPUT); ioport_set_pin_level(DBG_LED_PIN, DBG_LED_PIN_ON_LEVEL); dbg_init(); dbg_print("\r\n\n----------------------\r\n"); dbg_print("%s Bootloader\r\n", BOARD_NAME); dbg_print("Boot region: %x, size %dK\r\n", BOOT0_START, BOOT_SIZE / 1024); dbg_print("App region: %x, size %dK\r\n", APP0_START, (int)APP_SIZE / 1024); dbg_print(" - Code %dK + Info %dK\r\n", (int)APP_CODE_SIZE, (int)INFO_SIZE); dbg_print("----------------------\r\n"); /* bootloader initialize */ dbg_print("bl: init ...\r\n"); trigger_init(); memory_init(); media_init(file_list, MEDIA_FILE_LIST_LEN); dbg_print("bl: init done\r\n"); boot_region = _app_boot_get(); dbg_print("bl: current boot region %d\r\n", (int)boot_region); #ifdef MEM_LOCK_BOOT_REGION dbg_print("bl: lock boot region ...\r\n"); memory_lock((void *)BOOT0_START, (void *)BOOT0_END); dbg_print("bl: lock boot region done\r\n"); #endif /* load regions information * Single flash: from last page * Dual flash (remap) : from last page of last physical flash * Dual flash (mirror): from last page of boot flash */ dbg_print("bl: read regions info ...\r\n"); region_info_read((void *)INFO_ADDR(true), &info); /* Read for boot */ app_addr = (void *)(APP_START(boot_region)); app_valid = region_check_valid(app_addr, info.length[boot_region], info.signature[boot_region]); dbg_print("bl: read regions info done\r\n"); dbg_print("bl: trigger flag %s\r\n", trigger_modes_str[info.trigger]); dbg_print("bl: region\t%8d\t%8d\r\n", 0, 1); dbg_print("bl: size\t%8d\t%8d\r\n", (int)info.length[0], (int)info.length[1]); dbg_print("bl: sign\t%8x\t%8x\r\n", (unsigned)info.signature[0], (unsigned)info.signature[1]); dbg_print("bl: boot\t %c\t %c\r\n", boot_region ? ' ' : 'Y', boot_region ? 'Y' : ' '); dbg_print("bl: App @ %d, %x - data %x ...\r\n", (int)boot_region, (unsigned)app_addr, (unsigned)*(uint32_t *)app_addr); dbg_print("bl: App valid: %c\r\n", app_valid ? 'Y' : 'N'); #ifdef DBG_USE_INFO_EDIT /* InfoEdit */ _app_info_edit(&info); #endif /* bootloader trigger check */ dbg_print("bl: trigger ...\r\n"); trigger = trigger_poll(&info); dbg_print("bl: trigger mode %s\r\n", trigger_modes_str[trigger]); if (TRIGGER_BOOT == trigger) { goto main_run_app_check; } /* Now any other trigger load file to update application directly */ #ifdef DBG_USE_LED _app_led_blink(100, 1); #endif /* Update media file information */ if (info.boot_file_name[0]) { dbg_print("bl: boot file assigned, set it\r\n"); media_set_file_name(info.boot_file_name); } main_load_app: /* load new firmware */ #ifdef DBG_USE_USART load_region = boot_region; dbg_print("bl: download @ %d ...\r\n", load_region); #endif app_size = _app_load(&info, true); if (app_size == 0) { _app_led_error(); dbg_print("bl: download fail, retry\r\n"); goto main_load_app; } else { dbg_print("bl: download done, size %d\r\n", (int)app_size); } main_run_app_check: /* Is application valid */ dbg_print("bl: check app @ %d is valid\r\n", (int)info.boot_region); app_valid = region_check_valid(app_addr, info.length[info.boot_region], info.signature[info.boot_region]); if (!app_valid) { dbg_print("bl: application is not valid\r\n"); _app_led_error(); dbg_print("bl: reload firmware\r\n"); goto main_load_app; } dbg_print("bl: application is valid, run\r\n"); /* Turn off the led before jump to the app. */ _app_led_off(DBG_LED_PIN); /* cleanup */ dbg_print("bl: cleanup ...\r\n"); media_cleanup(); trigger_cleanup(); memory_cleanup(); dbg_print("bl: cleanup done\r\n"); /* load application */ dbg_print("bl: load application ...\r\n\n"); #ifdef DBG_USE_USART delay_ms(50); /* Wait USART lines idle */ dbg_cleanup(); delay_ms(50); #endif /* run application */ _app_exec(app_addr); return (int)app_addr; }
/** * Receive new firmware * * \param info Regions information struct * \param no_partition Use single partition, do not split memory to app + buff * * \return received firmware size */ static uint32_t _app_load(struct regions_info *info, bool no_partition) { void *addr, *info_addr; uint32_t *p_sign, *p_len; uint32_t rx_size; uint32_t target_region; uint32_t i = 0, flags = 0xFF; if (info->boot_region != 0 && info->boot_region != 1) { dbg_print("bl: Boot region information (%d) invalid\r\n", (int)info->boot_region); return 0; } /* Wait media connection */ i = 0; while (i < MEDIA_NUM_MAX) { media_select((enum media_types)i); if (media_connect()) { dbg_print("bl: Source media %s is ready\r\n", media_get_type_str((enum media_types)i)); break; } else if (flags & (1 << i)) { flags &= ~(1 << i); dbg_print("bl: Source media %s not ready\r\n", media_get_type_str((enum media_types)i)); } i++; } target_region = no_partition ? info->boot_region : (!info->boot_region); addr = (void *)APP_START(target_region); info_addr = (void *)INFO_ADDR(false); dbg_print("bl: Load to %x, info @ %x\r\n", (unsigned)addr, (unsigned)info_addr); dbg_print("bl: Unlock download buffer & info area ...\r\n"); memory_unlock(addr, (void *)((uint32_t)addr + APP_CODE_SIZE - 1)); memory_unlock(info_addr, (void *)((uint32_t)info_addr + INFO_SIZE - 1)); dbg_print("bl: Unlock download buffer & info area done\r\n"); dbg_print("bl: Erase download buffer & info area ...\r\n"); memory_erase( addr, APP_CODE_SIZE); memory_erase(info_addr, INFO_SIZE); dbg_print("bl: Erase download buffer & info area done\r\n"); #ifdef DBG_USE_LED _app_led_blink(50, 4); _app_led_on(DBG_LED_PIN); #endif /* Clear SW force boot trigger */ #ifdef TRIGGER_USE_FLAG info->trigger = TRIGGER_BOOT; #endif p_sign = &info->signature[target_region]; p_len = &info->length[target_region]; rx_size = media_load_file(addr, APP_SIZE, (uint8_t *)app_mem_block_buf, MEM_BLOCK_SIZE, _app_save_block); if (rx_size) { *p_sign = region_signature(addr, rx_size); *p_len = rx_size; } else { *p_sign = 0; *p_len = 0; } /* Save region information */ region_info_write(info_addr, info); dbg_print("bl: Lock download buffer & info area ...\r\n"); memory_lock(addr, (void *)((uint32_t)addr + APP_CODE_SIZE - 1)); memory_lock(info_addr, (void *)((uint32_t)info_addr + INFO_SIZE - 1)); dbg_print("bl: Lock download buffer & info area done\r\n"); #ifdef DBG_USE_LED _app_led_off(DBG_LED_PIN); #endif #if DUMP_ENABLE _dump_data("Downloaded APP:\r\n", addr, rx_size, true); _dump_data("INFO:\r\n", info_addr, INFO_SIZE, true); #endif return rx_size; }
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'}, {"num-threads", required_argument, NULL, 'n'}, {"range", required_argument, NULL, 'r'}, {"seed", required_argument, NULL, 's'}, {"update-rate", required_argument, NULL, 'u'}, {"move-rate", required_argument, NULL, 'm'}, {"snapshot-rate", required_argument, NULL, 'a'}, {"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, moves, moved, snapshots, snapshoted, 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; pthread_attr_t attr; thread_data_t *data; maintenance_thread_data_t *maintenance_data; pthread_t *threads; pthread_t *maintenance_threads; 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 load_factor = DEFAULT_LOAD; int move = DEFAULT_MOVE; int snapshot = DEFAULT_SNAPSHOT; 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:n:r:s:u:m:a:l: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: // Flag is automatically set break; case 'h': printf("intset -- STM stress test " "(hash table)\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" " -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" " -m , --move-rate <int>\n" " Percentage of move transactions (default=" XSTR(DEFAULT_MOVE) ")\n" " -a , --snapshot-rate <int>\n" " Percentage of snapshot transactions (default=" XSTR(DEFAULT_SNAPSHOT) ")\n" " -l , --load-factor <int>\n" " Ratio of keys over buckets (default=" XSTR(DEFAULT_LOAD) ")\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 = elastic-tx w/ optimized move.\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 '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 'm': move = atoi(optarg); break; case 'a': snapshot = atoi(optarg); break; case 'l': load_factor = 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); assert(move >= 0 && move <= update); assert(snapshot >= 0 && snapshot <= (100-update)); assert(initial < MAXHTLENGTH); assert(initial >= load_factor); printf("Set type : avl tree\n"); printf("Duration : %d\n", duration); printf("Initial size : %d\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("Load factor : %d\n", load_factor); printf("Move rate : %d\n", move); printf("Snapshot rate: %d\n", snapshot); printf("Elasticity : %d\n", unit_tx); printf("Alternate : %d\n", alternate); printf("Effective : %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); maxhtlength = (unsigned int) initial / load_factor; set = avl_set_new_alloc(0, nb_threads); //set->stop = &stop; stop = 0; // Init STM printf("Initializing STM\n"); TM_STARTUP(); // Populate set printf("Adding %d entries to set\n", initial); i = 0; maxhtlength = (int) (initial / load_factor); while (i < initial) { val = rand_range(range); if (avl_add(set, val, 0, 0) > 0) { last = val; i++; } } size = avl_set_size(set); validate_avltree(set, range); printf("Set size : %d\n", size); tree_size = avl_tree_size(set); printf("Tree size : %d\n", tree_size); // 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].load_factor = load_factor; data[i].move = move; data[i].snapshot = snapshot; data[i].unit_tx = unit_tx; data[i].alternate = alternate; data[i].effective = effective; data[i].nb_add = 0; data[i].nb_added = 0; data[i].nb_remove = 0; data[i].nb_removed = 0; data[i].nb_move = 0; data[i].nb_moved = 0; data[i].nb_snapshot = 0; data[i].nb_snapshoted = 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); APP_START(); // Start threads barrier_cross(&barrier); printf("STARTING...\n"); gettimeofday(&start, NULL); if (duration > 0) { nanosleep(&timeout, NULL); } else { sigemptyset(&block_set); sigsuspend(&block_set); } AO_store_full(&stop, 1); gettimeofday(&end, NULL); printf("STOPPING...\n"); //print_avltree(set); // 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); } } APP_END(); 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; moves = 0; moved = 0; snapshots = 0; snapshoted = 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(" #move : %lu\n", data[i].nb_move); printf(" #moved : %lu\n", data[i].nb_moved); printf(" #snapshot : %lu\n", data[i].nb_snapshot); printf(" #snapshoted : %lu\n", data[i].nb_snapshoted); 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) + (data[i].nb_move - data[i].nb_moved) + data[i].nb_snapshoted; updates += (data[i].nb_add + data[i].nb_remove + data[i].nb_move); effupds += data[i].nb_removed + data[i].nb_added + data[i].nb_moved; moves += data[i].nb_move; moved += data[i].nb_moved; snapshots += data[i].nb_snapshot; snapshoted += data[i].nb_snapshoted; 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)); validate_avltree(set, range); printf("Duration : %d (ms)\n", duration); printf("#txs : %lu (%f / s)\n", reads + updates + snapshots, (reads + updates + snapshots) * 1000.0 / duration); printf("#read txs : "); if (effective) { printf("%lu (%f / s)\n", effreads, effreads * 1000.0 / duration); printf(" #cont/snpsht: %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("#move txs : %lu (%f / s)\n", moves, moves * 1000.0 / duration); printf(" #moved : %lu (%f / s)\n", moved, moved * 1000.0 / duration); printf("#snapshot txs : %lu (%f / s)\n", snapshots, snapshots * 1000.0 / duration); printf(" #snapshoted : %lu (%f / s)\n", snapshoted, snapshoted * 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); // Delete set avl_set_delete(set); // Cleanup STM TM_SHUTDOWN(); free(threads); free(data); free(maintenance_threads); free(maintenance_data); return 0; }