usermode/library/pmalloc/src/threadheap.h

00001 
00002 //
00003 // The Hoard Multiprocessor Memory Allocator
00004 // www.hoard.org
00005 //
00006 // Author: Emery Berger, http://www.cs.utexas.edu/users/emery
00007 //
00008 // Copyright (c) 1998-2001, The University of Texas at Austin.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Library General Public License as
00012 // published by the Free Software Foundation, http://www.fsf.org.
00013 //
00014 // This library is distributed in the hope that it will be useful, but
00015 // WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Library General Public License for more details.
00018 //
00020 
00021 #ifndef _THREADHEAP_H_
00022 #define _THREADHEAP_H_
00023 
00024 #include "config.h"
00025 
00026 
00027 #include "hoardheap.h"
00028 
00029 class processHeap;     // forward declaration
00030 class persistentHeap;  // forward declaration
00031 
00032 //
00033 // We use one threadHeap for each thread (processor).
00034 //
00035 
00036 class threadHeap : public hoardHeap {
00037 
00038 public:
00039 
00040   threadHeap (void);
00041 
00042   // Memory allocation routines.
00043   void * malloc (const size_t sz);
00044   inline void * memalign (size_t alignment, size_t sz);
00045 
00046   // Find out how large an allocated object is.
00047   inline static size_t objectSize (void * ptr);
00048 
00049   // Set our process heap.
00050   inline void setpHeap (processHeap * p);
00051 
00052   // Set our persistent heap.
00053   inline void setPersistentHeap (persistentHeap * p);
00054 private:
00055 
00056   // Prevent copying and assignment.
00057   threadHeap (const threadHeap&);
00058   const threadHeap& operator= (const threadHeap&);
00059 
00060   // Our process heap.
00061   processHeap * _pHeap;
00062 
00063   // Our process heap.
00064   persistentHeap *      _persistentHeap;
00065 
00066   // We insert a cache pad here to avoid false sharing (the
00067   // processHeap holds an array of threadHeaps, and we don't want
00068   // these to share any cache lines).
00069   double _pad[CACHE_LINE / sizeof(double)];
00070 };
00071 
00072 
00073 void * threadHeap::memalign (size_t alignment,
00074                              size_t size)
00075 {
00076   // Calculate the amount of space we need
00077   // to satisfy the alignment requirements.
00078 
00079   size_t newSize;
00080 
00081   // If the alignment is less than the required alignment,
00082   // just call malloc.
00083   if (alignment <= ALIGNMENT) {
00084     return this->malloc (size);
00085   }
00086 
00087   if (alignment < sizeof(block)) {
00088     alignment = sizeof(block);
00089   }
00090 
00091   // Alignment must be a power of two!
00092   assert ((alignment & (alignment - 1)) == 0);
00093 
00094   // Leave enough room to align the block within the malloced space.
00095   newSize = size + sizeof(block) + alignment;
00096 
00097   // Now malloc the space up with a little extra (we'll put the block
00098   // pointer in right behind the allocated space).
00099 
00100   void * ptr = this->malloc (newSize);
00101   if ((((unsigned long) ptr) & -((long) alignment)) == 0) {
00102     // ptr is already aligned, so return it.
00103     assert (((unsigned long) ptr % alignment) == 0);
00104     return ptr;
00105 
00106   } else {
00107 
00108     // Align ptr.
00109     char * newptr = (char *)
00110       (((unsigned long) ptr + alignment - 1) & -((long) alignment));
00111 
00112     // If there's not enough room for the block header, skip to the
00113     // next aligned space within the block..
00114     if ((unsigned long) newptr - (unsigned long) ptr < sizeof(block)) {
00115       newptr += alignment;
00116     }
00117     assert (((unsigned long) newptr % alignment) == 0);
00118 
00119     // Copy the block from the start of the allocated memory.
00120     block * b = ((block *) ptr - 1);
00121 
00122     assert (b->isValid());
00123     assert (b->getSuperblock()->isValid());
00124     
00125     // Make sure there's enough room for the block header.
00126     assert (((unsigned long) newptr - (unsigned long) ptr) >= sizeof(block));
00127 
00128     block * p = ((block *) newptr - 1);
00129 
00130     // Make sure there's enough room allocated for size bytes.
00131     assert (((unsigned long) p - sizeof(block)) >= (unsigned long) b);
00132 
00133     if (p != b) {
00134       assert ((unsigned long) newptr > (unsigned long) ptr);
00135       // Copy the block header.
00136       *p = *b;
00137       assert (p->isValid());
00138       assert (p->getSuperblock()->isValid());
00139       
00140       // Set the next pointer to point to b with the 1 bit set.
00141       // When this block is freed, it will be treated specially.
00142       p->setNext ((block *) ((unsigned long) b | 1));
00143 
00144     } else {
00145       assert (ptr != newptr);
00146     }
00147 
00148     assert (((unsigned long) ptr + newSize) >= ((unsigned long) newptr + size));
00149     return newptr;
00150   }
00151 }
00152 
00153 
00154 size_t threadHeap::objectSize (void * ptr) 
00155 {
00156   // Find the superblock pointer.
00157   
00158   block * b = ((block *) ptr - 1);
00159   assert (b->isValid());
00160   superblock * sb = b->getSuperblock ();
00161   assert (sb);
00162   
00163   // Return the size.
00164   return sizeFromClass (sb->getBlockSizeClass());
00165 }
00166 
00167 
00168 void threadHeap::setpHeap (processHeap * p) 
00169 {
00170   _pHeap = p; 
00171 }
00172 
00173 void threadHeap::setPersistentHeap (persistentHeap * p) 
00174 {
00175   _persistentHeap = p; 
00176 }
00177 
00178 
00179 #endif // _THREADHEAP_H_
00180 

Generated on Sat Apr 23 11:43:35 2011 for Mnemosyne by  doxygen 1.4.7