diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-10-09 20:59:04 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-10-09 20:59:04 +0200 |
commit | 3ea2e82dc7b32703f5043c3b30b049905a0d07aa (patch) | |
tree | eae992a986a4ce66efa32845ecccc204a0c4c0e1 | |
parent | a05b2b856bf095dfd5f575c106d1a9e5ac6edd3c (diff) | |
download | busybox-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/Kbuild | 3 | ||||
-rw-r--r-- | shell/ash.c | 46 | ||||
-rw-r--r-- | shell/random.c | 37 | ||||
-rw-r--r-- | shell/random.h | 19 |
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:= | |||
8 | lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o | 8 | lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o |
9 | lib-$(CONFIG_HUSH) += hush.o match.o | 9 | lib-$(CONFIG_HUSH) += hush.o match.o |
10 | lib-$(CONFIG_CTTYHACK) += cttyhack.o | 10 | lib-$(CONFIG_CTTYHACK) += cttyhack.o |
11 | |||
11 | lib-$(CONFIG_SH_MATH_SUPPORT) += math.o | 12 | lib-$(CONFIG_SH_MATH_SUPPORT) += math.o |
13 | lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o | ||
14 | lib-$(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 | |||
12 | uint32_t FAST_FUNC | ||
13 | next_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 | |||
10 | typedef 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 | |||
19 | uint32_t next_random(random_t *rnd) FAST_FUNC; | ||