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 #include "src/__support/macros/config.h" 16 #if defined(LIBC_HASHTABLE_USE_GETRANDOM) 17 #include "src/errno/libc_errno.h" 18 #include "src/sys/random/getrandom.h" 19 #endif 20 21 namespace LIBC_NAMESPACE_DECL { 22 namespace internal { 23 namespace randomness { 24 // We need an initial state for the hash function. More entropy are to be added 25 // at the first use and each round of reseeding. The following random numbers 26 // are generated from https://www.random.org/cgi-bin/randbyte?nbytes=64&format=h 27 LIBC_INLINE_VAR thread_local HashState state = { 28 0x38049a7ea6f5a79b, 0x45cb02147c3f718a, 0x53eb431c12770718, 29 0x5b55742bd20a2fcb}; 30 LIBC_INLINE_VAR thread_local uint64_t counter = 0; 31 LIBC_INLINE_VAR constexpr uint64_t RESEED_PERIOD = 1024; next_random_seed()32LIBC_INLINE uint64_t next_random_seed() { 33 if (counter % RESEED_PERIOD == 0) { 34 uint64_t entropy[2]; 35 entropy[0] = reinterpret_cast<uint64_t>(&entropy); 36 entropy[1] = reinterpret_cast<uint64_t>(&state); 37 #if defined(LIBC_HASHTABLE_USE_GETRANDOM) 38 int errno_backup = libc_errno; 39 size_t count = sizeof(entropy); 40 uint8_t *buffer = reinterpret_cast<uint8_t *>(entropy); 41 while (count > 0) { 42 ssize_t len = getrandom(buffer, count, 0); 43 if (len == -1) { 44 if (libc_errno == ENOSYS) 45 break; 46 continue; 47 } 48 count -= len; 49 buffer += len; 50 } 51 libc_errno = errno_backup; 52 #endif 53 state.update(&entropy, sizeof(entropy)); 54 } 55 state.update(&counter, sizeof(counter)); 56 counter++; 57 return state.finish(); 58 } 59 60 } // namespace randomness 61 } // namespace internal 62 } // namespace LIBC_NAMESPACE_DECL 63 #endif // LLVM_LIBC_SRC___SUPPORT_HASHTABLE_RANDOMNESS_H 64