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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [services/] [memalloc/] [common/] [current/] [tests/] [malloc4.cxx] - Blame information for rev 851

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//=================================================================
2
//
3
//        malloc4.cxx
4
//
5
//        Stress test malloc(), calloc(), realloc() and free()
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 Free Software Foundation, 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      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//=================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):     jlarmour
43
// Contributors:  
44
// Date:          2000-05-30
45
// Description:   Contains a rigorous multithreaded test for malloc(),
46
//                calloc(), realloc() and free() functions
47
//
48
//
49
//####DESCRIPTIONEND####
50
 
51
// #define DEBUGTEST
52
 
53
// INCLUDES
54
 
55
#include <pkgconf/system.h>
56
#include <pkgconf/memalloc.h> // config header
57
#ifdef CYGPKG_ISOINFRA
58
# include <pkgconf/isoinfra.h>
59
# include <stdlib.h>
60
#endif
61
#ifdef CYGPKG_KERNEL
62
# include <pkgconf/kernel.h>
63
# include <cyg/kernel/thread.hxx>
64
# include <cyg/kernel/thread.inl>
65
# include <cyg/kernel/sched.hxx>
66
# include <cyg/kernel/sched.inl>
67
# include <cyg/kernel/sema.hxx>
68
#endif
69
#include <cyg/infra/testcase.h>
70
 
71
#if !defined(CYGPKG_KERNEL)
72
# define NA_MSG "Requires kernel"
73
#elif !defined(CYGFUN_KERNEL_THREADS_TIMER)
74
# define NA_MSG "Requires thread timers"
75
#elif !defined(CYGPKG_ISOINFRA)
76
# define NA_MSG "Requires isoinfra package"
77
#elif !CYGINT_ISO_MALLOC
78
# define NA_MSG "Requires malloc"
79
#elif !CYGINT_ISO_MALLINFO
80
# define NA_MSG "Requires mallinfo"
81
#elif !CYGINT_ISO_RAND
82
# define NA_MSG "Requires rand"
83
#elif defined(CYGIMP_MEMALLOC_MALLOC_DLMALLOC) && \
84
      !defined(CYGIMP_MEMALLOC_ALLOCATOR_DLMALLOC_THREADAWARE)
85
# define NA_MSG "Requires thread-safe dlmalloc"
86
#elif defined(CYGIMP_MEMALLOC_MALLOC_VARIABLE_SIMPLE) && \
87
      !defined(CYGSEM_MEMALLOC_ALLOCATOR_VARIABLE_THREADAWARE)
88
# define NA_MSG "Requires thread-safe variable block allocator"
89
#endif
90
 
91
#ifdef NA_MSG
92
 
93
externC void
94
cyg_start(void)
95
{
96
    CYG_TEST_INIT();
97
    CYG_TEST_NA( NA_MSG );
98
    CYG_TEST_FINISH("Done");
99
}
100
#else
101
//#define DEBUGTEST 1
102
#define NTHREADS 4
103
#include "testaux.hxx"
104
 
105
#include <cyg/infra/diag.h>
106
 
107
Cyg_Counting_Semaphore startsema;
108
 
109
volatile int stopnow = 0;
110
 
111
struct ptr {
112
    char* volatile p;
113
    volatile size_t size;
114
    volatile unsigned char busy;
115
};
116
 
117
#define STRINGIFY1( _x_ ) #_x_
118
#define STRINGIFY( _x_ ) STRINGIFY1( _x_ )
119
 
120
#define NUM_PTRS 100
121
#define WAITFORMEMDELAYMAX (cyg_test_is_simulator ? 1 : 3)
122
#define LOOPDELAYMAX       (cyg_test_is_simulator ? 1 : 3)
123
#define ITERATIONS         (cyg_test_is_simulator ? 10 : 200)
124
#define OUTPUTINTERVAL     (cyg_test_is_simulator ? 1 : 10)
125
 
126
int iterations = ITERATIONS;
127
 
128
static struct ptr ptrs[ NUM_PTRS ];
129
 
130
static __inline__ int
131
myrand(int limit, unsigned int *seed)
132
{
133
    int r;
134
    double l=(double)(limit+1);
135
    r=(int)( l*rand_r(seed) / (RAND_MAX+1.0) );
136
    return r;
137
}
138
 
139
size_t memsize;
140
 
141
static void
142
fill_with_data( struct ptr *p )
143
{
144
    unsigned int i, j;
145
    for (i=0; i < (p->size/4); i++)
146
        ((unsigned int *)p->p)[i] = (unsigned int)p;
147
    for ( j=i*4; j < p->size ; j++ )
148
        p->p[j] = ((char *)p)[j-i*4];
149
}
150
 
