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