Eneboo - Documentación para desarrolladores
|
00001 /* -*- C++ -*- */ 00002 00003 /* 00004 00005 Heap Layers: An Extensible Memory Allocation Infrastructure 00006 00007 Copyright (C) 2000-2004 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 _MMAPHEAP_H_ 00028 #define _MMAPHEAP_H_ 00029 00030 #if defined(_WIN32) 00031 #include <windows.h> 00032 #else 00033 // UNIX 00034 #include <sys/types.h> 00035 #include <sys/stat.h> 00036 #include <fcntl.h> 00037 #include <unistd.h> 00038 #include <sys/mman.h> 00039 #include <map> 00040 #endif 00041 00042 #include "sassert.h" 00043 #include "myhashmap.h" 00044 #include "stlallocator.h" 00045 #include "freelistheap.h" 00046 #include "zoneheap.h" 00047 #include "lockedheap.h" 00048 #include "spinlock.h" 00049 #include "hldefines.h" 00050 00051 #if HL_EXECUTABLE_HEAP 00052 #define HL_MMAP_PROTECTION_MASK (PROT_READ | PROT_WRITE | PROT_EXEC) 00053 #else 00054 #define HL_MMAP_PROTECTION_MASK (PROT_READ | PROT_WRITE) 00055 #endif 00056 00057 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) 00058 #define MAP_ANONYMOUS MAP_ANON 00059 #endif 00060 00061 00062 #include <new> 00063 00064 #ifdef __MINGW32__ 00065 #define _WIN32 00066 #include <windows.h> 00067 #endif 00068 00075 namespace HL { 00076 00077 class PrivateMmapHeap { 00078 public: 00079 00081 enum { ZeroMemory = 1 }; 00082 00083 #if defined(_WIN32) 00084 00085 // Microsoft Windows aligns all memory to a 64K boundary. 00086 enum { Alignment = 64 * 1024 }; 00087 00088 inline void * malloc (size_t sz) { 00089 // printf ("mmapheap: Size request = %d\n", sz); 00090 #if HL_EXECUTABLE_HEAP 00091 char * ptr = (char *) VirtualAlloc (NULL, sz, MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE); 00092 #else 00093 char * ptr = (char *) VirtualAlloc (NULL, sz, MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE); 00094 #endif 00095 return (void *) ptr; 00096 } 00097 00098 inline void free (void * ptr, size_t) { 00099 VirtualFree (ptr, 0, MEM_RELEASE); 00100 } 00101 00102 inline void free (void * ptr) { 00103 VirtualFree (ptr, 0, MEM_RELEASE); 00104 } 00105 00106 inline static size_t getSize (void * ptr) { 00107 MEMORY_BASIC_INFORMATION mbi; 00108 VirtualQuery (ptr, &mbi, sizeof(mbi)); 00109 return (size_t) mbi.RegionSize; 00110 } 00111 00112 #else 00113 00114 virtual ~PrivateMmapHeap (void) {} 00115 00116 #if defined(__SVR4) 00117 00118 // Solaris aligns all memory to a 64K boundary. 00119 enum { Alignment = 64 * 1024 }; 00120 #else 00121 // Linux and most other operating systems align memory to a 4K boundary. 00122 enum { Alignment = 4 * 1024 }; 00123 #endif 00124 00125 inline void * malloc (size_t sz) { 00126 #if defined(MAP_ALIGN) && defined(MAP_ANON) 00127 // Request memory aligned to the Alignment value above. 00128 void * ptr = mmap ((char *) Alignment, sz, HL_MMAP_PROTECTION_MASK, MAP_PRIVATE | MAP_ALIGN | MAP_ANON, -1, 0); 00129 #elif !defined(MAP_ANONYMOUS) 00130 static int fd = ::open ("/dev/zero", O_RDWR); 00131 void * ptr = mmap (NULL, sz, HL_MMAP_PROTECTION_MASK, MAP_PRIVATE, fd, 0); 00132 #else 00133 void * ptr = mmap (NULL, sz, HL_MMAP_PROTECTION_MASK, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 00134 #endif 00135 if (ptr == MAP_FAILED) { 00136 ptr = NULL; 00137 } 00138 return ptr; 00139 } 00140 00141 #if 1 00142 inline void free (void * ptr) { 00143 abort(); 00144 munmap (reinterpret_cast<char *>(ptr), getSize(ptr)); 00145 } 00146 00147 inline size_t getSize (void * ptr) { 00148 ptr = ptr; 00149 abort(); 00150 return Alignment; // Obviously broken. Such is life. 00151 } 00152 #endif 00153 00154 void free (void * ptr, size_t sz) 00155 { 00156 if ((long) sz < 0) { 00157 abort(); 00158 } 00159 00160 munmap (reinterpret_cast<char *>(ptr), sz); 00161 } 00162 00163 #endif 00164 00165 }; 00166 00167 00168 class MmapHeap : public PrivateMmapHeap { 00169 #if !defined(_WIN32) 00170 00171 private: 00172 00173 class MyHeap : public LockedHeap<SpinLockType, FreelistHeap<ZoneHeap<PrivateMmapHeap, 16384 - 16> > > {}; // FIX ME: 16 = size of ZoneHeap header. 00174 00175 typedef MyHashMap<void *, size_t, MyHeap> mapType; 00176 00177 protected: 00178 mapType MyMap; 00179 00180 SpinLockType MyMapLock; 00181 00182 public: 00183 inline void * malloc (size_t sz) { 00184 void * ptr = PrivateMmapHeap::malloc (sz); 00185 MyMapLock.lock(); 00186 MyMap.set (ptr, sz); 00187 MyMapLock.unlock(); 00188 assert (reinterpret_cast<size_t>(ptr) % Alignment == 0); 00189 return const_cast<void *>(ptr); 00190 } 00191 00192 inline size_t getSize (void * ptr) { 00193 MyMapLock.lock(); 00194 size_t sz = MyMap.get (ptr); 00195 MyMapLock.unlock(); 00196 return sz; 00197 } 00198 00199 // WORKAROUND: apparent gcc bug. 00200 void free (void * ptr, size_t sz) { 00201 PrivateMmapHeap::free (ptr, sz); 00202 } 00203 00204 inline void free (void * ptr) { 00205 assert (reinterpret_cast<size_t>(ptr) % Alignment == 0); 00206 MyMapLock.lock(); 00207 size_t sz = MyMap.get (ptr); 00208 PrivateMmapHeap::free (ptr, sz); 00209 MyMap.erase (ptr); 00210 MyMapLock.unlock(); 00211 } 00212 #endif 00213 }; 00214 00215 } 00216 00217 #endif