151
static void
152
check_data( struct ptr *p )
153
{
154
    unsigned int i, j;
155
    for (i=0; i < (p->size/4); i++)
156
        CYG_TEST_CHECK( ((unsigned int *)p->p)[i] == (unsigned int)p,
157
                        "Data didn't compare correctly");
158
    for ( j=i*4; j < p->size ; j++ )
159
        CYG_TEST_CHECK( p->p[j] == ((char *)p)[j-i*4],
160
                        "Data didn't compare correctly");
161
}
162
 
163
static void
164
check_zeroes( struct ptr *p )
165
{
166
    unsigned int i, j;
167
    for (i=0; i < (p->size/4); i++)
168
        CYG_TEST_CHECK( ((int *)p->p)[i] == 0,
169
                        "Zeroed data didn't compare correctly");
170
    for ( j=i*4; j < p->size ; j++ )
171
        CYG_TEST_CHECK( p->p[j] == 0,
172
                        "Zeroed data didn't compare correctly");
173
}
174
 
175
 
176
static void
177
thrmalloc( CYG_ADDRWORD data )
178
{
179
    int r, i;
180
    void *mem;
181
    unsigned int seed;
182
 
183
    startsema.wait();
184
 
185
    while (!stopnow) {
186
        r = myrand( NUM_PTRS-1, &seed );
187
 
188
        for (i=r+1; ; i++) {
189
            Cyg_Scheduler::lock();
190
            if (i == NUM_PTRS)
191
                i=0;
192
            if (!ptrs[i].busy && (ptrs[i].p == NULL) )
193
                break;
194
            Cyg_Scheduler::unlock();
195
            if ( i==r ) {
196
                Cyg_Thread::self()->delay( myrand(WAITFORMEMDELAYMAX, &seed) );
197
            }
198
        }
199
        ptrs[i].busy = 1;
200
        Cyg_Scheduler::unlock();
201
        r = myrand(memsize, &seed);
202
        mem = malloc(r);
203
        ptrs[i].p = (char *)mem;
204
        ptrs[i].size = r;
205
        if ( NULL != mem ) {
206
#ifdef DEBUGTEST
207
            diag_printf("malloc=%08x size=%d\n", mem, r);
208
#endif
209
            fill_with_data( &ptrs[i] );
210
        }
211
        ptrs[i].busy = 0;
212
        Cyg_Thread::self()->delay( myrand(LOOPDELAYMAX, &seed) );
213
    }
214
}
215
 
216
static void
217
thrcalloc( CYG_ADDRWORD data )
218
{
219
    int r, i;
220
    void *mem;
221
    unsigned int seed;
222
 
223
    startsema.wait();
224
 
225
    while (!stopnow) {
226
        r = myrand( NUM_PTRS-1, &seed );
227
 
228
        for (i=r+1; ; i++) {
229
            Cyg_Scheduler::lock();
230
            if (i == NUM_PTRS)
231
                i=0;
232
            if (!ptrs[i].busy && (ptrs[i].p == NULL) )
233
                break;
234
            Cyg_Scheduler::unlock();
235
            if ( i==r ) {
236
                Cyg_Thread::self()->delay( myrand(WAITFORMEMDELAYMAX, &seed) );
237
            }
238
        }
239
        ptrs[i].busy = 1;
240
        Cyg_Scheduler::unlock();
241
        r = myrand(memsize, &seed);
242
        mem = calloc( 1, r );
243
        ptrs[i].p = (char *)mem;
244
        ptrs[i].size = r;
245
        if ( NULL != mem ) {
246
#ifdef DEBUGTEST
247
            diag_printf("calloc=%08x size=%d\n", mem, r);
248
#endif
249
            check_zeroes( &ptrs[i] );
250
            fill_with_data( &ptrs[i] );
251
        }
252
        ptrs[i].busy = 0;
253
        Cyg_Thread::self()->delay( myrand(LOOPDELAYMAX, &seed) );
254
    }
255
}
256
 
