source: proiecte/swift/trunk/lib/hoard-371/src/heaplayers/coalesceableheap.h @ 176

Last change on this file since 176 was 176, checked in by (none), 14 years ago
  • imported repo from "guagal"
File size: 10.4 KB
Line 
1/* -*- C++ -*- */
2
3/*
4
5  Heap Layers: An Extensible Memory Allocation Infrastructure
6 
7  Copyright (C) 2000-2003 by Emery Berger
8  http://www.cs.umass.edu/~emery
9  emery@cs.umass.edu
10 
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation; either version 2 of the License, or
14  (at your option) any later version.
15 
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24
25*/
26
27/**
28 * @file coalesceableheap.h
29 * @brief Coalescing support, via RequireCoalesceable and CoalesceableHeap.
30 * @author Emery Berger
31 */
32
33#ifndef _COALESCEABLEHEAP_H_
34#define _COALESCEABLEHEAP_H_
35
36#include <assert.h>
37
38#define MULTIPLE_HEAP_SUPPORT 0
39
40/**
41 * @class RequireCoalesceable
42 * @brief Provides support for coalescing objects.
43 */
44
45namespace HL {
46
47template <class SuperHeap>
48class RequireCoalesceable : public SuperHeap {
49public:
50
51  // Some thin wrappers over Header methods.
52  inline static int getHeap (void * ptr)          { return Header::getHeader(ptr)->getHeap(); }
53  inline static void setHeap (void * ptr, int h)  { Header::getHeader(ptr)->setHeap(h); }
54  inline static int getPrevHeap (void * ptr)      { return Header::getHeader(ptr)->getPrevHeap(); }
55  inline static void setPrevHeap (void * ptr, int h) { Header::getHeader(ptr)->setPrevHeap(h); }
56
57  inline static size_t getSize (const void * ptr)       { return Header::getHeader(ptr)->getSize(); }
58
59  inline static void setSize (void * ptr, const size_t sz) { Header::getHeader(ptr)->setSize(sz); }
60  inline static size_t getPrevSize (void * ptr)   { return Header::getHeader(ptr)->getPrevSize(); }
61  inline static void setPrevSize (void * ptr, const size_t sz) { Header::getHeader(ptr)->setPrevSize(sz); }
62  inline static void markFree (void * ptr)        { Header::getHeader(ptr)->markFree(); }
63  inline static void markInUse (void * ptr)       { Header::getHeader(ptr)->markInUse(); }
64  inline static void markPrevInUse (void * ptr)   { Header::getHeader(ptr)->markPrevInUse(); }
65  inline static void markMmapped (void * ptr)     { Header::getHeader(ptr)->markMmapped(); }
66  inline static int isFree (void * ptr)           { return Header::getHeader(ptr)->isFree(); }
67  inline static int isPrevFree (void * ptr)       { return Header::getHeader(ptr)->isPrevFree(); }
68  inline static int isMmapped (void * ptr)        { return Header::getHeader(ptr)->isMmapped(); }
69  inline static void * getNext (const void * ptr)       { return Header::getHeader(ptr)->getNext(); }
70  inline static void * getPrev (const void * ptr)       { return Header::getHeader(ptr)->getPrev(); }
71
72  // The Header for every object, allocated or freed.
73  class Header {
74          friend class RequireCoalesceable<SuperHeap>;
75  public:
76
77    //
78    // Initialize a new object in a given buffer, with a previous & current object size.
79    // Returns the start of the object (i.e., just past the header).
80    //
81    inline static void * makeObject (void * buf, const size_t prevsz, const size_t sz) {
82          *((Header *) buf) = Header (prevsz, sz);
83          Header * nextHeader = (Header *) ((char *) ((Header *) buf + 1) + sz);
84//        Header * nextHeader = h->getNextHeader();
85//        nextHeader->markPrevInUse();
86          nextHeader->setPrevSize (sz);
87      // return Header::getObject (h);
88          return ((Header *) buf + 1);
89    }
90
91
92    inline void sanityCheck (void) {
93#ifndef NDEBUG
94      int headerSize = sizeof(Header);
95      assert (headerSize <= sizeof(double));
96      assert (getSize() == getNextHeader()->getPrevSize());
97      assert (isFree() == getNextHeader()->isPrevFree());
98      assert (getNextHeader()->getPrev() == getObject(this));
99#if 0
100      if (isPrevFree()) {
101        assert (getPrevSize() == getHeader(getPrev())->getSize());
102      }
103#endif
104#endif
105    }
106
107    // Get the header for a given object.
108    inline static Header * getHeader (const void * ptr) { return ((Header *) ptr - 1); }
109
110    // Get the object for a given header.
111    inline static void * getObject (const Header * hd)  { return (void *) (hd + 1); }
112
113    inline void setSize (const size_t sz)    { _size = sz; }
114    inline void setPrevSize (const size_t sz){ _prevSize = sz; }
115
116//  private:
117    inline size_t getPrevSize (void) const { return _prevSize; }
118
119    inline void markFree (void)        {
120                // printf ("markFree\n");
121                getNextHeader()->markPrevFree();
122        }
123    inline void markInUse (void)       {
124                // printf ("markInUse\n");
125                getNextHeader()->markPrevInUse();
126        }
127    inline void markMmapped (void)     { _isMmapped = IS_MMAPPED; }
128    inline void markNotMmapped (void)  { _isMmapped = NOT_MMAPPED; }
129    inline int isFree (void) const     {
130                // printf ("isFree\n");
131                return getNextHeader()->isPrevFree();
132        }
133    inline int isNextFree (void) const {
134                // printf ("isNextFree\n");
135                return getNextHeader()->getNextHeader()->isPrevFree();
136        }
137    inline int isMmapped (void) const  { return (_isMmapped != NOT_MMAPPED); }
138    inline void * getPrev (void) const {
139        //      fprintf (stderr, "coalesceableheap.h: %x, %d\n", this, getPrevSize());
140                return ((char *) this) - getPrevSize(); 
141        }
142    inline void * getNext (void) const { 
143                // printf ("getNext\n");
144                return ((char *) (this + 2)) + getSize();
145        }
146
147    inline void markPrevFree (void)    { _prevStatus = PREV_FREE; }
148    inline void markPrevInUse (void)   { _prevStatus = PREV_INUSE; }
149    inline int isPrevFree (void) const { return (_prevStatus != PREV_INUSE); }
150    inline size_t getSize (void) const { return _size; }
151
152#if MULTIPLE_HEAP_SUPPORT
153    inline int getHeap (void) const { return _currHeap; }
154    inline void setHeap (int h)     { _currHeap = h; }
155    inline int getPrevHeap (void) const { return _prevHeap; }
156    inline void setPrevHeap (int h) { _prevHeap = h; }
157#else
158    inline int getHeap (void) const { return 0; }
159    inline void setHeap (int)       {  }
160    inline int getPrevHeap (void) const { return 0; }
161    inline void setPrevHeap (int)   {  }
162#endif
163
164
165  private:
166
167    explicit inline Header (void) {}
168    explicit inline Header (const size_t prevsz, const size_t sz)
169      :
170      _prevSize (prevsz),
171      _size (sz),
172      // Assume that objects are NOT mmapped.
173      _isMmapped (NOT_MMAPPED)
174#if MULTIPLE_HEAP_SUPPORT
175      , _prevHeap (0),
176      _currHeap (0)
177#endif
178    {
179      assert (sizeof(Header) <= sizeof(double));
180    }
181
182    inline Header * getNextHeader (void) const {
183      // printf ("H\n");
184      return ((Header *) ((char *) (this + 1) + getSize()));
185    }
186
187#if !(MULTIPLE_HEAP_SUPPORT) // original
188
189    // Is the previous object free or in use?
190    enum { PREV_INUSE = 0, PREV_FREE = 1 };
191    unsigned int _prevStatus : 1;
192
193    // Is the current object mmapped?
194    enum { NOT_MMAPPED = 0, IS_MMAPPED = 1 };
195    unsigned int _isMmapped : 1;
196
197    // The size of the previous object.
198    enum { NUM_BITS_STOLEN_FROM_PREVSIZE = 2 };
199    size_t _prevSize : sizeof(size_t) * 8 - NUM_BITS_STOLEN_FROM_PREVSIZE;
200
201    // The size of the current object.
202    enum { NUM_BITS_STOLEN_FROM_SIZE = 0 };
203    size_t _size; // : sizeof(size_t) * 8 - NUM_BITS_STOLEN_FROM_SIZE;
204
205
206#else // new support for scalability...
207
208    // Support for 2^5 = 32 heaps.
209    enum { NUM_BITS_FOR_HEAP = 5 };
210
211    enum { NUM_BITS_STOLEN_FROM_SIZE = NUM_BITS_FOR_HEAP + 1 };     // 1 for isMmapped
212    enum { NUM_BITS_STOLEN_FROM_PREVSIZE = NUM_BITS_FOR_HEAP + 1 }; // 1 for isPrevFree
213
214    // Max object size.
215    enum { MAX_OBJECT_SIZE = 1 << (sizeof(size_t) * 8 - NUM_BITS_STOLEN_FROM_SIZE) };
216
217    //// word 1 ////
218
219    // The size of the previous object.
220    size_t _prevSize : sizeof(size_t) * 8 - NUM_BITS_STOLEN_FROM_PREVSIZE;
221
222    // What's the previous heap?
223    unsigned int _prevHeap : NUM_BITS_FOR_HEAP;
224
225    // Is the previous object free or in use?
226    enum { PREV_FREE = 0, PREV_INUSE = 1 };
227    unsigned int _prevStatus : 1;
228
229    //// word 2 ////
230
231    // The size of the current object.
232    size_t _size : sizeof(size_t) * 8 - NUM_BITS_STOLEN_FROM_SIZE;
233
234    // What's the current heap?
235    unsigned int _currHeap : NUM_BITS_FOR_HEAP;
236
237    // Is the current object mmapped?
238    enum { NOT_MMAPPED = 0, IS_MMAPPED = 1 };
239    unsigned int _isMmapped : 1;
240
241#endif
242  };
243
244  inline static void * makeObject (void * buf, const size_t prevsz, const size_t sz) {
245    return Header::makeObject (buf, prevsz, sz);
246  }
247
248  inline static Header * getHeader (const void * ptr) {
249    return Header::getHeader (ptr);
250  }
251
252};
253
254
255/**
256 * @class CoalesceableHeap
257 * @brief Manages coalesceable memory.
258 */
259
260template <class SuperHeap>
261class CoalesceableHeap : public RequireCoalesceable<SuperHeap> {
262public:
263
264  typedef typename RequireCoalesceable<SuperHeap>::Header Header;
265
266  inline CoalesceableHeap (void)
267  { }
268
269  inline void * malloc (const size_t sz) {
270    void * buf = SuperHeap::malloc (sz + sizeof(Header));
271    if (buf) {
272      Header * header = (Header *) buf;
273
274      //
275      // Record the size of this object in the current header
276      // and the next.
277      //
278
279      header->setSize (sz);
280
281      // Below was:
282//      Header * nextHeader = Header::getHeader (header->getNext());
283      Header * nextHeader = (Header *) ((char *) (header + 1) + sz);
284
285      nextHeader->setPrevSize (sz);
286
287#if 0
288      //
289      // As long as the source of this memory
290      // is always zeroed, these assertions will hold.
291      // The easiest way to do this is to use a ZeroHeap.
292      //
293      assert (header->isMmapped() == FALSE);
294      assert (nextHeader->getSize() ==  0);
295      assert (!nextHeader->isFree());
296      assert (!nextHeader->isPrevFree());
297
298#else
299
300      // If the memory is not zeroed, we need this section of code.
301
302      //
303      // Assume that everything allocated is NOT mmapped.
304      // It is the responsibility of a child layer
305      // to mark mmapped objects as such.
306      //
307
308      header->markNotMmapped ();
309
310      nextHeader->setSize (0);
311
312      //
313      // Mark the subsequent "object" as in use in order to prevent
314      // accidental coalescing.
315      //
316
317//        (nextHeader + 1)->markPrevInUse();
318      nextHeader->markInUse ();
319#endif
320
321      // Below was:
322      // return Header::getObject (header);
323      return (header + 1);
324    }
325    return NULL;
326  }
327 
328  inline void free (void * ptr) {
329    assert (SuperHeap::isFree(ptr));
330    SuperHeap::free ((Header *) ptr - 1);
331  }
332
333
334};
335
336};
337
338#endif // _COALESCEABLEHEAP_H_
339
Note: See TracBrowser for help on using the repository browser.