|
|
// ColdStore Mmap manager // Copyright (C) 1998,1999 Phillipe Hebrais, // see LICENSE (MD5 f5220f8f599e5e926f37cf32efe3ab68) for terms // $Id: qvmm_h.html,v 1.1.1.1 2000/04/09 01:07:51 skeptopotamus Exp $ #ifndef QVMM_H #define QVMM_H #include <sys/types.h> // DEBUGLOG turns on traces #ifdef DEBUGLOG #define DEBLOG(x) (x); #else #define DEBLOG(x) #endif /** ColdStore Mmap manager * @author Phillipe Hebrais * * Mmap maintains the store, providing * @li store information, * @li new page allocation, and * @li @ref Latch services</ul> to the application. */ class Mmap { // space for a store's magic number and Global region size /** actual size of store */ static size_t size; /** store's persistent header */ static int header[]; /** end of header */ static int end[]; /** first byte of non-header store (R/O!!!) */ static int store[]; public: /** store mmap'd base address (page aligned) */ static const void *const base = (void*)0x50000000; /** maximum size of store (page aligned) */ static const size_t max = 0x40000000; /** underlying page size of store (power of 2) */ static const size_t page_size = 4096; /** flag: is Mmap initialized? */ static bool initialized; // Initialize and uninit; /** Mmap the file as a store. * @param fd file descriptor of open store * @return current size of store */ static size_t open( int fd); /** Open and Mmap the named file as a store. * @param file file name * @return file descriptor of open store */ static int open(char *file); /** close the Mmap * @param fd file descriptor of open store */ static void close( int fd); /** Allocate a range of pages in the store * @param size size of allocation * @return allocated region */ static void* alloc( size_t size); // Munge pointers and sizes /** check the validity of a pointer * @param ptr pointer to be checked * @return true if the pointer is in the Mmap */ static int check( void* ptr) { return ptr >= base && (char*)ptr < (char*)base + max; } /** align a value to a page boundary * @param size value to align * @return page-aligned value */ static size_t align( size_t size) { return (size+page_size-1) & ~(page_size-1); } /** return the page which contains a pointer * @param ptr pointer to align * @return page-aligned pointer */ static void* pageof( void* ptr) { return (void*)(((size_t)ptr) & ~(page_size-1)); } // Latch ops; static void* locked( void); static void lock( void* l); static void unlock( void); }; /** cheap limited deadlock- & starvation-free interthread spinlock mutex * @author Phillipe Hebrais * * Latches provide simple mutual exclusion between forks. Each fork * may hold at most one Latch at a time. Page allocation uses * this latch, so it must be free or the allocation will fail. * * Use Latches only for very short term locking. * * The goal is to let as many forks as possible access concurrently the * database so that while one fork page faults, the others can continue * using the cpu. To avoid excessive serialization, we must reduce to a * minimum the amount of global locking required. * * Latches are meant to be very cheap (but limited) mutex. * * It avoids global locking by not using a wait queue. * Instead, a global hash table is used as rendez-vous point for * latch requests and forks wait by yielding and looping. * * The latching algorithm garantees deadlock and starvation freeness. */ class Latch { /** prime number > 2*n_forks */ static size_t const size = 4079; /** uSec to sleep while busy waiting for the spinlock */ static size_t const timeout = 1000; /** set of latches of given size */ static char latch[size]; public: /** lock a latch * @param target address to lock */ static void lock( void* target); /** unlock a latch * @param target locked address */ static void unlock( void* target); }; /** Entity allocated relative to an @ref Mmap * @author Phillipe Hebrais * * Memory instances are the basic currency of ColdStore, * providing interfaces to the store's features * @li extent-based (de&re)allocation * @li interface to @ref Latch locking of addresses * @li per-allocation information: @ref Memory::mySize @ref Memory::myAllocator * @li atomic low-level inc/dec ops: @ref Memory::inc @ref Memory::dec */ class Memory { public: /** the `unallocated' allocator */ static const void * const no_alloc = (void*)-1; /** lock this object */ void lock(void); /** unlock this object */ void unlock(void); /** Atomic counter increment */ static void inc( size_t& val) { asm volatile ("incl (%0)" : : "r" (&val) : "cc", "memory"); }; /** Atomic counter decrement */ static int dec( size_t& val) { int ret = 0; asm volatile ("decl (%2);jz 1f;incl %0;1:" : "=r" (ret) : "0" (ret), "r" (&val) : "cc", "memory"); return ret; } // C++ interface - new with optional allocator /** C++ extent placement new @arg size size of allocation in bytes @arg where neighborhood into which to allocate @returns storage allocated as requested */ void* operator new( size_t size, void* where=(void*)0); /** C++ extent additional placement new @arg size size of allocation in bytes @arg extra extra allocation in bytes @arg where neighborhood into which to allocate @returns storage allocated as requested */ void* operator new( size_t size, size_t extra, void* where=(void*)0); /** C++ object deletion @arg ptr a pointer returned by @ref operator new() @arg extra extra allocation in bytes @arg where neighborhood into which to allocate @returns storage allocated as requested */ void operator delete( void* ptr); /** C++ extent placement array new @arg size size of allocation in bytes @arg where neighborhood into which to allocate */ void* operator new[] (size_t size, void* where=(void*)0); /** C++ array object deletion @arg ptr a pointer returned by @ref operator new[]() @arg extra extra allocation in bytes @arg where neighborhood into which to allocate */ void operator delete[] ( void* ptr); // C interface /** C storage reallocation @arg addr a pointer to previously alloc'd storage @arg size size of new allocation in bytes @arg allocator neighborhood into which to allocate @returns storage allocated as requested */ static void* realloc( void* addr, size_t size, void* allocator=(void*)no_alloc); /** C storage allocation @arg size size of new allocation in bytes @arg allocator neighborhood into which to allocate @returns storage allocated as requested */ static void* alloc( size_t size, void* allocator); /** C storage deletion @arg ptr a pointer returned by @ref alloc() */ static void free( void* ptr); // utility accessors /** external size of allocation @arg ptr a pointer returned by @ref alloc() @returns size occupied by the allocation of ptr */ static size_t size(const void* ptr); /** internal size of some allocation */ size_t itsSize(const void* ptr) const; /** internal size of allocation surrounding this */ size_t mySize() const; /** allocator of given region @arg ptr a pointer to allocated storage @returns the neighborhood with which ptr is associated */ static void* allocator( void* ptr); /** allocator of instance @returns the neighborhood with which this is associated */ void *myAllocator() { return allocator(this); } // Health checks /** predicate: BTree is healthy */ static int check(void); /** Assert health of BTree */ static void Assert( void); #ifdef GUARD_ALLOC /** Check Guards' health */ static void *checkGuard(void *ptr, bool damage=false); protected: /** construct a pair of Guards around the allocation to * detect overwriting and double-deletion. */ static void *guard(void *ptr, void *alloc, size_t size); /** Non-destructively Validate Guards of this Memory instance */ void validGuard() const { Memory::Assert(); checkGuard((void*)this); } #else // no Guarding - hopefully these will be optimised out static void *checkGuard(void *ptr, bool damage=false) {return ptr;} protected: static void *guard(void *ptr, void *alloc, size_t size) {return ptr;} void validGuard() const {} #endif }; namespace qvmm { class RefCount : public Memory { protected: /** number of references to this Memory */ mutable size_t _refcount; public: /** Construct RefCount Memory note: Memory starts with 0 refcount */ RefCount(void) : _refcount(0) {} /** add a reference to this */ RefCount *upcount( void) const; /** remove a reference to this (possibly delete) */ void dncount( void); /** return the refcount of this */ size_t refcount( void) const { return _refcount; } }; } // Global new[] and delete[] with Allocator placement /** extent placement default array new operator using store */ void* operator new[] (size_t size, Memory* where); /** extent placement default new operator using store */ void* operator new (size_t size, Memory* where); #ifdef WRAP_MALLOC // This permits use to wrap the standard allocation functions // -wrap malloc -wrap free must appear in the ld linker command extern "C" { void *__wrap_malloc (size_t size); void __wrap_free (void *allocation); void *__wrap_realloc(void *ptr, size_t size); } #endif #endif // QVMM_H
Generated by: colin@sharedtech.dhis.org on Sat Nov 6 11:59:21 199. |