Fix issues with previous commit

This commit is contained in:
Justine Tunney 2024-09-10 01:59:46 -07:00
parent 2f48a02b44
commit a0a404a431
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
8 changed files with 122 additions and 57 deletions

View file

@ -86,19 +86,28 @@ static ssize_t GetRandomBsd(char *p, size_t n, void impl(char *, size_t)) {
} }
} }
static ssize_t GetDevUrandom(char *p, size_t n) { static ssize_t GetDevUrandom(char *p, size_t n, unsigned f) {
int fd; int fd;
int oflags;
ssize_t rc; ssize_t rc;
BLOCK_SIGNALS; const char *dev;
BLOCK_CANCELATION; BEGIN_CANCELATION_POINT;
fd = sys_openat(AT_FDCWD, "/dev/urandom", O_RDONLY | O_CLOEXEC, 0); if (f & GRND_RANDOM) {
dev = "/dev/random";
} else {
dev = "/dev/urandom";
}
oflags = O_RDONLY | O_CLOEXEC;
if (f & GRND_NONBLOCK)
oflags |= O_NONBLOCK;
fd = sys_openat(AT_FDCWD, dev, oflags, 0);
if (fd != -1) { if (fd != -1) {
rc = sys_read(fd, p, n); rc = sys_read(fd, p, n);
sys_close(fd);
} else { } else {
rc = -1; rc = -1;
} }
ALLOW_CANCELATION; END_CANCELATION_POINT;
ALLOW_SIGNALS;
return rc; return rc;
} }
@ -122,7 +131,7 @@ ssize_t __getrandom(void *p, size_t n, unsigned f) {
#endif #endif
} else { } else {
BEGIN_CANCELATION_POINT; BEGIN_CANCELATION_POINT;
rc = GetDevUrandom(p, n); rc = GetDevUrandom(p, n, f);
END_CANCELATION_POINT; END_CANCELATION_POINT;
} }
return rc; return rc;

View file

@ -27,7 +27,7 @@
static int _rand64_pid; static int _rand64_pid;
static unsigned __int128 _rand64_pool; static unsigned __int128 _rand64_pool;
pthread_mutex_t _rand64_lock_obj = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; pthread_mutex_t _rand64_lock_obj = PTHREAD_SIGNAL_SAFE_MUTEX_INITIALIZER_NP;
/** /**
* Returns nondeterministic random data. * Returns nondeterministic random data.

View file

@ -85,7 +85,7 @@ static void _onfork_child(void) {
if (IsWindows()) if (IsWindows())
__proc_wipe(); __proc_wipe();
__fds_lock_obj = (pthread_mutex_t)PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; __fds_lock_obj = (pthread_mutex_t)PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
_rand64_lock_obj = (pthread_mutex_t)PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; _rand64_lock_obj = (pthread_mutex_t)PTHREAD_SIGNAL_SAFE_MUTEX_INITIALIZER_NP;
_pthread_lock_obj = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; _pthread_lock_obj = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
atomic_store_explicit(&__maps.lock, 0, memory_order_relaxed); atomic_store_explicit(&__maps.lock, 0, memory_order_relaxed);
if (_weaken(_pthread_onfork_child)) if (_weaken(_pthread_onfork_child))

View file

@ -4,23 +4,76 @@
#include "libc/stdio/stdio.h" #include "libc/stdio/stdio.h"
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
#define BENCHMARK(ITERATIONS, WORK_PER_RUN, CODE) \ #define X(x) __expropriate(x)
do { \ #define V(x) __veil("r", x)
struct timespec start = timespec_mono(); \
for (int __i = 0; __i < ITERATIONS; ++__i) { \ #define BENCHMARK(ITERATIONS, WORK_PER_RUN, CODE) \
asm volatile("" ::: "memory"); \ do { \
CODE; \ struct timespec start = timespec_mono(); \
} \ for (int __i = 0; __i < ITERATIONS; ++__i) { \
long long work = ((WORK_PER_RUN) ? (WORK_PER_RUN) : 1) * (ITERATIONS); \ asm volatile("" ::: "memory"); \
double nanos = \ CODE; \
(timespec_tonanos(timespec_sub(timespec_mono(), start)) + work - 1) / \ } \
(double)work; \ double total_nanos = \
if (nanos < 1000) { \ (double)timespec_tonanos(timespec_sub(timespec_mono(), start)); \
printf("%10g ns %2dx %s\n", nanos, (ITERATIONS), #CODE); \ double total_work = \
} else { \ (double)((WORK_PER_RUN) ? (WORK_PER_RUN) : 1) * (ITERATIONS); \
printf("%10lld ns %2dx %s\n", (long long)nanos, (ITERATIONS), #CODE); \ _print_benchmark_result(total_nanos, total_work, ITERATIONS, #CODE); \
} \
} while (0) } while (0)
static void _print_benchmark_result(double total_nanos, double total_work,
int iterations, const char* code) {
double time_per_op = total_nanos / iterations;
double throughput = total_work / (total_nanos * 1e-9);
const char* throughput_unit;
const char* time_unit;
double time_value;
// Determine throughput unit
if (throughput >= 1e9) {
throughput /= 1e9;
throughput_unit = "G";
} else if (throughput >= 1e6) {
throughput /= 1e6;
throughput_unit = "M";
} else if (throughput >= 1e3) {
throughput /= 1e3;
throughput_unit = "K";
} else {
throughput_unit = " ";
}
// Determine time unit
if (time_per_op >= 1e6) {
time_value = time_per_op / 1e6;
time_unit = "ms";
} else if (time_per_op >= 1e3) {
time_value = time_per_op / 1e3;
time_unit = "µs";
} else {
time_value = time_per_op;
time_unit = "ns";
}
// Determine work unit
const char* work_unit;
double work_value = total_work / iterations;
if (work_value >= 1e9) {
work_value /= 1e9;
work_unit = "G";
} else if (work_value >= 1e6) {
work_value /= 1e6;
work_unit = "M";
} else if (work_value >= 1e3) {
work_value /= 1e3;
work_unit = "K";
} else {
work_unit = " ";
}
printf("%8.2f %-2s %6.2f %s/s %6.2f %s %2dx %s\n", time_value, time_unit,
throughput, throughput_unit, work_value, work_unit, iterations, code);
}
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_LIBC_TESTLIB_BENCHMARK_H_ */ #endif /* COSMOPOLITAN_LIBC_TESTLIB_BENCHMARK_H_ */

