diff options
author | sgk@chromium.org <sgk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-25 01:57:13 +0000 |
---|---|---|
committer | sgk@chromium.org <sgk@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-25 01:57:13 +0000 |
commit | 068ba6c7660d4aa2deea80ba22d2766b21e398f4 (patch) | |
tree | 9132bdff2ac7de2bc36dc7ec79ab98ca87232cf2 /third_party/tcmalloc/chromium/src/windows | |
parent | 5a28f8aaba4ec474d1b96b03bf2aabd513245740 (diff) | |
download | chromium_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.cc | 87 |
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) { |