16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* 26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org****************************************************************************** 36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* 46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Copyright (C) 2002-2012, International Business Machines 56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Corporation and others. All Rights Reserved. 66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* 76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org****************************************************************************** 86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* 96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* File cmemory.c ICU Heap allocation. 106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* All ICU heap allocation, both for C and C++ new of ICU 116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* class types, comes through these functions. 126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* 136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* If you have a need to replace ICU allocation, this is the 146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* place to do it. 156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* 166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Note that uprv_malloc(0) returns a non-NULL pointer, and 176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* that a subsequent free of that pointer value is a NOP. 186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* 196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org****************************************************************************** 206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/ 216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/uclean.h" 226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cmemory.h" 236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "putilimp.h" 246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uassert.h" 256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <stdlib.h> 266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* uprv_malloc(0) returns a pointer to this read-only data. */ 286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const int32_t zeroMem[] = {0, 0, 0, 0, 0, 0}; 296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* Function Pointers for user-supplied heap functions */ 316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const void *pContext; 326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UMemAllocFn *pAlloc; 336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UMemReallocFn *pRealloc; 346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UMemFreeFn *pFree; 356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* Flag indicating whether any heap allocations have happened. 376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Used to prevent changing out the heap functions after allocations have been made */ 386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool gHeapInUse; 396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if U_DEBUG && defined(UPRV_MALLOC_COUNT) 416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <stdio.h> 426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic int n=0; 436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic long b=0; 446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif 456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if U_DEBUG 476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic char gValidMemorySink = 0; 496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void uprv_checkValidMemory(const void *p, size_t n) { 516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org /* 526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Access the memory to ensure that it's all valid. 536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Load and save a computed value to try to ensure that the compiler 546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * does not throw away the whole loop. 556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * A thread analyzer might complain about un-mutexed access to gValidMemorySink 566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * which is true but harmless because no one ever uses the value in gValidMemorySink. 576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */ 586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org const char *s = (const char *)p; 596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org char c = gValidMemorySink; 606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org size_t i; 616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org U_ASSERT(p != NULL); 626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org for(i = 0; i < n; ++i) { 636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org c ^= s[i]; 646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org gValidMemorySink = c; 666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif /* U_DEBUG */ 696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void * U_EXPORT2 716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orguprv_malloc(size_t s) { 726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if U_DEBUG && defined(UPRV_MALLOC_COUNT) 736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if 1 746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org putchar('>'); 756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org fflush(stdout); 766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#else 776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org fprintf(stderr,"MALLOC\t#%d\t%ul bytes\t%ul total\n", ++n,s,(b+=s)); fflush(stderr); 786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif 796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif 806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (s > 0) { 816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org gHeapInUse = TRUE; 826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (pAlloc) { 836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return (*pAlloc)(pContext, s); 846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } else { 856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return uprv_default_malloc(s); 866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } else { 886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return (void *)zeroMem; 896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void * U_EXPORT2 936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orguprv_realloc(void * buffer, size_t size) { 946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if U_DEBUG && defined(UPRV_MALLOC_COUNT) 956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org putchar('~'); 966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org fflush(stdout); 976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif 986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (buffer == zeroMem) { 996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return uprv_malloc(size); 1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } else if (size == 0) { 1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (pFree) { 1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org (*pFree)(pContext, buffer); 1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } else { 1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org uprv_default_free(buffer); 1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return (void *)zeroMem; 1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } else { 1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org gHeapInUse = TRUE; 1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (pRealloc) { 1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return (*pRealloc)(pContext, buffer, size); 1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } else { 1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return uprv_default_realloc(buffer, size); 1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void U_EXPORT2 1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orguprv_free(void *buffer) { 1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if U_DEBUG && defined(UPRV_MALLOC_COUNT) 1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org putchar('<'); 1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org fflush(stdout); 1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif 1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (buffer != zeroMem) { 1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (pFree) { 1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org (*pFree)(pContext, buffer); 1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } else { 1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org uprv_default_free(buffer); 1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void * U_EXPORT2 1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orguprv_calloc(size_t num, size_t size) { 1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org void *mem = NULL; 1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org size *= num; 1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org mem = uprv_malloc(size); 1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (mem) { 1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org uprv_memset(mem, 0, size); 1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return mem; 1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CAPI void U_EXPORT2 1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgu_setMemoryFunctions(const void *context, UMemAllocFn *a, UMemReallocFn *r, UMemFreeFn *f, UErrorCode *status) 1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{ 1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (U_FAILURE(*status)) { 1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return; 1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (a==NULL || r==NULL || f==NULL) { 1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *status = U_ILLEGAL_ARGUMENT_ERROR; 1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return; 1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org if (gHeapInUse) { 1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org *status = U_INVALID_STATE_ERROR; 1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return; 1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org } 1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org pContext = context; 1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org pAlloc = a; 1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org pRealloc = r; 1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org pFree = f; 1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC UBool cmemory_cleanup(void) { 1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org pContext = NULL; 1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org pAlloc = NULL; 1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org pRealloc = NULL; 1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org pFree = NULL; 1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org gHeapInUse = FALSE; 1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return TRUE; 1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* 1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * gHeapInUse 1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Return True if ICU has allocated any memory. 1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Used by u_SetMutexFunctions() and similar to verify that ICU has not 1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * been used, that it is in a pristine initial state. 1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */ 1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_CFUNC UBool cmemory_inUse() { 1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org return gHeapInUse; 1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org} 1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 184