📄 pcsl_memory.c
字号:
/* * * * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program 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 version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. *//** * @file * * PCSL memory functions. * * With these functions, we have the ability to manage our own * memory pool. This avoids memory fragmentation in the overall * system. However, it does not address the potential problem * of memory fragmentation within the PCSL application itself. * * The memory pool is one contiguous chunk of memory split up * into various free or allocated blocks. All blocks have the * same layout. * * <table border=1> * <tr><th scope=col>Contents of the Memory Block</th></tr> * <tr><td>magic (value of 0xCAFE)</td></tr> * <tr><td>free (value of 0 or 1)</td></tr> * <tr><td>reserved/<sup>[*]</sup>guardSize</td></tr> * <tr><td>size</td></tr> * <tr><td><sup>[*]</sup>filename</td></tr> * <tr><td><sup>[*]</sup>lineno</td></tr> * <tr><td>1 .. size</td></tr> * <tr><td><sup>[*]</sup>1 .. guardSize</td></tr> * </table> * * <p>Items that have the prefix <sup>[*]</sup> are only enabled if memory * tracing is enabled. * * @warning This code is not thread safe. */#include <stdio.h>#include <stdarg.h>#include <string.h>#include <pcsl_memory.h>#include <pcsl_print.h>#include <pcsl_memory_port.h>#ifdef PCSL_DEBUG/* * define debug macros and function which use pcsl_print() for output */#define REPORT(msg) report(msg)#define REPORT1(msg, a1) report(msg, a1)#define REPORT2(msg, a1, a2) report(msg, a1, a2)#define REPORT3(msg, a1, a2, a3) report(msg, a1, a2, a3)#define REPORT4(msg, a1, a2, a3, a4) report(msg, a1, a2, a3, a4)/* * maximum lenght of debug output using report methods */#define RPT_BUF_LEN 200/* * buffer for constructing report strings */static char buf[RPT_BUF_LEN];/** * Report a variable argument message via pcsl_print. * * The <code>message</code> parameter is treated as a format * string to the standard C library call printf would be, with * conversion specifications (%s, %d, %c, etc) causing the * conversion and output of each successive argument after * <code>message</code> As with printf, having a conversion * character in <code>message</code> without an associated argument * following it is an error. * * To ensure that no character in <code>message</code> is * interpreted as requiring conversion, a safe way to call * this method is: * <code> report("%s", message); </code> * @param message detail message to go with the report * should not be NULL */static void report(char* message, ...){ va_list ap; if (message != NULL) { va_start(ap, message); #ifdef _WIN32 _vsnprintf(buf, RPT_BUF_LEN, message, ap);#else vsnprintf(buf, RPT_BUF_LEN, message, ap);#endif pcsl_print(buf); va_end(ap); }}/** * An internal helper function used when PCSL_DEBUG is defined. * * print_alloc( what, filename, lineno); */static void print_alloc(const char* what, char* filename, int lineno) { report("alloc: %s at %s line %d\n", what, filename, lineno);}#else /* PCSL_DEBUG is not defined */#define REPORT(msg)#define REPORT1(msg, a1)#define REPORT2(msg, a1, a2)#define REPORT3(msg, a1, a2, a3)#define REPORT4(msg, a1, a2, a3, a4)#endif #ifdef PCSL_DEBUG/** * If you are interested in very verbose output about every block allocated/coalesced/freed you can enable this define * Keep it zero otherwise */#define PCSL_TRACE_MEMORY 0#endif /** * If defined as non-zero, memory allocator will use best-fit algorithm. * If defined as zero, memory allocator will use first-fit algorithm. * * When first-fit algorithm is used, Java heap allocation can fail in SVM mode * even though there is enough free memory in the pool (see CR 6735718). * This is because first-fit allocation cause bad fragmentation for allocation * request patterns typical for SVM mode. */#define PCSL_BEST_FIT_ALLOCATION 1/** * Structure to hold memory blocks */typedef struct _pcslMemStruct { unsigned short magic; /* magic number */ char free; /* 1 == block is free, 0 == block is used */#ifdef PCSL_DEBUG char guardSize; /* Size of tail guard data; in bytes */#else char reserved;#endif unsigned int size; /* size of block */#ifdef PCSL_DEBUG char* filename; /* filename where allocation took place */ unsigned int lineno; /* line number wehre allocation took place */ unsigned int guard; /* memory guard */#endif} _PcslMemHdr, *_PcslMemHdrPtr;/* * Default size of pool usable for allocations; in bytes */#define DEFAULT_POOL_SIZE (8024*1024)/* * Byte boundary for word alignment */#define ALIGNMENT 0x00000003 /* Assumes word is 4-bytes *//* * Constant to verify a header's validity */#define MAGIC 0xCAFE/* * Constants to guard memory */#define GUARD_WORD 0x9A9A9A9A /* Assumes word is 4-bytes */#define GUARD_BYTE 0x9A/* * Minimum number of guard bytes to put at end of the memory block */#define GUARD_SIZE 4#ifdef PCSL_MEMORY_USE_STATIC/* Cannot allocate dynamic memory on the phone. Use static array. */static char PcslMemory[DEFAULT_POOL_SIZE]; /* Where PCSL memory starts */#else /* use malloc or similar function provided */static char* PcslMemory; /* Where PCSL memory starts */#endifstatic char* PcslMemoryStart; /* Aligned start of PCSL memory */static char* PcslMemoryEnd; /* End of memory */static int PcslMemoryHighWaterMark;static int PcslMemoryAllocated;static int pcsl_end_memory(int* count, int* size);static int verify_tail_guard_data(_PcslMemHdrPtr pcslMemoryHdr);/** * @internal * * FUNCTION: pcsl_end_memory() * TYPE: private operation * OVERVIEW: Finalize the PCSL memory pool * INTERFACE: * parameters: count address to store memory leak count * size address to store totol bytes of memory leaked * returns: the number of memory leaks detected * */static intpcsl_end_memory(int* count, int* size) { _PcslMemHdrPtr pcslMemoryHdr; char* pcslMemoryPtr; *count = 0; *size = 0; for (pcslMemoryPtr = PcslMemoryStart; pcslMemoryPtr < PcslMemoryEnd; pcslMemoryPtr += pcslMemoryHdr->size + sizeof(_PcslMemHdr)) { pcslMemoryHdr = (_PcslMemHdrPtr)pcslMemoryPtr; if (pcslMemoryHdr->magic != MAGIC) { REPORT1("ERROR: Corrupted start of memory header: 0x%p\n", pcslMemoryPtr); return -1; }#ifdef PCSL_DEBUG if (pcslMemoryHdr->guard != GUARD_WORD) { report("ERROR: Corrupted end of memory header: 0x%p\n", pcslMemoryPtr); return -1; } /* The memory block header is valid, now check the guard data */ if (verify_tail_guard_data(pcslMemoryHdr)) { report("ERROR: Memory overrun: 0x%p\n", pcslMemoryPtr); print_alloc("allocated", pcslMemoryHdr->filename, pcslMemoryHdr->lineno); }#endif if (pcslMemoryHdr->free != 1) {#ifdef PCSL_DEBUG report("WARNING: memory leak: size= %d address= 0x%p\n", pcslMemoryHdr->size, (void*)((char*)pcslMemoryHdr + sizeof(_PcslMemHdr))); print_alloc("allocated", pcslMemoryHdr->filename, pcslMemoryHdr->lineno);#endif pcsl_mem_free((void*)((char*)pcslMemoryHdr + sizeof(_PcslMemHdr))); *count += 1; *size += pcslMemoryHdr->size; } } return *count;}/** * FUNCTION: pcsl_mem_initialize_impl0() * TYPE: public operation * OVERVIEW: Initialize the PCSL memory pool * NOTE: This must only be called once * INTERFACE: * parameters: * startAddr Starting address of memory pool. If NULL, it will * be either dynamically or statically allocated. * size Size of memory pool to use; if size is <= 0, * the default memory pool size will be used * returns: 0 on succes; != 0 on failure * */intpcsl_mem_initialize_impl0(void *startAddr, int size) { _PcslMemHdrPtr pcslMemoryHdr; if (PcslMemoryStart != NULL) { /* avoid a double init */ return 0; } if (size <= 0) { /* size not specified, use the default */ size = DEFAULT_POOL_SIZE; } if (startAddr != NULL) { PcslMemory = (char *)startAddr; } else { #ifndef PCSL_MEMORY_USE_STATIC /* allocate the chunk of memory to C heap */ PcslMemory = (char*)pcsl_heap_allocate_port(size,&size); if (PcslMemory == NULL) { return -1; }#endif /* ! PCSL_MEMORY_USE_STATIC */ } PcslMemoryStart = PcslMemory; PcslMemoryEnd = PcslMemory + size - sizeof(_PcslMemHdr); /* Word alignment */ while (((long)PcslMemoryStart & ALIGNMENT) != 0) { PcslMemoryStart++; } pcslMemoryHdr = (_PcslMemHdrPtr)PcslMemoryStart; pcslMemoryHdr->magic = MAGIC; pcslMemoryHdr->free = 1; pcslMemoryHdr->size = (PcslMemory - PcslMemoryStart) + size - sizeof(_PcslMemHdr);#ifdef PCSL_DEBUG pcslMemoryHdr->guard = GUARD_WORD; pcslMemoryHdr->guardSize = 0;#endif return 0;}/** * FUNCTION: pcsl_mem_finalize_impl0() * TYPE: public operation * OVERVIEW: Finalize the PCSL memory pool * INTERFACE: * parameters: <none> * returns: <nothing> * */voidpcsl_mem_finalize_impl0() { int count, size, ret; ret = pcsl_end_memory(&count, &size);#ifdef PCSL_DEBUG if (ret > 0) { report("WARNING: %d memory leak(s); %d bytes!\n", count, size); } report("** Total memory: %d\n** Highwater mark:%d", pcsl_mem_get_total_heap_impl0(), PcslMemoryHighWaterMark);#endif #ifndef PCSL_MEMORY_USE_STATIC pcsl_heap_deallocate_port(PcslMemory); PcslMemory = NULL;#endif PcslMemoryStart = NULL; PcslMemoryEnd = NULL;}/** * FUNCTION: pcsl_mem_malloc_impl0() * TYPE: public operation * OVERVIEW: Allocate memory from the private PCSL memory pool * INTERFACE: * parameters: size Number of byte to allocate * filename Filename where allocation occured * lineno Line number where allocation occured * returns: pointer to the newly allocated memory * */#ifdef PCSL_DEBUGvoid*pcsl_mem_malloc_impl0(unsigned int size, char* filename, int lineno) {#elsevoid*pcsl_mem_malloc_impl0(unsigned int size) {#endif unsigned int numBytesToAllocate = size; void* loc = NULL; _PcslMemHdrPtr tempHdr = NULL; char* temp = NULL; char* pcslMemoryPtr; _PcslMemHdrPtr pcslMemoryHdr; _PcslMemHdrPtr fitBlockHdr = NULL;#ifdef PCSL_DEBUG int guardSize = 0; void* guardPos = NULL; int i = 0; numBytesToAllocate += GUARD_SIZE;#endif while ( (numBytesToAllocate & ALIGNMENT) != 0 ) { numBytesToAllocate++; } /* find a free slot */ for (pcslMemoryPtr = PcslMemoryStart; pcslMemoryPtr < PcslMemoryEnd; pcslMemoryPtr += pcslMemoryHdr->size + sizeof(_PcslMemHdr)) { pcslMemoryHdr = (_PcslMemHdrPtr)pcslMemoryPtr; if (pcslMemoryHdr->magic != MAGIC) { REPORT1("ERROR: Memory corruption at 0x%p\n", pcslMemoryPtr); return((void *) 0); } else { while ( 1 ) { /* coalescing */ if (pcslMemoryHdr->free == 1) { /* if current block is free */ temp = (char*)pcslMemoryHdr; temp += pcslMemoryHdr->size + sizeof(_PcslMemHdr); tempHdr = (_PcslMemHdrPtr)temp; if ((temp < PcslMemoryEnd) && (tempHdr->free == 1) && (tempHdr->magic == MAGIC)) { /* and the next block is free too */ /* then coalesce */ pcslMemoryHdr->size += tempHdr->size + sizeof(_PcslMemHdr);#ifdef PCSL_DEBUG pcslMemoryHdr->guardSize = 0;#if PCSL_TRACE_MEMORY REPORT2("DEBUG: Coalescing blocks 0x%p and 0x%p\n", pcslMemoryHdr, tempHdr);#endif #endif } else { break; } } else { break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -