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