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