void flash_write_block(uint8_t * buf, uintptr_t adr, uintptr_t len) { volatile uint8_t check; check = BOOT_SPM_CHECK_VAL; if (config_range(adr, len) || writeallow_range(adr, len)) { uintptr_t start = adr; uintptr_t end = adr + len; uintptr_t i = ~(SPM_PAGESIZE - 1) & start; uintptr_t e = i + SPM_PAGESIZE; uintptr_t start_a = start & ~0x1; uintptr_t end_a = end & ~0x1; DBG_ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { eeprom_busy_wait(); boot_spm_busy_wait(); bool change = 0; for (; i < start_a; i += 2) boot_page_fill(i, pgm_read_word(i)); if (start & 0x1) { uint16_t dat_old = pgm_read_word(i); uint16_t dat = (dat_old & 0x00ff) | (*buf << 8); change |= dat != dat_old; buf++; boot_page_fill(i, dat); i += 2; } for (; i < end_a; i += 2) { uint16_t dat_old = pgm_read_word(i); uint16_t dat = *buf; buf++; dat |= *buf << 8; buf++; change |= dat != dat_old; boot_page_fill(i, dat); } if (end & 0x1) { uint16_t dat_old = pgm_read_word(i); uint16_t dat = (dat_old & 0xff00) | *buf; change |= dat != dat_old; buf++; boot_page_fill(i, dat); i += 2; } for (; i < e; i += 2) boot_page_fill(i, pgm_read_word(i)); if (change) { assert(boot_page_erase_checked(adr, check) == 0); boot_spm_busy_wait(); assert(boot_page_write_checked(adr, check) == 0); boot_spm_busy_wait(); } boot_rww_enable(); } }
static int config_parse_args(int argc, char *argv[], struct benchmark_config *cfg) { enum extended_options { o_test_time = 128, o_ratio, o_pipeline, o_data_size_range, o_data_size_list, o_data_size_pattern, o_data_offset, o_expiry_range, o_data_import, o_data_verify, o_verify_only, o_key_prefix, o_key_minimum, o_key_maximum, o_key_pattern, o_key_stddev, o_key_median, o_show_config, o_hide_histogram, o_distinct_client_seed, o_randomize, o_client_stats, o_reconnect_interval, o_generate_keys, o_multi_key_get, o_select_db, o_no_expiry }; static struct option long_options[] = { { "server", 1, 0, 's' }, { "port", 1, 0, 'p' }, { "unix-socket", 1, 0, 'S' }, { "protocol", 1, 0, 'P' }, { "out-file", 1, 0, 'o' }, { "client-stats", 1, 0, o_client_stats }, { "run-count", 1, 0, 'x' }, { "debug", 0, 0, 'D' }, { "show-config", 0, 0, o_show_config }, { "hide-histogram", 0, 0, o_hide_histogram }, { "distinct-client-seed", 0, 0, o_distinct_client_seed }, { "randomize", 0, 0, o_randomize }, { "requests", 1, 0, 'n' }, { "clients", 1, 0, 'c' }, { "threads", 1, 0, 't' }, { "test-time", 1, 0, o_test_time }, { "ratio", 1, 0, o_ratio }, { "pipeline", 1, 0, o_pipeline }, { "data-size", 1, 0, 'd' }, { "data-offset", 1, 0, o_data_offset }, { "random-data", 0, 0, 'R' }, { "data-size-range", 1, 0, o_data_size_range }, { "data-size-list", 1, 0, o_data_size_list }, { "data-size-pattern", 1, 0, o_data_size_pattern }, { "expiry-range", 1, 0, o_expiry_range }, { "data-import", 1, 0, o_data_import }, { "data-verify", 0, 0, o_data_verify }, { "verify-only", 0, 0, o_verify_only }, { "generate-keys", 0, 0, o_generate_keys }, { "key-prefix", 1, 0, o_key_prefix }, { "key-minimum", 1, 0, o_key_minimum }, { "key-maximum", 1, 0, o_key_maximum }, { "key-pattern", 1, 0, o_key_pattern }, { "key-stddev", 1, 0, o_key_stddev }, { "key-median", 1, 0, o_key_median }, { "reconnect-interval", 1, 0, o_reconnect_interval }, { "multi-key-get", 1, 0, o_multi_key_get }, { "authenticate", 1, 0, 'a' }, { "select-db", 1, 0, o_select_db }, { "no-expiry", 0, 0, o_no_expiry }, { "help", 0, 0, 'h' }, { "version", 0, 0, 'v' }, { NULL, 0, 0, 0 } }; int option_index; int c; char *endptr; while ((c = getopt_long(argc, argv, "s:S:p:P:o:x:DRn:c:t:d:a:h", long_options, &option_index)) != -1) { switch (c) { case 'h': return -1; break; case 'v': puts(PACKAGE_STRING); puts("Copyright (C) 2011-2013 Garantia Data Ltd."); puts("This is free software. You may redistribute copies of it under the terms of"); puts("the GNU General Public License <http://www.gnu.org/licenses/gpl.html>."); puts("There is NO WARRANTY, to the extent permitted by law."); exit(0); case 's': cfg->server = optarg; break; case 'S': cfg->unix_socket = optarg; break; case 'p': endptr = NULL; cfg->port = (unsigned short) strtoul(optarg, &endptr, 10); if (!cfg->port || cfg->port > 65535 || !endptr || *endptr != '\0') { fprintf(stderr, "error: port must be a number in the range [1-65535].\n"); return -1; } break; case 'P': if (strcmp(optarg, "memcache_text") && strcmp(optarg, "memcache_binary") && strcmp(optarg, "redis")) { fprintf(stderr, "error: supported protocols are 'memcache_text', 'memcache_binary' and 'redis'.\n"); return -1; } cfg->protocol = optarg; break; case 'o': cfg->out_file = optarg; break; case o_client_stats: cfg->client_stats = optarg; break; case 'x': endptr = NULL; cfg->run_count = (unsigned int) strtoul(optarg, &endptr, 10); if (!cfg->run_count || !endptr || *endptr != '\0') { fprintf(stderr, "error: run count must be greater than zero.\n"); return -1; } break; case 'D': cfg->debug++; break; case o_show_config: cfg->show_config++; break; case o_hide_histogram: cfg->hide_histogram++; break; case o_distinct_client_seed: cfg->distinct_client_seed++; break; case o_randomize: cfg->randomize = (int)time(NULL); break; case 'n': endptr = NULL; if (strcmp(optarg, "allkeys")==0) cfg->requests = -1; else { cfg->requests = (unsigned int) strtoul(optarg, &endptr, 10); if (!cfg->requests || !endptr || *endptr != '\0') { fprintf(stderr, "error: requests must be greater than zero.\n"); return -1; } if (cfg->test_time) { fprintf(stderr, "error: --test-time and --requests are mutually exclusive.\n"); return -1; } } break; case 'c': endptr = NULL; cfg->clients = (unsigned int) strtoul(optarg, &endptr, 10); if (!cfg->clients || !endptr || *endptr != '\0') { fprintf(stderr, "error: clients must be greater than zero.\n"); return -1; } break; case 't': endptr = NULL; cfg->threads = (unsigned int) strtoul(optarg, &endptr, 10); if (!cfg->threads || !endptr || *endptr != '\0') { fprintf(stderr, "error: threads must be greater than zero.\n"); return -1; } break; case o_test_time: endptr = NULL; cfg->test_time = (unsigned int) strtoul(optarg, &endptr, 10); if (!cfg->test_time || !endptr || *endptr != '\0') { fprintf(stderr, "error: test time must be greater than zero.\n"); return -1; } if (cfg->requests) { fprintf(stderr, "error: --test-time and --requests are mutually exclusive.\n"); return -1; } break; case o_ratio: cfg->ratio = config_ratio(optarg); if (!cfg->ratio.is_defined()) { fprintf(stderr, "error: ratio must be expressed as [0-n]:[0-n].\n"); return -1; } break; case o_pipeline: endptr = NULL; cfg->pipeline = (unsigned int) strtoul(optarg, &endptr, 10); if (!cfg->pipeline || !endptr || *endptr != '\0') { fprintf(stderr, "error: pipeline must be greater than zero.\n"); return -1; } break; case 'd': endptr = NULL; cfg->data_size = (unsigned int) strtoul(optarg, &endptr, 10); if (!cfg->data_size || !endptr || *endptr != '\0') { fprintf(stderr, "error: data-size must be greater than zero.\n"); return -1; } break; case 'R': cfg->random_data = true; break; case o_data_offset: endptr = NULL; cfg->data_offset = (unsigned int) strtoul(optarg, &endptr, 10); if (!endptr || *endptr != '\0') { fprintf(stderr, "error: data-offset must be greater than or equal to zero.\n"); return -1; } break; case o_data_size_range: cfg->data_size_range = config_range(optarg); if (!cfg->data_size_range.is_defined() || cfg->data_size_range.min < 1) { fprintf(stderr, "error: data-size-range must be expressed as [1-n]-[1-n].\n"); return -1; } break; case o_data_size_list: cfg->data_size_list = config_weight_list(optarg); if (!cfg->data_size_list.is_defined()) { fprintf(stderr, "error: data-size-list must be expressed as [size1:weight1],...[sizeN:weightN].\n"); return -1; } break; case o_expiry_range: cfg->expiry_range = config_range(optarg); if (!cfg->expiry_range.is_defined()) { fprintf(stderr, "error: data-size-range must be expressed as [0-n]-[1-n].\n"); return -1; } break; case o_data_size_pattern: cfg->data_size_pattern = optarg; if (strlen(cfg->data_size_pattern) != 1 || (cfg->data_size_pattern[0] != 'R' && cfg->data_size_pattern[0] != 'S')) { fprintf(stderr, "error: data-size-pattern must be either R or S.\n"); return -1; } break; case o_data_import: cfg->data_import = optarg; break; case o_data_verify: cfg->data_verify = 1; break; case o_verify_only: cfg->verify_only = 1; cfg->data_verify = 1; // Implied break; case o_key_prefix: cfg->key_prefix = optarg; break; case o_key_minimum: endptr = NULL; cfg->key_minimum = (unsigned int) strtoul(optarg, &endptr, 10); if (cfg->key_minimum < 1 || !endptr || *endptr != '\0') { fprintf(stderr, "error: key-minimum must be greater than zero.\n"); return -1; } break; case o_key_maximum: endptr = NULL; cfg->key_maximum = (unsigned int) strtoul(optarg, &endptr, 10); if (cfg->key_maximum< 1 || !endptr || *endptr != '\0') { fprintf(stderr, "error: key-maximum must be greater than zero.\n"); return -1; } break; case o_key_stddev: endptr = NULL; cfg->key_stddev = (unsigned int) strtof(optarg, &endptr); if (cfg->key_stddev<= 0 || !endptr || *endptr != '\0') { fprintf(stderr, "error: key-stddev must be greater than zero.\n"); return -1; } break; case o_key_median: endptr = NULL; cfg->key_median = (unsigned int) strtof(optarg, &endptr); if (cfg->key_median<= 0 || !endptr || *endptr != '\0') { fprintf(stderr, "error: key-median must be greater than zero.\n"); return -1; } break; case o_key_pattern: cfg->key_pattern = optarg; if (strlen(cfg->key_pattern) != 3 || cfg->key_pattern[1] != ':' || (cfg->key_pattern[0] != 'R' && cfg->key_pattern[0] != 'S' && cfg->key_pattern[0] != 'G' && cfg->key_pattern[0] != 'P') || (cfg->key_pattern[2] != 'R' && cfg->key_pattern[2] != 'S' && cfg->key_pattern[2] != 'G' && cfg->key_pattern[2] != 'P')) { fprintf(stderr, "error: key-pattern must be in the format of [S/R/G]:[S/R/G].\n"); return -1; } break; case o_reconnect_interval: endptr = NULL; cfg->reconnect_interval = (unsigned int) strtoul(optarg, &endptr, 10); if (!cfg->reconnect_interval || !endptr || *endptr != '\0') { fprintf(stderr, "error: reconnect-interval must be greater than zero.\n"); return -1; } break; case o_generate_keys: cfg->generate_keys = 1; break; case o_multi_key_get: endptr = NULL; cfg->multi_key_get = (unsigned int) strtoul(optarg, &endptr, 10); if (cfg->multi_key_get <= 0 || !endptr || *endptr != '\0') { fprintf(stderr, "error: multi-key-get must be greater than zero.\n"); return -1; } break; case 'a': cfg->authenticate = optarg; break; case o_select_db: cfg->select_db = (int) strtoul(optarg, &endptr, 10); if (cfg->select_db < 0 || !endptr || *endptr != '\0') { fprintf(stderr, "error: select-db must be greater or equal zero.\n"); return -1; } break; case o_no_expiry: cfg->no_expiry = true; break; default: return -1; break; } } return 0; }