OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [language/] [c/] [libc/] [stdlib/] [v2_0/] [src/] [rand.cxx] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//===========================================================================
2
//
3
//      rand.cxx
4
//
5
//      ISO and POSIX 1003.1 standard random number generation functions
6
//
7
//===========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//===========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):     jlarmour
44
// Contributors:  
45
// Date:          2000-04-30
46
// Purpose:       Provides ISO C rand() and srand() functions, along with
47
//                POSIX 1003.1 rand_r() function
48
// Description:   This implements rand() and srand() of section 7.10.2.1 of
49
//                the ISO C standard. Also rand_r() defined in section 8.3.8
50
//                of the POSIX 1003.1 standard
51
// Usage:       
52
//
53
//####DESCRIPTIONEND####
54
//
55
//===========================================================================
56
 
57
// CONFIGURATION
58
 
59
#include <pkgconf/libc_stdlib.h>   // Configuration header
60
 
61
// INCLUDES
62
 
63
#include <cyg/infra/cyg_type.h>    // Common type definitions and support
64
#include <cyg/infra/cyg_trac.h>    // Tracing support
65
#include <cyg/infra/cyg_ass.h>     // Assertion support
66
#include <stdlib.h>                // Header for all stdlib functions
67
                                   // (like this one)
68
 
69
#ifdef CYGSEM_LIBC_PER_THREAD_RAND
70
# include <pkgconf/kernel.h>       // kernel configuration
71
# include <cyg/kernel/thread.hxx>  // per-thread data
72
# include <cyg/kernel/thread.inl>  // per-thread data
73
# include <cyg/kernel/mutex.hxx>   // mutexes
74
#endif
75
 
76
// TRACE
77
 
78
#if defined(CYGDBG_USE_TRACING) && defined(CYGNUM_LIBC_RAND_TRACE_LEVEL)
79
static int rand_trace = CYGNUM_LIBC_RAND_TRACE_LEVEL;
80
# define TL1 (0 < rand_trace)
81
#else
82
# define TL1 (0)
83
#endif
84
 
85
 
86
// STATICS
87
 
88
#ifdef CYGSEM_LIBC_PER_THREAD_RAND
89
static cyg_ucount32 rand_data_index=CYGNUM_KERNEL_THREADS_DATA_MAX;
90
static Cyg_Mutex rand_data_mutex CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_LIBC);
91
#else
92
static unsigned int cyg_libc_rand_seed = CYGNUM_LIBC_RAND_SEED;
93
#endif
94
 
95
// FUNCTIONS
96
 
97
int
98
rand( void )
99
{
100
    unsigned int *seed_p;
101
    int retval;
102
 
103
    CYG_REPORT_FUNCNAMETYPE( "rand", "returning %d" );
104
 
105
    // get seed for this thread (if relevant )
106
#ifdef CYGSEM_LIBC_PER_THREAD_RAND
107
    Cyg_Thread *self = Cyg_Thread::self();
108
 
109
    // Get a per-thread data slot if we haven't got one already
110
    // Do a simple test before locking and retrying test, as this is a
111
    // rare situation
112
    if (CYGNUM_KERNEL_THREADS_DATA_MAX==rand_data_index) {
113
        rand_data_mutex.lock();
114
        if (CYGNUM_KERNEL_THREADS_DATA_MAX==rand_data_index) {
115
 
116
            // the kernel just throws an assert if this doesn't work
117
            // FIXME: Should use real CDL to pre-allocate a slot at compile
118
            // time to ensure there are enough slots
119
            rand_data_index = self->new_data_index();
120
 
121
            // Initialize seed
122
            self->set_data(rand_data_index, CYGNUM_LIBC_RAND_SEED);
123
        }
124
        rand_data_mutex.unlock();
125
    } // if
126
 
127
    // we have a valid index now
128
 
129
    seed_p = (unsigned int *)self->get_data_ptr(rand_data_index);
130
#else
131
    seed_p = &cyg_libc_rand_seed;
132
#endif
133
 
134
    CYG_TRACE2( TL1, "Retrieved seed address %08x containing %d",
135
                seed_p, *seed_p );
136
    CYG_CHECK_DATA_PTR( seed_p, "Help! Returned address of seed is invalid!" );
137
 
138
    retval = rand_r( seed_p );
139
 
140
    CYG_REPORT_RETVAL( retval );
141
 
142
    return retval;
143
 
144
} // rand()
145
 
