Mercurial > flash_v2
diff packages/services/memalloc/common/current/tests/malloc4.cxx @ 115:6ed91473a1cd ecos-sw-2000-08-21
Merge from eCos master repository on 2000-08-21-22:40:54-BST
| author | jlarmour |
|---|---|
| date | Fri, 25 Aug 2000 17:32:38 +0000 |
| parents | |
| children | eb9fd8c04db3 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/services/memalloc/common/current/tests/malloc4.cxx @@ -0,0 +1,373 @@ +//================================================================= +// +// malloc4.cxx +// +// Stress test malloc(), calloc(), realloc() and free() +// +//================================================================= +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jlarmour +// Contributors: +// Date: 2000-05-30 +// Description: Contains a rigorous multithreaded test for malloc(), +// calloc(), realloc() and free() functions +// +// +//####DESCRIPTIONEND#### + +// INCLUDES + +#include <pkgconf/system.h> +#include <pkgconf/memalloc.h> // config header +#ifdef CYGPKG_ISOINFRA +# include <pkgconf/isoinfra.h> +# include <stdlib.h> +#endif +#ifdef CYGPKG_KERNEL +# include <pkgconf/kernel.h> +# include <cyg/kernel/thread.hxx> +# include <cyg/kernel/thread.inl> +# include <cyg/kernel/sched.hxx> +# include <cyg/kernel/sched.inl> +#endif +#include <cyg/infra/testcase.h> + +#if !defined(CYGPKG_KERNEL) +# define NA_MSG "Requires kernel" +#elif !defined(CYGFUN_KERNEL_THREADS_TIMER) +# define NA_MSG "Requires thread timers" +#elif !defined(CYGPKG_ISOINFRA) +# define NA_MSG "Requires isoinfra package" +#elif !CYGINT_ISO_MALLOC +# define NA_MSG "Requires malloc" +#elif !CYGINT_ISO_MALLINFO +# define NA_MSG "Requires mallinfo" +#elif !CYGINT_ISO_RAND +# define NA_MSG "Requires rand" +#elif defined(CYGIMP_MEMALLOC_MALLOC_DLMALLOC) && \ + !defined(CYGIMP_MEMALLOC_ALLOCATOR_DLMALLOC_THREADAWARE) +# define NA_MSG "Requires thread-safe dlmalloc" +#elif defined(CYGIMP_MEMALLOC_MALLOC_VARIABLE_SIMPLE) && \ + !defined(CYGSEM_MEMALLOC_ALLOCATOR_VARIABLE_THREADAWARE) +# define NA_MSG "Requires thread-safe variable block allocator" +#endif + +#ifdef NA_MSG + +externC void +cyg_start() +{ + CYG_TEST_INIT(); + CYG_TEST_NA( NA_MSG ); + CYG_TEST_FINISH("Done"); +} +#else + +#define NTHREADS 4 +#include "testaux.hxx" + +#include <cyg/infra/diag.h> + +volatile int gonow = 0; +volatile int stopnow = 0; + +struct ptr { + volatile char *p; + volatile size_t size; + volatile unsigned char busy; +}; + +#define STRINGIFY1( _x_ ) #_x_ +#define STRINGIFY( _x_ ) STRINGIFY1( _x_ ) + +#define NUM_PTRS 100 +#define WAITFORMEMDELAYMAX (cyg_test_is_simulator ? 1 : 3) +#define LOOPDELAYMAX (cyg_test_is_simulator ? 1 : 3) +#define ITERATIONS (cyg_test_is_simulator ? 10 : 200) +#define OUTPUTINTERVAL (cyg_test_is_simulator ? 1 : 10) + +int iterations = ITERATIONS; + +static struct ptr ptrs[ NUM_PTRS ]; + +static __inline__ int +myrand(int limit, unsigned int *seed) +{ + int r; + double l=(double)limit; + r=(int)( l*rand_r(seed) / RAND_MAX ); + return r; +} + +size_t memsize; + +static void +fill_with_data( struct ptr *p ) +{ + unsigned int i, j; + for (i=0; i < (p->size/4); i++) + ((unsigned int *)p->p)[i] = (unsigned int)p; + for ( j=i*4; j < p->size ; j++ ) + p->p[j] = ((char *)p)[j-i*4]; +} + +static void +check_data( struct ptr *p ) +{ + unsigned int i, j; + for (i=0; i < (p->size/4); i++) + CYG_TEST_CHECK( ((unsigned int *)p->p)[i] == (unsigned int)p, + "Data didn't compare correctly"); + for ( j=i*4; j < p->size ; j++ ) + CYG_TEST_CHECK( p->p[j] == ((char *)p)[j-i*4], + "Data didn't compare correctly"); +} + +static void +check_zeroes( struct ptr *p ) +{ + unsigned int i, j; + for (i=0; i < (p->size/4); i++) + CYG_TEST_CHECK( ((int *)p->p)[i] == 0, + "Zeroed data didn't compare correctly"); + for ( j=i*4; j < p->size ; j++ ) + CYG_TEST_CHECK( p->p[j] == 0, + "Zeroed data didn't compare correctly"); +} + + +static void +thrmalloc( CYG_ADDRWORD data ) +{ + int r, i; + void *mem; + unsigned int seed; + + while (!gonow) + Cyg_Thread::self()->delay(1); + + while (!stopnow) { + r = myrand( NUM_PTRS-1, &seed ); + + for (i=r+1; ; i++) { + Cyg_Scheduler::lock(); + if (i == NUM_PTRS) + i=0; + if (!ptrs[i].busy && (ptrs[i].p == NULL) ) + break; + Cyg_Scheduler::unlock(); + if ( i==r ) { + Cyg_Thread::self()->delay( myrand(WAITFORMEMDELAYMAX, &seed) ); + } + } + ptrs[i].busy = 1; + Cyg_Scheduler::unlock(); + r = myrand(memsize, &seed); + mem = malloc(r); + ptrs[i].p = (char *)mem; + ptrs[i].size = r; + if ( NULL != mem ) { +// diag_printf("malloc=%08x size=%d\n", mem, r); + fill_with_data( &ptrs[i] ); + } + ptrs[i].busy = 0; + Cyg_Thread::self()->delay( myrand(LOOPDELAYMAX, &seed) ); + } +} + +static void +thrcalloc( CYG_ADDRWORD data ) +{ + int r, i; + void *mem; + unsigned int seed; + + while (!gonow) + Cyg_Thread::self()->delay(1); + + while (!stopnow) { + r = myrand( NUM_PTRS-1, &seed ); + + for (i=r+1; ; i++) { + Cyg_Scheduler::lock(); + if (i == NUM_PTRS) + i=0; + if (!ptrs[i].busy && (ptrs[i].p == NULL) ) + break; + Cyg_Scheduler::unlock(); + if ( i==r ) { + Cyg_Thread::self()->delay( myrand(WAITFORMEMDELAYMAX, &seed) ); + } + } + ptrs[i].busy = 1; + Cyg_Scheduler::unlock(); + r = myrand(memsize, &seed); + mem = calloc( 1, r ); + ptrs[i].p = (char *)mem; + ptrs[i].size = r; + if ( NULL != mem ) { +// diag_printf("calloc=%08x size=%d\n", mem, r); + check_zeroes( &ptrs[i] ); + fill_with_data( &ptrs[i] ); + } + ptrs[i].busy = 0; + Cyg_Thread::self()->delay( myrand(LOOPDELAYMAX, &seed) ); + } +} + +static void +thrrealloc( CYG_ADDRWORD data ) +{ + int r, i; + void *mem; + unsigned int seed; + + while (!gonow) + Cyg_Thread::self()->delay(1); + + while (!stopnow) { + r = myrand( NUM_PTRS-1, &seed ); + + for (i=r+1; ; i++) { + Cyg_Scheduler::lock(); + if (i == NUM_PTRS) + i=0; + if (!ptrs[i].busy && (ptrs[i].p != NULL) ) + break; + Cyg_Scheduler::unlock(); + if ( i==r ) { + Cyg_Thread::self()->delay( myrand(WAITFORMEMDELAYMAX, &seed) ); + } + } + ptrs[i].busy = 1; + Cyg_Scheduler::unlock(); + check_data( &ptrs[i] ); + r = myrand(memsize, &seed); + mem = realloc( (void *)ptrs[i].p, r ); + if ( NULL != mem ) { +// diag_printf("realloc=%08x oldsize=%d newsize=%d\n", mem, ptrs[i].size, r); + ptrs[i].size = r; + ptrs[i].p = (char *)mem; + fill_with_data( &ptrs[i] ); + } + ptrs[i].busy = 0; + Cyg_Thread::self()->delay( myrand(LOOPDELAYMAX, &seed) ); + } +} + +static void +thrfree( CYG_ADDRWORD data ) +{ + int r, i; + int iter = 0; + struct mallinfo minfo; + unsigned int seed; + + minfo = mallinfo(); + memsize = (unsigned long) minfo.maxfree; + diag_printf("INFO:<Iteration 0, arenasize=%d, space free=%d, maxfree=%d>\n", + minfo.arena, minfo.fordblks, minfo.maxfree ); + gonow++; + + Cyg_Thread::self()->delay(1); + + while (1) { + if ( (iter > 0) && (0 == (iter % OUTPUTINTERVAL)) ) { + minfo = mallinfo(); + diag_printf("INFO:<Iteration %d, arenasize=%d, " + "space free=%d, maxfree=%d>\n", + iter, minfo.arena, minfo.fordblks, minfo.maxfree ); + } + + if ( iterations == iter++ ) + stopnow++; + + r = myrand( NUM_PTRS-1, &seed ); + + for (i=r+1; ; i++) { + Cyg_Scheduler::lock(); + if (i >= NUM_PTRS) + i=0; + if (!ptrs[i].busy && (ptrs[i].p != NULL) ) + break; + Cyg_Scheduler::unlock(); + if ( i==r ) { + if ( stopnow ) { + // we may have gone round all the ptrs even though one + // or more of them was busy, so check again just for that + int j; + for (j=0; j<NUM_PTRS; j++) + if (ptrs[j].busy) + break; + if ( j<NUM_PTRS ) + continue; + struct mallinfo minfo; + + minfo = mallinfo(); + diag_printf("INFO:<Iteration %d, arenasize=%d, " + "space free=%d, maxfree=%d>\n", + iter, minfo.arena, minfo.fordblks, + minfo.maxfree ); + CYG_TEST_PASS_FINISH("malloc4 test completed successfully"); + } else { + Cyg_Thread::self()->delay( + myrand(WAITFORMEMDELAYMAX, &seed) ); + } + } + } + ptrs[i].busy = 1; + Cyg_Scheduler::unlock(); + check_data( &ptrs[i] ); +// diag_printf("about to free %08x\n", ptrs[i].p); + free( (void *)ptrs[i].p ); + ptrs[i].p = NULL; + ptrs[i].busy = 0; + Cyg_Thread::self()->delay( myrand(LOOPDELAYMAX, &seed) ); + } +} + + +externC void +cyg_start() +{ + CYG_TEST_INIT(); + CYG_TEST_INFO("Starting malloc4 test"); + + new_thread(thrmalloc, 0); + new_thread(thrcalloc, 1); + new_thread(thrrealloc, 2); + new_thread(thrfree, 3); + + Cyg_Scheduler::start(); + + CYG_TEST_FAIL_FINISH("Not reached"); +} // main() + +#endif // !NA_MSG + +// EOF malloc4.cxx
