X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fmm%2Fmemory.c;h=ccaa8ec4d1b196c579f1c888b3a5893c52d2abae;hb=219e4a46e3d127d3c0883ee2e8635b4fe3c94d60;hp=15fb2991d276a8e9d36aa8ea310e6b58206b43d1;hpb=18d2d455ab62d52d35764eeeda50922e4e61a2a7;p=cacao.git diff --git a/src/mm/memory.c b/src/mm/memory.c index 15fb2991d..ccaa8ec4d 100644 --- a/src/mm/memory.c +++ b/src/mm/memory.c @@ -1,9 +1,7 @@ /* src/mm/memory.c - memory management - Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel, - C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring, - E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, - J. Wenninger, Institut f. Computersprachen - TU Wien + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -22,20 +20,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - $Id: memory.c 7369 2007-02-16 17:56:40Z twisti $ - */ #include "config.h" #include -#include -#include -#include -#include -#include -#include +#include #if defined(__DARWIN__) /* If we compile with -ansi on darwin, is not @@ -48,139 +39,37 @@ #include "arch.h" #include "mm/memory.h" + #include "native/native.h" -#if defined(ENABLE_THREADS) -# include "threads/threads-common.h" - -# include "threads/native/lock.h" -# include "threads/native/threads.h" -#else -# include "threads/none/lock.h" -#endif +#include "threads/lock-common.h" +#include "threads/thread.hpp" #include "toolbox/logging.h" -#include "vm/exceptions.h" -#include "vm/global.h" -#include "vm/stringlocal.h" -#include "vm/vm.h" -#include "vmcore/options.h" - -#if defined(ENABLE_STATISTICS) -# include "vmcore/statistics.h" -#endif - - -/* constants for ENABLE_MEMCHECK **********************************************/ - -#if defined(ENABLE_MEMCHECK) -#define MEMORY_CANARY_SIZE 16 -#define MEMORY_CANARY_FIRST_BYTE 0xca -#define MEMORY_CLEAR_BYTE 0xa5 -#endif /* defined(ENABLE_MEMCHECK) */ - - -/******************************************************************************* - - This structure is used for dump memory allocation if cacao - runs without threads. - -*******************************************************************************/ - -#if !defined(ENABLE_THREADS) -static dumpinfo_t _no_threads_dumpinfo; -#endif - -#if defined(ENABLE_THREADS) -#define DUMPINFO &((threadobject *) THREADOBJECT)->dumpinfo -#else -#define DUMPINFO &_no_threads_dumpinfo -#endif - - -/* global code memory variables ***********************************************/ - -#define DEFAULT_CODE_MEMORY_SIZE 128 * 1024 /* defaulting to 128kB */ - -#if defined(ENABLE_THREADS) -static java_objectheader *lock_code_memory = NULL; -#endif -static void *code_memory = NULL; -static int code_memory_size = 0; -static int pagesize = 0; - - -/* global variables ***********************************************************/ - -#if defined(ENABLE_THREADS) -static threadobject *thread_memory; -#endif - - -/* memory_init ***************************************************************** - - Initialize the memory subsystem. -*******************************************************************************/ - -bool memory_init(void) -{ -#if defined(ENABLE_THREADS) - /* create lock for code memory */ +#include "vm/global.h" +#include "vm/string.hpp" +#include "vm/vm.hpp" - lock_code_memory = NEW(java_objectheader); +#include "vm/options.h" +#include "vm/os.hpp" - lock_init_object_lock(lock_code_memory); +#if defined(ENABLE_STATISTICS) +# include "vm/statistics.h" #endif - /* get the pagesize of this architecture */ - pagesize = getpagesize(); +/* memory_mprotect ************************************************************* - /* everything's ok */ - - return true; -} - - -/* memory_mmap_anon ************************************************************ - - Maps anonymous memory, even on systems not defining - MAP_ANON(YMOUS). + Convenience function for mprotect. This function also does error + checking. *******************************************************************************/ -void *memory_mmap_anon(void *addr, size_t len, int prot, int flags) +void memory_mprotect(void *addr, size_t len, int prot) { - void *p; - -#if defined(MAP_ANON) || defined(MAP_ANONYMOUS) - p = mmap(addr, len, prot, -# if defined(MAP_ANON) - MAP_ANON | flags, -# else - MAP_ANONYMOUS | flags, -# endif - -1, 0); -#else - int fd; - - fd = open("/dev/zero", O_RDONLY, 0); - - if (fd == -1) - vm_abort("memory_mmap_anon: open failed: %s", strerror(errno)); - - p = mmap(addr, len, prot, flags, fd, 0); -#endif - -#if defined(MAP_FAILED) - if (p == MAP_FAILED) -#else - if (p == (void *) -1) -#endif - vm_abort("memory_mmap_anon: mmap failed: %s", strerror(errno)); - - return p; + if (os_mprotect(addr, len, prot) != 0) + vm_abort_errno("memory_mprotect: os_mprotect failed"); } @@ -193,11 +82,11 @@ void *memory_mmap_anon(void *addr, size_t len, int prot, int flags) *******************************************************************************/ -static void *memory_checked_alloc(s4 size) +void *memory_checked_alloc(size_t size) { /* always allocate memory zeroed out */ - void *p = calloc(size, 1); + void *p = os_calloc(size, 1); if (p == NULL) vm_abort("memory_checked_alloc: calloc failed: out of memory"); @@ -206,86 +95,7 @@ static void *memory_checked_alloc(s4 size) } -/* memory_cnew ***************************************************************** - - Allocates memory from the heap via mmap and make the memory read-, - write-, and executeable. - -*******************************************************************************/ - -void *memory_cnew(s4 size) -{ - void *p; - - LOCK_MONITOR_ENTER(lock_code_memory); - - size = MEMORY_ALIGN(size, ALIGNSIZE); - - /* check if enough memory is available */ - - if (size > code_memory_size) { - /* set default code size */ - - code_memory_size = DEFAULT_CODE_MEMORY_SIZE; - - /* do we need more? */ - - if (size > code_memory_size) - code_memory_size = size; - - /* align the size of the memory to be allocated */ - - code_memory_size = MEMORY_ALIGN(code_memory_size, pagesize); - -#if defined(ENABLE_STATISTICS) - if (opt_stat) { - codememusage += code_memory_size; - - if (codememusage > maxcodememusage) - maxcodememusage = codememusage; - } -#endif - - /* allocate the memory */ - - p = memory_mmap_anon(NULL, code_memory_size, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE); - - /* set global code memory pointer */ - - code_memory = p; - } - - /* get a memory chunk of the allocated memory */ - - p = code_memory; - - code_memory = (void *) ((ptrint) code_memory + size); - code_memory_size -= size; - - LOCK_MONITOR_EXIT(lock_code_memory); - - return p; -} - - -/* memory_cfree **************************************************************** - - Frees the code memory pointed to. - - ATTENTION: This function currently does NOTHING! Because we don't - have a memory management for code memory. - -*******************************************************************************/ - -void memory_cfree(void *p, s4 size) -{ - /* do nothing */ -} - - -void *mem_alloc(s4 size) +void *mem_alloc(int32_t size) { void *m; @@ -313,7 +123,7 @@ void *mem_alloc(s4 size) } -void *mem_realloc(void *src, s4 len1, s4 len2) +void *mem_realloc(void *src, int32_t len1, int32_t len2) { void *dst; @@ -332,7 +142,7 @@ void *mem_realloc(void *src, s4 len1, s4 len2) #if defined(ENABLE_MEMCHECK) if (len2 < len1) - memset((u1*)dst + len2, MEMORY_CLEAR_BYTE, len1 - len2); + os_memset((u1*)dst + len2, MEMORY_CLEAR_BYTE, len1 - len2); #endif dst = realloc(src, len2); @@ -342,14 +152,14 @@ void *mem_realloc(void *src, s4 len1, s4 len2) #if defined(ENABLE_MEMCHECK) if (len2 > len1) - memset((u1*)dst + len1, MEMORY_CLEAR_BYTE, len2 - len1); + os_memset((u1*)dst + len1, MEMORY_CLEAR_BYTE, len2 - len1); #endif return dst; } -void mem_free(void *m, s4 size) +void mem_free(void *m, int32_t size) { if (!m) { if (size == 0) @@ -366,10 +176,10 @@ void mem_free(void *m, s4 size) #if defined(ENABLE_MEMCHECK) /* destroy the contents */ - memset(m, MEMORY_CLEAR_BYTE, size); + os_memset(m, MEMORY_CLEAR_BYTE, size); #endif - free(m); + os_free(m); } @@ -382,19 +192,42 @@ void mem_free(void *m, s4 size) #if defined(ENABLE_THREADS) && !defined(NDEBUG) static void memory_thread(void) { + int32_t seconds; + + /* Prevent compiler warning. */ + + seconds = 1; + + /* If both arguments are specified, use the value of + ProfileMemoryUsage. */ + + if (opt_ProfileGCMemoryUsage) + seconds = opt_ProfileGCMemoryUsage; + + if (opt_ProfileMemoryUsage) + seconds = opt_ProfileMemoryUsage; + while (true) { - /* sleep thread for 2 seconds */ + /* sleep thread */ - threads_sleep(2 * 1000, 0); + threads_sleep(seconds * 1000, 0); # if defined(ENABLE_STATISTICS) + /* Print current date and time (only when we print to the + stdout). */ + + if (!opt_ProfileMemoryUsageGNUPlot) + statistics_print_date(); + /* print memory usage */ - statistics_print_memory_usage(); + if (opt_ProfileMemoryUsage) + statistics_print_memory_usage(); /* print GC memory usage */ - statistics_print_gc_memory_usage(); + if (opt_ProfileGCMemoryUsage) + statistics_print_gc_memory_usage(); # endif } } @@ -414,15 +247,11 @@ bool memory_start_thread(void) name = utf_new_char("Memory Profiler"); - thread_memory = threads_create_thread(name); + /* start the memory profiling thread */ - if (thread_memory == NULL) + if (!threads_thread_start_internal(name, memory_thread)) return false; - /* actually start the memory profiling thread */ - - threads_start_thread(thread_memory, memory_thread); - /* everything's ok */ return true; @@ -430,370 +259,6 @@ bool memory_start_thread(void) #endif -/* dump_check_canaries ********************************************************* - - Check canaries in dump memory. - - IN: - di...........dumpinfo_t * of the dump area to check - bottomsize...dump size down to which the dump area should be checked - (specify 0 to check the whole dump area) - - ERROR HANDLING: - If any canary has been changed, this function aborts the VM with - an error message. - -*******************************************************************************/ - -#if defined(ENABLE_MEMCHECK) -void dump_check_canaries(dumpinfo_t *di, s4 bottomsize) -{ - dump_allocation_t *da; - u1 *pm; - s4 i, j; - - /* iterate over all dump memory allocations above bottomsize */ - - da = di->allocations; - while (da && da->useddumpsize >= bottomsize) { - /* check canaries */ - - pm = da->mem - MEMORY_CANARY_SIZE; - for (i=0; isize, da->mem); - } - - pm = da->mem + da->size; - for (i=0; isize, da->mem); - } - - da = da->next; - } -} -#endif /* defined(ENABLE_MEMCHECK) */ - - -/* dump_alloc ****************************************************************** - - Allocate memory in the dump area. - - IN: - size.........size of block to allocate, in bytes - may be zero, in which case NULL is returned - - RETURN VALUE: - pointer to allocated memory, or - NULL iff `size` was zero - - ERROR HANDLING: - XXX This function uses `memory_checked_alloc`, which *exits* if no - memory could be allocated. - - THREADS: - dump_alloc is thread safe. Each thread has its own dump memory area. - - dump_alloc is a fast allocator suitable for scratch memory that can be - collectively freed when the current activity (eg. compiling) is done. - - You cannot selectively free dump memory. Before you start allocating it, - you remember the current size returned by `dump_size`. Later, when you no - longer need the memory, call `dump_release` with the remembered size and - all dump memory allocated since the call to `dump_size` will be freed. - -*******************************************************************************/ - -void *dump_alloc(s4 size) -{ -#if defined(DISABLE_DUMP) - - /* use malloc memory for dump memory (for debugging only!) */ - - return mem_alloc(size); - -#else /* !defined(DISABLE_DUMP) */ - - void *m; - dumpinfo_t *di; -#if defined(ENABLE_MEMCHECK) - s4 origsize = size; /* needed for the canary system */ -#endif - - /* If no threads are used, the dumpinfo structure is a static structure */ - /* defined at the top of this file. */ - - di = DUMPINFO; - - if (size == 0) - return NULL; - -#if defined(ENABLE_MEMCHECK) - size += 2*MEMORY_CANARY_SIZE; -#endif - - size = MEMORY_ALIGN(size, ALIGNSIZE); - - if (di->useddumpsize + size > di->allocateddumpsize) { - dumpblock_t *newdumpblock; - s4 newdumpblocksize; - - /* allocate a new dumplist structure */ - - newdumpblock = memory_checked_alloc(sizeof(dumpblock_t)); - - /* If requested size is greater than the default, make the new dump */ - /* block as big as the size requested. Else use the default size. */ - - if (size > DUMPBLOCKSIZE) { - newdumpblocksize = size; - - } else { - newdumpblocksize = DUMPBLOCKSIZE; - } - - /* allocate dumpblock memory */ - - newdumpblock->dumpmem = memory_checked_alloc(newdumpblocksize); - - newdumpblock->prev = di->currentdumpblock; - newdumpblock->size = newdumpblocksize; - di->currentdumpblock = newdumpblock; - - /* Used dump size is previously allocated dump size, because the */ - /* remaining free memory of the previous dump block cannot be used. */ - - di->useddumpsize = di->allocateddumpsize; - - /* increase the allocated dump size by the size of the new dump block */ - - di->allocateddumpsize += newdumpblocksize; - -#if defined(ENABLE_STATISTICS) - /* the amount of globally allocated dump memory (thread save) */ - - if (opt_stat) - globalallocateddumpsize += newdumpblocksize; -#endif - } - - /* current dump block base address + the size of the current dump block - */ - /* the size of the unused memory = new start address */ - - m = di->currentdumpblock->dumpmem + di->currentdumpblock->size - - (di->allocateddumpsize - di->useddumpsize); - -#if defined(ENABLE_MEMCHECK) - { - dump_allocation_t *da = NEW(dump_allocation_t); - s4 i; - u1 *pm; - - /* add the allocation to our linked list of allocations */ - - da->next = di->allocations; - da->mem = (u1*) m + MEMORY_CANARY_SIZE; - da->size = origsize; - da->useddumpsize = di->useddumpsize; - - di->allocations = da; - - /* write the canaries */ - - pm = (u1*)m; - for (i=0; imem + da->size; - for (i=0; isize); - } -#endif /* defined(ENABLE_MEMCHECK) */ - - /* increase used dump size by the allocated memory size */ - - di->useddumpsize += size; - -#if defined(ENABLE_STATISTICS) - if (opt_stat) - if (di->useddumpsize > maxdumpsize) - maxdumpsize = di->useddumpsize; -#endif - - return m; - -#endif /* defined(DISABLE_DUMP) */ -} - - -/* dump_realloc **************************************************************** - - Stupid realloc implementation for dump memory. Avoid, if possible. - -*******************************************************************************/ - -void *dump_realloc(void *src, s4 len1, s4 len2) -{ -#if defined(DISABLE_DUMP) - /* use malloc memory for dump memory (for debugging only!) */ - - return mem_realloc(src, len1, len2); -#else - void *dst = dump_alloc(len2); - - memcpy(dst, src, len1); - -#if defined(ENABLE_MEMCHECK) - /* destroy the source */ - memset(src, MEMORY_CLEAR_BYTE, len1); -#endif - - return dst; -#endif -} - - -/* dump_release **************************************************************** - - Release dump memory above the given size. - - IN: - size........All dump memory above this mark will be freed. Usually - `size` will be the return value of a `dump_size` call - made earlier. - - ERROR HANDLING: - XXX If the given size is invalid, this function *exits* with an - error message. - - See `dump_alloc`. - -*******************************************************************************/ - -void dump_release(s4 size) -{ -#if defined(DISABLE_DUMP) - - /* use malloc memory for dump memory (for debugging only!) */ - - /* do nothing */ - -#else /* !defined(DISABLE_DUMP) */ - - dumpinfo_t *di; - - /* If no threads are used, the dumpinfo structure is a static structure */ - /* defined at the top of this file. */ - - di = DUMPINFO; - - if ((size < 0) || (size > di->useddumpsize)) - vm_abort("Illegal dump release size: %d", size); - -#if defined(ENABLE_MEMCHECK) - { - dump_allocation_t *da, *next; - - /* check canaries */ - - dump_check_canaries(di, size); - - /* iterate over all dump memory allocations about to be released */ - - da = di->allocations; - while (da && da->useddumpsize >= size) { - next = da->next; - - /* invalidate the freed memory */ - - memset(da->mem, MEMORY_CLEAR_BYTE, da->size); - - FREE(da, dump_allocation_t); - - da = next; - } - di->allocations = da; - } -#endif /* defined(ENABLE_MEMCHECK) */ - - /* reset the used dump size to the size specified */ - - di->useddumpsize = size; - - while (di->currentdumpblock && di->allocateddumpsize - di->currentdumpblock->size >= di->useddumpsize) { - dumpblock_t *tmp = di->currentdumpblock; - - di->allocateddumpsize -= tmp->size; - di->currentdumpblock = tmp->prev; - -#if defined(ENABLE_STATISTICS) - /* the amount of globally allocated dump memory (thread save) */ - - if (opt_stat) - globalallocateddumpsize -= tmp->size; -#endif - - /* release the dump memory and the dumpinfo structure */ - - free(tmp->dumpmem); - free(tmp); - } - -#endif /* defined(DISABLE_DUMP) */ -} - - -/* dump_size ******************************************************************* - - Return the current size of the dump memory area. See `dump_alloc`. - -*******************************************************************************/ - -s4 dump_size(void) -{ -#if defined(DISABLE_DUMP) - /* use malloc memory for dump memory (for debugging only!) */ - - return 0; - -#else /* !defined(DISABLE_DUMP) */ - - dumpinfo_t *di; - - /* If no threads are used, the dumpinfo structure is a static structure */ - /* defined at the top of this file. */ - - di = DUMPINFO; - - if (di == NULL) - return 0; - - return di->useddumpsize; - -#endif /* defined(DISABLE_DUMP) */ -} - - /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where