257
static void
258
thrrealloc( CYG_ADDRWORD data )
259
{
260
    int r, i;
261
    void *mem;
262
    unsigned int seed;
263
 
264
    startsema.wait();
265
 
266
    while (!stopnow) {
267
        r = myrand( NUM_PTRS-1, &seed );
268
 
269
        for (i=r+1; ; i++) {
270
            Cyg_Scheduler::lock();
271
            if (i == NUM_PTRS)
272
                i=0;
273
            if (!ptrs[i].busy && (ptrs[i].p != NULL) )
274
                break;
275
            Cyg_Scheduler::unlock();
276
            if ( i==r ) {
277
                Cyg_Thread::self()->delay( myrand(WAITFORMEMDELAYMAX, &seed) );
278
            }
279
        }
280
        ptrs[i].busy = 1;
281
        Cyg_Scheduler::unlock();
282
        check_data( &ptrs[i] );
283
        r = myrand(memsize - 1, &seed) + 1;
284
        mem = realloc( (void *)ptrs[i].p, r );
285
        if ( NULL != mem ) {
286
#ifdef DEBUGTEST
287
            diag_printf("realloc=%08x oldsize=%d newsize=%d\n", mem, ptrs[i].size, r);
288
#endif
289
            ptrs[i].size = r;
290
            ptrs[i].p = (char *)mem;
291
            fill_with_data( &ptrs[i] );
292
        }
293
        ptrs[i].busy = 0;
294
        Cyg_Thread::self()->delay( myrand(LOOPDELAYMAX, &seed) );
295
    }
296
}
297
 
298
static void
299
thrfree( CYG_ADDRWORD data )
300
{
301
    int r, i;
302
    int iter = 0;
303
    struct mallinfo minfo;
304
    unsigned int seed;
305
 
306
    minfo = mallinfo();
307
    memsize = (unsigned long) minfo.maxfree;
308
    diag_printf("INFO:<Iteration 0, arenasize=%d, space free=%d, maxfree=%d>\n",
309
                minfo.arena, minfo.fordblks, minfo.maxfree );
310
 
311
    // wake the three threads above.
312
    startsema.post(); startsema.post(); startsema.post();
313
 
314
    Cyg_Thread::self()->delay(1);
315
 
316
    while (1) {
317
        if ( (iter > 0) && (0 == (iter % OUTPUTINTERVAL)) ) {
318
            minfo = mallinfo();
319
            diag_printf("INFO:<Iteration %d, arenasize=%d, "
320
                        "space free=%d, maxfree=%d>\n",
321
                        iter, minfo.arena, minfo.fordblks, minfo.maxfree );
322
        }
323
 
324
        if ( iterations == iter++ )
325
            stopnow++;
326
 
327
        r = myrand( NUM_PTRS-1, &seed );
328
 
329
        for (i=r+1; ; i++) {
330
            Cyg_Scheduler::lock();
331
            if (i >= NUM_PTRS)
332
                i=0;
333
            if (!ptrs[i].busy && (ptrs[i].p != NULL) )
334
                break;
335
            Cyg_Scheduler::unlock();
336
            if ( i==r ) {
337
                if ( stopnow ) {
338
                    // we may have gone round all the ptrs even though one
339
                    // or more of them was busy, so check again just for that
340
                    int j;
341
                    for (j=0; j<NUM_PTRS; j++)
342
                        if (ptrs[j].busy)
343
                            break;
344
                    if ( j<NUM_PTRS )
345
                        continue;
346
                    struct mallinfo minfo;
347
 
348
                    minfo = mallinfo();
349
                    diag_printf("INFO:<Iteration %d, arenasize=%d, "
350
                                "space free=%d, maxfree=%d>\n",
351
                                iter, minfo.arena, minfo.fordblks,
352
                                minfo.maxfree );
353
                    CYG_TEST_PASS_FINISH("malloc4 test completed successfully");
354
                } else {
355
                    Cyg_Thread::self()->delay(
356
                        myrand(WAITFORMEMDELAYMAX, &seed) );
357
                }
358
            }
359
        }
360
        ptrs[i].busy = 1;
361
        Cyg_Scheduler::unlock();
362
        check_data( &ptrs[i] );
363
#ifdef DEBUGTEST
364
        diag_printf("about to free %08x\n", ptrs[i].p);
365
#endif
366
        free( (void *)ptrs[i].p );
367
        ptrs[i].p = NULL;
368
        ptrs[i].busy = 0;
369
        Cyg_Thread::self()->delay( myrand(LOOPDELAYMAX, &seed) );
370
    }
371
}
372
 
373
 
374
externC void
375
cyg_start(void)
376
{
377
#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
378
    cyg_hal_invoke_constructors();
379
#endif
380
    CYG_TEST_INIT();
381
    CYG_TEST_INFO("Starting malloc4 test");
382
 
383
    new_thread(thrmalloc, 0);
384
    new_thread(thrcalloc, 1);
385
    new_thread(thrrealloc, 2);
386
    new_thread(thrfree, 3);
387
 
388
    Cyg_Scheduler::start();
389
 
390
    CYG_TEST_FAIL_FINISH("Not reached");
391
} // cyg_start()
392
 
393
#endif // !NA_MSG
394
 
395
// EOF malloc4.cxx

powered by: WebSVN 2.1.0

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