diff options
| author | J08nY | 2017-10-04 19:11:14 +0200 |
|---|---|---|
| committer | J08nY | 2017-10-04 19:11:14 +0200 |
| commit | 531c26c732ca8d01cd95c88c70bed6038bc8cba8 (patch) | |
| tree | 82cdab0616f0b3faa1436dc0b08f9d3cefdf36f4 | |
| parent | 53bdab0a3d0411bbdc092dc9c3ae5a0f8afa6c6d (diff) | |
| parent | 5fce9d7a2b6d012fbbbf1d5fd0c4759418c3d189 (diff) | |
| download | ecgen-531c26c732ca8d01cd95c88c70bed6038bc8cba8.tar.gz ecgen-531c26c732ca8d01cd95c88c70bed6038bc8cba8.tar.zst ecgen-531c26c732ca8d01cd95c88c70bed6038bc8cba8.zip | |
| -rw-r--r-- | README.md | 1 | ||||
| -rw-r--r-- | src/ecgen.c | 4 | ||||
| -rw-r--r-- | src/exhaustive/exhaustive.c | 11 | ||||
| -rw-r--r-- | src/io/cli.c | 21 | ||||
| -rw-r--r-- | src/misc/config.h | 1 | ||||
| -rw-r--r-- | src/util/timeout.c | 29 | ||||
| -rw-r--r-- | src/util/timeout.h | 56 |
7 files changed, 121 insertions, 2 deletions
@@ -40,6 +40,7 @@ Tool for generating Elliptic curve domain parameters. - `-m / --memory=SIZE` Use PARI stack of `SIZE` (can have suffix k/m/g). - `--threads=NUM` Use `NUM` threads. - `--thread-stack=SIZE` Use PARI stack of `SIZE` (per thread, can have suffix k/m/g). + - `--timeout=TIME` Timeout computation of a curve parameter after `TIME` (can have suffix s/m/h/d). #### Examples diff --git a/src/ecgen.c b/src/ecgen.c index c7c5871..822b0af 100644 --- a/src/ecgen.c +++ b/src/ecgen.c @@ -29,6 +29,7 @@ #include "invalid/invalid.h" #include "io/input.h" #include "io/output.h" +#include "util/timeout.h" const char *argp_program_version = "ecgen 0.6.0\n" @@ -50,6 +51,9 @@ bool init(void) { // init PARI PRNG if (!random_init()) return false; + // init the signal handlers, etc. for timeout handling + if (!timeout_init(&cfg)) return false; + // set datadir if specified if (cfg.datadir) { default0("datadir", cfg.datadir); diff --git a/src/exhaustive/exhaustive.c b/src/exhaustive/exhaustive.c index 5011490..b55bcca 100644 --- a/src/exhaustive/exhaustive.c +++ b/src/exhaustive/exhaustive.c @@ -15,6 +15,7 @@ #include "gen/seed.h" #include "io/output.h" #include "util/memory.h" +#include "util/timeout.h" exhaustive_t *exhaustive_new(void) { return try_calloc(sizeof(exhaustive_t)); } @@ -230,7 +231,15 @@ int exhaustive_gen_retry(curve_t *curve, const config_t *cfg, arg_t *arg = argss ? argss[state] : NULL; - int diff = generators[state](curve, cfg, arg, (offset_e)state); + int diff; + timeout_start(cfg->timeout) { + // This is not the best, but currently the best idea I have. + diff = start_offset - state; + } + else { + diff = generators[state](curve, cfg, arg, (offset_e)state); + } + timeout_stop(); int new_state = state + diff; if (new_state < start_offset) new_state = start_offset; diff --git a/src/io/cli.c b/src/io/cli.c index 77f279f..74e6cc7 100644 --- a/src/io/cli.c +++ b/src/io/cli.c @@ -4,7 +4,6 @@ */ #include "cli.h" #include <string.h> -#include <unistd.h> #include "exhaustive/ansi.h" char cli_doc[] = @@ -34,6 +33,7 @@ enum opt_keys { OPT_POINTS, OPT_THREADS, OPT_TSTACK, + OPT_TIMEOUT, OPT_ANOMALOUS }; @@ -68,6 +68,7 @@ struct argp_option cli_options[] = { {"memory", OPT_MEMORY, "SIZE", 0, "Use PARI stack of SIZE (can have suffix k/m/g).", 4}, {"threads", OPT_THREADS, "NUM", 0, "Use NUM threads.", 4}, {"thread-stack", OPT_TSTACK, "SIZE", 0, "Use PARI stack of SIZE (per thread, can have suffix k/m/g).", 4}, + {"timeout", OPT_TIMEOUT, "TIME", 0, "Timeout computation of a curve parameter after TIME (can have suffix s/m/h/d).", 4}, {0} }; // clang-format on @@ -87,6 +88,21 @@ static unsigned long cli_parse_memory(const char *str) { return read; } +static unsigned long cli_parse_time(const char *str) { + char *suffix = NULL; + unsigned long read = strtoul(str, &suffix, 10); + if (suffix) { + if (*suffix == 'm' || *suffix == 'M') { + read *= 60; + } else if (*suffix == 'h' || *suffix == 'H') { + read *= 3600; + } else if (*suffix == 'd' || *suffix == 'D') { + read *= 86400; + } + } + return read; +} + error_t cli_parse(int key, char *arg, struct argp_state *state) { config_t *cfg = state->input; @@ -100,6 +116,9 @@ error_t cli_parse(int key, char *arg, struct argp_state *state) { case OPT_TSTACK: cfg->thread_memory = cli_parse_memory(arg); break; + case OPT_TIMEOUT: + cfg->timeout = cli_parse_time(arg); + break; case OPT_THREADS: if (!strcmp(arg, "auto") || !strcmp(arg, "AUTO")) { long nprocs = sysconf(_SC_NPROCESSORS_ONLN); diff --git a/src/misc/config.h b/src/misc/config.h index 5069881..fe792d5 100644 --- a/src/misc/config.h +++ b/src/misc/config.h @@ -58,6 +58,7 @@ typedef struct { unsigned long memory; unsigned long threads; unsigned long thread_memory; + unsigned long timeout; enum format_e format; char *output; diff --git a/src/util/timeout.c b/src/util/timeout.c new file mode 100644 index 0000000..c9608a9 --- /dev/null +++ b/src/util/timeout.c @@ -0,0 +1,29 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ +#include "timeout.h" + +__thread jmp_buf timeout_ptr; +__thread bool timeout_in = false; +__thread timer_t timeout_timer; + +void timeout_handle(int signum, siginfo_t *siginfo, void *other) { + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGALRM); + sigprocmask(SIG_UNBLOCK, &mask, NULL); + + if (timeout_in) siglongjmp(timeout_ptr, 1); +} + +bool timeout_init(const config_t *cfg) { + struct sigaction new_action; + + new_action.sa_sigaction = timeout_handle; + sigemptyset(&new_action.sa_mask); + new_action.sa_flags = SA_SIGINFO; + + sigaction(SIGALRM, &new_action, NULL); + return true; +}
\ No newline at end of file diff --git a/src/util/timeout.h b/src/util/timeout.h new file mode 100644 index 0000000..2b615bb --- /dev/null +++ b/src/util/timeout.h @@ -0,0 +1,56 @@ +/* + * ecgen, tool for generating Elliptic curve domain parameters + * Copyright (C) 2017 J08nY + */ +#ifndef ECGEN_TIMEOUT_H +#define ECGEN_TIMEOUT_H + +#include <setjmp.h> +#include <sys/syscall.h> +#include <time.h> +#include <unistd.h> +#include "io/output.h" +#include "misc/config.h" + +extern __thread sigjmp_buf timeout_ptr; +extern __thread bool timeout_in; +extern __thread timer_t timeout_timer; + +/** + * @brief + */ +#define timeout_start(seconds) \ + if ((seconds) != 0) { \ + struct sigevent sevp; \ + sevp.sigev_notify = SIGEV_THREAD_ID; \ + sevp.sigev_signo = SIGALRM; \ + sevp._sigev_un._tid = (__pid_t)syscall(SYS_gettid); \ + \ + timer_create(CLOCK_MONOTONIC, &sevp, &timeout_timer); \ + struct itimerspec timer_time = { \ + .it_interval = {.tv_sec = 0, .tv_nsec = 0}, \ + .it_value = {.tv_sec = (seconds), .tv_nsec = 0}}; \ + timer_settime(timeout_timer, 0, &timer_time, NULL); \ + timeout_in = true; \ + }; \ + if ((seconds) != 0 && sigsetjmp(timeout_ptr, 1) == 1) + +/** + * @brief + */ +#define timeout_stop() \ + { \ + if (timeout_in) { \ + timeout_in = false; \ + timer_delete(timeout_timer); \ + } \ + } + +/** + * @brief + * @param cfg + * @return + */ +bool timeout_init(const config_t *cfg); + +#endif // ECGEN_TIMEOUT_H |
