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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [services/] [memalloc/] [common/] [v2_0/] [tests/] [malloc4.cxx] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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