VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/misc/rand.cpp@ 7389

Last change on this file since 7389 was 7169, checked in by vboxsync, 17 years ago

Doxygen fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 9.6 KB
Line 
1/* $Id: rand.cpp 7169 2008-02-27 13:16:24Z vboxsync $ */
2/** @file
3 * innotek Portable Runtime - Random Number
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <iprt/rand.h>
32#include <iprt/time.h>
33#include <iprt/asm.h>
34#include <iprt/err.h>
35#include <iprt/assert.h>
36#include <iprt/thread.h>
37#include "internal/rand.h"
38
39
40/*******************************************************************************
41* Global Variables *
42*******************************************************************************/
43/** Lazy init. */
44static volatile bool g_fInitialized = false;
45/** The context variable for the fallback path. */
46static uint32_t g_u32Ctx;
47
48
49/*******************************************************************************
50* Internal Functions *
51*******************************************************************************/
52static uint32_t rtRandGenBytesFallbackU31(uint32_t *pCtx);
53
54
55/**
56 * Lazy initialization of the native and fallback random byte sources.
57 *
58 */
59static void rtRandLazyInit(void)
60{
61 /*
62 * Seed the fallback random code.
63 */
64 g_u32Ctx = (uint32_t)(ASMReadTSC() >> 8);
65
66 /*
67 * Call host specific init.
68 */
69 rtRandLazyInitNative();
70 g_fInitialized = true;
71}
72
73
74/**
75 * Internal wrapper for the native and generic random byte methods.
76 *
77 * @param pv Where to store the random bytes.
78 * @param cb Number of bytes to generate.
79 */
80static void rtRandGenBytes(void *pv, size_t cb)
81{
82 Assert(cb);
83 if (RT_UNLIKELY(!g_fInitialized))
84 rtRandLazyInit();
85
86 int rc = rtRandGenBytesNative(pv, cb);
87 if (RT_FAILURE(rc))
88 rtRandGenBytesFallback(pv, cb);
89}
90
91
92/**
93 * Fills a buffer with random bytes.
94 *
95 * @param pv Where to store the random bytes.
96 * @param cb Number of bytes to generate.
97 */
98RTDECL(void) RTRandBytes(void *pv, size_t cb)
99{
100 if (cb)
101 rtRandGenBytes(pv, cb);
102}
103
104
105/**
106 * Generate a 32-bit signed random number in the set [i32First..i32Last].
107 *
108 * @returns The random number.
109 * @param i32First First number in the set.
110 * @param i32Last Last number in the set.
111 */
112RTDECL(int32_t) RTRandS32Ex(int32_t i32First, int32_t i32Last)
113{
114 /* get 4 random bytes. */
115 union
116 {
117 uint32_t off;
118 uint8_t ab[4];
119 } u;
120 rtRandGenBytes(&u.ab, sizeof(u));
121
122
123 /* squeeze it into the requested range. */
124 uint32_t offLast = i32Last - i32First;
125 if (u.off > offLast)
126 {
127 do
128 {
129 u.off >>= 1;
130 } while (u.off > offLast);
131 }
132 return i32First + u.off;
133}
134
135
136/**
137 * Generate a 32-bit signed random number.
138 *
139 * @returns The random number.
140 */
141RTDECL(int32_t) RTRandS32(void)
142{
143 return RTRandS32Ex(INT32_MIN, INT32_MAX);
144}
145
146
147/**
148 * Generate a 32-bit unsigned random number in the set [u32First..u32Last].
149 *
150 * @returns The random number.
151 * @param u32First First number in the set.
152 * @param u32Last Last number in the set.
153 */
154RTDECL(uint32_t) RTRandU32Ex(uint32_t u32First, uint32_t u32Last)
155{
156 /* get 4 random bytes. */
157 union
158 {
159 uint32_t off;
160 uint8_t ab[4];
161 } u;
162 rtRandGenBytes(&u.ab, sizeof(u));
163
164
165 /* squeeze it into the requested range. */
166 const uint32_t offLast = u32Last - u32First;
167 if (u.off > offLast)
168 {
169 do
170 {
171 u.off >>= 1;
172 } while (u.off > offLast);
173 }
174 return u32First + u.off;
175}
176
177
178/**
179 * Generate a 32-bit unsigned random number.
180 *
181 * @returns The random number.
182 */
183RTDECL(uint32_t) RTRandU32(void)
184{
185 return RTRandU32Ex(0, UINT32_MAX);
186}
187
188
189/**
190 * Generate a 64-bit signed random number in the set [i64First..i64Last].
191 *
192 * @returns The random number.
193 * @param i64First First number in the set.
194 * @param i64Last Last number in the set.
195 */
196RTDECL(int64_t) RTRandS64Ex(int64_t i64First, int64_t i64Last)
197{
198 /* get 8 random bytes. */
199 union
200 {
201 uint64_t off;
202 uint8_t ab[8];
203 } u;
204 rtRandGenBytes(&u.ab, sizeof(u));
205
206 /* squeeze it into the requested range. */
207 uint64_t offLast = i64Last - i64First;
208 if (u.off > offLast)
209 {
210 do
211 {
212 u.off >>= 1;
213 } while (u.off > offLast);
214 }
215 return i64First + u.off;
216}
217
218
219/**
220 * Generate a 64-bit signed random number.
221 *
222 * @returns The random number.
223 */
224RTDECL(int64_t) RTRandS64(void)
225{
226 return RTRandS64Ex(INT64_MIN, INT64_MAX);
227}
228
229
230/**
231 * Generate a 64-bit unsigned random number in the set [u64First..u64Last].
232 *
233 * @returns The random number.
234 * @param u64First First number in the set.
235 * @param u64Last Last number in the set.
236 */
237RTDECL(uint64_t) RTRandU64Ex(uint64_t u64First, uint64_t u64Last)
238{
239 /* get 8 random bytes. */
240 union
241 {
242 uint64_t off;
243 uint8_t ab[8];
244 } u;
245 rtRandGenBytes(&u.ab, sizeof(u));
246
247 /* squeeze it into the requested range. */
248 const uint64_t offLast = u64Last - u64First;
249 if (u.off > offLast)
250 {
251 do
252 {
253 u.off >>= 1;
254 } while (u.off > offLast);
255 }
256 return u64First + u.off;
257}
258
259
260/**
261 * Generate a 64-bit unsigned random number.
262 *
263 * @returns The random number.
264 */
265RTDECL(uint64_t) RTRandU64(void)
266{
267 return RTRandU64Ex(0, UINT64_MAX);
268}
269
270
271/**
272 * Fallback random byte source.
273 *
274 * @param pv Where to store the random bytes.
275 * @param cb Number of bytes to generate.
276 */
277void rtRandGenBytesFallback(void *pv, size_t cb)
278{
279 uint8_t *pb = (uint8_t *)pv;
280 for (unsigned i = 0;; i++)
281 {
282 uint32_t u32 = rtRandGenBytesFallbackU31(&g_u32Ctx);
283
284 *pb++ = (uint8_t)u32;
285 if (!--cb)
286 break;
287
288 u32 >>= 8;
289 *pb++ = (uint8_t)u32;
290 if (!--cb)
291 break;
292
293 u32 >>= 8;
294 *pb++ = (uint8_t)u32;
295 if (!--cb)
296 break;
297
298 /* Is this really a good idea? */
299 if (!(i % 3))
300 {
301 if (i)
302 RTThreadYield();
303 *pb++ = (uint8_t)ASMReadTSC();
304 if (!--cb)
305 break;
306 }
307 }
308
309}
310
311
312/*-
313 * Copyright (c) 1990, 1993
314 * The Regents of the University of California. All rights reserved.
315 *
316 * Redistribution and use in source and binary forms, with or without
317 * modification, are permitted provided that the following conditions
318 * are met:
319 * 1. Redistributions of source code must retain the above copyright
320 * notice, this list of conditions and the following disclaimer.
321 * 2. Redistributions in binary form must reproduce the above copyright
322 * notice, this list of conditions and the following disclaimer in the
323 * documentation and/or other materials provided with the distribution.
324 * 4. Neither the name of the University nor the names of its contributors
325 * may be used to endorse or promote products derived from this software
326 * without specific prior written permission.
327 *
328 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
329 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
330 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
331 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
332 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
333 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
334 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
335 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
336 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
337 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
338 * SUCH DAMAGE.
339 */
340
341/* The core of:
342__FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/stdlib/rand.c,v 1.16 2007/01/09 00:28:10 imp Exp $");
343*/
344
345/**
346 * Generates an unsigned 31 bit pseudo random number.
347 *
348 * @returns pseudo random number.
349 * @param pCtx The context.
350 */
351static uint32_t rtRandGenBytesFallbackU31(uint32_t *pCtx)
352{
353 /*
354 * Compute x = (7^5 * x) mod (2^31 - 1)
355 * without overflowing 31 bits:
356 * (2^31 - 1) = 127773 * (7^5) + 2836
357 *
358 * From "Random number generators: good ones are hard to find", Park and
359 * Miller, Communications of the ACM, vol. 31, no. 10, October 1988, p. 1195.
360 */
361 uint32_t Ctx = *pCtx;
362 if (!Ctx) /* must not be zero. */
363 Ctx = 0x20070212;
364 uint32_t Hi = Ctx / 127773;
365 uint32_t Lo = Ctx % 127773;
366 int32_t x = 16807 * Lo - 2836 * Hi;
367 if (x < 0)
368 x += INT32_MAX;
369 *pCtx = x;
370 return x % INT32_MAX;
371}
372
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette