summaryrefslogtreecommitdiffstats
path: root/third_party/tcmalloc/chromium/src/windows
diff options
context:
space:
mode:
authorsgk@chromium.org <sgk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-25 01:57:13 +0000
committersgk@chromium.org <sgk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-25 01:57:13 +0000
commit068ba6c7660d4aa2deea80ba22d2766b21e398f4 (patch)
tree9132bdff2ac7de2bc36dc7ec79ab98ca87232cf2 /third_party/tcmalloc/chromium/src/windows
parent5a28f8aaba4ec474d1b96b03bf2aabd513245740 (diff)
downloadchromium_src-068ba6c7660d4aa2deea80ba22d2766b21e398f4.zip
chromium_src-068ba6c7660d4aa2deea80ba22d2766b21e398f4.tar.gz
chromium_src-068ba6c7660d4aa2deea80ba22d2766b21e398f4.tar.bz2
Replace forked tcmalloc files with branches from current files to
preserve checkin history. svn cp the added config*.h files into the local patched branch. BUG=27911 TEST=none git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33031 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party/tcmalloc/chromium/src/windows')
-rw-r--r--third_party/tcmalloc/chromium/src/windows/port.cc87
1 files changed, 67 insertions, 20 deletions
diff --git a/third_party/tcmalloc/chromium/src/windows/port.cc b/third_party/tcmalloc/chromium/src/windows/port.cc
index 76a9e38..3902ca7 100644
--- a/third_party/tcmalloc/chromium/src/windows/port.cc
+++ b/third_party/tcmalloc/chromium/src/windows/port.cc
@@ -71,7 +71,8 @@ int getpagesize() {
if (pagesize == 0) {
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
- pagesize = system_info.dwPageSize;
+ pagesize = std::max(system_info.dwPageSize,
+ system_info.dwAllocationGranularity);
}
return pagesize;
}
@@ -182,44 +183,90 @@ pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)) {
// -----------------------------------------------------------------------
// These functions replace system-alloc.cc
+static SpinLock alloc_lock(SpinLock::LINKER_INITIALIZED);
+
// This is mostly like MmapSysAllocator::Alloc, except it does these weird
// munmap's in the middle of the page, which is forbidden in windows.
extern void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size,
size_t alignment) {
- // Safest is to make actual_size same as input-size.
- if (actual_size) {
- *actual_size = size;
- }
-
+ SpinLockHolder sh(&alloc_lock);
// Align on the pagesize boundary
const int pagesize = getpagesize();
if (alignment < pagesize) alignment = pagesize;
size = ((size + alignment - 1) / alignment) * alignment;
- // Ask for extra memory if alignment > pagesize
- size_t extra = 0;
- if (alignment > pagesize) {
- extra = alignment - pagesize;
+ // Report the total number of bytes the OS actually delivered. This might be
+ // greater than |size| because of alignment concerns. The full size is
+ // necessary so that adjacent spans can be coalesced.
+ // TODO(antonm): proper processing of alignments
+ // in actual_size and decommitting.
+ if (actual_size) {
+ *actual_size = size;
}
- void* result = VirtualAlloc(0, size + extra,
+ // We currently do not support alignments larger than the pagesize or
+ // alignments that are not multiples of the pagesize after being floored.
+ // If this ability is needed it can be done by the caller (assuming it knows
+ // the page size).
+ assert(alignment <= pagesize);
+
+ void* result = VirtualAlloc(0, size,
MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
if (result == NULL)
return NULL;
- // Adjust the return memory so it is aligned
- uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
- size_t adjust = 0;
- if ((ptr & (alignment - 1)) != 0) {
- adjust = alignment - (ptr & (alignment - 1));
- }
+ // If the result is not aligned memory fragmentation will result which can
+ // lead to pathological memory use.
+ assert((reinterpret_cast<uintptr_t>(result) & (alignment - 1)) == 0);
- ptr += adjust;
- return reinterpret_cast<void*>(ptr);
+ return result;
}
void TCMalloc_SystemRelease(void* start, size_t length) {
- // TODO(csilvers): should I be calling VirtualFree here?
+ if (VirtualFree(start, length, MEM_DECOMMIT))
+ return;
+
+ // The decommit may fail if the memory region consists of allocations
+ // from more than one call to VirtualAlloc. In this case, fall back to
+ // using VirtualQuery to retrieve the allocation boundaries and decommit
+ // them each individually.
+
+ char* ptr = static_cast<char*>(start);
+ char* end = ptr + length;
+ MEMORY_BASIC_INFORMATION info;
+ while (ptr < end) {
+ size_t resultSize = VirtualQuery(ptr, &info, sizeof(info));
+ assert(resultSize == sizeof(info));
+ size_t decommitSize = std::min<size_t>(info.RegionSize, end - ptr);
+ BOOL success = VirtualFree(ptr, decommitSize, MEM_DECOMMIT);
+ assert(success == TRUE);
+ ptr += decommitSize;
+ }
+}
+
+void TCMalloc_SystemCommit(void* start, size_t length)
+{
+ if (VirtualAlloc(start, length, MEM_COMMIT, PAGE_READWRITE) == start)
+ return;
+
+ // The commit may fail if the memory region consists of allocations
+ // from more than one call to VirtualAlloc. In this case, fall back to
+ // using VirtualQuery to retrieve the allocation boundaries and commit them
+ // each individually.
+
+ char* ptr = static_cast<char*>(start);
+ char* end = ptr + length;
+ MEMORY_BASIC_INFORMATION info;
+ while (ptr < end) {
+ size_t resultSize = VirtualQuery(ptr, &info, sizeof(info));
+ assert(resultSize == sizeof(info));
+
+ size_t commitSize = std::min<size_t>(info.RegionSize, end - ptr);
+ void* newAddress = VirtualAlloc(ptr, commitSize, MEM_COMMIT,
+ PAGE_READWRITE);
+ assert(newAddress == ptr);
+ ptr += commitSize;
+ }
}
bool RegisterSystemAllocator(SysAllocator *allocator, int priority) {