Panda3D
|
00001 // Filename: neverFreeMemory.cxx 00002 // Created by: drose (14Jun07) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "neverFreeMemory.h" 00016 #include "atomicAdjust.h" 00017 #include "memoryHook.h" 00018 00019 NeverFreeMemory * TVOLATILE NeverFreeMemory::_global_ptr; 00020 00021 // If a page has fewer than this many bytes remaining, never mind 00022 // about it. 00023 static const size_t min_page_remaining_size = 16; 00024 00025 // We always allocate at least this many bytes at a time. 00026 static const size_t min_page_size = 128 * 1024; // 128K 00027 00028 //////////////////////////////////////////////////////////////////// 00029 // Function: NeverFreeMemory::Constructor 00030 // Access: Private 00031 // Description: 00032 //////////////////////////////////////////////////////////////////// 00033 NeverFreeMemory:: 00034 NeverFreeMemory() { 00035 _total_alloc = 0; 00036 _total_used = 0; 00037 } 00038 00039 //////////////////////////////////////////////////////////////////// 00040 // Function: NeverFreeMemory::ns_alloc 00041 // Access: Private 00042 // Description: 00043 //////////////////////////////////////////////////////////////////// 00044 void *NeverFreeMemory:: 00045 ns_alloc(size_t size) { 00046 _lock.acquire(); 00047 00048 // We always allocate integer multiples of this many bytes, to 00049 // guarantee this minimum alignment. 00050 static const size_t alignment_size = MemoryHook::get_memory_alignment(); 00051 00052 // Round up to the next alignment_size. 00053 size = ((size + alignment_size - 1) / alignment_size) * alignment_size; 00054 00055 _total_used += size; 00056 00057 // Look for a page that has sufficient space remaining. 00058 00059 Pages::iterator pi = _pages.lower_bound(Page(NULL, size)); 00060 if (pi != _pages.end()) { 00061 // Here's a page with enough remaining space. 00062 Page page = (*pi); 00063 _pages.erase(pi); 00064 void *result = page.alloc(size); 00065 if (page._remaining >= min_page_remaining_size) { 00066 _pages.insert(page); 00067 } 00068 _lock.release(); 00069 return result; 00070 } 00071 00072 // We have to allocate a new page. Allocate at least min_page_size 00073 // bytes, and then round that up to the next _page_size bytes. 00074 size_t needed_size = max(size, min_page_size); 00075 needed_size = memory_hook->round_up_to_page_size(needed_size); 00076 void *start = memory_hook->mmap_alloc(needed_size, false); 00077 _total_alloc += needed_size; 00078 00079 Page page(start, needed_size); 00080 void *result = page.alloc(size); 00081 if (page._remaining >= min_page_remaining_size) { 00082 _pages.insert(page); 00083 } 00084 _lock.release(); 00085 return result; 00086 } 00087 00088 //////////////////////////////////////////////////////////////////// 00089 // Function: NeverFreeMemory::make_global_ptr 00090 // Access: Private, Static 00091 // Description: 00092 //////////////////////////////////////////////////////////////////// 00093 void NeverFreeMemory:: 00094 make_global_ptr() { 00095 NeverFreeMemory *ptr = new NeverFreeMemory; 00096 void *result = AtomicAdjust::compare_and_exchange_ptr 00097 ((void * TVOLATILE &)_global_ptr, (void *)NULL, (void *)ptr); 00098 if (result != NULL) { 00099 // Someone else got there first. 00100 delete ptr; 00101 } 00102 } 00103