1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/common/cmemory.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,183 @@ 1.4 +/* 1.5 +****************************************************************************** 1.6 +* 1.7 +* Copyright (C) 2002-2012, International Business Machines 1.8 +* Corporation and others. All Rights Reserved. 1.9 +* 1.10 +****************************************************************************** 1.11 +* 1.12 +* File cmemory.c ICU Heap allocation. 1.13 +* All ICU heap allocation, both for C and C++ new of ICU 1.14 +* class types, comes through these functions. 1.15 +* 1.16 +* If you have a need to replace ICU allocation, this is the 1.17 +* place to do it. 1.18 +* 1.19 +* Note that uprv_malloc(0) returns a non-NULL pointer, and 1.20 +* that a subsequent free of that pointer value is a NOP. 1.21 +* 1.22 +****************************************************************************** 1.23 +*/ 1.24 +#include "unicode/uclean.h" 1.25 +#include "cmemory.h" 1.26 +#include "putilimp.h" 1.27 +#include "uassert.h" 1.28 +#include <stdlib.h> 1.29 + 1.30 +/* uprv_malloc(0) returns a pointer to this read-only data. */ 1.31 +static const int32_t zeroMem[] = {0, 0, 0, 0, 0, 0}; 1.32 + 1.33 +/* Function Pointers for user-supplied heap functions */ 1.34 +static const void *pContext; 1.35 +static UMemAllocFn *pAlloc; 1.36 +static UMemReallocFn *pRealloc; 1.37 +static UMemFreeFn *pFree; 1.38 + 1.39 +/* Flag indicating whether any heap allocations have happened. 1.40 + * Used to prevent changing out the heap functions after allocations have been made */ 1.41 +static UBool gHeapInUse; 1.42 + 1.43 +#if U_DEBUG && defined(UPRV_MALLOC_COUNT) 1.44 +#include <stdio.h> 1.45 +static int n=0; 1.46 +static long b=0; 1.47 +#endif 1.48 + 1.49 +#if U_DEBUG 1.50 + 1.51 +static char gValidMemorySink = 0; 1.52 + 1.53 +U_CAPI void uprv_checkValidMemory(const void *p, size_t n) { 1.54 + /* 1.55 + * Access the memory to ensure that it's all valid. 1.56 + * Load and save a computed value to try to ensure that the compiler 1.57 + * does not throw away the whole loop. 1.58 + * A thread analyzer might complain about un-mutexed access to gValidMemorySink 1.59 + * which is true but harmless because no one ever uses the value in gValidMemorySink. 1.60 + */ 1.61 + const char *s = (const char *)p; 1.62 + char c = gValidMemorySink; 1.63 + size_t i; 1.64 + U_ASSERT(p != NULL); 1.65 + for(i = 0; i < n; ++i) { 1.66 + c ^= s[i]; 1.67 + } 1.68 + gValidMemorySink = c; 1.69 +} 1.70 + 1.71 +#endif /* U_DEBUG */ 1.72 + 1.73 +U_CAPI void * U_EXPORT2 1.74 +uprv_malloc(size_t s) { 1.75 +#if U_DEBUG && defined(UPRV_MALLOC_COUNT) 1.76 +#if 1 1.77 + putchar('>'); 1.78 + fflush(stdout); 1.79 +#else 1.80 + fprintf(stderr,"MALLOC\t#%d\t%ul bytes\t%ul total\n", ++n,s,(b+=s)); fflush(stderr); 1.81 +#endif 1.82 +#endif 1.83 + if (s > 0) { 1.84 + gHeapInUse = TRUE; 1.85 + if (pAlloc) { 1.86 + return (*pAlloc)(pContext, s); 1.87 + } else { 1.88 + return uprv_default_malloc(s); 1.89 + } 1.90 + } else { 1.91 + return (void *)zeroMem; 1.92 + } 1.93 +} 1.94 + 1.95 +U_CAPI void * U_EXPORT2 1.96 +uprv_realloc(void * buffer, size_t size) { 1.97 +#if U_DEBUG && defined(UPRV_MALLOC_COUNT) 1.98 + putchar('~'); 1.99 + fflush(stdout); 1.100 +#endif 1.101 + if (buffer == zeroMem) { 1.102 + return uprv_malloc(size); 1.103 + } else if (size == 0) { 1.104 + if (pFree) { 1.105 + (*pFree)(pContext, buffer); 1.106 + } else { 1.107 + uprv_default_free(buffer); 1.108 + } 1.109 + return (void *)zeroMem; 1.110 + } else { 1.111 + gHeapInUse = TRUE; 1.112 + if (pRealloc) { 1.113 + return (*pRealloc)(pContext, buffer, size); 1.114 + } else { 1.115 + return uprv_default_realloc(buffer, size); 1.116 + } 1.117 + } 1.118 +} 1.119 + 1.120 +U_CAPI void U_EXPORT2 1.121 +uprv_free(void *buffer) { 1.122 +#if U_DEBUG && defined(UPRV_MALLOC_COUNT) 1.123 + putchar('<'); 1.124 + fflush(stdout); 1.125 +#endif 1.126 + if (buffer != zeroMem) { 1.127 + if (pFree) { 1.128 + (*pFree)(pContext, buffer); 1.129 + } else { 1.130 + uprv_default_free(buffer); 1.131 + } 1.132 + } 1.133 +} 1.134 + 1.135 +U_CAPI void * U_EXPORT2 1.136 +uprv_calloc(size_t num, size_t size) { 1.137 + void *mem = NULL; 1.138 + size *= num; 1.139 + mem = uprv_malloc(size); 1.140 + if (mem) { 1.141 + uprv_memset(mem, 0, size); 1.142 + } 1.143 + return mem; 1.144 +} 1.145 + 1.146 +U_CAPI void U_EXPORT2 1.147 +u_setMemoryFunctions(const void *context, UMemAllocFn *a, UMemReallocFn *r, UMemFreeFn *f, UErrorCode *status) 1.148 +{ 1.149 + if (U_FAILURE(*status)) { 1.150 + return; 1.151 + } 1.152 + if (a==NULL || r==NULL || f==NULL) { 1.153 + *status = U_ILLEGAL_ARGUMENT_ERROR; 1.154 + return; 1.155 + } 1.156 + if (gHeapInUse) { 1.157 + *status = U_INVALID_STATE_ERROR; 1.158 + return; 1.159 + } 1.160 + pContext = context; 1.161 + pAlloc = a; 1.162 + pRealloc = r; 1.163 + pFree = f; 1.164 +} 1.165 + 1.166 + 1.167 +U_CFUNC UBool cmemory_cleanup(void) { 1.168 + pContext = NULL; 1.169 + pAlloc = NULL; 1.170 + pRealloc = NULL; 1.171 + pFree = NULL; 1.172 + gHeapInUse = FALSE; 1.173 + return TRUE; 1.174 +} 1.175 + 1.176 + 1.177 +/* 1.178 + * gHeapInUse 1.179 + * Return True if ICU has allocated any memory. 1.180 + * Used by u_SetMutexFunctions() and similar to verify that ICU has not 1.181 + * been used, that it is in a pristine initial state. 1.182 + */ 1.183 +U_CFUNC UBool cmemory_inUse() { 1.184 + return gHeapInUse; 1.185 +} 1.186 +