1///-*-C++-*-//////////////////////////////////////////////////////////////////
2//
3// The Hoard Multiprocessor Memory Allocator
4// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery
5//
6// Copyright (c) 1998-2000, The University of Texas at Austin.
7//
8// This library is free software; you can redistribute it and/or modify
9// it under the terms of the GNU Library General Public License as
10// published by the Free Software Foundation, http://www.fsf.org.
11//
12// This library is distributed in the hope that it will be useful, but
13// WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15// Library General Public License for more details.
16//
17//////////////////////////////////////////////////////////////////////////////
18
19/*
20  superblock.cpp
21  ------------------------------------------------------------------------
22  The superblock class controls a number of blocks (which are
23  allocatable units of memory).
24  ------------------------------------------------------------------------
25  Emery Berger                    | <http://www.cs.utexas.edu/users/emery>
26  Department of Computer Sciences |             <http://www.cs.utexas.edu>
27  University of Texas at Austin   |                <http://www.utexas.edu>
28  ========================================================================
29*/
30
31#include <string.h>
32
33#include "arch-specific.h"
34#include "config.h"
35#include "heap.h"
36#include "processheap.h"
37#include "superblock.h"
38
39using namespace BPrivate;
40
41
42superblock::superblock(int numBlocks,	// The number of blocks in the sb.
43                       int szclass,		// The size class of the blocks.
44                       hoardHeap * o)	// The heap that "owns" this sb.
45	:
46#if HEAP_DEBUG
47	_magic(SUPERBLOCK_MAGIC),
48#endif
49	_sizeClass(szclass),
50	_numBlocks(numBlocks),
51	_numAvailable(0),
52	_fullness(0), _freeList(NULL), _owner(o), _next(NULL), _prev(NULL)
53{
54	assert(_numBlocks >= 1);
55
56	// Determine the size of each block.
57	const int blksize = hoardHeap::align(sizeof(block)
58		+ hoardHeap::sizeFromClass(_sizeClass));
59
60	// Make sure this size is in fact aligned.
61	assert((blksize & hoardHeap::ALIGNMENT_MASK) == 0);
62
63	// Set the first block to just past this superblock header.
64	block *b = (block *) hoardHeap::align((unsigned long)(this + 1));
65
66	// Initialize all the blocks,
67	// and insert the block pointers into the linked list.
68	for (int i = 0; i < _numBlocks; i++) {
69		// Make sure the block is on a double-word boundary.
70		assert(((unsigned long)b & hoardHeap::ALIGNMENT_MASK) == 0);
71		new(b) block(this);
72		assert(b->getSuperblock() == this);
73		b->setNext(_freeList);
74		_freeList = b;
75		b = (block *)((char *)b + blksize);
76	}
77
78	_numAvailable = _numBlocks;
79	computeFullness();
80	assert((unsigned long)b <= hoardHeap::align(sizeof(superblock) + blksize * _numBlocks)
81		+ (unsigned long)this);
82
83	hoardLockInit(_upLock, "hoard superblock");
84}
85
86
87superblock *
88superblock::makeSuperblock(int sizeclass, processHeap *pHeap)
89{
90	// We need to get more memory.
91
92	char *buf;
93	int numBlocks = hoardHeap::numBlocks(sizeclass);
94
95	// Compute how much memory we need.
96	unsigned long moreMemory;
97	if (numBlocks > 1) {
98		moreMemory = hoardHeap::SUPERBLOCK_SIZE;
99		assert(moreMemory >= hoardHeap::align(sizeof(superblock)
100			+ (hoardHeap::align(sizeof(block)
101			+ hoardHeap::sizeFromClass(sizeclass))) * numBlocks));
102
103		// Get some memory from the process heap.
104		buf = (char *)pHeap->getSuperblockBuffer();
105	} else {
106		// One object.
107		assert(numBlocks == 1);
108
109		size_t blksize = hoardHeap::align(sizeof(block)
110			+ hoardHeap::sizeFromClass(sizeclass));
111		moreMemory = hoardHeap::align(sizeof(superblock) + blksize);
112
113		// Get space from the system.
114		buf = (char *)hoardSbrk(moreMemory);
115	}
116
117	// Make sure that we actually got the memory.
118	if (buf == NULL)
119		return 0;
120
121	buf = (char *)hoardHeap::align((unsigned long)buf);
122
123	// Make sure this buffer is double-word aligned.
124	assert(buf == (char *)hoardHeap::align((unsigned long)buf));
125	assert((((unsigned long)buf) & hoardHeap::ALIGNMENT_MASK) == 0);
126
127	// Instantiate the new superblock in the buffer.
128	return new(buf) superblock(numBlocks, sizeclass, NULL);
129}
130