Eneboo - Documentación para desarrolladores
|
00001 // -*- C++ -*- 00002 00009 #ifndef _ALIGNEDMMAP_H_ 00010 #define _ALIGNEDMMAP_H_ 00011 00012 #include "sassert.h" 00013 #include "myhashmap.h" 00014 #include "freelistheap.h" 00015 #include "mmapwrapper.h" 00016 #include "bumpalloc.h" 00017 #include "exactlyone.h" 00018 #include "mmapalloc.h" 00019 00020 using namespace std; 00021 using namespace HL; 00022 00023 namespace Hoard { 00024 00032 template <size_t Alignment_> 00033 class AlignedMmapInstance { 00034 public: 00035 00036 enum { Alignment = Alignment_ }; 00037 00038 inline void * malloc (size_t sz) { 00039 00040 // Round up sz to the nearest page. 00041 sz = (sz + HL::MmapWrapper::Size - 1) & ~(HL::MmapWrapper::Size - 1); 00042 00043 // If the memory is already suitably aligned, just track size requests. 00044 if ((size_t) HL::MmapWrapper::Alignment % (size_t) Alignment == 0) { 00045 void * ptr = HL::MmapWrapper::map (sz); 00046 MyMap.set (ptr, sz); 00047 return ptr; 00048 } 00049 00050 // Try a map call and hope that it's suitably aligned. If we get lucky, 00051 // we're done. 00052 00053 char * ptr = reinterpret_cast<char *>(HL::MmapWrapper::map (sz)); 00054 00055 if (ptr == align(ptr)) { 00056 // We're done. 00057 MyMap.set (ptr, sz); 00058 return ptr; 00059 } else { 00060 // Try again. 00061 HL::MmapWrapper::unmap ((void *) ptr, sz); 00062 } 00063 00064 // We have to align it ourselves. We get memory from 00065 // mmap, align a pointer in the space, and free the space before 00066 // and after the aligned segment. 00067 00068 ptr = reinterpret_cast<char *>(HL::MmapWrapper::map (sz + Alignment_)); 00069 00070 if (ptr == NULL) { 00071 return NULL; 00072 } 00073 00074 char * newptr = align (ptr); 00075 00076 // Unmap the part before (prolog) and after. 00077 00078 size_t prolog = (size_t) newptr - (size_t) ptr; 00079 00080 if (prolog > 0) { 00081 // Get rid of the prolog. 00082 HL::MmapWrapper::unmap (ptr, prolog); 00083 } 00084 00085 size_t epilog = Alignment_ - prolog; 00086 HL::MmapWrapper::unmap ((char *) newptr + sz, epilog); 00087 00088 // Now record the size associated with this pointer. 00089 00090 MyMap.set (newptr, sz); 00091 return newptr; 00092 } 00093 00094 inline void free (void * ptr) { 00095 00096 // Find the object. If we don't find it, we didn't allocate it. 00097 // For now, just ignore such an invalid free... 00098 00099 size_t requestedSize = MyMap.get (ptr); 00100 00101 if (requestedSize == 0) { 00102 return; 00103 } 00104 00105 HL::MmapWrapper::unmap (ptr, requestedSize); 00106 00107 // Finally, undo the mapping. 00108 MyMap.erase (ptr); 00109 } 00110 00111 inline size_t getSize (void * ptr) { 00112 return MyMap.get (ptr); 00113 } 00114 00115 00116 private: 00117 00119 inline static char * align (char * buf) { 00120 return (char *)(((size_t) buf + (Alignment_-1)) & ~(Alignment_-1)); 00121 } 00122 00123 // Manage information in a map that uses a custom heap for 00124 // allocation. 00125 00127 typedef void * keyType; 00128 00130 typedef size_t valType; 00131 00132 // The heap from which memory comes for the Map's purposes. 00133 // Objects come from chunks via mmap, and we manage these with a free list. 00134 class SourceHeap : public HL::FreelistHeap<BumpAlloc<65536, MmapAlloc> > { }; 00135 00137 typedef MyHashMap<keyType, valType, SourceHeap> mapType; 00138 00140 mapType MyMap; 00141 00142 }; 00143 00144 00151 template <size_t Alignment_, 00152 class LockType> 00153 class AlignedMmap : 00154 public ExactlyOne<LockedHeap<LockType, AlignedMmapInstance<Alignment_> > > 00155 { 00156 public: 00157 00158 enum { Alignment = Alignment_ }; 00159 00160 inline void * malloc (size_t sz) { 00161 return (*this)().malloc (sz); 00162 } 00163 inline void free (void * ptr) { 00164 return (*this)().free (ptr); 00165 } 00166 inline size_t getSize (void * ptr) const { 00167 return (*this)().getSize (ptr); 00168 } 00169 00170 }; 00171 00172 } 00173 00174 #endif