From owner-svn-src-head@freebsd.org Thu Aug 13 21:06:44 2020 Return-Path: Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id E29CC3AD08C; Thu, 13 Aug 2020 21:06:44 +0000 (UTC) (envelope-from mjguzik@gmail.com) Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "smtp.gmail.com", Issuer "GTS CA 1O1" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BSJz81QJ3z3ZsL; Thu, 13 Aug 2020 21:06:44 +0000 (UTC) (envelope-from mjguzik@gmail.com) Received: by mail-wr1-x435.google.com with SMTP id f12so6499569wru.13; Thu, 13 Aug 2020 14:06:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=vVSgphJx6NsEfZodVf94ov/VN/+xdyqkyiKjlbF3t6g=; b=psroPzwzOjwDKLXLN8N+DjLxtW2PArNJDUnO2D4REjpd4pyaB99wXiA67aN8SgtNQS 9QeIqtbIsQtq2Dmn7Bq5dNpFyULYjKUwX9ZTBijgcS6UDLMDPAWob3ofoV7jAIxrJX7j yTw2/Glr0fvhm73J9+adgFL0brWgedSZY6G5NIcvbCE5bQGBLzxk5ZEvhpBuGtl6k3D5 GGO8oj8oC30pPDhrjTEAvAXdrOPihxvZgskrmKAm7JHvLowbmH+X6IyuYsrTsXDZxvWz +hlY+IiZ969pl/RZnJJu3UxM3Yj1aJj63aDU35bpIB483/STPja0C4LHIbd7LIu2zn8+ 8ulw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=vVSgphJx6NsEfZodVf94ov/VN/+xdyqkyiKjlbF3t6g=; b=Cjn4yA4PagAY8+qHuFlb1unkUSZ3bDeD8hvWjpuXpa+gqMaA/RuNNisG5++ZA7GtD5 hi4aauYVU3SjeD8VkoOQT6gICONeDpvpyHxlRiyhhv6YBq2f+n6ZJ6MzYQ99Npmq1s4I NFJZ+s9l0+evzz9qSuaEDTbiMFBuRQoAZ5G8KBje9lz+6o5hQI56W8XsoPFEkfkVUDcj bjM+N+jE48xpyc3Yfj4nFPU6d075h2QLlkee/yaIdOVwB0v1KV3uUI1zKis6vw/gne+8 9hHdnRp52Yk//Rl2+t/3nZwKyGyht1AWM5y9NTKyH7FqkBqcKCaNUpOixQSUx2xj8EZc HW5Q== X-Gm-Message-State: AOAM531kbfEk7Tsia0yTjY8r3A2yfgVNR9A+0Zq2LQlLY1dGICuJJWq7 jGt+HSRsaYSojmfDKQiZWW5IrJmaM4NKcMj4UiYFiA== X-Google-Smtp-Source: ABdhPJyoXl11RMILpyz9GHnwDu4BDrnqZK7zkFUba7tBWeknFUxSLWGvZuVhdihIq7D7qUPvqJOhmDrdEtgQ90cUsV8= X-Received: by 2002:adf:82b2:: with SMTP id 47mr5502001wrc.17.1597352802017; Thu, 13 Aug 2020 14:06:42 -0700 (PDT) MIME-Version: 1.0 Received: by 2002:a5d:614c:0:0:0:0:0 with HTTP; Thu, 13 Aug 2020 14:06:41 -0700 (PDT) In-Reply-To: <202008132048.07DKmEO9069055@repo.freebsd.org> References: <202008132048.07DKmEO9069055@repo.freebsd.org> From: Mateusz Guzik Date: Thu, 13 Aug 2020 23:06:41 +0200 Message-ID: Subject: Re: svn commit: r364219 - in head: share/man/man9 sys/conf sys/contrib/pcg-c/include sys/kern sys/libkern sys/sys To: Conrad Meyer Cc: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Content-Type: text/plain; charset="UTF-8" X-Rspamd-Queue-Id: 4BSJz81QJ3z3ZsL X-Spamd-Bar: ---- Authentication-Results: mx1.freebsd.org; none X-Spamd-Result: default: False [-4.00 / 15.00]; REPLY(-4.00)[]; ASN(0.00)[asn:15169, ipnet:2a00:1450::/32, country:US] X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Aug 2020 21:06:45 -0000 I have trouble deciphering. Is this callable from interrupt context? If not, the code should assert it's not executing in one. If yes, it should probably just sched_pin. On 8/13/20, Conrad Meyer wrote: > Author: cem > Date: Thu Aug 13 20:48:14 2020 > New Revision: 364219 > URL: https://svnweb.freebsd.org/changeset/base/364219 > > Log: > Add prng(9) API > > Add prng(9) as a replacement for random(9) in the kernel. > > There are two major differences from random(9) and random(3): > > - General prng(9) APIs (prng32(9), etc) do not guarantee an > implementation or particular sequence; they should not be used for > repeatable simulations. > > - However, specific named API families are also exposed (for now: PCG), > and those are expected to be repeatable (when so-guaranteed by the > named > algorithm). > > Some minor differences from random(3) and earlier random(9): > > - PRNG state for the general prng(9) APIs is per-CPU; this eliminates > contention on PRNG state in SMP workloads. Each PCPU generator in an > SMP system produces a unique sequence. > > - Better statistical properties than the Park-Miller ("minstd") PRNG > (longer period, uniform distribution in all bits, passes > BigCrush/PractRand analysis). > > - Faster than Park-Miller ("minstd") PRNG -- no division is required to > step PCG-family PRNGs. > > For now, random(9) becomes a thin shim around prng32(). Eventually I > would like to mechanically switch consumers over to the explicit API. > > Reviewed by: kib, markj (previous version both) > Discussed with: markm > Differential Revision: https://reviews.freebsd.org/D25916 > > Added: > head/share/man/man9/prng.9 (contents, props changed) > head/sys/kern/subr_prng.c (contents, props changed) > head/sys/sys/prng.h (contents, props changed) > Modified: > head/share/man/man9/Makefile > head/sys/conf/files > head/sys/contrib/pcg-c/include/pcg_variants.h > head/sys/libkern/random.c > > Modified: head/share/man/man9/Makefile > ============================================================================== > --- head/share/man/man9/Makefile Thu Aug 13 20:28:35 2020 (r364218) > +++ head/share/man/man9/Makefile Thu Aug 13 20:48:14 2020 (r364219) > @@ -272,6 +272,7 @@ MAN= accept_filter.9 \ > printf.9 \ > prison_check.9 \ > priv.9 \ > + prng.9 \ > proc_rwmem.9 \ > pseudofs.9 \ > psignal.9 \ > @@ -1745,6 +1746,10 @@ MLINKS+=printf.9 log.9 \ > printf.9 uprintf.9 > MLINKS+=priv.9 priv_check.9 \ > priv.9 priv_check_cred.9 > +MLINKS+=prng.9 prng32.9 \ > + prng.9 prng32_bounded.9 \ > + prng.9 prng64.9 \ > + prng.9 prng64_bounded.9 > MLINKS+=proc_rwmem.9 proc_readmem.9 \ > proc_rwmem.9 proc_writemem.9 > MLINKS+=psignal.9 gsignal.9 \ > > Added: head/share/man/man9/prng.9 > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/share/man/man9/prng.9 Thu Aug 13 20:48:14 2020 (r364219) > @@ -0,0 +1,99 @@ > +.\"- > +.\" Copyright 2020 Conrad Meyer . All rights reserved. > +.\" > +.\" Redistribution and use in source and binary forms, with or without > +.\" modification, are permitted provided that the following conditions > +.\" are met: > +.\" 1. Redistributions of source code must retain the above copyright > +.\" notice, this list of conditions and the following disclaimer. > +.\" 2. Redistributions in binary form must reproduce the above copyright > +.\" notice, this list of conditions and the following disclaimer in the > +.\" documentation and/or other materials provided with the > distribution. > +.\" > +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND > +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR > PURPOSE > +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE > LIABLE > +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR > CONSEQUENTIAL > +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE > GOODS > +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, > STRICT > +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY > WAY > +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > +.\" SUCH DAMAGE. > +.\" > +.\" $FreeBSD$ > +.\" > +.Dd August 5, 2020 > +.Dt PRNG 9 > +.Os > +.Sh NAME > +.Nm prng > +.Nd "Kernel pseudo-random number generators" > +.Sh SYNOPSIS > +.In sys/prng.h > +.Ft uint32_t > +.Fn prng32 void > +.Ft uint32_t > +.Fn prng32_bounded "uint32_t bound" > +.Ft uint64_t > +.Fn prng64 void > +.Ft uint64_t > +.Fn prng64_bounded "uint64_t bound" > +.Sh DESCRIPTION > +.Ss GENERIC PRNG ROUTINES > +.Nm > +is a family of fast, > +.Em non-cryptographic > +pseudo-random number generators. > +Unlike > +.Xr random 9 , > +.Fn prng32 , > +.Fn prng32_bounded , > +.Fn prng64 , > +and > +.Fn prng64_bounded > +avoid shared global state, removing unnecessary contention on SMP > +systems. > +The routines are not explicitly tied to any specific implementation, and > +may produce different specific sequences on different hosts, reboots, or > +versions of > +.Fx . > +Different CPUs in SMP systems are guaranteed to produce different sequences > of > +integers. > +.Pp > +For > +.Em cryptographically secure > +random numbers generated by the > +.Xr random 4 > +kernel cryptographically secure random number generator subsystem, see > +.Xr arc4random 9 . > +.Pp > +.Bl -tag -width indent > +.It Fn prng32 > +Generate a 32-bit integer uniformly distributed in [0, 2^32-1]. > +.It Fn prng32_bounded bound > +Generate an integer uniformly in the range [0, bound-1]. > +.It Fn prng64 > +Generate a 64-bit integer uniformly distributed in [0, 2^64-1]. > +.It Fn prng64_bounded bound > +Generate an integer uniformly in the range [0, bound-1]. > +.El > +.Pp > +These routines are not reentrant; they are not safe to use in interrupt > +handlers ("interrupt filters" in > +.Xr bus_setup_intr 9 > +terminology). > +They are safe to use in all other kernel contexts, including interrupt > threads > +("ithreads"). > +.Ss REPRODUCIBLE PRNG APIS > +In addition to these per-CPU helpers, the > +.In sys/prng.h > +header also exposes the entire API of the PCG family of PRNGs as inline > +functions. > +The PCG-C API is described in full at > +.Lk https://www.pcg-random.org/using-pcg-c.html . > +.Sh HISTORY > +.Nm > +was introduced in > +.Fx 13 . > > Modified: head/sys/conf/files > ============================================================================== > --- head/sys/conf/files Thu Aug 13 20:28:35 2020 (r364218) > +++ head/sys/conf/files Thu Aug 13 20:48:14 2020 (r364219) > @@ -3834,6 +3834,7 @@ kern/subr_pctrie.c standard > kern/subr_pidctrl.c standard > kern/subr_power.c standard > kern/subr_prf.c standard > +kern/subr_prng.c standard > kern/subr_prof.c standard > kern/subr_rangeset.c standard > kern/subr_rman.c standard > > Modified: head/sys/contrib/pcg-c/include/pcg_variants.h > ============================================================================== > --- head/sys/contrib/pcg-c/include/pcg_variants.h Thu Aug 13 20:28:35 > 2020 (r364218) > +++ head/sys/contrib/pcg-c/include/pcg_variants.h Thu Aug 13 20:48:14 > 2020 (r364219) > @@ -36,22 +36,16 @@ > #ifndef PCG_VARIANTS_H_INCLUDED > #define PCG_VARIANTS_H_INCLUDED 1 > > -#include > - > -#if __SIZEOF_INT128__ > +#if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ > typedef __uint128_t pcg128_t; > #define PCG_128BIT_CONSTANT(high,low) \ > ((((pcg128_t)high) << 64) + low) > #define PCG_HAS_128BIT_OPS 1 > +#else > + #define PCG_HAS_128BIT_OPS 0 > #endif > > -#if __GNUC_GNU_INLINE__ && !defined(__cplusplus) > - #error Nonstandard GNU inlining semantics. Compile with -std=c99 or > better. > - /* We could instead use macros PCG_INLINE and PCG_EXTERN_INLINE > - but better to just reject ancient C code. */ > -#endif > - > -#if __cplusplus > +#ifdef __cplusplus > extern "C" { > #endif > > @@ -65,8 +59,8 @@ inline uint8_t pcg_rotr_8(uint8_t value, unsigned int > * recognizing idiomatic rotate code, so for clang we actually provide > * assembler directives (enabled with PCG_USE_INLINE_ASM). Boo, hiss. > */ > -#if PCG_USE_INLINE_ASM && __clang__ && (__x86_64__ || __i386__) > - asm ("rorb %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); > +#if PCG_USE_INLINE_ASM && defined(__clang__) && (defined(__x86_64__) || > defined(__i386__)) > + __asm__ ("rorb %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); > return value; > #else > return (value >> rot) | (value << ((- rot) & 7)); > @@ -75,8 +69,8 @@ inline uint8_t pcg_rotr_8(uint8_t value, unsigned int > > inline uint16_t pcg_rotr_16(uint16_t value, unsigned int rot) > { > -#if PCG_USE_INLINE_ASM && __clang__ && (__x86_64__ || __i386__) > - asm ("rorw %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); > +#if PCG_USE_INLINE_ASM && defined(__clang__) && (defined(__x86_64__) || > defined(__i386__)) > + __asm__ ("rorw %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); > return value; > #else > return (value >> rot) | (value << ((- rot) & 15)); > @@ -85,8 +79,8 @@ inline uint16_t pcg_rotr_16(uint16_t value, unsigned i > > inline uint32_t pcg_rotr_32(uint32_t value, unsigned int rot) > { > -#if PCG_USE_INLINE_ASM && __clang__ && (__x86_64__ || __i386__) > - asm ("rorl %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); > +#if PCG_USE_INLINE_ASM && defined(__clang__) && (defined(__x86_64__) || > defined(__i386__)) > + __asm__ ("rorl %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); > return value; > #else > return (value >> rot) | (value << ((- rot) & 31)); > @@ -95,10 +89,10 @@ inline uint32_t pcg_rotr_32(uint32_t value, unsigned i > > inline uint64_t pcg_rotr_64(uint64_t value, unsigned int rot) > { > -#if 0 && PCG_USE_INLINE_ASM && __clang__ && __x86_64__ > +#if 0 && PCG_USE_INLINE_ASM && defined(__clang__) && (defined(__x86_64__) > || defined(__i386__)) > /* For whatever reason, clang actually *does* generate rotq by > itself, so we don't need this code. */ > - asm ("rorq %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); > + __asm__ ("rorq %%cl, %0" : "=r" (value) : "0" (value), "c" (rot)); > return value; > #else > return (value >> rot) | (value << ((- rot) & 63)); > @@ -2491,18 +2485,6 @@ typedef struct pcg_state_setseq_128 > pcg128i_random_t > #define pcg128i_advance_r pcg_setseq_128_advance_r > #endif > > -extern uint32_t pcg32_random(void); > -extern uint32_t pcg32_boundedrand(uint32_t bound); > -extern void pcg32_srandom(uint64_t seed, uint64_t seq); > -extern void pcg32_advance(uint64_t delta); > - > -#if PCG_HAS_128BIT_OPS > -extern uint64_t pcg64_random(void); > -extern uint64_t pcg64_boundedrand(uint64_t bound); > -extern void pcg64_srandom(pcg128_t seed, pcg128_t seq); > -extern void pcg64_advance(pcg128_t delta); > -#endif > - > /* > * Static initialization constants (if you can't call srandom for some > * bizarre reason). > @@ -2536,7 +2518,7 @@ extern void pcg64_advance(pcg128_t delta); > #define PCG128I_INITIALIZER PCG_STATE_SETSEQ_128_INITIALIZER > #endif > > -#if __cplusplus > +#ifdef __cplusplus > } > #endif > > > Added: head/sys/kern/subr_prng.c > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/sys/kern/subr_prng.c Thu Aug 13 20:48:14 2020 (r364219) > @@ -0,0 +1,131 @@ > +/*- > + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD > + * > + * Copyright 2020 Conrad Meyer . All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR > PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR > CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, > STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY > WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + */ > + > +#include > +__FBSDID("$FreeBSD$"); > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#if !PCG_HAS_128BIT_OPS > +/* On 32-bit platforms, gang together two 32-bit generators. */ > +typedef struct { > + pcg32u_random_t states[2]; > +} pcg64u_random_t; > + > +static inline void > +pcg64u_srandom_r(pcg64u_random_t *state64, uint64_t seed) > +{ > + pcg32u_srandom_r(&state64->states[0], seed); > + pcg32u_srandom_r(&state64->states[1], seed); > +} > + > +static inline uint64_t > +pcg64u_random_r(pcg64u_random_t *state64) > +{ > + return ((((uint64_t)pcg32u_random_r(&state64->states[0])) << 32) | > + pcg32u_random_r(&state64->states[1])); > +} > + > +static inline uint64_t > +pcg64u_boundedrand_r(pcg64u_random_t *state64, uint64_t bound) > +{ > + uint64_t threshold = -bound % bound; > + for (;;) { > + uint64_t r = pcg64u_random_r(state64); > + if (r >= threshold) > + return (r % bound); > + } > +} > +#endif > + > +DPCPU_DEFINE_STATIC(pcg32u_random_t, pcpu_prng32_state); > +DPCPU_DEFINE_STATIC(pcg64u_random_t, pcpu_prng64_state); > + > +static void > +prng_init(void *dummy __unused) > +{ > + pcg32u_random_t *state; > + pcg64u_random_t *state64; > + int i; > + > + CPU_FOREACH(i) { > + state = DPCPU_ID_PTR(i, pcpu_prng32_state); > + pcg32u_srandom_r(state, 1); > + state64 = DPCPU_ID_PTR(i, pcpu_prng64_state); > + pcg64u_srandom_r(state64, 1); > + } > +} > +SYSINIT(prng_init, SI_SUB_CPU, SI_ORDER_ANY, prng_init, NULL); > + > +uint32_t > +prng32(void) > +{ > + uint32_t r; > + > + critical_enter(); > + r = pcg32u_random_r(DPCPU_PTR(pcpu_prng32_state)); > + critical_exit(); > + return (r); > +} > + > +uint32_t > +prng32_bounded(uint32_t bound) > +{ > + uint32_t r; > + > + critical_enter(); > + r = pcg32u_boundedrand_r(DPCPU_PTR(pcpu_prng32_state), bound); > + critical_exit(); > + return (r); > +} > + > +uint64_t > +prng64(void) > +{ > + uint64_t r; > + > + critical_enter(); > + r = pcg64u_random_r(DPCPU_PTR(pcpu_prng64_state)); > + critical_exit(); > + return (r); > +} > + > +uint64_t > +prng64_bounded(uint64_t bound) > +{ > + uint64_t r; > + > + critical_enter(); > + r = pcg64u_boundedrand_r(DPCPU_PTR(pcpu_prng64_state), bound); > + critical_exit(); > + return (r); > +} > > Modified: head/sys/libkern/random.c > ============================================================================== > --- head/sys/libkern/random.c Thu Aug 13 20:28:35 2020 (r364218) > +++ head/sys/libkern/random.c Thu Aug 13 20:48:14 2020 (r364219) > @@ -36,43 +36,14 @@ __FBSDID("$FreeBSD$"); > > #include > #include > +#include > #include > > -static u_long randseed = 937186357; /* after srandom(1), NSHUFF counted */ > - > /* > - * Pseudo-random number generator for perturbing the profiling clock, > - * and whatever else we might use it for. The result is uniform on > - * [0, 2^31 - 1]. > + * Pseudo-random number generator. The result is uniform in [0, 2^31 - > 1]. > */ > u_long > random(void) > { > - static bool warned = false; > - > - long x, hi, lo, t; > - > - /* Warn only once, or it gets very spammy. */ > - if (!warned) { > - gone_in(13, > - "random(9) is the obsolete Park-Miller LCG from 1988"); > - warned = true; > - } > - > - /* > - * Compute x[n + 1] = (7^5 * x[n]) mod (2^31 - 1). > - * From "Random number generators: good ones are hard to find", > - * Park and Miller, Communications of the ACM, vol. 31, no. 10, > - * October 1988, p. 1195. > - */ > - /* Can't be initialized with 0, so use another value. */ > - if ((x = randseed) == 0) > - x = 123459876; > - hi = x / 127773; > - lo = x % 127773; > - t = 16807 * lo - 2836 * hi; > - if (t < 0) > - t += 0x7fffffff; > - randseed = t; > - return (t); > + return (prng32()); > } > > Added: head/sys/sys/prng.h > ============================================================================== > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ head/sys/sys/prng.h Thu Aug 13 20:48:14 2020 (r364219) > @@ -0,0 +1,20 @@ > +/*- > + * This file is in the public domain. > + * > + * $FreeBSD$ > + */ > + > +#ifndef _SYS_PRNG_H_ > +#define _SYS_PRNG_H_ > + > +#define PCG_USE_INLINE_ASM 1 > +#include > + > +#ifdef _KERNEL > +__uint32_t prng32(void); > +__uint32_t prng32_bounded(__uint32_t bound); > +__uint64_t prng64(void); > +__uint64_t prng64_bounded(__uint64_t bound); > +#endif > + > +#endif > -- Mateusz Guzik