aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-10-09 20:59:04 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-10-09 20:59:04 +0200
commit3ea2e82dc7b32703f5043c3b30b049905a0d07aa (patch)
treeeae992a986a4ce66efa32845ecccc204a0c4c0e1
parenta05b2b856bf095dfd5f575c106d1a9e5ac6edd3c (diff)
downloadbusybox-w32-3ea2e82dc7b32703f5043c3b30b049905a0d07aa.tar.gz
busybox-w32-3ea2e82dc7b32703f5043c3b30b049905a0d07aa.tar.bz2
busybox-w32-3ea2e82dc7b32703f5043c3b30b049905a0d07aa.zip
ash: factor out $RANDOM support
function old new delta next_random - 46 +46 ash_main 1361 1356 -5 change_random 132 97 -35 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/2 up/down: 46/-40) Total: 6 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/Kbuild3
-rw-r--r--shell/ash.c46
-rw-r--r--shell/random.c37
-rw-r--r--shell/random.h19
4 files changed, 77 insertions, 28 deletions
diff --git a/shell/Kbuild b/shell/Kbuild
index 4d4741eff..03960a8ea 100644
--- a/shell/Kbuild
+++ b/shell/Kbuild
@@ -8,4 +8,7 @@ lib-y:=
8lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o 8lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o
9lib-$(CONFIG_HUSH) += hush.o match.o 9lib-$(CONFIG_HUSH) += hush.o match.o
10lib-$(CONFIG_CTTYHACK) += cttyhack.o 10lib-$(CONFIG_CTTYHACK) += cttyhack.o
11
11lib-$(CONFIG_SH_MATH_SUPPORT) += math.o 12lib-$(CONFIG_SH_MATH_SUPPORT) += math.o
13lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
14lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o
diff --git a/shell/ash.c b/shell/ash.c
index f2d372f4a..6ce621534 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -51,16 +51,19 @@
51#include <setjmp.h> 51#include <setjmp.h>
52#include <fnmatch.h> 52#include <fnmatch.h>
53#include "math.h" 53#include "math.h"
54#if ENABLE_ASH_RANDOM_SUPPORT
55# include "random.h"
56#endif
54 57
55#if defined SINGLE_APPLET_MAIN 58#if defined SINGLE_APPLET_MAIN
56/* STANDALONE does not make sense, and won't compile */ 59/* STANDALONE does not make sense, and won't compile */
57#undef CONFIG_FEATURE_SH_STANDALONE 60# undef CONFIG_FEATURE_SH_STANDALONE
58#undef ENABLE_FEATURE_SH_STANDALONE 61# undef ENABLE_FEATURE_SH_STANDALONE
59#undef IF_FEATURE_SH_STANDALONE 62# undef IF_FEATURE_SH_STANDALONE
60#undef IF_NOT_FEATURE_SH_STANDALONE(...) 63# undef IF_NOT_FEATURE_SH_STANDALONE(...)
61#define ENABLE_FEATURE_SH_STANDALONE 0 64# define ENABLE_FEATURE_SH_STANDALONE 0
62#define IF_FEATURE_SH_STANDALONE(...) 65# define IF_FEATURE_SH_STANDALONE(...)
63#define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__ 66# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
64#endif 67#endif
65 68
66#ifndef PIPE_BUF 69#ifndef PIPE_BUF
@@ -197,9 +200,7 @@ struct globals_misc {
197 200
198 /* Rarely referenced stuff */ 201 /* Rarely referenced stuff */
199#if ENABLE_ASH_RANDOM_SUPPORT 202#if ENABLE_ASH_RANDOM_SUPPORT
200 /* Random number generators */ 203 random_t random_gen;
201 int32_t random_galois_LFSR; /* Galois LFSR (fast but weak). signed! */
202 uint32_t random_LCG; /* LCG (fast but weak) */
203#endif 204#endif
204 pid_t backgndpid; /* pid of last background process */ 205 pid_t backgndpid; /* pid of last background process */
205 smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */ 206 smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */
@@ -224,8 +225,7 @@ extern struct globals_misc *const ash_ptr_to_globals_misc;
224#define gotsig (G_misc.gotsig ) 225#define gotsig (G_misc.gotsig )
225#define trap (G_misc.trap ) 226#define trap (G_misc.trap )
226#define trap_ptr (G_misc.trap_ptr ) 227#define trap_ptr (G_misc.trap_ptr )
227#define random_galois_LFSR (G_misc.random_galois_LFSR) 228#define random_gen (G_misc.random_gen )
228#define random_LCG (G_misc.random_LCG )
229#define backgndpid (G_misc.backgndpid ) 229#define backgndpid (G_misc.backgndpid )
230#define job_warning (G_misc.job_warning) 230#define job_warning (G_misc.job_warning)
231#define INIT_G_misc() do { \ 231#define INIT_G_misc() do { \
@@ -10075,28 +10075,18 @@ change_random(const char *value)
10075 /* Another example - taps at 32 31 30 10: */ 10075 /* Another example - taps at 32 31 30 10: */
10076 /* MASK = 0x00400007 */ 10076 /* MASK = 0x00400007 */
10077 10077
10078 uint32_t t;
10079
10078 if (value == NULL) { 10080 if (value == NULL) {
10079 /* "get", generate */ 10081 /* "get", generate */
10080 uint32_t t; 10082 t = next_random(&random_gen);
10081
10082 /* LCG has period of 2^32 and alternating lowest bit */
10083 random_LCG = 1664525 * random_LCG + 1013904223;
10084 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
10085 t = (random_galois_LFSR << 1);
10086 if (random_galois_LFSR < 0) /* if we just shifted 1 out of msb... */
10087 t ^= MASK;
10088 random_galois_LFSR = t;
10089 /* Both are weak, combining them gives better randomness
10090 * and ~2^64 period. & 0x7fff is probably bash compat
10091 * for $RANDOM range. Combining with subtraction is
10092 * just for fun. + and ^ would work equally well. */
10093 t = (t - random_LCG) & 0x7fff;
10094 /* set without recursion */ 10083 /* set without recursion */
10095 setvar(vrandom.text, utoa(t), VNOFUNC); 10084 setvar(vrandom.text, utoa(t), VNOFUNC);
10096 vrandom.flags &= ~VNOFUNC; 10085 vrandom.flags &= ~VNOFUNC;
10097 } else { 10086 } else {
10098 /* set/reset */ 10087 /* set/reset */
10099 random_galois_LFSR = random_LCG = strtoul(value, NULL, 10); 10088 t = strtoul(value, NULL, 10);
10089 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10100 } 10090 }
10101} 10091}
10102#endif 10092#endif
@@ -13271,7 +13261,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
13271#if ENABLE_ASH_RANDOM_SUPPORT 13261#if ENABLE_ASH_RANDOM_SUPPORT
13272 /* Can use monotonic_ns() for better randomness but for now it is 13262 /* Can use monotonic_ns() for better randomness but for now it is
13273 * not used anywhere else in busybox... so avoid bloat */ 13263 * not used anywhere else in busybox... so avoid bloat */
13274 random_galois_LFSR = random_LCG = rootpid + monotonic_us(); 13264 INIT_RANDOM_T(&random_gen, rootpid, monotonic_us());
13275#endif 13265#endif
13276 init(); 13266 init();
13277 setstackmark(&smark); 13267 setstackmark(&smark);
diff --git a/shell/random.c b/shell/random.c
new file mode 100644
index 000000000..a4dce846d
--- /dev/null
+++ b/shell/random.c
@@ -0,0 +1,37 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * $RANDOM support.
4 *
5 * Copyright (C) 2008 Denys Vlasenko
6 *
7 * Licensed under GPLv2, see file LICENSE in this tarball for details.
8 */
9#include "libbb.h"
10#include "random.h"
11
12uint32_t FAST_FUNC
13next_random(random_t *rnd)
14{
15 /* Galois LFSR parameter */
16 /* Taps at 32 31 29 1: */
17 enum { MASK = 0x8000000b };
18 /* Another example - taps at 32 31 30 10: */
19 /* MASK = 0x00400007 */
20
21 uint32_t t;
22
23 /* LCG has period of 2^32 and alternating lowest bit */
24 rnd->LCG = 1664525 * rnd->LCG + 1013904223;
25 /* Galois LFSR has period of 2^32-1 = 3 * 5 * 17 * 257 * 65537 */
26 t = (rnd->galois_LFSR << 1);
27 if (rnd->galois_LFSR < 0) /* if we just shifted 1 out of msb... */
28 t ^= MASK;
29 rnd->galois_LFSR = t;
30 /* Both are weak, combining them gives better randomness
31 * and ~2^64 period. & 0x7fff is probably bash compat
32 * for $RANDOM range. Combining with subtraction is
33 * just for fun. + and ^ would work equally well. */
34 t = (t - rnd->LCG) & 0x7fff;
35
36 return t;
37}
diff --git a/shell/random.h b/shell/random.h
new file mode 100644
index 000000000..2d29a60e8
--- /dev/null
+++ b/shell/random.h
@@ -0,0 +1,19 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * $RANDOM support.
4 *
5 * Copyright (C) 2008 Denys Vlasenko
6 *
7 * Licensed under GPLv2, see file LICENSE in this tarball for details.
8 */
9
10typedef struct random_t {
11 /* Random number generators */
12 int32_t galois_LFSR; /* Galois LFSR (fast but weak). signed! */
13 uint32_t LCG; /* LCG (fast but weak) */
14} random_t;
15
16#define INIT_RANDOM_T(rnd, nonzero, v) \
17 ((rnd)->galois_LFSR = (nonzero), (rnd)->LCG = (v))
18
19uint32_t next_random(random_t *rnd) FAST_FUNC;