History

random32: move the pseudo-random 32-bit definitions to prandom.h

The addition of percpu.h to the list of includes in random.h revealed some circular dependencies on arm64 and possibly other platforms. This include was added solely for the pseudo-random definitions, which have nothing to do with the rest of the definitions in this file but are still there for legacy reasons. This patch moves the pseudo-random parts to linux/prandom.h and the percpu.h include with it, which is now guarded by _LINUX_PRANDOM_H and protected against recursive inclusion. A further cleanup step would be to remove this from <linux/random.h> entirely, and make people who use the prandom infrastructure include just the new header file. That's a bit of a churn patch, but grepping for "prandom_" and "next_pseudo_random32" "struct rnd_state" should catch most users. But it turns out that that nice cleanup step is fairly painful, because a _lot_ of code currently seems to depend on the implicit include of <linux/random.h>, which can currently come in a lot of ways, including such fairly core headfers as <linux/net.h>. So the "nice cleanup" part may or may never happen.

Linus Torvalds committed 6 years ago

Commit c0842fb1 parent 2baa85d2 files · +82 −62Browse files

Showing the changes to include/linux (2 of 2 files). Show all

Unified · Split

2 files
  1. include/linux/prandom.h +78 −0
  2. include/linux/random.h +4 −62
include/linux/prandom.h+78−0
@@ -0,0 +1,78 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * include/linux/prandom.h
4 *
5 * Include file for the fast pseudo-random 32-bit
6 * generation.
7 */
8#ifndef _LINUX_PRANDOM_H
9#define _LINUX_PRANDOM_H
10
11#include <linux/types.h>
12#include <linux/percpu.h>
13
14u32 prandom_u32(void);
15void prandom_bytes(void *buf, size_t nbytes);
16void prandom_seed(u32 seed);
17void prandom_reseed_late(void);
18
19struct rnd_state {
20 __u32 s1, s2, s3, s4;
21};
22
23DECLARE_PER_CPU(struct rnd_state, net_rand_state);
24
25u32 prandom_u32_state(struct rnd_state *state);
26void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes);
27void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state);
28
29#define prandom_init_once(pcpu_state) \
30 DO_ONCE(prandom_seed_full_state, (pcpu_state))
31
32/**
33 * prandom_u32_max - returns a pseudo-random number in interval [0, ep_ro)
34 * @ep_ro: right open interval endpoint
35 *
36 * Returns a pseudo-random number that is in interval [0, ep_ro). Note
37 * that the result depends on PRNG being well distributed in [0, ~0U]
38 * u32 space. Here we use maximally equidistributed combined Tausworthe
39 * generator, that is, prandom_u32(). This is useful when requesting a
40 * random index of an array containing ep_ro elements, for example.
41 *
42 * Returns: pseudo-random number in interval [0, ep_ro)
43 */
44static inline u32 prandom_u32_max(u32 ep_ro)
45{
46 return (u32)(((u64) prandom_u32() * ep_ro) >> 32);
47}
48
49/*
50 * Handle minimum values for seeds
51 */
52static inline u32 __seed(u32 x, u32 m)
53{
54 return (x < m) ? x + m : x;
55}
56
57/**
58 * prandom_seed_state - set seed for prandom_u32_state().
59 * @state: pointer to state structure to receive the seed.
60 * @seed: arbitrary 64-bit value to use as a seed.
61 */
62static inline void prandom_seed_state(struct rnd_state *state, u64 seed)
63{
64 u32 i = (seed >> 32) ^ (seed << 10) ^ seed;
65
66 state->s1 = __seed(i, 2U);
67 state->s2 = __seed(i, 8U);
68 state->s3 = __seed(i, 16U);
69 state->s4 = __seed(i, 128U);
70}
71
72/* Pseudo random number generator from numerical recipes. */
73static inline u32 next_pseudo_random32(u32 seed)
74{
75 return seed * 1664525 + 1013904223;
76}
77
78#endif
include/linux/random.h+4−62
@@ -11,7 +11,6 @@ · 10 unmodified lines
11#include <linux/kernel.h>11#include <linux/kernel.h>
12#include <linux/list.h>12#include <linux/list.h>
13#include <linux/once.h>13#include <linux/once.h>
14#include <asm/percpu.h>
15 14
16#include <uapi/linux/random.h>15#include <uapi/linux/random.h>
17 16
@@ -111,63 +110,12 @@ declare_get_random_var_wait(long) · 93 unmodified lines
111 110
112unsigned long randomize_page(unsigned long start, unsigned long range);111unsigned long randomize_page(unsigned long start, unsigned long range);
113 112
114u32 prandom_u32(void);
115void prandom_bytes(void *buf, size_t nbytes);
116void prandom_seed(u32 seed);
117void prandom_reseed_late(void);
118
119struct rnd_state {
120 __u32 s1, s2, s3, s4;
121};
122
123DECLARE_PER_CPU(struct rnd_state, net_rand_state);
124
125u32 prandom_u32_state(struct rnd_state *state);
126void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes);
127void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state);
128
129#define prandom_init_once(pcpu_state) \
130 DO_ONCE(prandom_seed_full_state, (pcpu_state))
131
132/**
133 * prandom_u32_max - returns a pseudo-random number in interval [0, ep_ro)
134 * @ep_ro: right open interval endpoint
135 *
136 * Returns a pseudo-random number that is in interval [0, ep_ro). Note
137 * that the result depends on PRNG being well distributed in [0, ~0U]
138 * u32 space. Here we use maximally equidistributed combined Tausworthe
139 * generator, that is, prandom_u32(). This is useful when requesting a
140 * random index of an array containing ep_ro elements, for example.
141 *
142 * Returns: pseudo-random number in interval [0, ep_ro)
143 */
144static inline u32 prandom_u32_max(u32 ep_ro)
145{
146 return (u32)(((u64) prandom_u32() * ep_ro) >> 32);
147}
148
149/*113/*
150 * Handle minimum values for seeds114 * This is designed to be standalone for just prandom
151 */115 * users, but for now we include it from <linux/random.h>
152static inline u32 __seed(u32 x, u32 m)116 * for legacy reasons.
153{
154 return (x < m) ? x + m : x;
155}
156
157/**
158 * prandom_seed_state - set seed for prandom_u32_state().
159 * @state: pointer to state structure to receive the seed.
160 * @seed: arbitrary 64-bit value to use as a seed.
161 */117 */
162static inline void prandom_seed_state(struct rnd_state *state, u64 seed)118#include <linux/prandom.h>
163{
164 u32 i = (seed >> 32) ^ (seed << 10) ^ seed;
165
166 state->s1 = __seed(i, 2U);
167 state->s2 = __seed(i, 8U);
168 state->s3 = __seed(i, 16U);
169 state->s4 = __seed(i, 128U);
170}
171 119
172#ifdef CONFIG_ARCH_RANDOM120#ifdef CONFIG_ARCH_RANDOM
173# include <asm/archrandom.h>121# include <asm/archrandom.h>
@@ -210,10 +158,4 @@ static inline bool __init arch_get_random_long_early(unsigned long *v) · 36 unmodified lines
210}158}
211#endif159#endif
212 160
213/* Pseudo random number generator from numerical recipes. */
214static inline u32 next_pseudo_random32(u32 seed)
215{
216 return seed * 1664525 + 1013904223;
217}
218
219#endif /* _LINUX_RANDOM_H */161#endif /* _LINUX_RANDOM_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t