 Chromium Code Reviews
 Chromium Code Reviews Issue 222028:
  Rounds up VirtualAlloc calls on windows to dwAllocationGranularity to prevent fragmentation  (Closed)
    
  
    Issue 222028:
  Rounds up VirtualAlloc calls on windows to dwAllocationGranularity to prevent fragmentation  (Closed) 
  | OLD | NEW | 
|---|---|
| 1 /* Copyright (c) 2007, Google Inc. | 1 /* Copyright (c) 2007, Google Inc. | 
| 2 * All rights reserved. | 2 * All rights reserved. | 
| 3 * | 3 * | 
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without | 
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are | 
| 6 * met: | 6 * met: | 
| 7 * | 7 * | 
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright | 
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. | 
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above | 
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 64 va_end(ap); | 64 va_end(ap); | 
| 65 return r; | 65 return r; | 
| 66 } | 66 } | 
| 67 #endif | 67 #endif | 
| 68 | 68 | 
| 69 int getpagesize() { | 69 int getpagesize() { | 
| 70 static int pagesize = 0; | 70 static int pagesize = 0; | 
| 71 if (pagesize == 0) { | 71 if (pagesize == 0) { | 
| 72 SYSTEM_INFO system_info; | 72 SYSTEM_INFO system_info; | 
| 73 GetSystemInfo(&system_info); | 73 GetSystemInfo(&system_info); | 
| 74 pagesize = system_info.dwPageSize; | 74 pagesize = std::max(system_info.dwPageSize, | 
| 75 system_info.dwAllocationGranularity); | |
| 75 } | 76 } | 
| 76 return pagesize; | 77 return pagesize; | 
| 77 } | 78 } | 
| 78 | 79 | 
| 79 extern "C" PERFTOOLS_DLL_DECL void* __sbrk(ptrdiff_t increment) { | 80 extern "C" PERFTOOLS_DLL_DECL void* __sbrk(ptrdiff_t increment) { | 
| 80 LOG(FATAL, "Windows doesn't implement sbrk!\n"); | 81 LOG(FATAL, "Windows doesn't implement sbrk!\n"); | 
| 81 return NULL; | 82 return NULL; | 
| 82 } | 83 } | 
| 83 | 84 | 
| 84 // ----------------------------------------------------------------------- | 85 // ----------------------------------------------------------------------- | 
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 181 | 182 | 
| 182 // ----------------------------------------------------------------------- | 183 // ----------------------------------------------------------------------- | 
| 183 // These functions replace system-alloc.cc | 184 // These functions replace system-alloc.cc | 
| 184 | 185 | 
| 185 static SpinLock alloc_lock(SpinLock::LINKER_INITIALIZED); | 186 static SpinLock alloc_lock(SpinLock::LINKER_INITIALIZED); | 
| 186 | 187 | 
| 187 // This is mostly like MmapSysAllocator::Alloc, except it does these weird | 188 // This is mostly like MmapSysAllocator::Alloc, except it does these weird | 
| 188 // munmap's in the middle of the page, which is forbidden in windows. | 189 // munmap's in the middle of the page, which is forbidden in windows. | 
| 189 extern void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size, | 190 extern void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size, | 
| 190 size_t alignment) { | 191 size_t alignment) { | 
| 191 // Safest is to make actual_size same as input-size. | |
| 192 if (actual_size) { | |
| 193 *actual_size = size; | |
| 194 } | |
| 195 | |
| 196 SpinLockHolder sh(&alloc_lock); | 192 SpinLockHolder sh(&alloc_lock); | 
| 197 // Align on the pagesize boundary | 193 // Align on the pagesize boundary | 
| 198 const int pagesize = getpagesize(); | 194 const int pagesize = getpagesize(); | 
| 199 if (alignment < pagesize) alignment = pagesize; | 195 if (alignment < pagesize) alignment = pagesize; | 
| 200 size = ((size + alignment - 1) / alignment) * alignment; | 196 size = ((size + alignment - 1) / alignment) * alignment; | 
| 201 | 197 | 
| 202 // Ask for extra memory if alignment > pagesize | 198 // Safest is to make actual_size same as input-size. | 
| 
jar (doing other things)
2009/09/24 23:24:34
The unexplained "safest" comment could be elaborat
 | |
| 203 size_t extra = 0; | 199 // TODO(antonm): proper processing of alignments | 
| 204 if (alignment > pagesize) { | 200 // in actual_size and decommitting. | 
| 
jar (doing other things)
2009/09/24 23:24:34
I don't understand this TODO comment.  Can you cla
 | |
| 205 extra = alignment - pagesize; | 201 if (actual_size) { | 
| 202 *actual_size = size; | |
| 206 } | 203 } | 
| 207 | 204 | 
| 208 void* result = VirtualAlloc(0, size + extra, | 205 // We currently do not support alignments larger than the pagesize or | 
| 206 // alignments that are not multiples of the pagesize after being floored. | |
| 207 // If this ability is needed it can be done by the caller (assuming it knows | |
| 208 // the page size). | |
| 209 assert(alignment <= pagesize); | |
| 210 | |
| 211 void* result = VirtualAlloc(0, size, | |
| 209 MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); | 212 MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); | 
| 210 if (result == NULL) | 213 if (result == NULL) | 
| 211 return NULL; | 214 return NULL; | 
| 212 | 215 | 
| 213 // Adjust the return memory so it is aligned | 216 // If the result is not aligned memory fragmentation will result which can | 
| 214 uintptr_t ptr = reinterpret_cast<uintptr_t>(result); | 217 // lead to pathological memory use. | 
| 215 size_t adjust = 0; | 218 assert((reinterpret_cast<uintptr_t>(result) & (alignment - 1)) == 0); | 
| 216 if ((ptr & (alignment - 1)) != 0) { | |
| 217 adjust = alignment - (ptr & (alignment - 1)); | |
| 218 } | |
| 219 | 219 | 
| 220 ptr += adjust; | 220 return result; | 
| 221 return reinterpret_cast<void*>(ptr); | |
| 222 } | 221 } | 
| 223 | 222 | 
| 224 void TCMalloc_SystemRelease(void* start, size_t length) { | 223 void TCMalloc_SystemRelease(void* start, size_t length) { | 
| 225 if (VirtualFree(start, length, MEM_DECOMMIT)) | 224 if (VirtualFree(start, length, MEM_DECOMMIT)) | 
| 226 return; | 225 return; | 
| 227 | 226 | 
| 228 // The decommit may fail if the memory region consists of allocations | 227 // The decommit may fail if the memory region consists of allocations | 
| 229 // from more than one call to VirtualAlloc. In this case, fall back to | 228 // from more than one call to VirtualAlloc. In this case, fall back to | 
| 230 // using VirtualQuery to retrieve the allocation boundaries and decommit | 229 // using VirtualQuery to retrieve the allocation boundaries and decommit | 
| 231 // them each individually. | 230 // them each individually. | 
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 292 if ((strlen(fname) >= prefix_length) && | 291 if ((strlen(fname) >= prefix_length) && | 
| 293 (memcmp(fname, prefix, prefix_length) == 0)) { | 292 (memcmp(fname, prefix, prefix_length) == 0)) { | 
| 294 RAW_VLOG(0, "Removing old heap profile %s\n", fname); | 293 RAW_VLOG(0, "Removing old heap profile %s\n", fname); | 
| 295 // TODO(csilvers): we really need to unlink dirname + fname | 294 // TODO(csilvers): we really need to unlink dirname + fname | 
| 296 _unlink(fname); | 295 _unlink(fname); | 
| 297 } | 296 } | 
| 298 } while (FindNextFileA(hFind, &found) != FALSE); // A is for Ansi | 297 } while (FindNextFileA(hFind, &found) != FALSE); // A is for Ansi | 
| 299 FindClose(hFind); | 298 FindClose(hFind); | 
| 300 } | 299 } | 
| 301 } | 300 } | 
| OLD | NEW |