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