xref: /haiku/src/system/libroot/posix/malloc/hoard2/superblock.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 /*
21*8728f479SAugustin Cavalier   superblock.h
22*8728f479SAugustin Cavalier   ------------------------------------------------------------------------
23*8728f479SAugustin Cavalier   The superblock class controls a number of blocks (which are
24*8728f479SAugustin Cavalier   allocatable units of memory).
25*8728f479SAugustin Cavalier   ------------------------------------------------------------------------
26*8728f479SAugustin Cavalier   Emery Berger                    | <http://www.cs.utexas.edu/users/emery>
27*8728f479SAugustin Cavalier   Department of Computer Sciences |             <http://www.cs.utexas.edu>
28*8728f479SAugustin Cavalier   University of Texas at Austin   |                <http://www.utexas.edu>
29*8728f479SAugustin Cavalier   ========================================================================
30*8728f479SAugustin Cavalier */
31*8728f479SAugustin Cavalier 
32*8728f479SAugustin Cavalier #ifndef _SUPERBLOCK_H_
33*8728f479SAugustin Cavalier #define _SUPERBLOCK_H_
34*8728f479SAugustin Cavalier 
35*8728f479SAugustin Cavalier #include "config.h"
36*8728f479SAugustin Cavalier #include "arch-specific.h"
37*8728f479SAugustin Cavalier #include "block.h"
38*8728f479SAugustin Cavalier 
39*8728f479SAugustin Cavalier 
40*8728f479SAugustin Cavalier namespace BPrivate {
41*8728f479SAugustin Cavalier 
42*8728f479SAugustin Cavalier class hoardHeap;				// forward declaration
43*8728f479SAugustin Cavalier class processHeap;				// forward declaration
44*8728f479SAugustin Cavalier 
45*8728f479SAugustin Cavalier class superblock {
46*8728f479SAugustin Cavalier 	public:
47*8728f479SAugustin Cavalier 		// Construct a superblock for a given size class and set the heap
48*8728f479SAugustin Cavalier 		// owner.
49*8728f479SAugustin Cavalier 		superblock(int numblocks, int sizeclass, hoardHeap *owner);
~superblock(void)50*8728f479SAugustin Cavalier 		~superblock(void) {}
51*8728f479SAugustin Cavalier 
52*8728f479SAugustin Cavalier 		// Make (allocate or re-use) a superblock for a given size class.
53*8728f479SAugustin Cavalier 		static superblock *makeSuperblock(int sizeclass, processHeap *pHeap);
54*8728f479SAugustin Cavalier 
55*8728f479SAugustin Cavalier 		// Find out who allocated this superblock.
56*8728f479SAugustin Cavalier 		inline hoardHeap *getOwner(void);
57*8728f479SAugustin Cavalier 
58*8728f479SAugustin Cavalier 		// Set the superblock's owner.
59*8728f479SAugustin Cavalier 		inline void setOwner(hoardHeap *o);
60*8728f479SAugustin Cavalier 
61*8728f479SAugustin Cavalier 		// Get a block from the superblock.
62*8728f479SAugustin Cavalier 		inline block *getBlock(void);
63*8728f479SAugustin Cavalier 
64*8728f479SAugustin Cavalier 		// Put a block back in the superblock.
65*8728f479SAugustin Cavalier 		inline void putBlock(block *b);
66*8728f479SAugustin Cavalier 
67*8728f479SAugustin Cavalier 		// How many blocks are available?
68*8728f479SAugustin Cavalier 		inline int getNumAvailable(void);
69*8728f479SAugustin Cavalier 
70*8728f479SAugustin Cavalier 		// How many blocks are there, in total?
71*8728f479SAugustin Cavalier 		inline int getNumBlocks(void);
72*8728f479SAugustin Cavalier 
73*8728f479SAugustin Cavalier 		// What size class are blocks in this superblock?
74*8728f479SAugustin Cavalier 		inline int getBlockSizeClass(void);
75*8728f479SAugustin Cavalier 
76*8728f479SAugustin Cavalier 		// Insert this superblock before the next one.
77*8728f479SAugustin Cavalier 		inline void insertBefore(superblock *nextSb);
78*8728f479SAugustin Cavalier 
79*8728f479SAugustin Cavalier 		// Return the next pointer (to the next superblock in the list).
80*8728f479SAugustin Cavalier 		inline superblock *const getNext(void);
81*8728f479SAugustin Cavalier 
82*8728f479SAugustin Cavalier 		// Return the prev pointer (to the previous superblock in the list).
83*8728f479SAugustin Cavalier 		inline superblock *const getPrev(void);
84*8728f479SAugustin Cavalier 
85*8728f479SAugustin Cavalier 		// Compute the 'fullness' of this superblock.
86*8728f479SAugustin Cavalier 		inline void computeFullness(void);
87*8728f479SAugustin Cavalier 
88*8728f479SAugustin Cavalier 		// Return the 'fullness' of this superblock.
89*8728f479SAugustin Cavalier 		inline int getFullness(void);
90*8728f479SAugustin Cavalier 
91*8728f479SAugustin Cavalier #if HEAP_FRAG_STATS
92*8728f479SAugustin Cavalier 		// Return the amount of waste in every allocated block.
93*8728f479SAugustin Cavalier 		int getMaxInternalFragmentation(void);
94*8728f479SAugustin Cavalier #endif
95*8728f479SAugustin Cavalier 
96*8728f479SAugustin Cavalier 		// Remove this superblock from its linked list.
97*8728f479SAugustin Cavalier 		inline void remove(void);
98*8728f479SAugustin Cavalier 
99*8728f479SAugustin Cavalier 		// Is this superblock valid? (i.e.,
100*8728f479SAugustin Cavalier 		// does it have the right magic number?)
101*8728f479SAugustin Cavalier 		inline int isValid(void);
102*8728f479SAugustin Cavalier 
103*8728f479SAugustin Cavalier 		void
upLock(void)104*8728f479SAugustin Cavalier 		upLock(void)
105*8728f479SAugustin Cavalier 		{
106*8728f479SAugustin Cavalier 			hoardLock(_upLock);
107*8728f479SAugustin Cavalier 		}
108*8728f479SAugustin Cavalier 
109*8728f479SAugustin Cavalier 		void
upUnlock(void)110*8728f479SAugustin Cavalier 		upUnlock(void)
111*8728f479SAugustin Cavalier 		{
112*8728f479SAugustin Cavalier 			hoardUnlock(_upLock);
113*8728f479SAugustin Cavalier 		}
114*8728f479SAugustin Cavalier 
115*8728f479SAugustin Cavalier 	private:
116*8728f479SAugustin Cavalier 		// Disable copying and assignment.
117*8728f479SAugustin Cavalier 
118*8728f479SAugustin Cavalier 		superblock(const superblock &);
119*8728f479SAugustin Cavalier 		const superblock & operator=(const superblock &);
120*8728f479SAugustin Cavalier 
121*8728f479SAugustin Cavalier 		// Used for sanity checking.
122*8728f479SAugustin Cavalier 		enum { SUPERBLOCK_MAGIC = 0xCAFEBABE };
123*8728f479SAugustin Cavalier 
124*8728f479SAugustin Cavalier #if HEAP_DEBUG
125*8728f479SAugustin Cavalier 		unsigned long _magic;
126*8728f479SAugustin Cavalier #endif
127*8728f479SAugustin Cavalier 
128*8728f479SAugustin Cavalier 		const int _sizeClass;		// The size class of blocks in the superblock.
129*8728f479SAugustin Cavalier 		const int _numBlocks;		// The number of blocks in the superblock.
130*8728f479SAugustin Cavalier 		int _numAvailable;			// The number of blocks available.
131*8728f479SAugustin Cavalier 		int _fullness;				// How full is this superblock?
132*8728f479SAugustin Cavalier 		// (which SUPERBLOCK_FULLNESS group is it in)
133*8728f479SAugustin Cavalier 		block *_freeList;			// A pointer to the first free block.
134*8728f479SAugustin Cavalier 		hoardHeap *_owner;			// The heap who owns this superblock.
135*8728f479SAugustin Cavalier 		superblock *_next;			// The next superblock in the list.
136*8728f479SAugustin Cavalier 		superblock *_prev;			// The previous superblock in the list.
137*8728f479SAugustin Cavalier 
138*8728f479SAugustin Cavalier 		hoardLockType _upLock;		// Lock this when moving a superblock to the global (process) heap.
139*8728f479SAugustin Cavalier 
140*8728f479SAugustin Cavalier 		// We insert a cache pad here to prevent false sharing with the
141*8728f479SAugustin Cavalier 		// first block (which immediately follows the superblock).
142*8728f479SAugustin Cavalier 		double _pad[CACHE_LINE / sizeof(double)];
143*8728f479SAugustin Cavalier };
144*8728f479SAugustin Cavalier 
145*8728f479SAugustin Cavalier 
146*8728f479SAugustin Cavalier hoardHeap *
getOwner(void)147*8728f479SAugustin Cavalier superblock::getOwner(void)
148*8728f479SAugustin Cavalier {
149*8728f479SAugustin Cavalier 	assert(isValid());
150*8728f479SAugustin Cavalier 	hoardHeap *o = _owner;
151*8728f479SAugustin Cavalier 	return o;
152*8728f479SAugustin Cavalier }
153*8728f479SAugustin Cavalier 
154*8728f479SAugustin Cavalier 
155*8728f479SAugustin Cavalier void
setOwner(hoardHeap * o)156*8728f479SAugustin Cavalier superblock::setOwner(hoardHeap *o)
157*8728f479SAugustin Cavalier {
158*8728f479SAugustin Cavalier 	assert(isValid());
159*8728f479SAugustin Cavalier 	_owner = o;
160*8728f479SAugustin Cavalier }
161*8728f479SAugustin Cavalier 
162*8728f479SAugustin Cavalier 
163*8728f479SAugustin Cavalier block *
getBlock(void)164*8728f479SAugustin Cavalier superblock::getBlock(void)
165*8728f479SAugustin Cavalier {
166*8728f479SAugustin Cavalier 	assert(isValid());
167*8728f479SAugustin Cavalier 	// Pop off a block from this superblock's freelist,
168*8728f479SAugustin Cavalier 	// if there is one available.
169*8728f479SAugustin Cavalier 	if (_freeList == NULL) {
170*8728f479SAugustin Cavalier 		// The freelist is empty.
171*8728f479SAugustin Cavalier 		assert(getNumAvailable() == 0);
172*8728f479SAugustin Cavalier 		return NULL;
173*8728f479SAugustin Cavalier 	}
174*8728f479SAugustin Cavalier 
175*8728f479SAugustin Cavalier 	assert(getNumAvailable() > 0);
176*8728f479SAugustin Cavalier 	block *b = _freeList;
177*8728f479SAugustin Cavalier 	_freeList = _freeList->getNext();
178*8728f479SAugustin Cavalier 	_numAvailable--;
179*8728f479SAugustin Cavalier 
180*8728f479SAugustin Cavalier 	b->setNext(NULL);
181*8728f479SAugustin Cavalier 
182*8728f479SAugustin Cavalier 	computeFullness();
183*8728f479SAugustin Cavalier 	return b;
184*8728f479SAugustin Cavalier }
185*8728f479SAugustin Cavalier 
186*8728f479SAugustin Cavalier 
187*8728f479SAugustin Cavalier void
putBlock(block * b)188*8728f479SAugustin Cavalier superblock::putBlock(block *b)
189*8728f479SAugustin Cavalier {
190*8728f479SAugustin Cavalier 	assert(isValid());
191*8728f479SAugustin Cavalier 	// Push a block onto the superblock's freelist.
192*8728f479SAugustin Cavalier 	assert(b->isValid());
193*8728f479SAugustin Cavalier 	assert(b->getSuperblock() == this);
194*8728f479SAugustin Cavalier 	assert(getNumAvailable() < getNumBlocks());
195*8728f479SAugustin Cavalier 	b->setNext(_freeList);
196*8728f479SAugustin Cavalier 	_freeList = b;
197*8728f479SAugustin Cavalier 	_numAvailable++;
198*8728f479SAugustin Cavalier 	computeFullness();
199*8728f479SAugustin Cavalier }
200*8728f479SAugustin Cavalier 
201*8728f479SAugustin Cavalier 
202*8728f479SAugustin Cavalier int
getNumAvailable(void)203*8728f479SAugustin Cavalier superblock::getNumAvailable(void)
204*8728f479SAugustin Cavalier {
205*8728f479SAugustin Cavalier 	assert(isValid());
206*8728f479SAugustin Cavalier 	return _numAvailable;
207*8728f479SAugustin Cavalier }
208*8728f479SAugustin Cavalier 
209*8728f479SAugustin Cavalier 
210*8728f479SAugustin Cavalier int
getNumBlocks(void)211*8728f479SAugustin Cavalier superblock::getNumBlocks(void)
212*8728f479SAugustin Cavalier {
213*8728f479SAugustin Cavalier 	assert(isValid());
214*8728f479SAugustin Cavalier 	return _numBlocks;
215*8728f479SAugustin Cavalier }
216*8728f479SAugustin Cavalier 
217*8728f479SAugustin Cavalier 
218*8728f479SAugustin Cavalier int
getBlockSizeClass(void)219*8728f479SAugustin Cavalier superblock::getBlockSizeClass(void)
220*8728f479SAugustin Cavalier {
221*8728f479SAugustin Cavalier 	assert(isValid());
222*8728f479SAugustin Cavalier 	return _sizeClass;
223*8728f479SAugustin Cavalier }
224*8728f479SAugustin Cavalier 
225*8728f479SAugustin Cavalier 
226*8728f479SAugustin Cavalier superblock * const
getNext(void)227*8728f479SAugustin Cavalier superblock::getNext(void)
228*8728f479SAugustin Cavalier {
229*8728f479SAugustin Cavalier 	assert(isValid());
230*8728f479SAugustin Cavalier 	return _next;
231*8728f479SAugustin Cavalier }
232*8728f479SAugustin Cavalier 
233*8728f479SAugustin Cavalier superblock * const
getPrev(void)234*8728f479SAugustin Cavalier superblock::getPrev(void)
235*8728f479SAugustin Cavalier {
236*8728f479SAugustin Cavalier 	assert(isValid());
237*8728f479SAugustin Cavalier 	return _prev;
238*8728f479SAugustin Cavalier }
239*8728f479SAugustin Cavalier 
240*8728f479SAugustin Cavalier 
241*8728f479SAugustin Cavalier void
insertBefore(superblock * nextSb)242*8728f479SAugustin Cavalier superblock::insertBefore(superblock * nextSb)
243*8728f479SAugustin Cavalier {
244*8728f479SAugustin Cavalier 	assert(isValid());
245*8728f479SAugustin Cavalier 	// Insert this superblock before the next one (nextSb).
246*8728f479SAugustin Cavalier 	assert(nextSb != this);
247*8728f479SAugustin Cavalier 	_next = nextSb;
248*8728f479SAugustin Cavalier 	if (nextSb) {
249*8728f479SAugustin Cavalier 		_prev = nextSb->_prev;
250*8728f479SAugustin Cavalier 		nextSb->_prev = this;
251*8728f479SAugustin Cavalier 	}
252*8728f479SAugustin Cavalier }
253*8728f479SAugustin Cavalier 
254*8728f479SAugustin Cavalier 
255*8728f479SAugustin Cavalier void
remove(void)256*8728f479SAugustin Cavalier superblock::remove(void)
257*8728f479SAugustin Cavalier {
258*8728f479SAugustin Cavalier 	// Remove this superblock from a doubly-linked list.
259*8728f479SAugustin Cavalier 	if (_next)
260*8728f479SAugustin Cavalier 		_next->_prev = _prev;
261*8728f479SAugustin Cavalier 	if (_prev)
262*8728f479SAugustin Cavalier 		_prev->_next = _next;
263*8728f479SAugustin Cavalier 
264*8728f479SAugustin Cavalier 	_prev = NULL;
265*8728f479SAugustin Cavalier 	_next = NULL;
266*8728f479SAugustin Cavalier }
267*8728f479SAugustin Cavalier 
268*8728f479SAugustin Cavalier 
269*8728f479SAugustin Cavalier int
isValid(void)270*8728f479SAugustin Cavalier superblock::isValid(void)
271*8728f479SAugustin Cavalier {
272*8728f479SAugustin Cavalier 	assert(_numBlocks > 0);
273*8728f479SAugustin Cavalier 	assert(_numAvailable <= _numBlocks);
274*8728f479SAugustin Cavalier 	assert(_sizeClass >= 0);
275*8728f479SAugustin Cavalier 	return 1;
276*8728f479SAugustin Cavalier }
277*8728f479SAugustin Cavalier 
278*8728f479SAugustin Cavalier 
279*8728f479SAugustin Cavalier void
computeFullness(void)280*8728f479SAugustin Cavalier superblock::computeFullness(void)
281*8728f479SAugustin Cavalier {
282*8728f479SAugustin Cavalier 	assert(isValid());
283*8728f479SAugustin Cavalier 	_fullness = (((SUPERBLOCK_FULLNESS_GROUP - 1)
284*8728f479SAugustin Cavalier 		* (getNumBlocks() - getNumAvailable())) / getNumBlocks());
285*8728f479SAugustin Cavalier }
286*8728f479SAugustin Cavalier 
287*8728f479SAugustin Cavalier 
288*8728f479SAugustin Cavalier int
getFullness(void)289*8728f479SAugustin Cavalier superblock::getFullness(void)
290*8728f479SAugustin Cavalier {
291*8728f479SAugustin Cavalier 	assert(isValid());
292*8728f479SAugustin Cavalier 	return _fullness;
293*8728f479SAugustin Cavalier }
294*8728f479SAugustin Cavalier 
295*8728f479SAugustin Cavalier }	// namespace BPrivate
296*8728f479SAugustin Cavalier 
297*8728f479SAugustin Cavalier #endif // _SUPERBLOCK_H_
298