usermode/library/pmalloc/src/wrapper.cpp

00001 
00002 //
00003 // The Hoard Multiprocessor Memory Allocator
00004 // www.hoard.org
00005 //
00006 // Author: Emery Berger, http://www.cs.utexas.edu/users/emery
00007 //
00008 // Copyright (c) 1998-2001, The University of Texas at Austin.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Library General Public License as
00012 // published by the Free Software Foundation, http://www.fsf.org.
00013 //
00014 // This library is distributed in the hope that it will be useful, but
00015 // WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Library General Public License for more details.
00018 //
00020 
00021 /*
00022   wrapper.cpp
00023   ------------------------------------------------------------------------
00024   Implementations of malloc(), free(), etc. in terms of hoard.
00025   This lets us link in hoard in place of the stock malloc.
00026   ------------------------------------------------------------------------
00027   @(#) $Id: wrapper.cpp,v 1.40 2001/12/10 20:11:29 emery Exp $
00028   ------------------------------------------------------------------------
00029   Emery Berger                    | <http://www.cs.utexas.edu/users/emery>
00030   Department of Computer Sciences |             <http://www.cs.utexas.edu>
00031   University of Texas at Austin   |                <http://www.utexas.edu>
00032   ========================================================================
00033 */
00034 
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <strings.h>
00038 #if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x420
00039 #include <new>
00040 #endif
00041 #include "config.h"
00042 
00043 #include "threadheap.h"
00044 #include "processheap.h"
00045 #include "persistentheap.h"
00046 #include "arch-specific.h"
00047 
00048 #include "genalloc.h"
00049 
00050 #include <itm.h>
00051 #include "mtm/include/txlock.h"
00052 
00053 m_txmutex_t generic_pmalloc_txmutex = PTHREAD_MUTEX_INITIALIZER;
00054 
00055 //
00056 // Access exactly one instance of the global persistent heap
00057 // (which contains objects allocated in previous incarnations).
00058 // We create this object dynamically to avoid bloating the object code.
00059 //
00060 
00061 inline static persistentHeap * getPersistentAllocator (void) {
00062   static char * buf = (char *) hoardGetMemory (sizeof(persistentHeap));
00063   static persistentHeap * theAllocator = new (buf) persistentHeap;
00064   return theAllocator;
00065 }
00066 
00067 
00068 //
00069 // Access exactly one instance of the process heap
00070 // (which contains the thread heaps).
00071 // We create this object dynamically to avoid bloating the object code.
00072 //
00073 
00074 inline static processHeap * getAllocator (persistentHeap *persistentHeap) {
00075   static char * buf = (char *) hoardGetMemory (sizeof(processHeap));
00076   static processHeap * theAllocator = new (buf) processHeap(persistentHeap);
00077   return theAllocator;
00078 }
00079 
00080 #define HOARD_MALLOC          pmalloc
00081 #define HOARD_MALLOC_TXN      pmallocTxn
00082 #define HOARD_FREE            pfree
00083 #define HOARD_FREE_TXN        pfreeTxn
00084 #define HOARD_REALLOC         prealloc
00085 #define HOARD_REALLOC_TXN     preallocTxn
00086 #define HOARD_CALLOC          pcalloc
00087 #define HOARD_MEMALIGN        pmemalign
00088 #define HOARD_VALLOC          pvalloc
00089 #define HOARD_GET_USABLE_SIZE pmalloc_usable_size
00090 
00091 //extern "C" __attribute__((tm_callable)) void * HOARD_MALLOC (size_t sz);
00092 
00093 extern "C" void * HOARD_MALLOC(size_t);
00094 extern "C" void * HOARD_MALLOC_TXN(size_t);
00095 extern "C" void   HOARD_FREE(void *);
00096 extern "C" void   HOARD_FREE_TXN(void *);
00097 extern "C" void * HOARD_REALLOC(void *, size_t);
00098 extern "C" void * HOARD_REALLOC_TXN(void *, size_t);
00099 extern "C" void * HOARD_CALLOC(size_t, size_t);
00100 extern "C" void * HOARD_MEMALIGN(size_t, size_t);
00101 extern "C" void * HOARD_VALLOC(size_t);
00102 extern "C" size_t HOARD_GET_USABLE_SIZE(void *);
00103 
00104 __attribute__((tm_wrapping(HOARD_MALLOC))) void *HOARD_MALLOC_TXN(size_t);
00105 __attribute__((tm_wrapping(HOARD_FREE))) void HOARD_FREE_TXN(void *);
00106 __attribute__((tm_wrapping(HOARD_REALLOC))) void *HOARD_REALLOC_TXN(void *, size_t);
00107 
00108 
00109 static void * pmalloc_internal (size_t sz)
00110 {
00111         void                  *addr;
00112         static persistentHeap *persistentheap = getPersistentAllocator();
00113         static processHeap    *pHeap = getAllocator(persistentheap);
00114 
00115         if (sz == 0) {
00116                 sz = 1;
00117         }
00118         //printf("pmalloc[START]: size = %d\n",  (int) sz);
00119 
00120         if (sz >= SUPERBLOCK_SIZE/2) {
00121                 //printf("pmalloc.vista[START]: size = %d\n",  (int) sz);
00122                 /* Fall back to the standard persistent allocator. 
00123                  * Begin a new atomic block to force the compiler to fall through down the TM 
00124                  * instrumented path. Actually we are already in the transactional path so
00125                  * this atomic block should execute as a nested transaction.
00126                  */
00127                 __tm_atomic 
00128                 {
00129                         /* 
00130                          * FIXME: We don't need the lock as we execute with isolation on
00131                          * We should make the library work properly when transactions don't provide
00132                          * isolation. A way to do it would be to use TXlocks:
00133                          *
00134                          *   m_txmutex_lock(&generic_pmalloc_txmutex); 
00135                          *   addr = GENERIC_PMALLOC(sz);
00136                          *   m_txmutex_unlock(&generic_pmalloc_txmutex);
00137                          *
00138                          */
00139                         addr = GENERIC_PMALLOC(sz);
00140                 }
00141         } else {
00142                 //printf("pmalloc.hoard[START]: size = %d\n",  (int) sz);
00143                 addr = pHeap->getHeap(pHeap->getHeapIndex()).malloc (sz);
00144         }
00145         //printf("pmalloc[DONE]: addr=%p,  size = %d\n",  addr, (int) sz);
00146         return addr;
00147 }
00148 
00149 extern "C" void * HOARD_MALLOC (size_t sz)
00150 {
00151         // FIXME: Change the API to ensure atomicity of the allocation as described 
00152         // in the design document 
00153         return pmalloc_internal(sz);
00154 }
00155 
00156 extern "C" void * HOARD_MALLOC_TXN (size_t sz)
00157 {
00158         return pmalloc_internal(sz);
00159 }
00160 
00161 extern "C" void * HOARD_CALLOC (size_t nelem, size_t elsize)
00162 {
00163         static persistentHeap * persistentheap = getPersistentAllocator();
00164         static processHeap    * pHeap = getAllocator(persistentheap);
00165         size_t                  sz = nelem * elsize;
00166 
00167         if (sz == 0) {
00168                 sz = 1;
00169         }
00170         void * ptr = pHeap->getHeap(pHeap->getHeapIndex()).malloc (sz);
00171         // Zero out the malloc'd block.
00172         memset (ptr, 0, sz);
00173         return ptr;
00174 }
00175 
00176 static void free_internal (void * ptr)
00177 {
00178         static persistentHeap * persistentheap = getPersistentAllocator();
00179 
00180         //printf("free: %p [%p - %p)\n",
00181         //        ptr,
00182         //        ((uintptr_t) persistentheap->getPersistentSegmentBase()),
00183         //              ((uintptr_t) persistentheap->getPersistentSegmentBase() + PERSISTENTHEAP_SIZE));
00184 
00185         /* Find out which heap this block has been allocated from. */
00186         if ((uintptr_t) ptr >= ((uintptr_t) persistentheap->getPersistentSegmentBase()) &&
00187             (uintptr_t) ptr < ((uintptr_t) persistentheap->getPersistentSegmentBase() + PERSISTENTHEAP_SIZE))
00188         {
00189                 persistentheap->free (ptr);
00190         } else {
00191                 __tm_atomic 
00192                 {
00193                         GENERIC_PFREE (ptr);
00194                 }
00195         }
00196 }
00197 
00198 
00199 extern "C" void HOARD_FREE (void* ptr)
00200 {
00201         free_internal(ptr);
00202         //std::cerr << "Called persistent memory allocator outside of transaction." << std::endl;
00203         //abort();
00204 }
00205 
00206 
00207 extern "C" void HOARD_FREE_TXN (void * ptr)
00208 {
00209         free_internal(ptr);
00210 }
00211 
00212 
00213 extern "C" void * HOARD_MEMALIGN (size_t, size_t)
00214 {
00215         //TODO: Implement memalign
00216         assert(0);
00217 #if 0  
00218         static persistentHeap * persistentheap = getPersistentAllocator();
00219         static processHeap    * pHeap = getAllocator(persistentheap);
00220         void * addr = pHeap->getHeap(pHeap->getHeapIndex()).memalign (alignment, size);
00221         return addr;
00222 #endif 
00223         return NULL;
00224 }
00225 
00226 
00227 extern "C" void * HOARD_VALLOC (size_t size)
00228 {
00229         return HOARD_MEMALIGN (hoardGetPageSize(), size);
00230 }
00231 
00232 
00233 static void * prealloc_internal (void * ptr, size_t sz)
00234 {
00235         _ITM_transaction *tx;
00236         static persistentHeap * persistentheap = getPersistentAllocator();
00237 
00238         if (ptr == NULL) {
00239                 return pmalloc_internal (sz);
00240         }
00241         if (sz == 0) {
00242                 free_internal (ptr);
00243         return NULL;
00244         }
00245 
00246         size_t objSize;
00247         /* If object allocated from the Hoard heap then check whether there
00248          * the existing object can hold the new size
00249          */
00250         if ((uintptr_t) ptr >= ((uintptr_t) persistentheap->getPersistentSegmentBase()) &&
00251             (uintptr_t) ptr < ((uintptr_t) persistentheap->getPersistentSegmentBase() + PERSISTENTHEAP_SIZE))
00252         {
00253 
00254                 // If the existing object can hold the new size,
00255                 // just return it.
00256                 objSize = persistentHeap::objectSize (ptr);
00257 
00258                 if (objSize >= sz) {
00259                         return ptr;
00260                 }
00261         } else {
00262                 objSize = GENERIC_OBJSIZE(ptr);
00263         }
00264 
00265         // Allocate a new block of size sz.
00266         void * buf = pmalloc_internal (sz);
00267 
00268         // Copy the contents of the original object
00269         // up to the size of the new block.
00270 
00271         size_t minSize = (objSize < sz) ? objSize : sz;
00272         tx = _ITM_getTransaction();
00273         _ITM_memcpyRtWt (tx, buf, ptr, minSize);
00274 
00275         // Free the old block.
00276         free_internal (ptr);
00277 
00278         // Return a pointer to the new one.
00279         return buf;
00280 }
00281 
00282         
00283 extern "C" void * HOARD_REALLOC (void * ptr, size_t sz)
00284 {
00285         return prealloc_internal(ptr, sz);
00286 }
00287 
00288 
00289 extern "C" void * HOARD_REALLOC_TXN (void * ptr, size_t sz)
00290 {
00291         return prealloc_internal(ptr, sz);
00292 }
00293 
00294 
00295 extern "C" size_t HOARD_GET_USABLE_SIZE (void * ptr)
00296 {
00297   return threadHeap::objectSize (ptr);
00298 }
00299 
00300 
00301 #if 0
00302 extern "C" void malloc_stats (void)
00303 {
00304   TheWrapper.TheAllocator()->stats();
00305 }
00306 #endif
00307 
00308 
00309 
00310 /* Transactional Wrappers for volatile memory allocator -- This should be part of MTM? */
00311 
00312 /* 
00313  * TODO: Dynamic Memory allocator should be implemented using commit/undo 
00314  * actions as described by Intel. Implementation should go into MTM
00315  */
00316 __attribute__((tm_wrapping(malloc))) void *malloc_txn(size_t sz) 
00317 {
00318         return malloc(sz);
00319 }
00320 
00321 __attribute__((tm_wrapping(realloc))) void *realloc_txn(void *ptr, size_t sz) 
00322 {
00323         return realloc(ptr, sz);
00324 }
00325 
00326 __attribute__((tm_wrapping(free))) void free_txn(void *ptr) 
00327 {
00328         free(ptr);
00329 }

Generated on Sat Apr 23 11:43:35 2011 for Mnemosyne by  doxygen 1.4.7