aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/random.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2013-08-23 15:01:53 +0200
committerJan Beulich <jbeulich@suse.com>2013-08-23 15:01:53 +0200
commit829b8498cc781f5ed8f7b9e16378f448b4d45213 (patch)
treefa6057dc0bf1586818a82815a0fff3243a969f21 /xen/common/random.c
parent3829655bd3ad2b1150bd94955fc6988dec6b98f2 (diff)
downloadxen-829b8498cc781f5ed8f7b9e16378f448b4d45213.tar.gz
xen-829b8498cc781f5ed8f7b9e16378f448b4d45213.tar.bz2
xen-829b8498cc781f5ed8f7b9e16378f448b4d45213.zip
un-alias cpumask_any() from cpumask_first()
In order to achieve more symmetric distribution of certain things, cpumask_any() shouldn't always pick the first CPU (which frequently will end up being CPU0). To facilitate that, introduce a library-like function to obtain random numbers. The per-architecture function is supposed to return zero if no valid random number can be obtained (implying that if occasionally zero got produced as random number, it wouldn't be considered such). As fallback this uses the trivial algorithm from the C standard, extended to produce "unsigned int" results. Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Keir Fraser <keir@xen.org> Reviewed-by: George Dunlap <george.dunlap@eu.citrix.com>
Diffstat (limited to 'xen/common/random.c')
-rw-r--r--xen/common/random.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/xen/common/random.c b/xen/common/random.c
new file mode 100644
index 0000000000..4a28a24b4c
--- /dev/null
+++ b/xen/common/random.c
@@ -0,0 +1,29 @@
+#include <xen/percpu.h>
+#include <xen/random.h>
+#include <xen/time.h>
+#include <asm/random.h>
+
+static DEFINE_PER_CPU(unsigned int, seed);
+
+unsigned int get_random(void)
+{
+ unsigned int next = this_cpu(seed), val = arch_get_random();
+
+ if ( unlikely(!next) )
+ next = val ?: NOW();
+
+ if ( !val )
+ {
+ unsigned int i;
+
+ for ( i = 0; i < sizeof(val) * 8; i += 11 )
+ {
+ next = next * 1103515245 + 12345;
+ val |= ((next >> 16) & 0x7ff) << i;
+ }
+ }
+
+ this_cpu(seed) = next;
+
+ return val;
+}