1///-*-C++-*-//////////////////////////////////////////////////////////////////
2//
3// Hoard: A Fast, Scalable, and Memory-Efficient Allocator
4//        for Shared-Memory Multiprocessors
5// Contact author: Emery Berger, http://www.cs.utexas.edu/users/emery
6//
7// Copyright (c) 1998-2000, The University of Texas at Austin.
8//
9// This library is free software; you can redistribute it and/or modify
10// it under the terms of the GNU Library General Public License as
11// published by the Free Software Foundation, http://www.fsf.org.
12//
13// This library is distributed in the hope that it will be useful, but
14// WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16// Library General Public License for more details.
17//
18//////////////////////////////////////////////////////////////////////////////
19
20//#include <limits.h>
21#include <string.h>
22
23#include "config.h"
24
25#include "heap.h"
26#include "threadheap.h"
27#include "processheap.h"
28
29using namespace BPrivate;
30
31
32threadHeap::threadHeap(void)
33	:_pHeap(0)
34{
35}
36
37
38// malloc (sz):
39//   inputs: the size of the object to be allocated.
40//   returns: a pointer to an object of the appropriate size.
41//   side effects: allocates a block from a superblock;
42//                 may call sbrk() (via makeSuperblock).
43
44void *
45threadHeap::malloc(const size_t size)
46{
47#if MAX_INTERNAL_FRAGMENTATION == 2
48	if (size > 1063315264UL) {
49		debug_printf("malloc() of %lu bytes asked\n", size);
50		return NULL;
51	}
52#endif
53
54	const int sizeclass = sizeClass(size);
55	block *b = NULL;
56
57	lock();
58
59	// Look for a free block.
60	// We usually have memory locally so we first look for space in the
61	// superblock list.
62
63	superblock *sb = findAvailableSuperblock(sizeclass, b, _pHeap);
64	if (sb == NULL) {
65		// We don't have memory locally.
66		// Try to get more from the process heap.
67
68		assert(_pHeap);
69		sb = _pHeap->acquire((int)sizeclass, this);
70
71		// If we didn't get any memory from the process heap,
72		// we'll have to allocate our own superblock.
73		if (sb == NULL) {
74			sb = superblock::makeSuperblock(sizeclass, _pHeap);
75			if (sb == NULL) {
76				// We're out of memory!
77				unlock();
78				return NULL;
79			}
80#if HEAP_LOG
81			// Record the memory allocation.
82			MemoryRequest m;
83			m.allocate((int)sb->getNumBlocks() *
84				(int)sizeFromClass(sb->getBlockSizeClass()));
85			_pHeap->getLog(getIndex()).append(m);
86#endif
87#if HEAP_FRAG_STATS
88			_pHeap->setAllocated(0,
89				sb->getNumBlocks() * sizeFromClass(sb->getBlockSizeClass()));
90#endif
91		}
92		// Get a block from the superblock.
93		b = sb->getBlock();
94		assert(b != NULL);
95
96		// Insert the superblock into our list.
97		insertSuperblock(sizeclass, sb, _pHeap);
98	}
99
100	assert(b != NULL);
101	assert(b->isValid());
102	assert(sb->isValid());
103
104	b->markAllocated();
105
106#if HEAP_LOG
107	MemoryRequest m;
108	m.malloc((void *)(b + 1), align(size));
109	_pHeap->getLog(getIndex()).append(m);
110#endif
111#if HEAP_FRAG_STATS
112	b->setRequestedSize(align(size));
113	_pHeap->setAllocated(align(size), 0);
114#endif
115
116	unlock();
117
118	// Skip past the block header and return the pointer.
119	return (void *)(b + 1);
120}
121