xref: /haiku/src/system/libroot/posix/malloc/hoard2/processheap.h (revision 8728f4797fcb3e99b6e1ec2629efbf4119c37497)
1*8728f479SAugustin Cavalier ///-*-C++-*-//////////////////////////////////////////////////////////////////
2*8728f479SAugustin Cavalier //
3*8728f479SAugustin Cavalier // Hoard: A Fast, Scalable, and Memory-Efficient Allocator
4*8728f479SAugustin Cavalier //        for Shared-Memory Multiprocessors
5*8728f479SAugustin Cavalier // Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery
6*8728f479SAugustin Cavalier //
7*8728f479SAugustin Cavalier // Copyright (c) 1998-2000, The University of Texas at Austin.
8*8728f479SAugustin Cavalier //
9*8728f479SAugustin Cavalier // This library is free software; you can redistribute it and/or modify
10*8728f479SAugustin Cavalier // it under the terms of the GNU Library General Public License as
11*8728f479SAugustin Cavalier // published by the Free Software Foundation, http://www.fsf.org.
12*8728f479SAugustin Cavalier //
13*8728f479SAugustin Cavalier // This library is distributed in the hope that it will be useful, but
14*8728f479SAugustin Cavalier // WITHOUT ANY WARRANTY; without even the implied warranty of
15*8728f479SAugustin Cavalier // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16*8728f479SAugustin Cavalier // Library General Public License for more details.
17*8728f479SAugustin Cavalier //
18*8728f479SAugustin Cavalier //////////////////////////////////////////////////////////////////////////////
19*8728f479SAugustin Cavalier 
20*8728f479SAugustin Cavalier /* We use one processHeap for the whole program. */
21*8728f479SAugustin Cavalier 
22*8728f479SAugustin Cavalier #ifndef _PROCESSHEAP_H_
23*8728f479SAugustin Cavalier #define _PROCESSHEAP_H_
24*8728f479SAugustin Cavalier 
25*8728f479SAugustin Cavalier #include "config.h"
26*8728f479SAugustin Cavalier 
27*8728f479SAugustin Cavalier #include <stdio.h>
28*8728f479SAugustin Cavalier #include <stdlib.h>
29*8728f479SAugustin Cavalier 
30*8728f479SAugustin Cavalier #include "arch-specific.h"
31*8728f479SAugustin Cavalier #include "heap.h"
32*8728f479SAugustin Cavalier #if USE_PRIVATE_HEAPS
33*8728f479SAugustin Cavalier #	include "privateheap.h"
34*8728f479SAugustin Cavalier #	define HEAPTYPE privateHeap
35*8728f479SAugustin Cavalier #else
36*8728f479SAugustin Cavalier #	define HEAPTYPE threadHeap
37*8728f479SAugustin Cavalier #	include "threadheap.h"
38*8728f479SAugustin Cavalier #endif
39*8728f479SAugustin Cavalier 
40*8728f479SAugustin Cavalier #if HEAP_LOG
41*8728f479SAugustin Cavalier #	include "memstat.h"
42*8728f479SAugustin Cavalier #	include "log.h"
43*8728f479SAugustin Cavalier #endif
44*8728f479SAugustin Cavalier 
45*8728f479SAugustin Cavalier 
46*8728f479SAugustin Cavalier namespace BPrivate {
47*8728f479SAugustin Cavalier 
48*8728f479SAugustin Cavalier class processHeap : public hoardHeap {
49*8728f479SAugustin Cavalier 	public:
50*8728f479SAugustin Cavalier 		// Always grab at least this many superblocks' worth of memory which
51*8728f479SAugustin Cavalier 		// we parcel out.
52*8728f479SAugustin Cavalier 		enum { REFILL_NUMBER_OF_SUPERBLOCKS = 16 };
53*8728f479SAugustin Cavalier 
54*8728f479SAugustin Cavalier 		processHeap();
~processHeap(void)55*8728f479SAugustin Cavalier 		~processHeap(void)
56*8728f479SAugustin Cavalier 		{
57*8728f479SAugustin Cavalier #if HEAP_STATS
58*8728f479SAugustin Cavalier 			stats();
59*8728f479SAugustin Cavalier #endif
60*8728f479SAugustin Cavalier 		}
61*8728f479SAugustin Cavalier 		// Memory deallocation routines.
62*8728f479SAugustin Cavalier 		void free(void *ptr);
63*8728f479SAugustin Cavalier 
64*8728f479SAugustin Cavalier 		// Print out statistics information.
65*8728f479SAugustin Cavalier 		void stats(void);
66*8728f479SAugustin Cavalier 
67*8728f479SAugustin Cavalier 		// Get a thread heap index.
68*8728f479SAugustin Cavalier 		inline int getHeapIndex(void);
69*8728f479SAugustin Cavalier 
70*8728f479SAugustin Cavalier 		// Get thread heap max.
71*8728f479SAugustin Cavalier 		inline int getMaxThreadHeaps(void);
72*8728f479SAugustin Cavalier 
73*8728f479SAugustin Cavalier 		// Get the thread heap with index i.
74*8728f479SAugustin Cavalier 		inline HEAPTYPE & getHeap(int i);
75*8728f479SAugustin Cavalier 
76*8728f479SAugustin Cavalier 		// Extract a superblock.
77*8728f479SAugustin Cavalier 		inline superblock *acquire(const int c, hoardHeap * dest);
78*8728f479SAugustin Cavalier 
79*8728f479SAugustin Cavalier 		// Get space for a superblock.
80*8728f479SAugustin Cavalier 		inline char *getSuperblockBuffer(void);
81*8728f479SAugustin Cavalier 
82*8728f479SAugustin Cavalier 		// Insert a superblock.
83*8728f479SAugustin Cavalier 		inline void release(superblock * sb);
84*8728f479SAugustin Cavalier 
85*8728f479SAugustin Cavalier #if HEAP_LOG
86*8728f479SAugustin Cavalier 		// Get the log for index i.
87*8728f479SAugustin Cavalier 		inline Log < MemoryRequest > &getLog(int i);
88*8728f479SAugustin Cavalier #endif
89*8728f479SAugustin Cavalier 
90*8728f479SAugustin Cavalier #if HEAP_FRAG_STATS
91*8728f479SAugustin Cavalier 		// Declare that we have allocated an object.
92*8728f479SAugustin Cavalier 		void setAllocated(int requestedSize, int actualSize);
93*8728f479SAugustin Cavalier 
94*8728f479SAugustin Cavalier 		// Declare that we have deallocated an object.
95*8728f479SAugustin Cavalier 		void setDeallocated(int requestedSize, int actualSize);
96*8728f479SAugustin Cavalier 
97*8728f479SAugustin Cavalier 		// Return the number of wasted bytes at the high-water mark
98*8728f479SAugustin Cavalier 		// (maxAllocated - maxRequested)
99*8728f479SAugustin Cavalier 		inline int getFragmentation(void);
100*8728f479SAugustin Cavalier 
101*8728f479SAugustin Cavalier 		int
getMaxAllocated(void)102*8728f479SAugustin Cavalier 		getMaxAllocated(void)
103*8728f479SAugustin Cavalier 		{
104*8728f479SAugustin Cavalier 			return _maxAllocated;
105*8728f479SAugustin Cavalier 		}
106*8728f479SAugustin Cavalier 
107*8728f479SAugustin Cavalier 		int
getInUseAtMaxAllocated(void)108*8728f479SAugustin Cavalier 		getInUseAtMaxAllocated(void)
109*8728f479SAugustin Cavalier 		{
110*8728f479SAugustin Cavalier 			return _inUseAtMaxAllocated;
111*8728f479SAugustin Cavalier 		}
112*8728f479SAugustin Cavalier 
113*8728f479SAugustin Cavalier 		int
getMaxRequested(void)114*8728f479SAugustin Cavalier 		getMaxRequested(void)
115*8728f479SAugustin Cavalier 		{
116*8728f479SAugustin Cavalier 			return _maxRequested;
117*8728f479SAugustin Cavalier 		}
118*8728f479SAugustin Cavalier #endif
119*8728f479SAugustin Cavalier 
120*8728f479SAugustin Cavalier 	private:
121*8728f479SAugustin Cavalier 		// Hide the lock & unlock methods.
122*8728f479SAugustin Cavalier 		void
lock(void)123*8728f479SAugustin Cavalier 		lock(void)
124*8728f479SAugustin Cavalier 		{
125*8728f479SAugustin Cavalier 			hoardHeap::lock();
126*8728f479SAugustin Cavalier 		}
127*8728f479SAugustin Cavalier 
128*8728f479SAugustin Cavalier 		void
unlock(void)129*8728f479SAugustin Cavalier 		unlock(void)
130*8728f479SAugustin Cavalier 		{
131*8728f479SAugustin Cavalier 			hoardHeap::unlock();
132*8728f479SAugustin Cavalier 		}
133*8728f479SAugustin Cavalier 
134*8728f479SAugustin Cavalier 		// Prevent copying and assignment.
135*8728f479SAugustin Cavalier 		processHeap(const processHeap &);
136*8728f479SAugustin Cavalier 		const processHeap & operator=(const processHeap &);
137*8728f479SAugustin Cavalier 
138*8728f479SAugustin Cavalier 		// The per-thread heaps.
139*8728f479SAugustin Cavalier 		HEAPTYPE* theap;
140*8728f479SAugustin Cavalier 
141*8728f479SAugustin Cavalier #if HEAP_FRAG_STATS
142*8728f479SAugustin Cavalier 		// Statistics required to compute fragmentation.  We cannot
143*8728f479SAugustin Cavalier 		// unintrusively keep track of these on a multiprocessor, because
144*8728f479SAugustin Cavalier 		// this would become a bottleneck.
145*8728f479SAugustin Cavalier 
146*8728f479SAugustin Cavalier 		int _currentAllocated;
147*8728f479SAugustin Cavalier 		int _currentRequested;
148*8728f479SAugustin Cavalier 		int _maxAllocated;
149*8728f479SAugustin Cavalier 		int _maxRequested;
150*8728f479SAugustin Cavalier 		int _inUseAtMaxAllocated;
151*8728f479SAugustin Cavalier 		int _fragmentation;
152*8728f479SAugustin Cavalier 
153*8728f479SAugustin Cavalier 		// A lock to protect these statistics.
154*8728f479SAugustin Cavalier 		hoardLockType _statsLock;
155*8728f479SAugustin Cavalier #endif
156*8728f479SAugustin Cavalier 
157*8728f479SAugustin Cavalier #if HEAP_LOG
158*8728f479SAugustin Cavalier 		Log < MemoryRequest >* _log;
159*8728f479SAugustin Cavalier #endif
160*8728f479SAugustin Cavalier 
161*8728f479SAugustin Cavalier 		// A lock for the superblock buffer.
162*8728f479SAugustin Cavalier 		hoardLockType _bufferLock;
163*8728f479SAugustin Cavalier 
164*8728f479SAugustin Cavalier 		char *_buffer;
165*8728f479SAugustin Cavalier 		int _bufferCount;
166*8728f479SAugustin Cavalier };
167*8728f479SAugustin Cavalier 
168*8728f479SAugustin Cavalier 
169*8728f479SAugustin Cavalier HEAPTYPE &
getHeap(int i)170*8728f479SAugustin Cavalier processHeap::getHeap(int i)
171*8728f479SAugustin Cavalier {
172*8728f479SAugustin Cavalier 	assert(theap != NULL);
173*8728f479SAugustin Cavalier 	assert(i >= 0);
174*8728f479SAugustin Cavalier 	assert(i < fMaxThreadHeaps);
175*8728f479SAugustin Cavalier 	return theap[i];
176*8728f479SAugustin Cavalier }
177*8728f479SAugustin Cavalier 
178*8728f479SAugustin Cavalier 
179*8728f479SAugustin Cavalier #if HEAP_LOG
180*8728f479SAugustin Cavalier Log<MemoryRequest > &
getLog(int i)181*8728f479SAugustin Cavalier processHeap::getLog(int i)
182*8728f479SAugustin Cavalier {
183*8728f479SAugustin Cavalier 	assert(_log != NULL);
184*8728f479SAugustin Cavalier 	assert(i >= 0);
185*8728f479SAugustin Cavalier 	assert(i < fMaxThreadHeaps + 1);
186*8728f479SAugustin Cavalier 	return _log[i];
187*8728f479SAugustin Cavalier }
188*8728f479SAugustin Cavalier #endif
189*8728f479SAugustin Cavalier 
190*8728f479SAugustin Cavalier 
191*8728f479SAugustin Cavalier // Hash out the thread id to a heap and return an index to that heap.
192*8728f479SAugustin Cavalier 
193*8728f479SAugustin Cavalier int
getHeapIndex(void)194*8728f479SAugustin Cavalier processHeap::getHeapIndex(void)
195*8728f479SAugustin Cavalier {
196*8728f479SAugustin Cavalier 	// Here we use the number of processors as the maximum number of heaps.
197*8728f479SAugustin Cavalier 	// In fact, for efficiency, we just round up to the highest power of two,
198*8728f479SAugustin Cavalier 	// times two.
199*8728f479SAugustin Cavalier 	int tid = find_thread(NULL) & _numProcessorsMask;
200*8728f479SAugustin Cavalier 	assert(tid < fMaxThreadHeaps);
201*8728f479SAugustin Cavalier 	return tid;
202*8728f479SAugustin Cavalier }
203*8728f479SAugustin Cavalier 
204*8728f479SAugustin Cavalier 
205*8728f479SAugustin Cavalier // Return the maximum number of heaps.
206*8728f479SAugustin Cavalier 
207*8728f479SAugustin Cavalier int
getMaxThreadHeaps(void)208*8728f479SAugustin Cavalier processHeap::getMaxThreadHeaps(void)
209*8728f479SAugustin Cavalier {
210*8728f479SAugustin Cavalier 	return fMaxThreadHeaps;
211*8728f479SAugustin Cavalier }
212*8728f479SAugustin Cavalier 
213*8728f479SAugustin Cavalier 
214*8728f479SAugustin Cavalier superblock *
acquire(const int sizeclass,hoardHeap * dest)215*8728f479SAugustin Cavalier processHeap::acquire(const int sizeclass, hoardHeap * dest)
216*8728f479SAugustin Cavalier {
217*8728f479SAugustin Cavalier 	lock();
218*8728f479SAugustin Cavalier 
219*8728f479SAugustin Cavalier 	// Remove the superblock with the most free space.
220*8728f479SAugustin Cavalier 	superblock *maxSb = removeMaxSuperblock(sizeclass);
221*8728f479SAugustin Cavalier 	if (maxSb)
222*8728f479SAugustin Cavalier 		maxSb->setOwner(dest);
223*8728f479SAugustin Cavalier 
224*8728f479SAugustin Cavalier 	unlock();
225*8728f479SAugustin Cavalier 
226*8728f479SAugustin Cavalier 	return maxSb;
227*8728f479SAugustin Cavalier }
228*8728f479SAugustin Cavalier 
229*8728f479SAugustin Cavalier 
230*8728f479SAugustin Cavalier inline char *
getSuperblockBuffer(void)231*8728f479SAugustin Cavalier processHeap::getSuperblockBuffer(void)
232*8728f479SAugustin Cavalier {
233*8728f479SAugustin Cavalier 	char *buf;
234*8728f479SAugustin Cavalier 	hoardLock(_bufferLock);
235*8728f479SAugustin Cavalier 	if (_bufferCount == 0) {
236*8728f479SAugustin Cavalier 		_buffer = (char *)hoardSbrk(SUPERBLOCK_SIZE
237*8728f479SAugustin Cavalier 			* REFILL_NUMBER_OF_SUPERBLOCKS);
238*8728f479SAugustin Cavalier 		_bufferCount = REFILL_NUMBER_OF_SUPERBLOCKS;
239*8728f479SAugustin Cavalier 	}
240*8728f479SAugustin Cavalier 
241*8728f479SAugustin Cavalier 	buf = _buffer;
242*8728f479SAugustin Cavalier 	_buffer += SUPERBLOCK_SIZE;
243*8728f479SAugustin Cavalier 	_bufferCount--;
244*8728f479SAugustin Cavalier 	hoardUnlock(_bufferLock);
245*8728f479SAugustin Cavalier 
246*8728f479SAugustin Cavalier 	return buf;
247*8728f479SAugustin Cavalier }
248*8728f479SAugustin Cavalier 
249*8728f479SAugustin Cavalier 
250*8728f479SAugustin Cavalier // Put a superblock back into our list of superblocks.
251*8728f479SAugustin Cavalier 
252*8728f479SAugustin Cavalier void
release(superblock * sb)253*8728f479SAugustin Cavalier processHeap::release(superblock *sb)
254*8728f479SAugustin Cavalier {
255*8728f479SAugustin Cavalier 	assert(EMPTY_FRACTION * sb->getNumAvailable() > sb->getNumBlocks());
256*8728f479SAugustin Cavalier 
257*8728f479SAugustin Cavalier 	lock();
258*8728f479SAugustin Cavalier 
259*8728f479SAugustin Cavalier 	// Insert the superblock.
260*8728f479SAugustin Cavalier 	insertSuperblock(sb->getBlockSizeClass(), sb, this);
261*8728f479SAugustin Cavalier 
262*8728f479SAugustin Cavalier 	unlock();
263*8728f479SAugustin Cavalier }
264*8728f479SAugustin Cavalier 
265*8728f479SAugustin Cavalier }	// namespace BPrivate
266*8728f479SAugustin Cavalier 
267*8728f479SAugustin Cavalier #endif // _PROCESSHEAP_H_
268