From: "George Spelvin" <linux@horizon.com>
To: penberg@kernel.org
Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux@horizon.com
Subject: Re: [PATCH] Make /proc/slabinfo 0400
Date: 7 Mar 2011 12:49:34 -0500 [thread overview]
Message-ID: <20110307174934.15811.qmail@science.horizon.com> (raw)
In-Reply-To: <20110307141948.11415.qmail@science.horizon.com>
To go with my earlier code, here's a (proof of concept) more efficient
random number generator for a series of small values. A bit more code,
but a lot less calls to half_md4_transform.
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 773007d..6b3fd4e 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1658,6 +1658,84 @@ unsigned int get_random_int(void)
return ret;
}
+struct random_mod_state {
+ unsigned int x, lim; /* Invariant: 0 <= x < lim, and random */
+ __u8 const *seed;
+ unsigned len;
+};
+
+void
+get_random_mod_start(struct random_mod_state *s)
+{
+ s->x = 0;
+ s->lim = 0;
+ s->len = 0;
+
+ preempt_disable(); /* For access to percpu variables */
+}
+
+/*
+ * Return a random 0 <= x < m. This is exacctly uniformly distributed,
+ * which "random() % m" is not, and it is economical with seed entropy.
+ * For example, this can shuffle 27 elements (27! > 2^93) with only
+ * one call to half_md4_transform.
+ *
+ * This is limited to 24-bit moduli m; larger values risk overflow.
+ */
+unsigned
+get_random_mod(struct random_mod_state *s, unsigned m)
+{
+ unsigned x = s->x, lim = x->lim;
+
+ for (;;) {
+ unsigned k;
+
+ /* Ensure lim >= m */
+ while (lim < m) {
+ /* Invoke underlying random bit source */
+ if (!s->len--) {
+ __u32 *h = __get_cpu_var(get_random_int_hash);
+ struct keydata const *keyptr = get_keyptr();
+ cycles_t c = get_cycles();
+
+ /* Throw in some extra seed material */
+ h[0] += (__u32)c;
+ h[1] += (__u32)(c>>16>>16); /* 32-bit safe */
+ h[2] += current->pid + jiffies;
+
+ half_md4_transform(h, keyptr->secret);
+
+ /* And use last 12 bytes as random numbers */
+ s->seed = (__u8 *)(h + 1);
+ s->len = 11; /* Pre-decremented */
+ }
+ /* Add one byte to state */
+ x = x<<8 | *s->seed++;
+ lim <<= 8;
+ }
+ /*
+ * Core loop. We occasionally have to discard and regenerate
+ * to ensure uniformity.
+ */
+ k = lim % m;
+ if (x >= k) {
+ x -= k; lim -= k;
+ /* Final result: Return x % m, keep x / m */
+ s->x = x/m; s->lim = lim/m;
+ return x % m;
+ }
+ /* Non-uniform: keep fractional part and try again */
+ lim = k;
+ }
+}
+
+void
+get_random_mod_stop(struct random_mod_state *s)
+{
+ (void)s;
+ preempt_enable(); /* Drop lock on s->seed */
+}
+
/*
* randomize_range() returns a start address such that
*
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2011-03-07 17:49 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-07 14:19 [PATCH] Make /proc/slabinfo 040 George Spelvin
2011-03-07 17:49 ` George Spelvin [this message]
-- strict thread matches above, loose matches on Subject: below --
2011-03-03 17:50 [PATCH] Make /proc/slabinfo 0400 Dan Rosenberg
2011-03-03 18:17 ` Dave Hansen
2011-03-03 18:29 ` Dan Rosenberg
2011-03-03 20:58 ` Matt Mackall
2011-03-03 21:16 ` Dan Rosenberg
2011-03-03 21:44 ` Matt Mackall
2011-03-03 22:30 ` Dan Rosenberg
2011-03-03 23:08 ` Matt Mackall
2011-03-04 0:32 ` Dave Hansen
2011-03-04 0:50 ` Theodore Tso
2011-03-04 6:52 ` Pekka Enberg
2011-03-04 17:36 ` Dave Hansen
2011-03-04 17:48 ` Linus Torvalds
2011-03-04 18:14 ` Matt Mackall
2011-03-04 20:02 ` Pekka Enberg
2011-03-04 20:31 ` Matt Mackall
2011-03-04 20:42 ` Dan Rosenberg
2011-03-04 20:56 ` Pekka Enberg
2011-03-04 21:08 ` Dan Rosenberg
2011-03-04 21:30 ` Pekka Enberg
2011-03-04 21:44 ` Dan Rosenberg
2011-03-04 22:10 ` Pekka Enberg
2011-03-04 22:14 ` Pekka Enberg
2011-03-04 23:02 ` Matt Mackall
2011-03-05 16:25 ` Ted Ts'o
2011-03-06 13:19 ` Alan Cox
2011-03-07 14:56 ` Dan Rosenberg
2011-03-07 16:02 ` Matt Mackall
2011-03-04 20:37 ` Dan Rosenberg
2011-03-04 20:58 ` Pekka Enberg
2011-03-04 21:10 ` Dan Rosenberg
2011-03-06 0:42 ` Jesper Juhl
2011-03-06 0:57 ` Dan Rosenberg
2011-03-06 1:09 ` Matt Mackall
2011-03-06 1:15 ` Jesper Juhl
2011-03-07 16:40 ` Christoph Lameter
2011-03-04 21:12 ` Matt Mackall
2011-03-04 11:58 ` Alan Cox
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110307174934.15811.qmail@science.horizon.com \
--to=linux@horizon.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=penberg@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).