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