inorder: enforce 78-character rule
[gem5.git] / src / base / fast_alloc.hh
1 /*
2 * Copyright (c) 2000-2001, 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Steve Reinhardt
29 */
30
31 /*
32 * This code was originally written by Steve Reinhardt as part of
33 * the Wisconsin Wind Tunnel simulator. Relicensed as part of M5
34 * by permission.
35 */
36
37 #ifndef __BASE_FAST_ALLOC_HH__
38 #define __BASE_FAST_ALLOC_HH__
39
40 #include <cstddef>
41
42 // Fast structure allocator. Designed for small objects that are
43 // frequently allocated and deallocated. This code is derived from the
44 // 'alloc_struct' package used in WWT and Blizzard. C++ provides a
45 // much nicer framework for the same optimization. The package is
46 // implemented as a class, FastAlloc. Allocation and deletion are
47 // performed using FastAlloc's new and delete operators. Any object
48 // that derives from the FastAlloc class will transparently use this
49 // allocation package.
50
51 // The static allocate() and deallocate() methods can also be called
52 // directly if desired.
53
54 // In order for derived classes to call delete with the correct
55 // structure size even when they are deallocated via a base-type
56 // pointer, they must have a virtual destructor. It is sufficient for
57 // FastAlloc to declare a virtual destructor (as it does); it is not
58 // required for derived classes to declare their own destructor. The
59 // compiler will automatically generate a virtual destructor for each
60 // derived class. However, it is more efficient if each derived class
61 // defines an inline destructor, so that the compiler can statically
62 // collapse the destructor call chain back up the inheritance
63 // hierarchy.
64
65 #include "config/no_fast_alloc.hh"
66 #include "config/fast_alloc_debug.hh"
67 #include "config/fast_alloc_stats.hh"
68
69 #if NO_FAST_ALLOC
70
71 class FastAlloc
72 {
73 };
74
75 #else
76
77 #if FAST_ALLOC_DEBUG
78 #include "base/types.hh"
79 #endif
80
81 class FastAlloc
82 {
83 public:
84 static void *allocate(size_t);
85 static void deallocate(void *, size_t);
86
87 void *operator new(size_t);
88 void operator delete(void *, size_t);
89
90 #if FAST_ALLOC_DEBUG
91 FastAlloc();
92 FastAlloc(FastAlloc *, FastAlloc *); // for inUseHead, see below
93 virtual ~FastAlloc();
94 #else
95 virtual ~FastAlloc() {}
96 #endif
97
98 private:
99
100 // Max_Alloc_Size is the largest object that can be allocated with
101 // this class. There's no fundamental limit, but this limits the
102 // size of the freeLists array. Let's not make this really huge
103 // like in Blizzard.
104 static const size_t Max_Alloc_Size = 512;
105
106 // Alloc_Quantum is the difference in size between adjacent
107 // buckets in the free list array.
108 static const int Log2_Alloc_Quantum = 3;
109 static const int Alloc_Quantum = (1 << Log2_Alloc_Quantum);
110
111 // Num_Buckets = bucketFor(Max_Alloc_Size) + 1
112 static const int Num_Buckets =
113 ((Max_Alloc_Size + Alloc_Quantum - 1) >> Log2_Alloc_Quantum) + 1;
114
115 // when we call new() for more structures, how many should we get?
116 static const int Num_Structs_Per_New = 20;
117
118 static int bucketFor(size_t);
119 static void *moreStructs(int bucket);
120
121 static void *freeLists[Num_Buckets];
122
123 #if FAST_ALLOC_STATS
124 static unsigned newCount[Num_Buckets];
125 static unsigned deleteCount[Num_Buckets];
126 static unsigned allocCount[Num_Buckets];
127 #endif
128
129 #if FAST_ALLOC_DEBUG
130 // per-object debugging fields
131 bool inUse; // in-use flag
132 FastAlloc *inUsePrev; // ptrs to build list of in-use objects
133 FastAlloc *inUseNext;
134 Tick whenAllocated;
135
136 // static (global) debugging vars
137 static int numInUse; // count in-use objects
138 static FastAlloc inUseHead; // dummy head for list of in-use objects
139
140 public:
141 // functions to dump debugging info (see fast_alloc.cc for C
142 // versions that might be more agreeable to call from gdb)
143 static void dump_summary();
144 static void dump_oldest(int n);
145 static void dump_oldest_of_type(int n, const char *type_name);
146 #endif
147 };
148
149 inline int
150 FastAlloc::bucketFor(size_t sz)
151 {
152 return (sz + Alloc_Quantum - 1) >> Log2_Alloc_Quantum;
153 }
154
155 inline void *
156 FastAlloc::allocate(size_t sz)
157 {
158 int b;
159 void *p;
160
161 if (sz > Max_Alloc_Size)
162 return (void *)::new char[sz];
163
164 b = bucketFor(sz);
165 p = freeLists[b];
166
167 if (p)
168 freeLists[b] = *(void **)p;
169 else
170 p = moreStructs(b);
171
172 #if FAST_ALLOC_STATS
173 ++newCount[b];
174 #endif
175
176 return p;
177 }
178
179 inline void
180 FastAlloc::deallocate(void *p, size_t sz)
181 {
182 int b;
183
184 if (sz > Max_Alloc_Size) {
185 ::delete [] (char *)p;
186 return;
187 }
188
189 b = bucketFor(sz);
190 *(void **)p = freeLists[b];
191 freeLists[b] = p;
192 #if FAST_ALLOC_STATS
193 ++deleteCount[b];
194 #endif
195 }
196
197 inline void *
198 FastAlloc::operator new(size_t sz)
199 {
200 return allocate(sz);
201 }
202
203 inline void
204 FastAlloc::operator delete(void *p, size_t sz)
205 {
206 deallocate(p, sz);
207 }
208
209 #endif // NO_FAST_ALLOC
210
211 #endif // __BASE_FAST_ALLOC_HH__