146
 
147
int
148
rand_r( unsigned int *seed )
149
{
150
    int retval;
151
 
152
    CYG_REPORT_FUNCNAMETYPE( "rand_r", "returning %d" );
153
 
154
    CYG_CHECK_DATA_PTR( seed, "pointer to seed invalid!" );
155
 
156
#if defined(CYGIMP_LIBC_RAND_SIMPLEST)
157
 
158
    // This algorithm sucks in the lower bits
159
 
160
    *seed = (*seed * 1103515245) + 12345; // permutate seed
161
 
162
    retval = (int)( *seed & RAND_MAX );
163
 
164
#elif defined(CYGIMP_LIBC_RAND_SIMPLE1)
165
 
166
    // The above algorithm sucks in the lower bits, so we shave them off
167
    // and repeat a couple of times to make it up
168
 
169
    unsigned int s=*seed;
170
    unsigned int uret;
171
 
172
    s = (s * 1103515245) + 12345; // permutate seed
173
    // Only use top 11 bits
174
    uret = s & 0xffe00000;
175
 
176
    s = (s * 1103515245) + 12345; // permutate seed
177
    // Only use top 14 bits
178
    uret += (s & 0xfffc0000) >> 11;
179
 
180
    s = (s * 1103515245) + 12345; // permutate seed
181
    // Only use top 7 bits
182
    uret += (s & 0xfe000000) >> (11+14);
183
 
184
    retval = (int)(uret & RAND_MAX);
185
    *seed = s;
186
 
187
#elif defined(CYGIMP_LIBC_RAND_KNUTH1)
188
 
189
// This is the code supplied in Knuth Vol 2 section 3.6 p.185 bottom
190
 
191
#define MM 2147483647    // a Mersenne prime
192
#define AA 48271         // this does well in the spectral test
193
#define QQ 44488         // (long)(MM/AA)
194
#define RR 3399          // MM % AA; it is important that RR<QQ
195
 
196
    *seed = AA*(*seed % QQ) - RR*(unsigned int)(*seed/QQ);
197
    if (*seed < 0)
198
        *seed += MM;
199
 
200
    retval = (int)( *seed & RAND_MAX );
201
 
202
#else
203
# error No valid implementation for rand()!
204
#endif
205
 
206
    CYG_REPORT_RETVAL( retval );
207
 
208
    return retval;
209
 
210
} // rand_r()
211
 
212
 
213
void
214
srand( unsigned int seed )
215
{
216
    CYG_REPORT_FUNCNAME( "srand" );
217
 
218
    CYG_REPORT_FUNCARG1DV( (int)seed );
219
 
220
    // get seed for this thread ( if relevant )
221
#ifdef CYGSEM_LIBC_PER_THREAD_RAND
222
    Cyg_Thread *self = Cyg_Thread::self();
223
 
224
    // Get a per-thread data slot if we haven't got one already
225
    // Do a simple test before locking and retrying test, as this is a
226
    // rare situation
227
    if (CYGNUM_KERNEL_THREADS_DATA_MAX==rand_data_index) {
228
        rand_data_mutex.lock();
229
        if (CYGNUM_KERNEL_THREADS_DATA_MAX==rand_data_index) {
230
 
231
            // the kernel just throws an assert if this doesn't work
232
            // FIXME: Should use real CDL to pre-allocate a slot at compile
233
            // time to ensure there are enough slots
234
            rand_data_index = self->new_data_index();
235
 
236
        }
237
        rand_data_mutex.unlock();
238
    } // if
239
 
240
    // we have a valid index now
241
 
242
    self->set_data(rand_data_index, (CYG_ADDRWORD) seed);
243
#else
244
    cyg_libc_rand_seed = seed;
245
#endif
246
 
247
    CYG_REPORT_RETURN();
248
 
249
} // srand()
250
 
251
// EOF rand.cxx

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.