|
|
@ -480,78 +480,118 @@ static double bench_algo_stage2( |
|
|
|
enum sha256_algos algo |
|
|
|
enum sha256_algos algo |
|
|
|
) |
|
|
|
) |
|
|
|
{ |
|
|
|
{ |
|
|
|
#if defined(__linux) |
|
|
|
// Here, the gig is to safely run a piece of code that potentially
|
|
|
|
// Make a shared+anonymous mmap
|
|
|
|
// crashes. Unfortunately, the Right Way (tm) to do this is rather
|
|
|
|
const size_t map_size = 4096; |
|
|
|
// heavily platform dependent :(
|
|
|
|
void *map = mmap( |
|
|
|
|
|
|
|
(void*)NULL, |
|
|
|
double rate = -1.23457; |
|
|
|
map_size, |
|
|
|
|
|
|
|
PROT_READ | |
|
|
|
#if defined(unix) |
|
|
|
PROT_WRITE, |
|
|
|
|
|
|
|
MAP_SHARED | |
|
|
|
// Make a pipe: [readFD, writeFD]
|
|
|
|
MAP_ANONYMOUS, |
|
|
|
int pfd[2]; |
|
|
|
-1, |
|
|
|
int r = pipe(pfd); |
|
|
|
0 |
|
|
|
if (r<0) { |
|
|
|
); |
|
|
|
perror("pipe - failed to create pipe for --algo auto"); |
|
|
|
if ((void*)-1 == map) { |
|
|
|
|
|
|
|
perror("bench algo, mmap failed"); |
|
|
|
|
|
|
|
exit(1); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Load a canary rate in the map
|
|
|
|
// Make pipe non blocking
|
|
|
|
double rate = -1.23457; |
|
|
|
set_non_blocking(pfd[0], 1); |
|
|
|
memcpy(map, &rate, sizeof(rate)); |
|
|
|
set_non_blocking(pfd[1], 1); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Don't allow a crashing child to kill the main process
|
|
|
|
|
|
|
|
sighandler_t sr0 = signal(SIGPIPE, SIG_IGN); |
|
|
|
|
|
|
|
sighandler_t sr1 = signal(SIGPIPE, SIG_IGN); |
|
|
|
|
|
|
|
if (SIG_ERR==sr0 || SIG_ERR==sr1) { |
|
|
|
|
|
|
|
perror("signal - failed to edit signal mask for --algo auto"); |
|
|
|
|
|
|
|
exit(1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Fork a child to do the actual benchmarking
|
|
|
|
// Fork a child to do the actual benchmarking
|
|
|
|
pid_t child_pid = fork(); |
|
|
|
pid_t child_pid = fork(); |
|
|
|
|
|
|
|
if (child_pid<0) { |
|
|
|
|
|
|
|
perror("fork - failed to create a child process for --algo auto"); |
|
|
|
|
|
|
|
exit(1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Do the dangerous work in the child, knowing we might crash
|
|
|
|
if (0==child_pid) { |
|
|
|
if (0==child_pid) { |
|
|
|
|
|
|
|
|
|
|
|
// Do the dangerous work in the child
|
|
|
|
// TODO: some umask trickery to prevent coredumps
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Benchmark this algorithm
|
|
|
|
double r = bench_algo_stage3(algo); |
|
|
|
double r = bench_algo_stage3(algo); |
|
|
|
|
|
|
|
|
|
|
|
// Load result in shared map and bail
|
|
|
|
// We survived, send result to parent and bail
|
|
|
|
memcpy(map, &r, sizeof(r)); |
|
|
|
int loop_count = 0; |
|
|
|
|
|
|
|
while (1) { |
|
|
|
|
|
|
|
ssize_t bytes_written = write(pfd[1], &r, sizeof(r)); |
|
|
|
|
|
|
|
int try_again = (0==bytes_written || (bytes_written<0 && EAGAIN==errno)); |
|
|
|
|
|
|
|
int success = (sizeof(r)==(size_t)bytes_written); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (success) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!try_again) { |
|
|
|
|
|
|
|
perror("write - child failed to write benchmark result to pipe"); |
|
|
|
|
|
|
|
exit(1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (5<loop_count) { |
|
|
|
|
|
|
|
applog(LOG_ERR, "child tried %d times to communicate with parent, giving up", loop_count); |
|
|
|
|
|
|
|
exit(1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
++loop_count; |
|
|
|
|
|
|
|
sleep(1); |
|
|
|
|
|
|
|
} |
|
|
|
exit(0); |
|
|
|
exit(0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Parent waits for a result from child
|
|
|
|
// Parent waits for a result from child
|
|
|
|
int nb_loops = 0; |
|
|
|
int loop_count = 0; |
|
|
|
while (1) { |
|
|
|
while (1) { |
|
|
|
|
|
|
|
|
|
|
|
// Wait for child to die
|
|
|
|
// Wait for child to die
|
|
|
|
int status; |
|
|
|
int status; |
|
|
|
int r = waitpid(child_pid, &status, WNOHANG); |
|
|
|
int r = waitpid(child_pid, &status, WNOHANG); |
|
|
|
if (child_pid==r) { |
|
|
|
if ((child_pid==r) || (r<0 && ECHILD==errno)) { |
|
|
|
// Child died somehow. Copy result and bail
|
|
|
|
|
|
|
|
memcpy(&rate, map, sizeof(rate)); |
|
|
|
// Child died somehow. Grab result and bail
|
|
|
|
|
|
|
|
double tmp; |
|
|
|
|
|
|
|
ssize_t bytes_read = read(pfd[0], &tmp, sizeof(tmp)); |
|
|
|
|
|
|
|
if (sizeof(tmp)==(size_t)bytes_read) |
|
|
|
|
|
|
|
rate = tmp; |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
} else if (r<0) { |
|
|
|
} else if (r<0) { |
|
|
|
perror("bench_algo: waitpid failed. giving up."); |
|
|
|
perror("bench_algo: waitpid failed. giving up."); |
|
|
|
exit(1); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Give up on child after a ~60s
|
|
|
|
// Give up on child after a ~60s
|
|
|
|
if (60<nb_loops) { |
|
|
|
if (60<loop_count) { |
|
|
|
kill(child_pid, SIGKILL); |
|
|
|
kill(child_pid, SIGKILL); |
|
|
|
waitpid(child_pid, &status, 0); |
|
|
|
waitpid(child_pid, &status, 0); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Wait a bit longer
|
|
|
|
// Wait a bit longer
|
|
|
|
++nb_loops; |
|
|
|
++loop_count; |
|
|
|
sleep(1); |
|
|
|
sleep(1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Clean up shared map
|
|
|
|
// Close pipe
|
|
|
|
int r = munmap(map, map_size); |
|
|
|
r = close(pfd[0]); |
|
|
|
if (r<0) { |
|
|
|
if (r<0) { |
|
|
|
perror("bench algo, munmap failed"); |
|
|
|
perror("close - failed to close read end of pipe for --algo auto"); |
|
|
|
exit(1); |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
} |
|
|
|
#else |
|
|
|
#else |
|
|
|
// Not on linux, just run the risk of an illegal instruction
|
|
|
|
// Not on linux, just run the risk of an illegal instruction
|
|
|
|
rate = bench_algo_stage3(algo); |
|
|
|
rate = bench_algo_stage3(algo); |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#endif // defined(unix)
|
|
|
|
|
|
|
|
|
|
|
|
// Done
|
|
|
|
// Done
|
|
|
|
return rate; |
|
|
|
return rate; |
|
|
|