Eneboo - Documentación para desarrolladores
src/hoard/src/heaplayers/experimental/seg.h
Ir a la documentación de este archivo.
00001 // -*- C++ -*-
00002 
00003 /*
00004 
00005   Heap Layers: An Extensible Memory Allocation Infrastructure
00006   
00007   Copyright (C) 2000-2003 by Emery Berger
00008   http://www.cs.umass.edu/~emery
00009   emery@cs.umass.edu
00010   
00011   This program is free software; you can redistribute it and/or modify
00012   it under the terms of the GNU General Public License as published by
00013   the Free Software Foundation; either version 2 of the License, or
00014   (at your option) any later version.
00015   
00016   This program is distributed in the hope that it will be useful,
00017   but WITHOUT ANY WARRANTY; without even the implied warranty of
00018   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019   GNU General Public License for more details.
00020   
00021   You should have received a copy of the GNU General Public License
00022   along with this program; if not, write to the Free Software
00023   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 
00025 */
00026 
00027 #ifndef _SEG_H_
00028 #define _SEG_H_
00029 
00030 #include <assert.h>
00031 
00032 #include "sassert.h"
00033 #include "reaplet.h"
00034 
00035 namespace HL {
00036 
00037 template <int ReapletSize,
00038           class SizeClassComputer,
00039           class TopHeap>
00040 class Seg : public TopHeap {
00041 public:
00042 
00043   enum { Alignment = sizeof(double) };
00044 
00045 private:
00046 
00047   Seg (void)
00048   {
00049     sassert <(sizeof(Reaplet<ReapletSize>) == ReapletSize)> verifyReapletSize;
00050   }
00051   
00052   class SanityChecker {
00053   public:
00054     SanityChecker (Seg * s)
00055       : _s (s)
00056       {
00057         _s->sanityCheck();
00058       }
00059     ~SanityChecker (void) {
00060       _s->sanityCheck();
00061     }
00062   private:
00063     Seg * _s;
00064   };
00065 
00066 
00067 #if 1
00068   enum { TopAlignment = TopHeap::Alignment };
00069 
00070   class VerifyAlignment :
00071     public sassert <TopAlignment % ReapletSize == 0> {};
00072 #endif
00073 
00074 public:
00075 
00076   __forceinline Seg (void) {
00077     for (int i = 0; i < SizeClassComputer::NUM_BINS; i++) {
00078       available[i] = 0;
00079       full[i] = 0;
00080     }
00081   }
00082 
00083   ~Seg (void) {
00084     clear();
00085   }
00086 
00087   __forceinline void * malloc (size_t sz) {
00088     SanityChecker c (this);
00089     assert (sz <= SizeClassComputer::BIG_OBJECT);
00090     const int SizeClass = SizeClassComputer::getSizeClass (sz);
00091     // Try to use one of our reaplets to satisfy the request.
00092     Reaplet<ReapletSize> * const xs = available[SizeClass];
00093     if (xs) {
00094       //      assert (!xs->isFull());
00095       // We've got one. Now try to get some memory from it.
00096       void * const ptr = xs->malloc (SizeClassComputer::bins[SizeClass]);
00097       //      printf ("allocated: %x\n", ptr);
00098       if (ptr) {
00099         // Success! We're out of here.
00100         return ptr;
00101       } else {
00102         // It's full.
00103         //      printf ("Full - adios.\n");
00104         removeFromAvailable (xs, SizeClass);
00105       }
00106     }
00107     //    printf ("slow!\n");
00108     // We have to go get more memory.
00109     return slowPathGetMoreMemory (sz);
00110   }
00111 
00112 
00113   __forceinline static size_t getSize (void * ptr) {
00114     return (enclosingReaplet (ptr))->getSize();
00115   }
00116 
00117   __forceinline void free (void * ptr) {
00118     SanityChecker c (this);
00119     // printf ("seg free: r = %x\n", r);
00120     Reaplet<ReapletSize> * r = enclosingReaplet (ptr);
00121     //    printf ("freeing %x to %x\n", ptr, r);
00122     //    if (sz <= SizeClassComputer::BIG_OBJECT) {
00123     // It's a small object. Free it.
00124     bool wasFull = r->isFull(); //  || !r->getAmountAllocated()) {
00125     r->free (ptr);
00126     if (wasFull) {
00127       moveFromFullToAvailable (r);
00128     }
00129   }
00130 
00131   void clear (void) {
00132     SanityChecker c (this);
00133     for (int i = 0; i < SizeClassComputer::NUM_BINS; i++) {
00134       clearOut (full[i]);
00135       clearOut (available[i]);
00136     }
00137   }
00138 
00139 private:
00140 
00141   __forceinline void * slowPathGetMoreMemory (const size_t sz) {
00142     //    printf ("slowpathgetmorememory\n");
00143     SanityChecker c (this);
00144     if (sz <= SizeClassComputer::BIG_OBJECT) {
00145       const int SizeClass = SizeClassComputer::getSizeClass (sz);
00146       do {
00147         // printf ("looking for more memory.\n");
00148         Reaplet<ReapletSize> * xs = available[SizeClass];
00149         // Look for an available reaplet.
00150         if (xs != 0) {
00151           assert (!xs->isFull());
00152           // We've got one. Now try to get some memory from it.
00153           void * ptr = xs->malloc (SizeClassComputer::bins[SizeClass]);
00154           if (ptr) {
00155             // Success!
00156             //      printf ("amt free = %d\n", enclosingReaplet(ptr)->getAmountFree());
00157             // printf ("success: found more memory.\n");
00158             return ptr;
00159           } else {
00160             //      printf ("Adios!\n");
00161             // This reaplet is out of memory.
00162             // Remove it from the available list.
00163             removeFromAvailable (xs, SizeClass);
00164             // Put it on the full list.
00165             putOnFullList (xs, SizeClass);
00166           }
00167         } else {
00168           // The current bin is empty - make another reaplet.
00169           int r = insertNewReaplet (SizeClass);
00170           if (!r) {
00171             return 0;
00172           }
00173         }
00174       } while (1);
00175     } else {
00176       return makeBigObject (sz);
00177     }
00178   }
00179 
00180   __forceinline void sanityCheck (void) {
00181 #if !defined(NDEBUG)
00182     // FIX ME
00183     //#error "whoa dude. slowing things down."
00184     Reaplet<ReapletSize> * q;
00185     for (int i = 0; i < SizeClassComputer::NUM_BINS; i++) {
00186       // Visit the available list.
00187       q = available[i];
00188       if (q) {
00189         assert (q->getPrev() == 0);
00190       }
00191       while (q) {
00192         if (q->isFull()) {
00193           // printf ("allocated = %d\n", q->getAmountAllocated());
00194         }
00195         assert (!q->isFull());
00196         q = (Reaplet<ReapletSize> *) q->getNext();
00197       }
00198       // Now visit the full list.
00199       q = full[i];
00200       if (q) {
00201         assert (q->getPrev() == 0);
00202       }
00203       while (q) {
00204         assert (q->isFull());
00205         q = (Reaplet<ReapletSize> *) q->getNext();
00206       }
00207     }
00208 #endif
00209   }
00210 
00211   __forceinline
00212   void putOnFullList (Reaplet<ReapletSize> * xs,
00213                       const int SizeClass) {
00214     // printf ("putOnFullList %d\n", SizeClass);
00215     SanityChecker c (this);
00216     //    assert (!xs->isFull());
00217     xs->setNext (full[SizeClass]);
00218     xs->setPrev (0);
00219     if (full[SizeClass]) {
00220       full[SizeClass]->setPrev (xs);
00221     }
00222     full[SizeClass] = xs;
00223     //    xs->markFull();
00224   }
00225 
00226   __forceinline void clearOut (Reaplet<ReapletSize> *& list) {
00227     SanityChecker c (this);
00228     Reaplet<ReapletSize> * q;
00229     q = list;
00230     while (q) {
00231       Reaplet<ReapletSize> * c = q;
00232       q = (Reaplet<ReapletSize> *) q->getNext();
00233       TopHeap::free (c);
00234     }
00235     list = 0;
00236   }
00237 
00238   __forceinline void removeFromFullList (Reaplet<ReapletSize> * r,
00239                                          const size_t sz) {
00240     //    printf ("removeFromFullList\n");
00241     // prev <-> r <-> next =>
00242     // prev <-> next
00243     SanityChecker c (this);
00244     //    assert (r->isFull());
00245     // Remove from full list.
00246     Reaplet<ReapletSize> * prev, * next;
00247     prev = (Reaplet<ReapletSize> *) r->getPrev();
00248     next = (Reaplet<ReapletSize> *) r->getNext();
00249     assert (prev != r);
00250     assert (next != r);
00251     if (prev) {
00252       prev->setNext (next);
00253     }
00254     if (next) {
00255       next->setPrev (prev);
00256     }
00257     const int SizeClass = SizeClassComputer::getSizeClass (sz);
00258     if (r == full[SizeClass]) {
00259       assert (prev == 0);
00260       full[SizeClass] = next;
00261     }
00262     assert (full[SizeClass] != r);
00263     // r->setPrev (0);
00264     // r->setNext (0);
00265     //    r->markNotFull();
00266   }
00267 
00268   __forceinline
00269   void moveFromFullToAvailable (Reaplet<ReapletSize> * r) {
00270     SanityChecker c (this);
00271     const size_t sz = r->getSize();
00272     removeFromFullList (r, sz);
00273     // Put it on the available list.
00274     addToAvailableList (r, sz);
00275     assert (r->getPrev() == 0);
00276   }
00277 
00278   __forceinline
00279   void removeAndFreeReaplet (Reaplet<ReapletSize> * r)
00280   {
00281     SanityChecker c (this);
00282     assert (!r->isFull());
00283     const size_t sz = r->getSize();
00284     Reaplet<ReapletSize> * n
00285       = (Reaplet<ReapletSize> *) r->getNext();
00286     Reaplet<ReapletSize> * p
00287       = (Reaplet<ReapletSize> *) r->getPrev();
00288     if (n) {
00289       n->setPrev (p);
00290     }
00291     if (p) {
00292       p->setNext (n);
00293     }
00294     int sizeclass = SizeClassComputer::getSizeClass (sz);
00295     if (available[sizeclass] == r) {
00296       available[sizeclass] = n;
00297     }
00298     //r->setPrev ((Reaplet<ReapletSize> *) 1);
00299     //r->setNext ((Reaplet<ReapletSize> *) 1);
00300     //r->clear();
00301     TopHeap::free (r);
00302     //  printf ("reset %d\n", sz);
00303   }
00304 
00305   __forceinline
00306   int insertNewReaplet (int SizeClass)
00307   {
00308     // printf ("insertNewReaplet\n");
00309     SanityChecker c (this);
00310     void * m = TopHeap::malloc (ReapletSize);
00311     // NOTE: TopHeap *must* add a reaplet prefix.
00312     // Ensure m is aligned properly.
00313     assert (((size_t) m & (ReapletSize - 1)) == 0);
00314     if (m == 0) {
00315       // printf ("NO MORE MEMORY!\n");
00316       // No more memory.
00317       return 0;
00318     }
00319     // Make a new Reaplet for this size class.
00320     size_t ssz = SizeClassComputer::getClassSize (SizeClass);
00321     
00322     // printf ("new reaplet!: ssz = %d\n", ssz);
00323     available[SizeClass] = new (m) Reaplet<ReapletSize> (ssz);
00324     available[SizeClass]->clear();
00325     return 1;
00326   }
00327 
00328 protected:
00329 
00330   __forceinline
00331   void addToAvailableList (Reaplet<ReapletSize> * r,
00332                            size_t sz)
00333   {
00334     SanityChecker c (this);
00335     //    assert (!r->isFull());
00336     const int SizeClass = SizeClassComputer::getSizeClass (sz);
00337     Reaplet<ReapletSize> * head = available[SizeClass];
00338 
00339     assert (head != r);
00340 
00341     // r
00342     // => r <-> head
00343     
00344     r->setPrev (0);
00345     r->setNext (head);
00346     if (head) {
00347       head->setPrev (r);
00348     }
00349     available[SizeClass] = r;
00350   }
00351 
00352 private:
00353 
00354   NO_INLINE void removeFromAvailable (Reaplet<ReapletSize> * xs,
00355                                           const int SizeClass) {
00356     //    printf ("removefromavailable %d.\n", SizeClass);
00357     // The reaplet xs is out of memory.
00358     // Remove it from the linked list.
00359     // Note that it is the head of the linked list.
00360     //  printf ("Removing REAPLET %x\n", xs);
00361     assert (xs->isFull());
00362     assert (xs->getPrev() == 0);
00363     Reaplet<ReapletSize> * n
00364       = (Reaplet<ReapletSize> *) xs->getNext();
00365     if (n) {
00366       // printf ("setprev.\n");
00367       n->setPrev (0);
00368       assert (!n->isFull());
00369     }
00370     available[SizeClass] = n;
00371     SanityChecker c (this);
00372     // xs->setPrev ((Reaplet<ReapletSize> *) 1);
00373     // xs->setNext ((Reaplet<ReapletSize> *) 1);
00374     assert (n == 0 || (n->getPrev() == 0));
00375   }
00376 
00377   __forceinline static Reaplet<ReapletSize> * enclosingReaplet (void * ptr) {
00378     // Find the enclosing reaplet for this pointer.
00379     Reaplet<ReapletSize> * r
00380       = (Reaplet<ReapletSize> *) (((size_t) ptr) & ~(ReapletSize - 1));
00381     return r;
00382   }
00383 
00384 #if 1
00385   NO_INLINE
00386   void * makeBigObject (size_t sz) {
00387     //    printf ("makeBigObject\n");
00388     SanityChecker c (this);
00389     //    printf ("make big object: %d\n", sz);
00390     // Allocate big objects from the top heap. These must be
00391     // ReapletSize aligned.
00392     assert (sz > SizeClassComputer::BIG_OBJECT);
00393     ReapletBase * m
00394       = (ReapletBase *) TopHeap::malloc (sz + sizeof(ReapletBase));
00395     // printf ("m = %x, size = %d\n", m, ReapletSize);
00396     assert (((size_t) m & (ReapletSize - 1)) == 0);
00397     // Put a reaplet base object as a header in the beginning. We
00398     // need this for size information.
00399     if (m == 0) {
00400       return 0;
00401     }
00402     new (m) ReapletBase (sz, (char *) (m + 1)); 
00403     return (void *) (m + 1);
00404   }
00405 #endif
00406 
00407   Reaplet<ReapletSize> * available[SizeClassComputer::NUM_BINS];
00408   Reaplet<ReapletSize> * full[SizeClassComputer::NUM_BINS];
00409 };
00410 
00411 };
00412 
00413 #endif
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Enumeraciones Valores de enumeraciones Propiedades Amigas 'defines'