"Fossies" - the Fresh Open Source Software Archive

Member "heaplayers-351/allocators/hoard/libhoard-tls.cpp" (30 Dec 2005, 9492 Bytes) of package /linux/misc/old/heaplayers_3_5_1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "libhoard-tls.cpp" see the Fossies "Dox" file reference documentation.

    1 /* -*- C++ -*- */
    2 
    3 // The Hoard Multiprocessor Memory Allocator
    4 // www.hoard.org
    5 //
    6 // Author: Emery Berger, http://www.cs.umass.edu/~emery
    7 //
    8 // Copyright (c) 1998-2003, The University of Texas at Austin.
    9 //
   10 // This library is free software; you can redistribute it and/or modify
   11 // it under the terms of the GNU Library General Public License as
   12 // published by the Free Software Foundation, http://www.fsf.org.
   13 //
   14 // This library is distributed in the hope that it will be useful, but
   15 // WITHOUT ANY WARRANTY; without even the implied warranty of
   16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   17 // Library General Public License for more details.
   18 //
   19 //////////////////////////////////////////////////////////////////////////////
   20 
   21 /*
   22  * @file   libhoard.cpp
   23  * @brief  This file replaces malloc etc. in your application.
   24  * @author Emery Berger <http://www.cs.umass.edu/~emery>
   25  */
   26 
   27 #include <stdlib.h>
   28 
   29 // #define USE_HOARD_TLS 1
   30 
   31 #if defined(_WIN32)
   32 #define __thread __declspec(thread)
   33 #endif
   34 
   35 #include "cpuinfo.h"
   36 #include "hoard.h"
   37 #include "VERSION.h"
   38 
   39 typedef bins<MySuperblockType<SmallHeap>::Header, SUPERBLOCK_SIZE> MyBinType;
   40 enum { num_bins = MyBinType::NUM_BINS };
   41 
   42 __thread int initialized = 0;
   43 __thread ProcessHeap::SuperblockType * local_superblock[num_bins];
   44 __thread int hoard_tid;
   45 
   46 volatile int anyThreadCreated = 0;
   47 
   48 const int MaxThreads = 128;
   49 const int NumHeaps = 16;
   50 
   51 template <class SuperHeap>
   52 class PerThreadSuperblockHeap : public SuperHeap {
   53 public:
   54   inline void * malloc (size_t sz) {
   55       fprintf (stderr, "DODODODOOD\n");
   56       return SuperHeap::malloc (sz);
   57 
   58 
   59     int c = MyBinType::getSizeClass (sz);
   60     if ((c < 0) || (c >= num_bins)) {
   61       //      abort();
   62       return NULL;
   63     }
   64 
   65     // Fast path.
   66     if (local_superblock[c]) {
   67       void * ptr = local_superblock[c]->malloc (sz);
   68       if (ptr) {
   69     return ptr;
   70       }
   71     }
   72 
   73     return mallocSlowPath (c, sz);
   74   }
   75 
   76   void * mallocSlowPath (int c, size_t sz) {
   77     while (1) {
   78       if (local_superblock[c] == NULL) {
   79     // Get a superblock.
   80     local_superblock[c] = reinterpret_cast<typename ProcessHeap::SuperblockType *> (SuperHeap::get (sz, NULL));
   81       }
   82       if (local_superblock[c] == NULL) {
   83     local_superblock[c] = reinterpret_cast<typename ProcessHeap::SuperblockType *> (getAnotherSuperblock (sz));
   84       }
   85       if (local_superblock[c] == NULL) {
   86     fprintf (stderr, "HOLY CRAP %s!\n", __FILE__);
   87         abort();
   88     return SuperHeap::malloc (sz);
   89       }
   90       void * ptr = local_superblock[c]->malloc (sz);
   91       if (ptr) {
   92     return ptr;
   93       }
   94       // The superblock has been entirely consumed. Get rid of it.
   95       put (reinterpret_cast<typename SuperHeap::SuperblockType *>(local_superblock[c]), sz);
   96       local_superblock[c] = NULL;
   97       printf ("iterate...\n");
   98     }
   99   }
  100 
  101   inline void free (void * ptr) {
  102     // If the free is to this superblock, free it directly
  103     // without a lock.
  104 
  105     // FIX ME!!
  106      SuperHeap::free (ptr);
  107      return;
  108 
  109     // FIX ME!!
  110 
  111     int c = MyBinType::getSizeClass (getSize(ptr));
  112     if ((local_superblock[c] != NULL) && (ptr >= local_superblock[c]) && (ptr <= local_superblock[c] + 1)) {
  113       local_superblock[c]->free (ptr);
  114     } else {
  115       SuperHeap::free (ptr);
  116     }
  117   }
  118 };
  119 
  120 class TheCustomHeapType ;
  121 
  122 class TheCustomHeapType : public HL::ANSIWrapper<HL::HybridHeap<bins<MySuperblockType<SmallHeap>::Header, SUPERBLOCK_SIZE>::BIG_OBJECT, PerThreadSuperblockHeap<ThreadPoolHeap<MaxThreads, NumHeaps, HoardHeapX> >, BigHeap> > {};
  123 
  124 // class TheCustomHeapType : public HL::ANSIWrapper<HL::HybridHeap<bins<MySuperblockType<SmallHeap>::Header, SUPERBLOCK_SIZE>::BIG_OBJECT, ThreadPoolHeap<MaxThreads, NumHeaps, HoardHeapX>, BigHeap> > {};
  125 
  126 inline static TheCustomHeapType * getCustomHeap (void) {
  127   static char thBuf[sizeof(TheCustomHeapType)];
  128   static TheCustomHeapType * th = new (thBuf) TheCustomHeapType;
  129   return th;
  130 }
  131 
  132 #if defined(_WIN32)
  133 #pragma warning(disable:4273)
  134 #endif
  135 
  136 #include "wrapper.cpp"
  137 
  138 static void * handle;
  139 
  140 static void initializeMaps (void);
  141 
  142 static TheLockType heapLock;
  143 
  144 static void acquireHeapLock (void) {
  145   heapLock.lock();
  146 }
  147 
  148 static void releaseHeapLock (void) {
  149   heapLock.unlock();
  150 }
  151 
  152 
  153 class InitializeMe {
  154 public:
  155   InitializeMe (void) {
  156 #if defined(RTLD_NEXT)
  157     handle = RTLD_NEXT; // dlopen ("libpthread.so", RTLD_NOW);
  158 #endif
  159     initializeMaps();
  160   }
  161 };
  162 
  163 void _init (void) {
  164   static InitializeMe please;
  165 }
  166 
  167 static void initializeMaps (void) {
  168   int i;
  169 #if 0
  170   for (i = 0; i < MaxThreads; i++) {
  171     getCustomHeap()->setTidMap(i, 0);
  172   }
  173   for (i = 0; i < MaxHeaps; i++) {
  174     getCustomHeap()->setInusemap (i, 0);
  175   }
  176 #endif
  177 }
  178 
  179 static void findUnusedHeap (void) {
  180   // Find an unused heap.
  181   acquireHeapLock();
  182   
  183 #if 0
  184   int tid = CPUInfo::getThreadId() % TheCustomHeapType::MaxThreads;
  185 
  186   int i = 0;
  187   while ((i < TheCustomHeapType::MaxHeaps) && (getCustomHeap()->getInusemap(i)))
  188     i++;
  189   if (i >= TheCustomHeapType::MaxHeaps) {
  190     //    printf ("DOH! all in use!\n");
  191     // Every heap is in use: pick a random victim.
  192     i = (int) ( TheCustomHeapType::MaxHeaps * ((double) rand() / (double) RAND_MAX));
  193   }
  194 
  195   //  printf ("thread %d acquiring heap %d\n", tid, i);
  196 
  197   getCustomHeap()->setInusemap (i, 1);
  198   getCustomHeap()->setTidMap (tid, i);
  199   releaseHeapLock();
  200 #endif
  201 }
  202 
  203 static void releaseHeap (void) {
  204 #if 0
  205   // Decrement the ref-count on the current heap.
  206 
  207   acquireHeapLock();
  208   enum { VerifyPowerOfTwo = 1 / ((TheCustomHeapType::MaxThreads & ~(TheCustomHeapType::MaxThreads-1))) };
  209 
  210   int tid = CPUInfo::getThreadId() & (TheCustomHeapType::MaxThreads - 1);
  211   int heapIndex = getCustomHeap()->getTidMap (tid);
  212 
  213   //  printf ("thread %d releasing heap %d\n", tid, heapIndex);
  214  
  215   getCustomHeap()->setInusemap (heapIndex, 0);
  216 
  217   // Prevent underruns (defensive programming).
  218 
  219   if (getCustomHeap()->getInusemap (heapIndex) < 0) {
  220     getCustomHeap()->setInusemap (heapIndex, 0);
  221   }
  222   releaseHeapLock();
  223 #endif
  224 }
  225 
  226 #if !defined(_WIN32)
  227 
  228 // NOTE: Relies on libpthread being a shared library.
  229 
  230 #include <pthread.h>
  231 #include <dlfcn.h>
  232 
  233 template <class T1, class T2>
  234 class MyPair {
  235 public:
  236   T1 first;
  237   T2 second;
  238 };
  239 
  240 
  241 extern "C" {
  242 
  243   typedef void * (*threadFunctionType) (void *);
  244 
  245   typedef  
  246   int (*pthread_create_function) (pthread_t *thread,
  247                   const  pthread_attr_t *attr,
  248                   threadFunctionType start_routine,
  249                   void *arg);
  250   
  251   typedef
  252   void (*pthread_exit_function) (void *);
  253 
  254   static void exitRoutine (void) {
  255     releaseHeap();
  256     // Dispose of any local superblocks.
  257     for (int i = 0; i < num_bins; i++) {
  258       if (superblock[i]) {
  259     getCustomHeap()->put (reinterpret_cast<TheCustomHeapType::SuperblockType *>(superblock[i]), MyBinType::getClassSize(i));
  260     superblock[i] = NULL;
  261       }
  262     }
  263   }
  264 
  265 
  266   void * startMeUp (void * a)
  267   {
  268     anyThreadCreated = 1;
  269 
  270     findUnusedHeap();
  271 
  272     MyPair<threadFunctionType, void *> * z
  273       = (MyPair<threadFunctionType, void *> *) a;
  274     threadFunctionType f = z->first;
  275     void * arg = z->second;
  276     delete z;
  277     void * result = (*f)(arg);
  278     exitRoutine();
  279     return result;
  280   }
  281 
  282   int pthread_create (pthread_t *thread,
  283               const  pthread_attr_t *attr,
  284               threadFunctionType start_routine,
  285               void * arg)
  286   {
  287     //    static InitializeMe init = startRoutine();
  288     static pthread_create_function f = NULL;
  289     initialized = 0;
  290     hoard_tid = CPUInfo::getThreadId();
  291 #if defined(linux)
  292     char fname[] = "pthread_create";
  293 #else
  294     char fname[] = "_pthread_create";
  295 #endif
  296 
  297     if (f == NULL) {
  298       f = (pthread_create_function) dlsym (RTLD_NEXT, fname);
  299     }
  300 
  301     MyPair<threadFunctionType, void *> * newarg
  302       = new MyPair<threadFunctionType, void *>();
  303 
  304     newarg->first  = start_routine;
  305     newarg->second = arg;
  306 
  307     int result = (*f)(thread, attr, startMeUp, newarg);
  308     
  309     return result;
  310   }
  311 
  312   void pthread_exit (void * arg)
  313   {
  314 #if defined(linux)
  315     static pthread_exit_function f
  316       = (pthread_exit_function) dlsym (RTLD_NEXT, "pthread_exit");
  317 #else
  318     static pthread_exit_function f
  319       = (pthread_exit_function) dlsym (RTLD_NEXT, "_pthread_exit");
  320 #endif
  321     exitRoutine();
  322     (*f)(arg);
  323   }
  324 }
  325 
  326 #elif defined(_WIN32)
  327 
  328 #include <stdio.h>
  329 
  330 extern "C"
  331 BOOL WINAPI DllMain(HANDLE hinstDLL, DWORD fdwReason, LPVOID lpreserved)
  332 {
  333   int i;
  334   int tid;
  335   static int np = CPUInfo::computeNumProcessors();
  336   switch (fdwReason) {
  337   case DLL_PROCESS_ATTACH:
  338     fprintf (stderr, "This software uses the Hoard scalable memory allocator (version " HOARD_VERSION_STRING ").\nCopyright (C) 2005 Emery Berger, The University of Texas at Austin,\nand University of Massachusetts, Amherst.\nFor more information, see http://www.hoard.org\n");
  339     initializeMaps();
  340     break;
  341   case DLL_THREAD_ATTACH:
  342     hoard_tid = CPUInfo::getThreadId();
  343     for (int i = 0; i < num_bins; i++) {
  344       local_superblock[i] = NULL;
  345     }
  346     if (np != 1) {
  347       // This relies on atomic stores in spinlock.h.
  348       anyThreadCreated = 1;
  349     }
  350     if (np == 1) {
  351       // Assign the thread to heap 0.
  352       // FIX ME
  353       // getCustomHeap()->setTidMap ((int) CPUInfo::getThreadId() % TheCustomHeapType::MaxThreads, 0);
  354     } else {
  355       findUnusedHeap();
  356     }
  357     break;
  358   case DLL_THREAD_DETACH:
  359     // Do we want to reset anyThreadCreated?
  360     for (int i = 0; i < num_bins; i++) {
  361       // Dispose of local_superblocks here.
  362       local_superblock[i] = NULL;
  363     }
  364     if (np != 1) {
  365       releaseHeap();
  366     }
  367     break;
  368   default:
  369     return TRUE;
  370   }
  371   return TRUE;
  372 }
  373 
  374 #endif