mirror of
https://github.com/GOSTSec/sgminer
synced 2025-01-23 13:04:29 +00:00
On unix, make algo benchmark more generic
This commit is contained in:
parent
01886493cf
commit
6fd06387b3
102
main.c
102
main.c
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user