1 | //===-- HashTable Randomness ------------------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLVM_LIBC_SRC___SUPPORT_HASHTABLE_RANDOMNESS_H |
10 | #define LLVM_LIBC_SRC___SUPPORT_HASHTABLE_RANDOMNESS_H |
11 | |
12 | #include "src/__support/common.h" |
13 | #include "src/__support/hash.h" |
14 | #include "src/__support/macros/attributes.h" |
15 | #if defined(LIBC_HASHTABLE_USE_GETRANDOM) |
16 | #include "src/errno/libc_errno.h" |
17 | #include "src/sys/random/getrandom.h" |
18 | #endif |
19 | |
20 | namespace LIBC_NAMESPACE { |
21 | namespace internal { |
22 | namespace randomness { |
23 | // We need an initial state for the hash function. More entropy are to be added |
24 | // at the first use and each round of reseeding. The following random numbers |
25 | // are generated from https://www.random.org/cgi-bin/randbyte?nbytes=64&format=h |
26 | LIBC_INLINE_VAR thread_local HashState state = { |
27 | 0x38049a7ea6f5a79b, 0x45cb02147c3f718a, 0x53eb431c12770718, |
28 | 0x5b55742bd20a2fcb}; |
29 | LIBC_INLINE_VAR thread_local uint64_t counter = 0; |
30 | LIBC_INLINE_VAR constexpr uint64_t RESEED_PERIOD = 1024; |
31 | LIBC_INLINE uint64_t next_random_seed() { |
32 | if (counter % RESEED_PERIOD == 0) { |
33 | uint64_t entropy[2]; |
34 | entropy[0] = reinterpret_cast<uint64_t>(&entropy); |
35 | entropy[1] = reinterpret_cast<uint64_t>(&state); |
36 | #if defined(LIBC_HASHTABLE_USE_GETRANDOM) |
37 | int errno_backup = libc_errno; |
38 | ssize_t count = sizeof(entropy); |
39 | uint8_t *buffer = reinterpret_cast<uint8_t *>(entropy); |
40 | while (count > 0) { |
41 | ssize_t len = getrandom(buffer, count, 0); |
42 | if (len == -1) { |
43 | if (libc_errno == ENOSYS) |
44 | break; |
45 | continue; |
46 | } |
47 | count -= len; |
48 | buffer += len; |
49 | } |
50 | libc_errno = errno_backup; |
51 | #endif |
52 | state.update(ptr: &entropy, size: sizeof(entropy)); |
53 | } |
54 | state.update(ptr: &counter, size: sizeof(counter)); |
55 | counter++; |
56 | return state.finish(); |
57 | } |
58 | |
59 | } // namespace randomness |
60 | } // namespace internal |
61 | } // namespace LIBC_NAMESPACE |
62 | #endif // LLVM_LIBC_SRC___SUPPORT_HASHTABLE_RANDOMNESS_H |
63 | |