15f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian// Copyright (c) 2005, 2007, Google Inc. 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Redistribution and use in source and binary forms, with or without 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// modification, are permitted provided that the following conditions are 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// met: 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// * Redistributions of source code must retain the above copyright 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// notice, this list of conditions and the following disclaimer. 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// * Redistributions in binary form must reproduce the above 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// copyright notice, this list of conditions and the following disclaimer 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// in the documentation and/or other materials provided with the 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// distribution. 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// * Neither the name of Google Inc. nor the names of its 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// contributors may be used to endorse or promote products derived from 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// this software without specific prior written permission. 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// --- 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Author: Sanjay Ghemawat 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#if !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC) 350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "TCSystemAlloc.h" 360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <algorithm> 380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "Assertions.h" 390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "TCSpinLock.h" 400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "UnusedParam.h" 41dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "VMTags.h" 420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if HAVE(STDINT_H) 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <stdint.h> 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#elif HAVE(INTTYPES_H) 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <inttypes.h> 478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <sys/types.h> 498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 51d0825bca7fe65beaee391d30da42e937db621564Steve Block#if OS(WINDOWS) 528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "windows.h" 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else 548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <errno.h> 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <unistd.h> 568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <sys/mman.h> 578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef MAP_ANONYMOUS 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define MAP_ANONYMOUS MAP_ANON 618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochusing namespace std; 640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Structure for discovering alignment 668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectunion MemoryAligner { 678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project void* p; 688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project double d; 698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t s; 708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}; 718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic SpinLock spinlock = SPINLOCK_INITIALIZER; 738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Page size is initialized on demand 758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic size_t pagesize = 0; 768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Configuration parameters. 788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// if use_devmem is true, either use_sbrk or use_mmap must also be true. 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// For 2.2 kernels, it looks like the sbrk address space (500MBish) and 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// the mmap address space (1300MBish) are disjoint, so we need both allocators 828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// to get as much virtual memory as possible. 838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef WTF_CHANGES 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool use_devmem = false; 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if HAVE(SBRK) 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool use_sbrk = false; 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if HAVE(MMAP) 928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool use_mmap = true; 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if HAVE(VIRTUALALLOC) 968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool use_VirtualAlloc = true; 978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Flags to keep us from retrying allocators that failed. 1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool devmem_failure = false; 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool sbrk_failure = false; 1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool mmap_failure = false; 1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool VirtualAlloc_failure = false; 1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef WTF_CHANGES 1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectDEFINE_int32(malloc_devmem_start, 0, 1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project "Physical memory starting location in MB for /dev/mem allocation." 1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project " Setting this to 0 disables /dev/mem allocation"); 1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectDEFINE_int32(malloc_devmem_limit, 0, 1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project "Physical memory limit location in MB for /dev/mem allocation." 1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project " Setting this to 0 means no limit."); 1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else 1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const int32_t FLAGS_malloc_devmem_start = 0; 1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const int32_t FLAGS_malloc_devmem_limit = 0; 1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if HAVE(SBRK) 1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void* TrySbrk(size_t size, size_t *actual_size, size_t alignment) { 1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size = ((size + alignment - 1) / alignment) * alignment; 1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // could theoretically return the "extra" bytes here, but this 1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // is simple and correct. 1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (actual_size) 1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *actual_size = size; 1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project void* result = sbrk(size); 1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (result == reinterpret_cast<void*>(-1)) { 1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project sbrk_failure = true; 1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NULL; 1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Is it aligned? 1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project uintptr_t ptr = reinterpret_cast<uintptr_t>(result); 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ((ptr & (alignment-1)) == 0) return result; 1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Try to get more memory for alignment 1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t extra = alignment - (ptr & (alignment-1)); 1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project void* r2 = sbrk(extra); 1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (reinterpret_cast<uintptr_t>(r2) == (ptr + size)) { 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Contiguous with previous result 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return reinterpret_cast<void*>(ptr + extra); 1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Give up and ask for "size + alignment - 1" bytes so 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // that we can find an aligned region within it. 1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project result = sbrk(size + alignment - 1); 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (result == reinterpret_cast<void*>(-1)) { 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project sbrk_failure = true; 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NULL; 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ptr = reinterpret_cast<uintptr_t>(result); 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ((ptr & (alignment-1)) != 0) { 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ptr += alignment - (ptr & (alignment-1)); 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return reinterpret_cast<void*>(ptr); 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif /* HAVE(SBRK) */ 1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if HAVE(MMAP) 1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void* TryMmap(size_t size, size_t *actual_size, size_t alignment) { 1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Enforce page alignment 1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (pagesize == 0) pagesize = getpagesize(); 1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (alignment < pagesize) alignment = pagesize; 1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size = ((size + alignment - 1) / alignment) * alignment; 1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // could theoretically return the "extra" bytes here, but this 1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // is simple and correct. 1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (actual_size) 1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *actual_size = size; 1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Ask for extra memory if alignment > pagesize 1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t extra = 0; 1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (alignment > pagesize) { 1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project extra = alignment - pagesize; 1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project void* result = mmap(NULL, size + extra, 180635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project PROT_READ | PROT_WRITE, 1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project MAP_PRIVATE|MAP_ANONYMOUS, 182dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block VM_TAG_FOR_TCMALLOC_MEMORY, 0); 1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (result == reinterpret_cast<void*>(MAP_FAILED)) { 1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project mmap_failure = true; 1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NULL; 1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Adjust the return memory so it is aligned 1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project uintptr_t ptr = reinterpret_cast<uintptr_t>(result); 1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t adjust = 0; 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ((ptr & (alignment - 1)) != 0) { 1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project adjust = alignment - (ptr & (alignment - 1)); 1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Return the unused memory to the system 1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (adjust > 0) { 1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project munmap(reinterpret_cast<void*>(ptr), adjust); 1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (adjust < extra) { 2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project munmap(reinterpret_cast<void*>(ptr + adjust + size), extra - adjust); 2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ptr += adjust; 2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return reinterpret_cast<void*>(ptr); 2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif /* HAVE(MMAP) */ 2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if HAVE(VIRTUALALLOC) 2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void* TryVirtualAlloc(size_t size, size_t *actual_size, size_t alignment) { 2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Enforce page alignment 2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (pagesize == 0) { 2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SYSTEM_INFO system_info; 2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project GetSystemInfo(&system_info); 2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project pagesize = system_info.dwPageSize; 2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (alignment < pagesize) alignment = pagesize; 2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size = ((size + alignment - 1) / alignment) * alignment; 2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // could theoretically return the "extra" bytes here, but this 2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // is simple and correct. 2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (actual_size) 2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *actual_size = size; 2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Ask for extra memory if alignment > pagesize 2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t extra = 0; 2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (alignment > pagesize) { 2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project extra = alignment - pagesize; 2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project void* result = VirtualAlloc(NULL, size + extra, 2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, 234635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project PAGE_READWRITE); 2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (result == NULL) { 2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VirtualAlloc_failure = true; 2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NULL; 2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Adjust the return memory so it is aligned 2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project uintptr_t ptr = reinterpret_cast<uintptr_t>(result); 2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t adjust = 0; 2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ((ptr & (alignment - 1)) != 0) { 2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project adjust = alignment - (ptr & (alignment - 1)); 2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Return the unused memory to the system - we'd like to release but the best we can do 2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // is decommit, since Windows only lets you free the whole allocation. 2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (adjust > 0) { 2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VirtualFree(reinterpret_cast<void*>(ptr), adjust, MEM_DECOMMIT); 2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (adjust < extra) { 2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VirtualFree(reinterpret_cast<void*>(ptr + adjust + size), extra-adjust, MEM_DECOMMIT); 2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ptr += adjust; 2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return reinterpret_cast<void*>(ptr); 2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif /* HAVE(MMAP) */ 2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef WTF_CHANGES 2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void* TryDevMem(size_t size, size_t *actual_size, size_t alignment) { 2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static bool initialized = false; 2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static off_t physmem_base; // next physical memory address to allocate 2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static off_t physmem_limit; // maximum physical address allowed 2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project static int physmem_fd; // file descriptor for /dev/mem 2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Check if we should use /dev/mem allocation. Note that it may take 2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // a while to get this flag initialized, so meanwhile we fall back to 2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // the next allocator. (It looks like 7MB gets allocated before 2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // this flag gets initialized -khr.) 2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (FLAGS_malloc_devmem_start == 0) { 2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // NOTE: not a devmem_failure - we'd like TCMalloc_SystemAlloc to 2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // try us again next time. 2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NULL; 2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!initialized) { 2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project physmem_fd = open("/dev/mem", O_RDWR); 2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (physmem_fd < 0) { 2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project devmem_failure = true; 2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NULL; 2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project physmem_base = FLAGS_malloc_devmem_start*1024LL*1024LL; 2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project physmem_limit = FLAGS_malloc_devmem_limit*1024LL*1024LL; 2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project initialized = true; 2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Enforce page alignment 2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (pagesize == 0) pagesize = getpagesize(); 2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (alignment < pagesize) alignment = pagesize; 2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size = ((size + alignment - 1) / alignment) * alignment; 2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // could theoretically return the "extra" bytes here, but this 2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // is simple and correct. 2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (actual_size) 2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *actual_size = size; 3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Ask for extra memory if alignment > pagesize 3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t extra = 0; 3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (alignment > pagesize) { 3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project extra = alignment - pagesize; 3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // check to see if we have any memory left 3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (physmem_limit != 0 && physmem_base + size + extra > physmem_limit) { 3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project devmem_failure = true; 3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NULL; 3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 312635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project void *result = mmap(0, size + extra, PROT_READ | PROT_WRITE, 3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project MAP_SHARED, physmem_fd, physmem_base); 3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (result == reinterpret_cast<void*>(MAP_FAILED)) { 3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project devmem_failure = true; 3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NULL; 3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project uintptr_t ptr = reinterpret_cast<uintptr_t>(result); 3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Adjust the return memory so it is aligned 3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t adjust = 0; 3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if ((ptr & (alignment - 1)) != 0) { 3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project adjust = alignment - (ptr & (alignment - 1)); 3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Return the unused virtual memory to the system 3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (adjust > 0) { 3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project munmap(reinterpret_cast<void*>(ptr), adjust); 3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (adjust < extra) { 3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project munmap(reinterpret_cast<void*>(ptr + adjust + size), extra - adjust); 3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ptr += adjust; 3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project physmem_base += adjust + size; 3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return reinterpret_cast<void*>(ptr); 3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid* TCMalloc_SystemAlloc(size_t size, size_t *actual_size, size_t alignment) { 3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Discard requests that overflow 3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (size + alignment < size) return NULL; 3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project SpinLockHolder lock_holder(&spinlock); 3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Enforce minimum alignment 3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (alignment < sizeof(MemoryAligner)) alignment = sizeof(MemoryAligner); 3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Try twice, once avoiding allocators that failed before, and once 3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // more trying all allocators even if they failed before. 3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project for (int i = 0; i < 2; i++) { 3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef WTF_CHANGES 3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (use_devmem && !devmem_failure) { 3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project void* result = TryDevMem(size, actual_size, alignment); 3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (result != NULL) return result; 3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if HAVE(SBRK) 3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (use_sbrk && !sbrk_failure) { 3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project void* result = TrySbrk(size, actual_size, alignment); 3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (result != NULL) return result; 3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if HAVE(MMAP) 3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (use_mmap && !mmap_failure) { 3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project void* result = TryMmap(size, actual_size, alignment); 3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (result != NULL) return result; 3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if HAVE(VIRTUALALLOC) 3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (use_VirtualAlloc && !VirtualAlloc_failure) { 3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project void* result = TryVirtualAlloc(size, actual_size, alignment); 3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (result != NULL) return result; 3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // nothing worked - reset failure flags and try again 3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project devmem_failure = false; 3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project sbrk_failure = false; 3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project mmap_failure = false; 3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project VirtualAlloc_failure = false; 3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return NULL; 3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 3918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#if HAVE(MADV_FREE_REUSE) 3928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid TCMalloc_SystemRelease(void* start, size_t length) 3948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 3958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian while (madvise(start, length, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { } 3968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 3978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 3985f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#elif HAVE(MADV_FREE) || HAVE(MADV_DONTNEED) 3998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid TCMalloc_SystemRelease(void* start, size_t length) 4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // MADV_FREE clears the modified bit on pages, which allows 4035f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian // them to be discarded immediately. 4045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#if HAVE(MADV_FREE) 4055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian const int advice = MADV_FREE; 4065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#else 4075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian const int advice = MADV_DONTNEED; 4085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#endif 4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (FLAGS_malloc_devmem_start) { 4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // It's not safe to use MADV_DONTNEED if we've been mapping 4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // /dev/mem for heap memory 4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return; 4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (pagesize == 0) pagesize = getpagesize(); 4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project const size_t pagemask = pagesize - 1; 4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t new_start = reinterpret_cast<size_t>(start); 4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t end = new_start + length; 4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project size_t new_end = end; 4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Round up the starting address and round down the ending address 4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // to be page aligned: 4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project new_start = (new_start + pagesize - 1) & ~pagemask; 4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project new_end = new_end & ~pagemask; 4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT((new_start & pagemask) == 0); 4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT((new_end & pagemask) == 0); 4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(new_start >= reinterpret_cast<size_t>(start)); 4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project ASSERT(new_end <= end); 4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (new_end > new_start) { 4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // Note -- ignoring most return codes, because if this fails it 4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // doesn't matter... 4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project while (madvise(reinterpret_cast<char*>(new_start), new_end - new_start, 4355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian advice) == -1 && 4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project errno == EAGAIN) { 4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // NOP 4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 4408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#elif HAVE(MMAP) 4438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid TCMalloc_SystemRelease(void* start, size_t length) 4458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 446635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project void* newAddress = mmap(start, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); 4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project // If the mmap failed then that's ok, we just won't return the memory to the system. 448635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project ASSERT_UNUSED(newAddress, newAddress == start || newAddress == reinterpret_cast<void*>(MAP_FAILED)); 4498f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} 4508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#elif HAVE(VIRTUALALLOC) 4520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid TCMalloc_SystemRelease(void* start, size_t length) 4540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{ 4550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (VirtualFree(start, length, MEM_DECOMMIT)) 4560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return; 4570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // The decommit may fail if the memory region consists of allocations 4590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // from more than one call to VirtualAlloc. In this case, fall back to 4600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // using VirtualQuery to retrieve the allocation boundaries and decommit 4610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // them each individually. 4620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch char* ptr = static_cast<char*>(start); 4640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch char* end = ptr + length; 4650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch MEMORY_BASIC_INFORMATION info; 4660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while (ptr < end) { 4670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch size_t resultSize = VirtualQuery(ptr, &info, sizeof(info)); 4680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT_UNUSED(resultSize, resultSize == sizeof(info)); 4690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch size_t decommitSize = min<size_t>(info.RegionSize, end - ptr); 4710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch BOOL success = VirtualFree(ptr, decommitSize, MEM_DECOMMIT); 4720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT_UNUSED(success, success); 4730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ptr += decommitSize; 4740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 4750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch} 4760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#else 4788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Platforms that don't support returning memory use an empty inline version of TCMalloc_SystemRelease 4808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// declared in TCSystemAlloc.h 481635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project 482635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif 4838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#if HAVE(MADV_FREE_REUSE) 4858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid TCMalloc_SystemCommit(void* start, size_t length) 4878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{ 4888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian while (madvise(start, length, MADV_FREE_REUSE) == -1 && errno == EAGAIN) { } 4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 4918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#elif HAVE(VIRTUALALLOC) 4928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 4930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid TCMalloc_SystemCommit(void* start, size_t length) 4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 4950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (VirtualAlloc(start, length, MEM_COMMIT, PAGE_READWRITE) == start) 4960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch return; 4970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 4980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // The commit may fail if the memory region consists of allocations 4990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // from more than one call to VirtualAlloc. In this case, fall back to 5000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // using VirtualQuery to retrieve the allocation boundaries and commit them 5010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch // each individually. 5020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch char* ptr = static_cast<char*>(start); 5040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch char* end = ptr + length; 5050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch MEMORY_BASIC_INFORMATION info; 5060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch while (ptr < end) { 5070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch size_t resultSize = VirtualQuery(ptr, &info, sizeof(info)); 5080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT_UNUSED(resultSize, resultSize == sizeof(info)); 5090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 5100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch size_t commitSize = min<size_t>(info.RegionSize, end - ptr); 5110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch void* newAddress = VirtualAlloc(ptr, commitSize, MEM_COMMIT, PAGE_READWRITE); 5120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ASSERT_UNUSED(newAddress, newAddress == ptr); 5130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch ptr += commitSize; 5140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch } 5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 5168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 5178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#else 5188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 5198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// Platforms that don't need to explicitly commit memory use an empty inline version of TCMalloc_SystemCommit 5208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian// declared in TCSystemAlloc.h 5218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian 5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 5232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 5242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#endif // #if !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC) 5252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 526