source: SVN/cambria/redboot/packages/services/memalloc/common/current/tests/malloc4.cxx @ 1

Last change on this file since 1 was 1, checked in by Tim Harvey, 2 years ago

restored latest version of files from server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 11.3 KB
Line 
1//=================================================================
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
94externC void
95cyg_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
108Cyg_Counting_Semaphore startsema;
109
110volatile int stopnow = 0;
111
112struct 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
127int iterations = ITERATIONS;
128
129static struct ptr ptrs[ NUM_PTRS ];
130
131static __inline__ int
132myrand(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
140size_t memsize;
141
142static void
143fill_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
152static void
153check_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
164static void
165check_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
177static void
178thrmalloc( 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
217static void
218thrcalloc( 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
258static void
259thrrealloc( 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
299static void
300thrfree( 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
375externC void
376cyg_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
Note: See TracBrowser for help on using the repository browser.