VMAllocator Class Reference

VMAllocator is an implementation of the CacheAllocator interface in terms of OS page allocation calls. More...

#include <VMAllocator.h>

Inheritance diagram for VMAllocator:

CacheAllocator List of all members.

Public Member Functions

 VMAllocator (size_t cbAlloc, size_t nLocked=0)
 Constructs a new VMAllocator.
virtual ~VMAllocator ()
virtual void * allocate (int *pErrorCode=NULL)
 Allocates a chunk of memory of size determined by the constructor.
virtual int deallocate (void *pMem, int *pErrorCode=NULL)
 Deallocates a chunk of memory.
virtual int setProtection (void *pMem, uint cb, bool readOnly, int *pErrorCode=NULL)
 Changes protection state for a contiguous range of virtual memory.
virtual size_t getBytesAllocated () const
 
Returns:
number of bytes currently allocated


Private Attributes

size_t cbAlloc
size_t nAllocs
bool bLockPages

Detailed Description

VMAllocator is an implementation of the CacheAllocator interface in terms of OS page allocation calls.

Definition at line 35 of file VMAllocator.h.


Constructor & Destructor Documentation

VMAllocator::VMAllocator ( size_t  cbAlloc,
size_t  nLocked = 0 
) [explicit]

Constructs a new VMAllocator.

Parameters:
cbAlloc number of bytes per allocation; all calls to allocate must specify this same value
nLocked if nonzero, specifies that allocations should be locked in memory, and that no more than the specified number will be allocated at any one time

Definition at line 38 of file VMAllocator.cpp.

References bLockPages, cbAlloc, and nAllocs.

00039 {
00040     cbAlloc = cbAllocInit;
00041     nAllocs = 0;
00042     if (nLocked) {
00043 #ifdef RLIMIT_MEMLOCK
00044         struct rlimit rl;
00045         if (::getrlimit(RLIMIT_MEMLOCK,&rl)) {
00046             throw SysCallExcn("getrlimit failed");
00047         }
00048         if (rl.rlim_cur != RLIM_INFINITY) {
00049             // REVIEW:  what if other stuff in the same process needs
00050             // locked pages?
00051             rl.rlim_cur = nLocked*cbAlloc;
00052             rl.rlim_max = nLocked*cbAlloc;
00053             if (::setrlimit(RLIMIT_MEMLOCK,&rl)) {
00054                 throw SysCallExcn("setrlimit failed");
00055             }
00056         }
00057 #endif
00058         bLockPages = true;
00059     } else {
00060         bLockPages = false;
00061     }
00062 }

VMAllocator::~VMAllocator (  )  [virtual]

Definition at line 64 of file VMAllocator.cpp.

References getBytesAllocated().

00065 {
00066     // This assertion indicates that not all allocated pages were deallocated.
00067     // In relation to LER-5976: in debug builds, each allocation is divided
00068     // into 3 sections (two guard pages surrounding the actual allocation).
00069     // The mprotect calls in allocate(int *) can fail in low memory situations
00070     // (the kernel may allocate private memory as it tracks a single mmap
00071     // region being split in three).  When this occurs, subsequent munmap calls
00072     // (even on different regions) in deallocate sometimes fail, leading to a
00073     // failure of this assertion.  This should not occur in release builds,
00074     // since no guard pages are allocated or protected. NOTE: On Ubuntu Edgy
00075     // Eft (2.6.17-12-generic SMP), the munmap calls in deallocate fails three
00076     // times, then inexplicably begin succeeding.  Retrying the failed calls
00077     // then succeeds.
00078     assert(!getBytesAllocated());
00079 }


Member Function Documentation

void * VMAllocator::allocate ( int *  pErrorCode = NULL  )  [virtual]

Allocates a chunk of memory of size determined by the constructor.

Parameters:
pErrorCode on error and if non-NULL, the int referenced is modified to contain the OS error code
Returns:
the allocated chunk; NULL if memory cannot be allocated (see pErrorCode for OS error code)

Implements CacheAllocator.

Definition at line 81 of file VMAllocator.cpp.

References bLockPages, cbAlloc, SysCallExcn::getCurrentErrorCode(), and nAllocs.

Referenced by RandomAccessFileDeviceTest::testAsyncIO().

