00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef _MMAPHEAP_H_
00028 #define _MMAPHEAP_H_
00029
00030 #if defined(_WIN32)
00031 #include <windows.h>
00032 #else
00033
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
00070 namespace HL {
00071
00072 class PrivateMmapHeap {
00073 public:
00074
00076 enum { ZeroMemory = 1 };
00077
00078 #if defined(_WIN32)
00079
00080
00081 enum { Alignment = 64 * 1024 };
00082
00083 inline void * malloc (size_t sz) {
00084
00085 #if HL_EXECUTABLE_HEAP
00086 char * ptr = (char *) VirtualAlloc (NULL, sz, MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
00087 #else
00088 char * ptr = (char *) VirtualAlloc (NULL, sz, MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);
00089 #endif
00090 return (void *) ptr;
00091 }
00092
00093 inline void free (void * ptr, size_t) {
00094 VirtualFree (ptr, 0, MEM_RELEASE);
00095 }
00096
00097 inline void free (void * ptr) {
00098 VirtualFree (ptr, 0, MEM_RELEASE);
00099 }
00100
00101 inline static size_t getSize (void * ptr) {
00102 MEMORY_BASIC_INFORMATION mbi;
00103 VirtualQuery (ptr, &mbi, sizeof(mbi));
00104 return (size_t) mbi.RegionSize;
00105 }
00106
00107 #else
00108
00109 virtual ~PrivateMmapHeap (void) {}
00110
00111 #if defined(__SVR4)
00112
00113
00114 enum { Alignment = 64 * 1024 };
00115 #else
00116
00117 enum { Alignment = 4 * 1024 };
00118 #endif
00119
00120 inline void * malloc (size_t sz) {
00121 #if defined(MAP_ALIGN) && defined(MAP_ANON)
00122
00123 void * ptr = mmap ((char *) Alignment, sz, HL_MMAP_PROTECTION_MASK, MAP_PRIVATE | MAP_ALIGN | MAP_ANON | MAP_POPULATE, -1, 0);
00124 #elif !defined(MAP_ANONYMOUS)
00125 static int fd = ::open ("/dev/zero", O_RDWR);
00126 void * ptr = mmap (NULL, sz, HL_MMAP_PROTECTION_MASK, MAP_PRIVATE | MAP_POPULATE, fd, 0);
00127 #else
00128 void * ptr = mmap (NULL, sz, HL_MMAP_PROTECTION_MASK, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
00129 #endif
00130 if (ptr == MAP_FAILED) {
00131 ptr = NULL;
00132 }
00133 return ptr;
00134 }
00135
00136 #if 1
00137 inline void free (void * ptr) {
00138 abort();
00139 munmap (reinterpret_cast<char *>(ptr), getSize(ptr));
00140 }
00141
00142 inline size_t getSize (void * ptr) {
00143 ptr = ptr;
00144 abort();
00145 return Alignment;
00146 }
00147 #endif
00148
00149 void free (void * ptr, size_t sz)
00150 {
00151 if ((long) sz < 0) {
00152 abort();
00153 }
00154
00155 munmap (reinterpret_cast<char *>(ptr), sz);
00156 }
00157
00158 #endif
00159
00160 };
00161
00162
00163 class MmapHeap : public PrivateMmapHeap {
00164 #if !defined(_WIN32)
00165
00166 private:
00167
00168 enum {NSIZE = 4 * 4 * 1024};
00169
00170
00171 class MyHeap : public LockedHeap<SpinLockType, FreelistHeap<ZoneHeap<PrivateMmapHeap, NSIZE - 16> > > {};
00172
00173 typedef MyHashMap<void *, size_t, MyHeap> mapType;
00174
00175 protected:
00176 mapType MyMap;
00177
00178 SpinLockType MyMapLock;
00179
00180 public:
00181 inline void * malloc (size_t sz) {
00182 void * ptr = PrivateMmapHeap::malloc (sz);
00183 MyMapLock.lock();
00184 MyMap.set (ptr, sz);
00185 MyMapLock.unlock();
00186 assert (reinterpret_cast<size_t>(ptr) % Alignment == 0);
00187 return const_cast<void *>(ptr);
00188 }
00189
00190 inline size_t getSize (void * ptr) {
00191 MyMapLock.lock();
00192 size_t sz = MyMap.get (ptr);
00193 MyMapLock.unlock();
00194 return sz;
00195 }
00196
00197
00198 void free (void * ptr, size_t sz) {
00199 PrivateMmapHeap::free (ptr, sz);
00200 }
00201
00202 inline void free (void * ptr) {
00203 assert (reinterpret_cast<size_t>(ptr) % Alignment == 0);
00204 MyMapLock.lock();
00205 size_t sz = MyMap.get (ptr);
00206 PrivateMmapHeap::free (ptr, sz);
00207 MyMap.erase (ptr);
00208 MyMapLock.unlock();
00209 }
00210 #endif
00211 };
00212
00213 }
00214
00215 #endif