View file

@ -47,6 +47,9 @@ COSMOPOLITAN_C_START_
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP {0, {}, PTHREAD_MUTEX_RECURSIVE} #define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP {0, {}, PTHREAD_MUTEX_RECURSIVE}
#define PTHREAD_SIGNAL_SAFE_MUTEX_INITIALIZER_NP \
{0, {}, PTHREAD_MUTEX_RECURSIVE | PTHREAD_PROCESS_SHARED}
#ifndef __cplusplus #ifndef __cplusplus
#define _PTHREAD_ATOMIC(x) _Atomic(x) #define _PTHREAD_ATOMIC(x) _Atomic(x)
#else #else

View file

@ -21,7 +21,7 @@
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/stdio/rand.h" #include "libc/stdio/rand.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/testlib/ezbench.h" #include "libc/testlib/benchmark.h"
#include "libc/testlib/testlib.h" #include "libc/testlib/testlib.h"
static void *golden(void *p, int c, size_t n) { static void *golden(void *p, int c, size_t n) {
@ -64,36 +64,11 @@ TEST(bzero, hug) {
} }
} }
BENCH(memset, bench) { #define N (256 * 1024 * 1024)
int n, max = 8 * 1024 * 1024;
char *volatile p = gc(malloc(max));
EZBENCH_N("memset", 0, memset(p, -1, 0));
for (n = 2; n <= max; n *= 2) {
EZBENCH_N("memset", n - 1, memset(p, -1, n - 1));
EZBENCH_N("memset", n, memset(p, -1, n));
}
EZBENCH_N("memset16", 0, memset16((char16_t *)p, -1, 0));
for (n = 2; n <= max; n *= 2) {
EZBENCH_N("memset16", n, memset16((char16_t *)p, -1, n / 2));
}
EZBENCH_N("bzero", 0, bzero(p, 0));
for (n = 2; n <= max; n *= 2) {
EZBENCH_N("bzero", n - 1, bzero(p, n - 1));
EZBENCH_N("bzero", n, bzero(p, n));
}
}
BENCH(strlen, bench) { BENCH(strlen, bench) {
int n, max = 8 * 1024 * 1024; static char A[N];
char *volatile p = gc(calloc(max + 1, 1)); memset(A, 2, N);
EZBENCH_N("strlen", 0, strlen(p)); for (int n = 1; n <= N; n *= 2)
for (n = 2; n <= max; n *= 2) { BENCHMARK(100, n, X(memset(V(A), 1, n)));
memset(p, -1, n - 1);
EZBENCH_N("strlen", n - 1, strlen(p));
p[n - 1] = -1;
EZBENCH_N("strlen", n, strlen(p));
}
} }

View file

@ -16,10 +16,34 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/assert.h"
#include "libc/stdio/rand.h" #include "libc/stdio/rand.h"
#include "libc/testlib/benchmark.h"
#include "libc/testlib/testlib.h" #include "libc/testlib/testlib.h"
uint64_t getrandom64(void) {
uint64_t x;
unassert(getrandom(&x, 8, 0) == 8);
return x;
}
uint64_t getentropy64(void) {
uint64_t x;
unassert(!getentropy(&x, 8));
return x;
}
TEST(lemur64, test) { TEST(lemur64, test) {
EXPECT_EQ(1819718037028923529, lemur64()); EXPECT_EQ(1819718037028923529, lemur64());
EXPECT_EQ(-3120132252617434764, lemur64()); EXPECT_EQ(-3120132252617434764, lemur64());
} }
BENCH(lemur64, bench) {
BENCHMARK(10000, 8, X(lemur64()));
BENCHMARK(10000, 4, X(rand()));
BENCHMARK(10000, 8, X(_rand64()));
BENCHMARK(10000, 8, X(rdrand()));
BENCHMARK(10000, 8, X(rdseed()));
BENCHMARK(10000, 8, X(getrandom64()));
BENCHMARK(10000, 8, X(getentropy64()));
}

View file

@ -19,6 +19,7 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include "libc/assert.h"
#define MAXIMUM 1e9 #define MAXIMUM 1e9
#define ITERATIONS 10 #define ITERATIONS 10
@ -45,7 +46,7 @@ void TestSleepRelative(int clock) {
if (clock_gettime(clock, &t1)) if (clock_gettime(clock, &t1))
return; return;
for (int i = 0; i < ITERATIONS; ++i) { for (int i = 0; i < ITERATIONS; ++i) {
assert(!clock_nanosleep(clock, 0, &wf, 0)); unassert(!clock_nanosleep(clock, 0, &wf, 0));
} }
clock_gettime(clock, &t2); clock_gettime(clock, &t2);
long took = timespec_tonanos(timespec_sub(t2, t1)) / ITERATIONS; long took = timespec_tonanos(timespec_sub(t2, t1)) / ITERATIONS;