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; next_random_seed()31LIBC_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(&entropy, sizeof(entropy)); 53 } 54 state.update(&counter, 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