1 // -*- C++ -*- 2 3 /* 4 5 The Hoard Multiprocessor Memory Allocator 6 www.hoard.org 7 8 Author: Emery Berger, http://www.cs.umass.edu/~emery 9 10 Copyright (c) 1998-2012 Emery Berger 11 12 This program is free software; you can redistribute it and/or modify 13 it under the terms of the GNU General Public License as published by 14 the Free Software Foundation; either version 2 of the License, or 15 (at your option) any later version. 16 17 This program is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program; if not, write to the Free Software 24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 26 */ 27 28 #ifndef HOARD_HEAPMANAGER_H 29 #define HOARD_HEAPMANAGER_H 30 31 #include <cstdlib> 32 #include <mutex> 33 34 #include "hoardconstants.h" 35 #include "heaplayers.h" 36 37 namespace Hoard { 38 39 template <typename LockType, 40 typename HeapType> 41 class HeapManager : public HeapType { 42 public: 43 44 enum { Alignment = HeapType::Alignment }; 45 HeapManager()46 HeapManager() 47 { 48 std::lock_guard<LockType> g (heapLock); 49 50 /// Initialize all heap maps (nothing yet assigned). 51 for (auto i = 0; i < HeapType::MaxThreads; i++) { 52 HeapType::setTidMap (i, 0); 53 } 54 for (auto i = 0; i < HeapType::MaxHeaps; i++) { 55 HeapType::setInusemap (i, 0); 56 } 57 } 58 59 /// Set this thread's heap id to 0. chooseZero()60 void chooseZero() { 61 std::lock_guard<LockType> g (heapLock); 62 HeapType::setTidMap (HL::CPUInfo::getThreadId() % Hoard::MaxThreads, 0); 63 } 64 findUnusedHeap()65 int findUnusedHeap() { 66 67 std::lock_guard<LockType> g (heapLock); 68 69 auto tid_original = HL::CPUInfo::getThreadId(); 70 auto tid = tid_original % HeapType::MaxThreads; 71 72 int i = 0; 73 while ((i < HeapType::MaxHeaps) && (HeapType::getInusemap(i))) 74 i++; 75 if (i >= HeapType::MaxHeaps) { 76 // Every heap is in use: pick a random heap. 77 #if defined(_WIN32) 78 auto randomNumber = rand(); 79 #else 80 auto randomNumber = (int) lrand48(); 81 #endif 82 i = randomNumber % HeapType::MaxHeaps; 83 } 84 85 HeapType::setInusemap (i, 1); 86 HeapType::setTidMap ((int) tid, i); 87 88 return i; 89 } 90 releaseHeap()91 void releaseHeap() { 92 // Decrement the ref-count on the current heap. 93 94 std::lock_guard<LockType> g (heapLock); 95 96 // Statically ensure that the number of threads is a power of two. 97 enum { VerifyPowerOfTwo = 1 / ((HeapType::MaxThreads & ~(HeapType::MaxThreads-1))) }; 98 99 auto tid = (int) (HL::CPUInfo::getThreadId() & (HeapType::MaxThreads - 1)); 100 auto heapIndex = HeapType::getTidMap (tid); 101 102 HeapType::setInusemap (heapIndex, 0); 103 104 // Prevent underruns (defensive programming). 105 106 if (HeapType::getInusemap (heapIndex) < 0) { 107 HeapType::setInusemap (heapIndex, 0); 108 } 109 } 110 111 112 private: 113 114 // Disable copying. 115 116 HeapManager (const HeapManager&); 117 HeapManager& operator= (const HeapManager&); 118 119 /// The lock, to ensure mutual exclusion. 120 LockType heapLock; 121 }; 122 123 } 124 125 #endif 126