diff --git a/library/GNUmakefile.68k b/library/GNUmakefile.68k index 159af7f..fbef100 100644 --- a/library/GNUmakefile.68k +++ b/library/GNUmakefile.68k @@ -1,5 +1,5 @@ # -# $Id: GNUmakefile.68k,v 1.77 2005-11-27 10:28:15 obarthel Exp $ +# $Id: GNUmakefile.68k,v 1.78 2005-11-28 09:53:51 obarthel Exp $ # # :ts=8 # @@ -284,6 +284,7 @@ C_LIB = \ stdlib_abs.o \ stdlib_alloca.o \ stdlib_alloca_cleanup.o \ + stdlib_alloca_trap.o \ stdlib_assertion_failure.o \ stdlib_atexit.o \ stdlib_atoi.o \ @@ -307,6 +308,7 @@ C_LIB = \ stdlib_free.o \ stdlib_getdefstacksize.o \ stdlib_getenv.o \ + stdlib_getmemstats.o \ stdlib_getsp.o \ stdlib_get_errno.o \ stdlib_isresident.o \ @@ -337,6 +339,7 @@ C_LIB = \ stdlib_rand_r.o \ stdlib_realloc.o \ stdlib_red_black.o \ + stdlib_resetmemstats.o \ stdlib_semaphore.o \ stdlib_setenv.o \ stdlib_setjmp.o \ @@ -489,13 +492,16 @@ UNIX_LIB = \ stdio_rename.o \ stdlib_alloca.o \ stdlib_alloca_cleanup.o \ + stdlib_alloca_trap.o \ stdlib_arg.o \ + stdlib_getmemstats.o \ stdlib_main.o \ stdlib_mkdtemp.o \ stdlib_mkstemp.o \ stdlib_mktemp.o \ stdlib_malloc.o \ stdlib_realloc.o \ + stdlib_resetmemstats.o \ stdlib_system.o \ termios_cfgetispeed.o \ termios_cfgetospeed.o \ diff --git a/library/GNUmakefile.os4 b/library/GNUmakefile.os4 index c70755d..aa786b9 100644 --- a/library/GNUmakefile.os4 +++ b/library/GNUmakefile.os4 @@ -1,5 +1,5 @@ # -# $Id: GNUmakefile.os4,v 1.89 2005-11-27 10:28:15 obarthel Exp $ +# $Id: GNUmakefile.os4,v 1.90 2005-11-28 09:53:51 obarthel Exp $ # # :ts=8 # @@ -318,6 +318,7 @@ C_LIB = \ stdlib_abs.o \ stdlib_alloca.o \ stdlib_alloca_cleanup.o \ + stdlib_alloca_trap.o \ stdlib_assertion_failure.o \ stdlib_atexit.o \ stdlib_atoi.o \ @@ -341,6 +342,7 @@ C_LIB = \ stdlib_free.o \ stdlib_getdefstacksize.o \ stdlib_getenv.o \ + stdlib_getmemstats.o \ stdlib_getsp.o \ stdlib_get_errno.o \ stdlib_isresident.o \ @@ -371,6 +373,7 @@ C_LIB = \ stdlib_rand_r.o \ stdlib_realloc.o \ stdlib_red_black.o \ + stdlib_resetmemstats.o \ stdlib_semaphore.o \ stdlib_setenv.o \ stdlib_setjmp.o \ @@ -524,13 +527,16 @@ UNIX_LIB = \ stdio_rename.o \ stdlib_alloca.o \ stdlib_alloca_cleanup.o \ + stdlib_alloca_trap.o \ stdlib_arg.o \ + stdlib_getmemstats.o \ stdlib_main.o \ stdlib_mkdtemp.o \ stdlib_mkstemp.o \ stdlib_mktemp.o \ stdlib_malloc.o \ stdlib_realloc.o \ + stdlib_resetmemstats.o \ stdlib_system.o \ termios_cfgetispeed.o \ termios_cfgetospeed.o \ diff --git a/library/changes b/library/changes index 3ce18bb..8cddcf6 100644 --- a/library/changes +++ b/library/changes @@ -22,6 +22,25 @@ calls to succeed in trying to reallocate the same chunk of memory due to a race condition. Fixed. +- Added a new function __get_mem_stats() (the prototype is in ) which + can be used to query the current and maximum memory usage, counting the + allocations performed through malloc(), free() and all other functions which + use them. + +- Added another function called __reset_max_mem_stats() which will reset the + counters for "maximum amount of memory used" and "maximum number of chunks + allocated" to the current figures for these values. + +- Fixed the alloca() declaration in so that software which keys + off the fact whether or not the alloca preprocessor symbol is defined + will do the right thing. + +- Added an optional call-back function which can be called if alloca() + is about to return NULL, which some software does not consider. + Rather than letting such software drop into an illegal memory access + or worse, that call-back function will be invoked instead, which can + print an error message and eventually call abort(). + c.lib 1.197 (4.11.2005) diff --git a/library/include/dos.h b/library/include/dos.h index 600903f..b337e4f 100644 --- a/library/include/dos.h +++ b/library/include/dos.h @@ -1,5 +1,5 @@ /* - * $Id: dos.h,v 1.15 2005-11-27 10:28:15 obarthel Exp $ + * $Id: dos.h,v 1.16 2005-11-28 09:53:51 obarthel Exp $ * * :ts=4 * @@ -51,6 +51,10 @@ #include #endif /* _STDIO_H */ +#ifndef _STDDEF_H +#include +#endif /* _STDDEF_H */ + /****************************************************************************/ #ifndef EXEC_LIBRARIES_H @@ -202,6 +206,47 @@ extern ULONG __free_memory_threshold; /****************************************************************************/ +/* + * You can monitor how much memory, and in how many chunks, is allocated + * over the lifetime of your program. Call the following function with + * non-NULL parameters to obtain the current state of memory allocations. + * Parameters called with NULL instead of pointer to the counters to + * be filled in will be ignored. + */ +extern void __get_mem_stats(size_t * current_memory,size_t * max_memory, + size_t * current_chunks,size_t * max_chunks); + +/* + * The following function will reset the counters for "maximum amount + * of memory used" and "maximum number of chunks used" to the figures + * for the current memory usage. + */ +extern void __reset_max_mem_stats(void); + +/****************************************************************************/ + +/* + * If you use the clib2-supplied alloca() function, which will allocate + * memory from the system pool rather than extending the current stack + * frame, then your program will use a lot less stack space. It might + * use a lot more system memory, though. While the system memory usage + * solves the problem of a program crashing due to ever increasing + * stack usage, which is hard to gauge, there is problem in that many + * programs which call alloca() never test if the value returned is + * not NULL. They just assume that alloca() will always succeed. If + * you use the clib2-supplied alloca() function then the result may in + * fact be NULL. In which case the program making the call might just + * crash because of a missing NULL test. + * + * You can avoid trouble by filling in a pointer to a function which + * will be called when the clib2-supplied alloca() function finds that it + * must return NULL. That function is expected to print an error message + * and to call abort(). + */ +extern void (*__alloca_trap)(void); + +/****************************************************************************/ + /* * The following section lists variables and function pointers which are used * by the startup code right after the program is launched. These variables are diff --git a/library/include/stdlib.h b/library/include/stdlib.h index 9417c47..8a8b741 100644 --- a/library/include/stdlib.h +++ b/library/include/stdlib.h @@ -1,5 +1,5 @@ /* - * $Id: stdlib.h,v 1.14 2005-11-27 10:28:15 obarthel Exp $ + * $Id: stdlib.h,v 1.15 2005-11-28 09:53:51 obarthel Exp $ * * :ts=4 * @@ -168,8 +168,11 @@ extern int rand_r(unsigned int * seed); * -D__USE_CLIB2_ALLOCA to your build makefile. */ +#if defined(alloca) +#undef alloca +#endif /* alloca */ + #if defined(__GNUC__) && !defined(__USE_CLIB2_ALLOCA) - #undef alloca #define alloca(size) __builtin_alloca(size) #else extern void * alloca(size_t size); @@ -178,6 +181,10 @@ extern int rand_r(unsigned int * seed); extern void * __alloca(size_t size,const char *file,int line); #define alloca(size) __alloca((size),__FILE__,__LINE__) + #else + /* This is necessary because some applications key off the fact that + alloca is a symbol defined by the preprocessor. */ + #define alloca alloca #endif /* __MEM_DEBUG */ #endif /* __GNUC__ */ diff --git a/library/smakefile b/library/smakefile index 8f7c3d5..b292445 100644 --- a/library/smakefile +++ b/library/smakefile @@ -1,5 +1,5 @@ # -# $Id: smakefile,v 1.57 2005-11-27 09:26:55 obarthel Exp $ +# $Id: smakefile,v 1.58 2005-11-28 09:53:51 obarthel Exp $ # # :ts=8 # @@ -483,6 +483,7 @@ STDLIB_OBJ = \ stdlib_abs.o \ stdlib_alloca.o \ stdlib_alloca_cleanup.o \ + stdlib_alloca_trap.o \ stdlib_assertion_failure.o \ stdlib_atexit.o \ stdlib_atof.o \ @@ -511,6 +512,7 @@ STDLIB_OBJ = \ stdlib_free.o \ stdlib_getdefstacksize.o \ stdlib_getenv.o \ + stdlib_getmemstats.o \ stdlib_getsp.o \ stdlib_isresident.o \ stdlib_labs.o \ @@ -535,6 +537,7 @@ STDLIB_OBJ = \ stdlib_rand_r.o \ stdlib_realloc.o \ stdlib_red_black.o \ + stdlib_resetmemstats.o \ stdlib_setenv.o \ stdlib_setjmp.o \ stdlib_set_process_window.o \ diff --git a/library/stdlib_alloca.c b/library/stdlib_alloca.c index b13373f..d5313df 100644 --- a/library/stdlib_alloca.c +++ b/library/stdlib_alloca.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_alloca.c,v 1.8 2005-11-27 09:26:55 obarthel Exp $ + * $Id: stdlib_alloca.c,v 1.9 2005-11-28 09:53:51 obarthel Exp $ * * :ts=4 * @@ -170,6 +170,11 @@ __alloca(size_t size,const char * file,int line) __memory_unlock(); + /* If we are about to return NULL and a trap function is + provided, call it rather than returning NULL. */ + if(result == NULL && __alloca_trap != NULL) + (*__alloca_trap)(); + return(result); } diff --git a/library/stdlib_alloca_trap.c b/library/stdlib_alloca_trap.c new file mode 100644 index 0000000..7ea180d --- /dev/null +++ b/library/stdlib_alloca_trap.c @@ -0,0 +1,40 @@ +/* + * $Id: stdlib_alloca_trap.c,v 1.1 2005-11-28 09:53:51 obarthel Exp $ + * + * :ts=4 + * + * Portable ISO 'C' (1994) runtime library for the Amiga computer + * Copyright (c) 2002-2005 by Olaf Barthel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Neither the name of Olaf Barthel nor the names of contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _STDLIB_HEADERS_H +#include "stdlib_headers.h" +#endif /* _STDLIB_HEADERS_H */ + +/****************************************************************************/ + +void NOCOMMON (*__alloca_trap)(void); diff --git a/library/stdlib_free.c b/library/stdlib_free.c index b56c978..7996c9d 100644 --- a/library/stdlib_free.c +++ b/library/stdlib_free.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_free.c,v 1.11 2005-11-27 09:26:55 obarthel Exp $ + * $Id: stdlib_free.c,v 1.12 2005-11-28 09:53:51 obarthel Exp $ * * :ts=4 * @@ -372,6 +372,9 @@ remove_and_free_memory_node(struct MemoryNode * mn) else FreeMem(mn,allocation_size); + __current_memory_allocated -= allocation_size; + __current_num_memory_chunks_allocated--; + __memory_unlock(); } @@ -412,9 +415,6 @@ __free_memory_node(struct MemoryNode * mn,const char * UNUSED file,int UNUSED li } else { - __current_memory_allocated -= size; - __current_num_memory_chunks_allocated--; - remove_and_free_memory_node(mn); } } diff --git a/library/stdlib_getmemstats.c b/library/stdlib_getmemstats.c new file mode 100644 index 0000000..ca6fdf8 --- /dev/null +++ b/library/stdlib_getmemstats.c @@ -0,0 +1,58 @@ +/* + * $Id: stdlib_getmemstats.c,v 1.1 2005-11-28 09:53:51 obarthel Exp $ + * + * :ts=4 + * + * Portable ISO 'C' (1994) runtime library for the Amiga computer + * Copyright (c) 2002-2005 by Olaf Barthel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Neither the name of Olaf Barthel nor the names of contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _STDLIB_HEADERS_H +#include "stdlib_headers.h" +#endif /* _STDLIB_HEADERS_H */ + +/****************************************************************************/ + +void +__get_mem_stats(size_t * current_memory,size_t * max_memory,size_t * current_chunks,size_t * max_chunks) +{ + __memory_lock(); + + if(current_memory != NULL) + (*current_memory) = __current_memory_allocated; + + if(max_memory != NULL) + (*max_memory) = __maximum_memory_allocated; + + if(current_chunks != NULL) + (*current_chunks) = __current_num_memory_chunks_allocated; + + if(max_chunks != NULL) + (*max_chunks) = __maximum_num_memory_chunks_allocated; + + __memory_unlock(); +} diff --git a/library/stdlib_headers.h b/library/stdlib_headers.h index 7d439cb..750dcb4 100644 --- a/library/stdlib_headers.h +++ b/library/stdlib_headers.h @@ -1,5 +1,5 @@ /* - * $Id: stdlib_headers.h,v 1.19 2005-11-27 09:26:55 obarthel Exp $ + * $Id: stdlib_headers.h,v 1.20 2005-11-28 09:53:51 obarthel Exp $ * * :ts=4 * @@ -197,6 +197,10 @@ extern BOOL NOCOMMON __lib_startup; /****************************************************************************/ +extern void NOCOMMON (*__alloca_trap)(void); + +/****************************************************************************/ + #ifndef _STDLIB_PROTOS_H #include "stdlib_protos.h" #endif /* _STDLIB_PROTOS_H */ diff --git a/library/stdlib_malloc.c b/library/stdlib_malloc.c index f8fe21b..6d1bc6a 100644 --- a/library/stdlib_malloc.c +++ b/library/stdlib_malloc.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_malloc.c,v 1.17 2005-11-27 09:26:55 obarthel Exp $ + * $Id: stdlib_malloc.c,v 1.18 2005-11-28 09:53:51 obarthel Exp $ * * :ts=4 * @@ -54,18 +54,16 @@ /****************************************************************************/ -#ifdef __MEM_DEBUG - unsigned long NOCOMMON __maximum_memory_allocated; unsigned long NOCOMMON __current_memory_allocated; unsigned long NOCOMMON __maximum_num_memory_chunks_allocated; unsigned long NOCOMMON __current_num_memory_chunks_allocated; -#if defined(__USE_MEM_TREES) -struct MemoryTree NOCOMMON __memory_tree; -#endif /* __USE_MEM_TREES */ +/****************************************************************************/ -#endif /* __MEM_DEBUG */ +#if defined(__MEM_DEBUG) && defined(__USE_MEM_TREES) +struct MemoryTree NOCOMMON __memory_tree; +#endif /* __MEM_DEBUG && __USE_MEM_TREES */ /****************************************************************************/ @@ -160,6 +158,14 @@ __allocate_memory(size_t size,BOOL never_free,const char * UNUSED unused_file,in AddTail((struct List *)&__memory_list,(struct Node *)mn); + __current_memory_allocated += allocation_size; + if(__maximum_memory_allocated < __current_memory_allocated) + __maximum_memory_allocated = __current_memory_allocated; + + __current_num_memory_chunks_allocated++; + if(__maximum_num_memory_chunks_allocated < __current_num_memory_chunks_allocated) + __maximum_num_memory_chunks_allocated = __current_num_memory_chunks_allocated; + #ifdef __MEM_DEBUG { char * head = (char *)(mn + 1); @@ -178,14 +184,6 @@ __allocate_memory(size_t size,BOOL never_free,const char * UNUSED unused_file,in memset(body,MALLOC_NEW_FILL,size); memset(tail,MALLOC_TAIL_FILL,MALLOC_TAIL_SIZE); - __current_memory_allocated += size; - if(__maximum_memory_allocated < __current_memory_allocated) - __maximum_memory_allocated = __current_memory_allocated; - - __current_num_memory_chunks_allocated++; - if(__maximum_num_memory_chunks_allocated < __current_num_memory_chunks_allocated) - __maximum_num_memory_chunks_allocated = __current_num_memory_chunks_allocated; - #ifdef __MEM_DEBUG_LOG { kprintf("[%s] + %10ld 0x%08lx [",__program_name,size,body); diff --git a/library/stdlib_resetmemstats.c b/library/stdlib_resetmemstats.c new file mode 100644 index 0000000..38623e2 --- /dev/null +++ b/library/stdlib_resetmemstats.c @@ -0,0 +1,49 @@ +/* + * $Id: stdlib_resetmemstats.c,v 1.1 2005-11-28 09:53:51 obarthel Exp $ + * + * :ts=4 + * + * Portable ISO 'C' (1994) runtime library for the Amiga computer + * Copyright (c) 2002-2005 by Olaf Barthel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Neither the name of Olaf Barthel nor the names of contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _STDLIB_HEADERS_H +#include "stdlib_headers.h" +#endif /* _STDLIB_HEADERS_H */ + +/****************************************************************************/ + +void +__reset_max_mem_stats(void) +{ + __memory_lock(); + + __maximum_memory_allocated = __current_memory_allocated; + __maximum_num_memory_chunks_allocated = __current_num_memory_chunks_allocated; + + __memory_unlock(); +}