#include "scrypt_platform.h"
#include <sys/time.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include "crypto_scrypt.h"
#include "scryptenc_cpuperf.h"
#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
struct timespec {
long tv_sec;
long tv_nsec;
};
#endif
#ifdef HAVE_CLOCK_GETTIME
static clock_t clocktouse;
static int
getclockres(double * resd)
{
struct timespec res;
#ifdef CLOCK_VIRTUAL
if (clock_getres(CLOCK_VIRTUAL, &res) == 0)
clocktouse = CLOCK_VIRTUAL;
else
#endif
#ifdef CLOCK_MONOTONIC
if (clock_getres(CLOCK_MONOTONIC, &res) == 0)
clocktouse = CLOCK_MONOTONIC;
else
#endif
if (clock_getres(CLOCK_REALTIME, &res) == 0)
clocktouse = CLOCK_REALTIME;
else
return (-1);
*resd = res.tv_sec + res.tv_nsec * 0.000000001;
return (0);
}
static int
getclocktime(struct timespec * ts)
{
if (clock_gettime(clocktouse, ts))
return (-1);
return (0);
}
#else
static int
getclockres(double * resd)
{
*resd = 1.0 / CLOCKS_PER_SEC;
return (0);
}
static int
getclocktime(struct timespec * ts)
{
struct timeval tv;
if (gettimeofday(&tv, NULL))
return (-1);
ts->tv_sec = tv.tv_sec;
ts->tv_nsec = tv.tv_usec * 1000;
return (0);
}
#endif
static int
getclockdiff(struct timespec * st, double * diffd)
{
struct timespec en;
if (getclocktime(&en))
return (1);
*diffd = (en.tv_nsec - st->tv_nsec) * 0.000000001 +
(en.tv_sec - st->tv_sec);
return (0);
}
int
scryptenc_cpuperf(double * opps)
{
struct timespec st;
double resd, diffd;
uint64_t i = 0;
if (getclockres(&resd))
return (2);
#ifdef DEBUG
fprintf(stderr, "Clock resolution is %f\n", resd);
#endif
if (getclocktime(&st))
return (2);
do {
if (crypto_scrypt(NULL, 0, NULL, 0, 16, 1, 1, NULL, 0))
return (3);
if (getclockdiff(&st, &diffd))
return (2);
if (diffd > 0)
break;
} while (1);
if (getclocktime(&st))
return (2);
do {
if (crypto_scrypt(NULL, 0, NULL, 0, 128, 1, 1, NULL, 0))
return (3);
i += 512;
if (getclockdiff(&st, &diffd))
return (2);
if (diffd > resd)
break;
} while (1);
#ifdef DEBUG
fprintf(stderr, "%ju salsa20/8 cores performed in %f seconds\n",
(uintmax_t)i, diffd);
#endif
*opps = i / diffd;
return (0);
}