usermode/library/malloc-original/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 
00031 //
00032 // We use one threadHeap for each thread (processor).
00033 //
00034 
00035 class threadHeap : public hoardHeap {
00036 
00037 public:
00038 
00039   threadHeap (void);
00040 
00041   // Memory allocation routines.
00042   void * malloc (const size_t sz);
00043   inline void * memalign (size_t alignment, size_t sz);
00044 
00045   // Find out how large an allocated object is.
00046   inline static size_t objectSize (void * ptr);
00047 
00048   // Set our process heap.
00049   inline void setpHeap (processHeap * p);
00050 
00051 private:
00052 
00053   // Prevent copying and assignment.
00054   threadHeap (const threadHeap&);
00055   const threadHeap& operator= (const threadHeap&);
00056 
00057   // Our process heap.
00058   processHeap * _pHeap;
00059 
00060   // We insert a cache pad here to avoid false sharing (the
00061   // processHeap holds an array of threadHeaps, and we don't want
00062   // these to share any cache lines).
00063   double _pad[CACHE_LINE / sizeof(double)];
00064 };
00065 
00066 
00067 void * threadHeap::memalign (size_t alignment,
00068                              size_t size)
00069 {
00070   // Calculate the amount of space we need
00071   // to satisfy the alignment requirements.
00072 
00073   size_t newSize;
00074 
00075   // If the alignment is less than the required alignment,
00076   // just call malloc.
00077   if (alignment <= ALIGNMENT) {
00078     return this->malloc (size);
00079   }
00080 
00081   if (alignment < sizeof(block)) {
00082     alignment = sizeof(block);
00083   }
00084 
00085   // Alignment must be a power of two!
00086   assert ((alignment & (alignment - 1)) == 0);
00087 
00088   // Leave enough room to align the block within the malloced space.
00089   newSize = size + sizeof(block) + alignment;
00090 
00091   // Now malloc the space up with a little extra (we'll put the block
00092   // pointer in right behind the allocated space).
00093 
00094   void * ptr = this->malloc (newSize);
00095   if ((((unsigned long) ptr) & -((long) alignment)) == 0) {
00096     // ptr is already aligned, so return it.
00097     assert (((unsigned long) ptr % alignment) == 0);
00098     return ptr;
00099 
00100   } else {
00101 
00102     // Align ptr.
00103     char * newptr = (char *)
00104       (((unsigned long) ptr + alignment - 1) & -((long) alignment));
00105 
00106     // If there's not enough room for the block header, skip to the
00107     // next aligned space within the block..
00108     if ((unsigned long) newptr - (unsigned long) ptr < sizeof(block)) {
00109       newptr += alignment;
00110     }
00111     assert (((unsigned long) newptr % alignment) == 0);
00112 
00113     // Copy the block from the start of the allocated memory.
00114     block * b = ((block *) ptr - 1);
00115 
00116     assert (b->isValid());
00117     assert (b->getSuperblock()->isValid());
00118     
00119     // Make sure there's enough room for the block header.
00120     assert (((unsigned long) newptr - (unsigned long) ptr) >= sizeof(block));
00121 
00122     block * p = ((block *) newptr - 1);
00123 
00124     // Make sure there's enough room allocated for size bytes.
00125     assert (((unsigned long) p - sizeof(block)) >= (unsigned long) b);
00126 
00127     if (p != b) {
00128       assert ((unsigned long) newptr > (unsigned long) ptr);
00129       // Copy the block header.
00130       *p = *b;
00131       assert (p->isValid());
00132       assert (p->getSuperblock()->isValid());
00133       
00134       // Set the next pointer to point to b with the 1 bit set.
00135       // When this block is freed, it will be treated specially.
00136       p->setNext ((block *) ((unsigned long) b | 1));
00137 
00138     } else {
00139       assert (ptr != newptr);
00140     }
00141 
00142     assert (((unsigned long) ptr + newSize) >= ((unsigned long) newptr + size));
00143     return newptr;
00144   }
00145 }
00146 
00147 
00148 size_t threadHeap::objectSize (void * ptr) 
00149 {
00150   // Find the superblock pointer.
00151   
00152   block * b = ((block *) ptr - 1);
00153   assert (b->isValid());
00154   superblock * sb = b->getSuperblock ();
00155   assert (sb);
00156   
00157   // Return the size.
00158   return sizeFromClass (sb->getBlockSizeClass());
00159 }
00160 
00161 
00162 void threadHeap::setpHeap (processHeap * p) 
00163 {
00164   _pHeap = p; 
00165 }
00166 
00167 #endif // _THREADHEAP_H_
00168 

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