00082 {
00083 #ifdef HAVE_MMAP
00084 
00085     uint cbActualAlloc = cbAlloc;
00086 #ifndef NDEBUG
00087     // For a debug build, allocate "fence" regions before and after each
00088     // allocated buffer.  This helps to catch stray pointers around buffer
00089     // boundaries.  The fence size is one OS memory page, since that's
00090     // the minimum unit of protection, and also guarantees 512-byte
00091     // alignment for O_DIRECT file access.
00092     cbActualAlloc += 2*getpagesize();
00093 #endif
00094 
00095     void *v = ::mmap(
00096         NULL,cbActualAlloc,
00097         PROT_READ | PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS,-1,0);
00098     if (v == MAP_FAILED) {
00099         if (pErrorCode != NULL) {
00100             *pErrorCode = SysCallExcn::getCurrentErrorCode();
00101         }
00102         return NULL;
00103     }
00104 
00105 #ifndef NDEBUG
00106     PBuffer p = static_cast<PBuffer>(v);
00107     memset(p, 0xFE, getpagesize());
00108     if (::mprotect(p, getpagesize(), PROT_NONE)) {
00109         if (pErrorCode != NULL) {
00110             *pErrorCode = SysCallExcn::getCurrentErrorCode();
00111         }
00112         ::munmap(v,cbAlloc);
00113         return NULL;
00114     }
00115     p += getpagesize();
00116     memset(p, 0xFF, cbAlloc);
00117     v = p;
00118     p += cbAlloc;
00119     memset(p, 0xFE, getpagesize());
00120     if (::mprotect(p, getpagesize(), PROT_NONE)) {
00121         if (pErrorCode != NULL) {
00122             *pErrorCode = SysCallExcn::getCurrentErrorCode();
00123         }
00124         ::munmap(v,cbAlloc);
00125         return NULL;
00126     }
00127 #endif
00128 
00129     if (bLockPages) {
00130         if (::mlock(v,cbAlloc)) {
00131             if (pErrorCode != NULL) {
00132                 *pErrorCode = SysCallExcn::getCurrentErrorCode();
00133             }
00134             ::munmap(v,cbAlloc);
00135             return NULL;
00136         }
00137     }
00138 #else
00139     void *v = malloc(cbAlloc);
00140     if (v == NULL) {
00141         if (pErrorCode != NULL) {
00142             *pErrorCode = SysCallExcn::getCurrentErrorCode();
00143         }
00144         return NULL;
00145     }
00146 #endif
00147     ++nAllocs;
00148     return v;
00149 }

int VMAllocator::deallocate ( void *  pMem,
int *  pErrorCode = NULL 
) [virtual]

Deallocates a chunk of memory.

Parameters:
pMem the allocated memory
pErrorCode on error and if non-NULL, the int referenced is modified to contain the OS error code
Returns:
0 on success; -1 if memory cannot be deallocated (see pErrorCode for OS error code)

Implements CacheAllocator.

Definition at line 151 of file VMAllocator.cpp.

References bLockPages, cbAlloc, free(), SysCallExcn::getCurrentErrorCode(), and nAllocs.

Referenced by RandomAccessFileDeviceTest::testAsyncIO().

00152 {
00153 #ifdef HAVE_MMAP
00154     if (bLockPages) {
00155         if (::munlock(p,cbAlloc)) {
00156             if (pErrorCode != NULL) {
00157                 *pErrorCode = SysCallExcn::getCurrentErrorCode();
00158             }
00159             return -1;
00160         }
00161     }
00162 
00163     uint cbActualAlloc = cbAlloc;
00164 #ifndef NDEBUG
00165     PBuffer p2 = static_cast<PBuffer>(p);
00166     p2 -= getpagesize();
00167     p = p2;
00168     cbActualAlloc += 2*getpagesize();
00169 #endif
00170     if (::munmap((caddr_t)p,cbActualAlloc)) {
00171         if (pErrorCode != NULL) {
00172             *pErrorCode = SysCallExcn::getCurrentErrorCode();
00173         }
00174         return -1;
00175     }
00176 #else
00177     free(p);
00178 #endif
00179     --nAllocs;
00180 
00181     return 0;
00182 }

int VMAllocator::setProtection ( void *  pMem,
uint  cb,
bool  readOnly,
int *  pErrorCode = NULL 
) [virtual]

Changes protection state for a contiguous range of virtual memory.

Parameters:
pMem start of range
cb number of bytes in range
readOnly true for read-only; false for read-write (TODO jvs 7-Feb-2006: support no-access as well)
pErrorCode on error and if non-NULL, the int referenced is modified to contain the OS error code
Returns:
0 on success; -1 if an error occurs while manupulating memory protections (see pErrorCode for OS error code)

Implements CacheAllocator.

Definition at line 189 of file VMAllocator.cpp.

References SysCallExcn::getCurrentErrorCode().

00191 {
00192     // FIXME jvs 7-Feb-2006:  use autoconf to get HAVE_MPROTECT instead
00193 #ifdef HAVE_MMAP
00194     int prot = PROT_READ;
00195     if (!readOnly) {
00196         prot |= PROT_WRITE;
00197     }
00198     if (::mprotect(pMem, cb, prot)) {
00199         if (pErrorCode != NULL) {
00200             *pErrorCode = SysCallExcn::getCurrentErrorCode();
00201         }
00202         return -1;
00203     }
00204 #endif
00205 
00206     return 0;
00207 }

size_t VMAllocator::getBytesAllocated (  )  const [virtual]

Returns:
number of bytes currently allocated

Implements CacheAllocator.

Definition at line 184 of file VMAllocator.cpp.

References cbAlloc, and nAllocs.

Referenced by ~VMAllocator().

00185 {
00186     return nAllocs*cbAlloc;
00187 }


Member Data Documentation

size_t VMAllocator::cbAlloc [private]

Definition at line 38 of file VMAllocator.h.

Referenced by allocate(), deallocate(), getBytesAllocated(), and VMAllocator().

size_t VMAllocator::nAllocs [private]

Definition at line 39 of file VMAllocator.h.

Referenced by allocate(), deallocate(), getBytesAllocated(), and VMAllocator().

bool VMAllocator::bLockPages [private]

Definition at line 40 of file VMAllocator.h.

Referenced by allocate(), deallocate(), and VMAllocator().


The documentation for this class was generated from the following files:
Generated on Mon Jun 22 04:00:49 2009 for Fennel by  doxygen 1.5.1