📄 malloc4.cxx
字号:
//=================================================================//// malloc4.cxx//// Stress test malloc(), calloc(), realloc() and free()////=================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//=================================================================//#####DESCRIPTIONBEGIN####//// Author(s): jlarmour// Contributors: // Date: 2000-05-30// Description: Contains a rigorous multithreaded test for malloc(),// calloc(), realloc() and free() functions//////####DESCRIPTIONEND####// #define DEBUGTEST// 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># include <cyg/kernel/sema.hxx>#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_MSGexternC voidcyg_start(void){ CYG_TEST_INIT(); CYG_TEST_NA( NA_MSG ); CYG_TEST_FINISH("Done");}#else//#define DEBUGTEST 1#define NTHREADS 4#include "testaux.hxx"#include <cyg/infra/diag.h>Cyg_Counting_Semaphore startsema;volatile int stopnow = 0;struct ptr { char* volatile 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__ intmyrand(int limit, unsigned int *seed){ int r; double l=(double)(limit+1); r=(int)( l*rand_r(seed) / (RAND_MAX+1.0) ); return r;}size_t memsize;static voidfill_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 voidcheck_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 voidcheck_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 voidthrmalloc( CYG_ADDRWORD data ){ int r, i; void *mem; unsigned int seed; startsema.wait(); 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 ) {#ifdef DEBUGTEST diag_printf("malloc=%08x size=%d\n", mem, r);#endif fill_with_data( &ptrs[i] ); } ptrs[i].busy = 0; Cyg_Thread::self()->delay( myrand(LOOPDELAYMAX, &seed) ); }}static voidthrcalloc( CYG_ADDRWORD data ){ int r, i; void *mem; unsigned int seed; startsema.wait(); 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 ) {#ifdef DEBUGTEST diag_printf("calloc=%08x size=%d\n", mem, r);#endif check_zeroes( &ptrs[i] ); fill_with_data( &ptrs[i] ); } ptrs[i].busy = 0; Cyg_Thread::self()->delay( myrand(LOOPDELAYMAX, &seed) ); }}static voidthrrealloc( CYG_ADDRWORD data ){ int r, i; void *mem; unsigned int seed; startsema.wait(); 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 - 1, &seed) + 1; mem = realloc( (void *)ptrs[i].p, r ); if ( NULL != mem ) {#ifdef DEBUGTEST diag_printf("realloc=%08x oldsize=%d newsize=%d\n", mem, ptrs[i].size, r);#endif 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 voidthrfree( 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 ); // wake the three threads above. startsema.post(); startsema.post(); startsema.post(); 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] );#ifdef DEBUGTEST diag_printf("about to free %08x\n", ptrs[i].p);#endif free( (void *)ptrs[i].p ); ptrs[i].p = NULL; ptrs[i].busy = 0; Cyg_Thread::self()->delay( myrand(LOOPDELAYMAX, &seed) ); }}externC voidcyg_start(void){#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG cyg_hal_invoke_constructors();#endif 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");} // cyg_start()#endif // !NA_MSG// EOF malloc4.cxx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -