xref: /haiku/src/system/libroot/posix/malloc/hoard2/threadheap.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 #ifndef _THREADHEAP_H_
21*8728f479SAugustin Cavalier #define _THREADHEAP_H_
22*8728f479SAugustin Cavalier 
23*8728f479SAugustin Cavalier #include "config.h"
24*8728f479SAugustin Cavalier 
25*8728f479SAugustin Cavalier #include <string.h>
26*8728f479SAugustin Cavalier 
27*8728f479SAugustin Cavalier #include "heap.h"
28*8728f479SAugustin Cavalier 
29*8728f479SAugustin Cavalier namespace BPrivate {
30*8728f479SAugustin Cavalier 
31*8728f479SAugustin Cavalier class processHeap;		 // forward declaration
32*8728f479SAugustin Cavalier 
33*8728f479SAugustin Cavalier //
34*8728f479SAugustin Cavalier // We use one threadHeap for each thread (processor).
35*8728f479SAugustin Cavalier //
36*8728f479SAugustin Cavalier 
37*8728f479SAugustin Cavalier class threadHeap : public hoardHeap {
38*8728f479SAugustin Cavalier 	public:
39*8728f479SAugustin Cavalier 		threadHeap(void);
40*8728f479SAugustin Cavalier 
41*8728f479SAugustin Cavalier 		// Memory allocation routines.
42*8728f479SAugustin Cavalier 		void *malloc(const size_t sz);
43*8728f479SAugustin Cavalier 		inline void *memalign(size_t alignment, size_t sz);
44*8728f479SAugustin Cavalier 
45*8728f479SAugustin Cavalier 		// Find out how large an allocated object is.
46*8728f479SAugustin Cavalier 		inline static size_t objectSize(void *ptr);
47*8728f479SAugustin Cavalier 
48*8728f479SAugustin Cavalier 		// Set our process heap.
49*8728f479SAugustin Cavalier 		inline void setpHeap(processHeap *p);
50*8728f479SAugustin Cavalier 
51*8728f479SAugustin Cavalier 	private:
52*8728f479SAugustin Cavalier 		// Prevent copying and assignment.
53*8728f479SAugustin Cavalier 		threadHeap(const threadHeap &);
54*8728f479SAugustin Cavalier 		const threadHeap &operator=(const threadHeap &);
55*8728f479SAugustin Cavalier 
56*8728f479SAugustin Cavalier 		// Our process heap.
57*8728f479SAugustin Cavalier 		processHeap *_pHeap;
58*8728f479SAugustin Cavalier 
59*8728f479SAugustin Cavalier 		// We insert a cache pad here to avoid false sharing (the
60*8728f479SAugustin Cavalier 		// processHeap holds an array of threadHeaps, and we don't want
61*8728f479SAugustin Cavalier 		// these to share any cache lines).
62*8728f479SAugustin Cavalier 		double _pad[CACHE_LINE / sizeof(double)];
63*8728f479SAugustin Cavalier };
64*8728f479SAugustin Cavalier 
65*8728f479SAugustin Cavalier 
66*8728f479SAugustin Cavalier void *
memalign(size_t alignment,size_t size)67*8728f479SAugustin Cavalier threadHeap::memalign(size_t alignment, size_t size)
68*8728f479SAugustin Cavalier {
69*8728f479SAugustin Cavalier 	// Calculate the amount of space we need
70*8728f479SAugustin Cavalier 	// to satisfy the alignment requirements.
71*8728f479SAugustin Cavalier 
72*8728f479SAugustin Cavalier 	size_t newSize;
73*8728f479SAugustin Cavalier 
74*8728f479SAugustin Cavalier 	// If the alignment is less than the required alignment,
75*8728f479SAugustin Cavalier 	// just call malloc.
76*8728f479SAugustin Cavalier 	if (alignment <= ALIGNMENT)
77*8728f479SAugustin Cavalier 		return this->malloc(size);
78*8728f479SAugustin Cavalier 
79*8728f479SAugustin Cavalier 	if (alignment < sizeof(block))
80*8728f479SAugustin Cavalier 		alignment = sizeof(block);
81*8728f479SAugustin Cavalier 
82*8728f479SAugustin Cavalier 	// Alignment must be a power of two!
83*8728f479SAugustin Cavalier 	assert((alignment & (alignment - 1)) == 0);
84*8728f479SAugustin Cavalier 
85*8728f479SAugustin Cavalier 	// Leave enough room to align the block within the malloced space.
86*8728f479SAugustin Cavalier 	newSize = size + sizeof(block) + alignment;
87*8728f479SAugustin Cavalier 
88*8728f479SAugustin Cavalier 	// Now malloc the space up with a little extra (we'll put the block
89*8728f479SAugustin Cavalier 	// pointer in right behind the allocated space).
90*8728f479SAugustin Cavalier 
91*8728f479SAugustin Cavalier 	void *ptr = this->malloc(newSize);
92*8728f479SAugustin Cavalier 	if ((((unsigned long) ptr) & -((long) alignment)) == 0) {
93*8728f479SAugustin Cavalier 		// ptr is already aligned, so return it.
94*8728f479SAugustin Cavalier 		assert(((unsigned long) ptr % alignment) == 0);
95*8728f479SAugustin Cavalier 		return ptr;
96*8728f479SAugustin Cavalier 	} else {
97*8728f479SAugustin Cavalier 		// Align ptr.
98*8728f479SAugustin Cavalier 		char *newptr = (char *)(((unsigned long)ptr + alignment - 1) & -((long)alignment));
99*8728f479SAugustin Cavalier 
100*8728f479SAugustin Cavalier 		// If there's not enough room for the block header, skip to the
101*8728f479SAugustin Cavalier 		// next aligned space within the block..
102*8728f479SAugustin Cavalier 		if ((unsigned long)newptr - (unsigned long)ptr < sizeof(block))
103*8728f479SAugustin Cavalier 			newptr += alignment;
104*8728f479SAugustin Cavalier 
105*8728f479SAugustin Cavalier 		assert(((unsigned long)newptr % alignment) == 0);
106*8728f479SAugustin Cavalier 
107*8728f479SAugustin Cavalier 		// Copy the block from the start of the allocated memory.
108*8728f479SAugustin Cavalier 		block *b = ((block *)ptr - 1);
109*8728f479SAugustin Cavalier 
110*8728f479SAugustin Cavalier 		assert(b->isValid());
111*8728f479SAugustin Cavalier 		assert(b->getSuperblock()->isValid());
112*8728f479SAugustin Cavalier 
113*8728f479SAugustin Cavalier 		// Make sure there's enough room for the block header.
114*8728f479SAugustin Cavalier 		assert(((unsigned long)newptr - (unsigned long)ptr) >=
115*8728f479SAugustin Cavalier 		       sizeof(block));
116*8728f479SAugustin Cavalier 
117*8728f479SAugustin Cavalier 		block *p = ((block *)newptr - 1);
118*8728f479SAugustin Cavalier 
119*8728f479SAugustin Cavalier 		// Make sure there's enough room allocated for size bytes.
120*8728f479SAugustin Cavalier 		assert(((unsigned long)p - sizeof(block)) >= (unsigned long)b);
121*8728f479SAugustin Cavalier 
122*8728f479SAugustin Cavalier 		if (p != b) {
123*8728f479SAugustin Cavalier 			assert((unsigned long)newptr > (unsigned long)ptr);
124*8728f479SAugustin Cavalier 			// Copy the block header.
125*8728f479SAugustin Cavalier 			*p = *b;
126*8728f479SAugustin Cavalier 			assert(p->isValid());
127*8728f479SAugustin Cavalier 			assert(p->getSuperblock()->isValid());
128*8728f479SAugustin Cavalier 
129*8728f479SAugustin Cavalier 			// Set the next pointer to point to b with the 1 bit set.
130*8728f479SAugustin Cavalier 			// When this block is freed, it will be treated specially.
131*8728f479SAugustin Cavalier 			p->setNext((block *)((unsigned long)b | 1));
132*8728f479SAugustin Cavalier 		} else
133*8728f479SAugustin Cavalier 			assert(ptr != newptr);
134*8728f479SAugustin Cavalier 
135*8728f479SAugustin Cavalier 		assert(((unsigned long)ptr + newSize) >=
136*8728f479SAugustin Cavalier 		       ((unsigned long)newptr + size));
137*8728f479SAugustin Cavalier 		return newptr;
138*8728f479SAugustin Cavalier 	}
139*8728f479SAugustin Cavalier }
140*8728f479SAugustin Cavalier 
141*8728f479SAugustin Cavalier 
142*8728f479SAugustin Cavalier size_t
objectSize(void * ptr)143*8728f479SAugustin Cavalier threadHeap::objectSize(void *ptr)
144*8728f479SAugustin Cavalier {
145*8728f479SAugustin Cavalier 	// Find the superblock pointer.
146*8728f479SAugustin Cavalier 	block *b = ((block *)ptr - 1);
147*8728f479SAugustin Cavalier 	assert(b->isValid());
148*8728f479SAugustin Cavalier 	superblock *sb = b->getSuperblock();
149*8728f479SAugustin Cavalier 	assert(sb);
150*8728f479SAugustin Cavalier 
151*8728f479SAugustin Cavalier 	// Return the size.
152*8728f479SAugustin Cavalier 	return sizeFromClass(sb->getBlockSizeClass());
153*8728f479SAugustin Cavalier }
154*8728f479SAugustin Cavalier 
155*8728f479SAugustin Cavalier 
setpHeap(processHeap * p)156*8728f479SAugustin Cavalier void threadHeap::setpHeap(processHeap *p)
157*8728f479SAugustin Cavalier {
158*8728f479SAugustin Cavalier 	_pHeap = p;
159*8728f479SAugustin Cavalier }
160*8728f479SAugustin Cavalier 
161*8728f479SAugustin Cavalier }	// namespace BPrivate
162*8728f479SAugustin Cavalier 
163*8728f479SAugustin Cavalier #endif				 // _THREADHEAP_H_
164