├── test └── falsesharingexample │ ├── a │ ├── thread_memtest │ └── Makefile ├── doc └── ppopp006.pdf ├── runtime ├── manual.pdf ├── handleAccess.o ├── heaplayers │ ├── util │ │ ├── sparc-interchange.il │ │ ├── x86_64-interchange.il │ │ ├── x86-interchange.il │ │ ├── blockinglock.h │ │ ├── guard.h │ │ ├── hash.h │ │ ├── sassert.h │ │ ├── bitindex.cpp │ │ ├── recursivelock.h │ │ ├── winlock.h │ │ ├── fred.h │ │ ├── posixlock.h │ │ ├── bitindex.h │ │ └── sllist.h │ ├── bins.h │ ├── experimental │ │ ├── pad.h │ │ ├── cacheheap.h │ │ ├── thinlock.h │ │ ├── prefetchheap.h │ │ ├── splitheap.h │ │ ├── binheap.h │ │ ├── lazyheap.h │ │ ├── counteddictionary.h │ │ ├── kingsmodheap.h │ │ ├── multiheap.h │ │ ├── theap.h │ │ ├── emptychunkheap.h │ │ ├── cartesianheap.h │ │ ├── combineheap.h │ │ ├── topslotheap.h │ │ ├── strictslotheap.h │ │ ├── slotheap.h │ │ ├── sizethreadheap.h │ │ ├── fifofreelist.h │ │ ├── lazyslotheap.h │ │ ├── multimalloc.h │ │ └── batchheap.h │ ├── tryheap.h │ ├── fixedsizeheap.h │ ├── padheap.h │ ├── checkheap.h │ ├── sbrkheap.h │ ├── hldefines.h │ ├── debugheap.h │ ├── freelistheap.h │ ├── freesllist.h │ ├── profileheap.h │ ├── hybridheap.h │ ├── nullheap.h │ ├── perclassheap.h │ ├── boundedfreelistheap.h │ ├── bins4k.h │ ├── lockedheap.h │ ├── leamallocheap.h │ ├── exceptionheap.h │ ├── addheap.h │ ├── oneheap.h │ ├── staticheap.h │ ├── mallocheap.h │ ├── stats.h │ ├── stats.cpp │ ├── adapt.h │ ├── adaptheap.h │ ├── ansiwrapper.h │ ├── sizethreadheap.h │ ├── sizeownerheap.h │ ├── fifofreelist.h │ ├── fifodlfreelist.h │ ├── sizeheap.h │ ├── gnuwrapper.cpp │ ├── unique.h │ ├── threadspecificheap.h │ ├── firstfitheap.h │ ├── localmallocheap.h │ ├── chunkheap.h │ ├── utility.h │ ├── slopheap.h │ ├── sbrk.c │ ├── kingsleyheap.h │ └── threadheap.h ├── objectinfo.h ├── x.log ├── xplock.h ├── finetime.h ├── privateheap.h ├── xglobals.h ├── cachepredict.h ├── libfuncs.h ├── mm.h ├── Makefile ├── hashfuncs.h ├── elfinfo.h ├── objectheader.h ├── spinlock.h ├── callsite.h ├── xoneheap.h ├── internalheap.h ├── handleAccessInline.h ├── finetime.c ├── cacheinfo.h ├── xrun.h ├── handleAccess.c └── bigheap.h ├── README.md ├── paper └── PPoPP-2014 │ ├── fig │ ├── perf.pdf │ ├── memusage.pdf │ ├── sample.pdf │ ├── Potential1.pdf │ ├── Potential2.pdf │ ├── Potential3.pdf │ ├── memusage-old.pdf │ ├── performance.xlsx │ ├── perfsensitive.pdf │ ├── DefaultsPaper.pptx │ ├── absolutememory.pdf │ ├── trackpotential.pdf │ ├── linearregression.psedocode │ └── linearregression.report │ ├── ppopp006-liu.pdf │ ├── acknowledge.tex │ ├── table.tex │ ├── futurework.tex │ ├── conclusion.tex │ ├── abstract.tex │ ├── issues.tex │ ├── Makefile │ └── discuss.tex └── compiler └── readme /test/falsesharingexample/a: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/ppopp006.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/doc/ppopp006.pdf -------------------------------------------------------------------------------- /runtime/manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/runtime/manual.pdf -------------------------------------------------------------------------------- /runtime/handleAccess.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/runtime/handleAccess.o -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Predator - Predictive False Sharing Detection 2 | ============================================= 3 | 4 | -------------------------------------------------------------------------------- /paper/PPoPP-2014/fig/perf.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/paper/PPoPP-2014/fig/perf.pdf -------------------------------------------------------------------------------- /paper/PPoPP-2014/fig/memusage.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/paper/PPoPP-2014/fig/memusage.pdf -------------------------------------------------------------------------------- /paper/PPoPP-2014/fig/sample.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/paper/PPoPP-2014/fig/sample.pdf -------------------------------------------------------------------------------- /paper/PPoPP-2014/ppopp006-liu.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/paper/PPoPP-2014/ppopp006-liu.pdf -------------------------------------------------------------------------------- /paper/PPoPP-2014/fig/Potential1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/paper/PPoPP-2014/fig/Potential1.pdf -------------------------------------------------------------------------------- /paper/PPoPP-2014/fig/Potential2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/paper/PPoPP-2014/fig/Potential2.pdf -------------------------------------------------------------------------------- /paper/PPoPP-2014/fig/Potential3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/paper/PPoPP-2014/fig/Potential3.pdf -------------------------------------------------------------------------------- /paper/PPoPP-2014/fig/memusage-old.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/paper/PPoPP-2014/fig/memusage-old.pdf -------------------------------------------------------------------------------- /paper/PPoPP-2014/fig/performance.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/paper/PPoPP-2014/fig/performance.xlsx -------------------------------------------------------------------------------- /paper/PPoPP-2014/fig/perfsensitive.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/paper/PPoPP-2014/fig/perfsensitive.pdf -------------------------------------------------------------------------------- /paper/PPoPP-2014/fig/DefaultsPaper.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/paper/PPoPP-2014/fig/DefaultsPaper.pptx -------------------------------------------------------------------------------- /paper/PPoPP-2014/fig/absolutememory.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/paper/PPoPP-2014/fig/absolutememory.pdf -------------------------------------------------------------------------------- /paper/PPoPP-2014/fig/trackpotential.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/paper/PPoPP-2014/fig/trackpotential.pdf -------------------------------------------------------------------------------- /test/falsesharingexample/thread_memtest: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plasma-umass/Predator/HEAD/test/falsesharingexample/thread_memtest -------------------------------------------------------------------------------- /runtime/heaplayers/util/sparc-interchange.il: -------------------------------------------------------------------------------- 1 | .inline MyInterlockedExchange,8 2 | 3 | mov %o0,%o2 4 | mov %o1,%o0 5 | swap [%o2],%o0 6 | 7 | .end 8 | -------------------------------------------------------------------------------- /runtime/heaplayers/util/x86_64-interchange.il: -------------------------------------------------------------------------------- 1 | .inline MyInterlockedExchange,0 2 | 3 | movq %rsi,%rax 4 | lock 5 | xchgq %rax,(%rdi) 6 | 7 | .end 8 | -------------------------------------------------------------------------------- /runtime/heaplayers/util/x86-interchange.il: -------------------------------------------------------------------------------- 1 | .inline MyInterlockedExchange,0 2 | 3 | movl (%esp),%ecx 4 | movl 4(%esp),%eax 5 | lock 6 | xchgl %eax,(%ecx) 7 | 8 | .end 9 | -------------------------------------------------------------------------------- /runtime/heaplayers/bins.h: -------------------------------------------------------------------------------- 1 | #ifndef _BINS_H_ 2 | #define _BINS_H_ 3 | 4 | namespace HL { 5 | 6 | template 7 | class bins; 8 | 9 | } 10 | 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /compiler/readme: -------------------------------------------------------------------------------- 1 | Patch: 2 | First, download the source code from http://llvm.org/releases/download.html#3.2. 3 | 4 | Usage: 5 | To compile a file with instrumenter, we should explicitly mention the instrumentation tool: 6 | -finstrumenter 7 | 8 | clang -Wl,/home/tongping/work/falsesharing/project/runtime/libdefault64.so -finstrumenter -g -O0 9 | 10 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/pad.h: -------------------------------------------------------------------------------- 1 | #ifndef _PAD_H_ 2 | #define _PAD_H_ 3 | 4 | 5 | // Add a cache-pad to an object. 6 | 7 | template 8 | class Pad : public Super { 9 | private: 10 | // Add a pad field with a name that is unlikely 11 | // to conflict with a real field name. 12 | char _pad_QWERTYUIOP1234567890[CacheLineSize]; 13 | }; 14 | 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /runtime/heaplayers/util/blockinglock.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _BLOCKINGLOCK_H_ 4 | #define _BLOCKINGLOCK_H_ 5 | 6 | #if defined(_WIN32) 7 | #include "winlock.h" 8 | #else 9 | #include "posixlock.h" 10 | #endif 11 | 12 | namespace HL { 13 | 14 | class BlockingLock : 15 | #if defined(_WIN32) 16 | public WinLockType {}; 17 | #else 18 | public PosixLockType {}; 19 | #endif 20 | 21 | } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /paper/PPoPP-2014/acknowledge.tex: -------------------------------------------------------------------------------- 1 | This material is based upon work supported by the National Science 2 | Foundation under Grant No. 1012195-CCF. The authors thank Junjie Gu for his assistance with LLVM. The authors also thank Charlie Curtsinger, Dimitar Gochev, John Altidor and the anonymous reviewers for their helpful suggestions during the development of this work. Tongping Liu was supported by an internship while at Huawei US Research Center. -------------------------------------------------------------------------------- /runtime/heaplayers/util/guard.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _GUARD_H_ 4 | #define _GUARD_H_ 5 | 6 | namespace HL { 7 | 8 | template 9 | class Guard { 10 | public: 11 | inline Guard (LockType& l) 12 | : _lock (l) 13 | { 14 | _lock.lock(); 15 | } 16 | 17 | inline ~Guard (void) { 18 | _lock.unlock(); 19 | } 20 | private: 21 | LockType& _lock; 22 | }; 23 | 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/cacheheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _CACHEHEAP_H_ 4 | #define _CACHEHEAP_H_ 5 | 6 | template 7 | class CacheHeap : public Super { 8 | public: 9 | 10 | inline void * malloc (size_t sz) { 11 | void * ptr = mySuper.malloc (sz); 12 | return ptr; 13 | } 14 | 15 | inline void free (void * ptr) { 16 | // Insert checks here! 17 | mySuper.free (ptr); 18 | } 19 | 20 | private: 21 | 22 | Super mySuper; 23 | }; 24 | 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/thinlock.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _THINLOCK_H_ 4 | #define _THINLOCK_H_ 5 | 6 | #include 7 | 8 | class ThinLock { 9 | public: 10 | 11 | ThinLock (void) 12 | { 13 | InitializeCriticalSection (&crit); 14 | } 15 | 16 | inline void lock (void) { 17 | EnterCriticalSection (&crit); 18 | } 19 | 20 | inline void unlock (void) { 21 | LeaveCriticalSection (&crit); 22 | } 23 | 24 | private: 25 | CRITICAL_SECTION crit; 26 | }; 27 | 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /runtime/heaplayers/tryheap.h: -------------------------------------------------------------------------------- 1 | #ifndef _TRYHEAP_H_ 2 | #define _TRYHEAP_H_ 3 | 4 | template 5 | class TryHeap : public Heap2 { 6 | public: 7 | TryHeap (void) 8 | {} 9 | 10 | inline void * malloc (size_t sz) { 11 | void * ptr = heap1.malloc (sz); 12 | if (ptr == NULL) 13 | ptr = Heap2::malloc (sz); 14 | return ptr; 15 | } 16 | 17 | inline void free (void * ptr) { 18 | heap1.free (ptr); 19 | } 20 | 21 | private: 22 | Heap1 heap1; 23 | }; 24 | 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /runtime/heaplayers/util/hash.h: -------------------------------------------------------------------------------- 1 | #ifndef _HL_HASH_H_ 2 | #define _HL_HASH_H_ 3 | 4 | #include 5 | 6 | namespace HL { 7 | template 8 | extern size_t hash (Key k); 9 | 10 | template <> 11 | inline size_t hash (void * v) { 12 | return (size_t) v; 13 | } 14 | 15 | template <> 16 | inline size_t hash (const void * v) { 17 | return (size_t) ((size_t) v); 18 | } 19 | 20 | template <> 21 | inline size_t hash (int v) { 22 | return (size_t) v; 23 | } 24 | } 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /runtime/heaplayers/fixedsizeheap.h: -------------------------------------------------------------------------------- 1 | #ifndef _FIXEDSIZEHEAP_H_ 2 | #define _FIXEDSIZEHEAP_H_ 3 | 4 | 5 | template 6 | class FixedSizeHeap : public SH { 7 | public: 8 | inline void * malloc (size_t sz) { 9 | assert (sz <= Size); 10 | //printf ("malloc\n"); 11 | return SH::malloc (Size); 12 | } 13 | inline void free (void * ptr) { 14 | //printf ("free\n"); 15 | SH::free (ptr); 16 | } 17 | protected: 18 | inline static size_t size (void * p) { 19 | return Size; 20 | } 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /paper/PPoPP-2014/fig/linearregression.psedocode: -------------------------------------------------------------------------------- 1 | struct 2 | { 3 | pthread_t tid; POINT_T *points; 4 | int num_elems; long long SX; 5 | long long SY; long long SXX; 6 | long long SYY; long long SXY; 7 | } lreg_args; 8 | 9 | void * lreg_thread ( void * args_in ) { 10 | struct lreg_args * args = args_in ; 11 | for(i=0; inum_elems; i++) { 12 | args->SX+=args->points[i].x; 13 | args->SXX+=args->points[i].x*args->points[i].x; 14 | args->SY+=args->points[i].y; 15 | args->SYY+=args->points[i].y*args->points[i].y; 16 | args->SXY+=args->points[i].x*args->points[i].y; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /runtime/heaplayers/util/sassert.h: -------------------------------------------------------------------------------- 1 | #ifndef _SASSERT_H_ 2 | #define _SASSERT_H_ 3 | 4 | /** 5 | * @class sassert 6 | * @brief Implements compile-time assertion checking. 7 | * @author Emery Berger 8 | * 9 | * @code 10 | * sassert<(1+1 == 2)> CheckOnePlusOneIsTwo; 11 | * @endcode 12 | * 13 | * This code is part of the Hoard distribution and is governed by its license. 14 | * 15 | * 16 | */ 17 | 18 | namespace HL { 19 | 20 | template 21 | class sassert; 22 | 23 | template<> class sassert<1> { 24 | public: 25 | enum { VALUE = 1 }; 26 | }; 27 | 28 | } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/prefetchheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _PREFETCHHEAP_H_ 4 | #define _PREFETCHHEAP_H_ 5 | 6 | #define prefetcht0 __asm _emit 0x0f __asm _emit 0x18 __asm _emit 0x08 7 | 8 | 9 | template 10 | class PrefetchHeap : public Super { 11 | public: 12 | 13 | inline void * malloc (size_t sz) { 14 | void * Address = Super::malloc (sz); 15 | #ifdef _M_IX86 16 | // Prefetch this ptr before we return. 17 | __asm 18 | { 19 | mov eax,Address // Load Address. 20 | prefetcht0 // Prefetch into the L1. 21 | } 22 | #endif 23 | return Address; 24 | } 25 | 26 | inline void free (void * ptr) { 27 | Super::free (ptr); 28 | } 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /runtime/heaplayers/padheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _PADHEAP_H_ 4 | #define _PADHEAP_H_ 5 | 6 | #include 7 | 8 | // Pad object size requests. 9 | 10 | template 11 | class PadHeap : public SuperHeap { 12 | public: 13 | 14 | inline void * malloc (size_t sz) { 15 | return SuperHeap::malloc (roundup(sz)); 16 | } 17 | 18 | private: 19 | 20 | inline size_t roundup (size_t sz) { 21 | // NB: CacheLineSize MUST be a power of two. 22 | // The assertion below checks this. 23 | assert ((CacheLineSize & (CacheLineSize-1)) == 0); 24 | size_t roundup = (sz + CacheLineSize - 1) & ~((int) CacheLineSize-1); 25 | assert (roundup >= sz); 26 | return roundup; 27 | } 28 | }; 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/splitheap.h: -------------------------------------------------------------------------------- 1 | #ifndef _SPLITHEAP_H_ 2 | #define _SPLITHEAP_H_ 3 | 4 | template 5 | class SplitHeap : public SuperHeap { 6 | public: 7 | inline void * malloc (const size_t sz) 8 | { 9 | void * ptr = SuperHeap::malloc (sz); 10 | if (ptr != NULL) { 11 | markInUse (ptr); 12 | size_t oldSize = getSize(ptr); 13 | if (oldSize <= sz + sizeof(double)) { 14 | return ptr; 15 | } else { 16 | void * splitPiece = split (ptr, sz); 17 | if (splitPiece != NULL) { 18 | // printf ("split %d into %d and %d\n", oldSize, getSize(ptr), getSize(splitPiece)); 19 | markFree (splitPiece); 20 | SuperHeap::free (splitPiece); 21 | } 22 | } 23 | } 24 | return ptr; 25 | } 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /paper/PPoPP-2014/fig/linearregression.report: -------------------------------------------------------------------------------- 1 | FALSE SHARING HEAP OBJECT: start 0x40000038 end 0x40000238 (with size 200). 2 | Number of accesses: 5153102690; Number of invalidations: 175020; Number of writes: 13636004. 3 | 4 | Callsite stack: 5 | ./stddefines.h:53 6 | ./linear_regression-pthread.c:133 7 | 8 | Word level information: 9 | ...... 10 | Address 0x40000070 (line 16777217): reads 339508 writes 339507 by thread 1 11 | Address 0x40000080 (line 16777218): reads 2716059 writes 0 by thread 2 12 | ...... 13 | Address 0x400000b0 (line 16777218): reads 339507 writes 339508 by thread 2 14 | Address 0x400000c0 (line 16777219): reads 2716061 writes 0 by thread 3 15 | Address 0x400000c8 (line 16777219): reads 339507 writes 0 by thread 3 16 | 17 | 18 | -------------------------------------------------------------------------------- /runtime/heaplayers/checkheap.h: -------------------------------------------------------------------------------- 1 | #ifndef _CHECKHEAP_H_ 2 | #define _CHECKHEAP_H_ 3 | 4 | 5 | template 6 | class CheckHeap : public SuperHeap { 7 | private: 8 | enum { RECEIVED_A_NULL_OBJECT_FROM_MALLOC = 0 }; 9 | enum { RECEIVED_AN_UNALIGNED_OBJECT_FROM_MALLOC = 0 }; 10 | public: 11 | inline void * malloc (size_t sz) { 12 | void * addr = SuperHeap::malloc (sz); 13 | if (addr == NULL) { 14 | assert (RECEIVED_A_NULL_OBJECT_FROM_MALLOC); 15 | printf ("RECEIVED_A_NULL_OBJECT_FROM_MALLOC\n"); 16 | abort(); 17 | } 18 | if ((unsigned long) addr % sizeof(double) != 0) { 19 | assert (RECEIVED_AN_UNALIGNED_OBJECT_FROM_MALLOC); 20 | printf ("RECEIVED_AN_UNALIGNED_OBJECT_FROM_MALLOC\n"); 21 | abort(); 22 | } 23 | return addr; 24 | } 25 | }; 26 | 27 | 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /test/falsesharingexample/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | rm -f thread_memtest.bc thread_memtest-afterinstrument.bc thread_memtest-afterinstrument.ll 3 | # clang -Wl,/home/tongping/work/falsesharing/project/runtime/libdefault64.so -g -O2 thread_memtest.c -lpthread -o thread_memtest 4 | clang -Wl,/nfs/cm/scratch1/tonyliu/grace/branches/falsesharing/project/runtime/libdefault64.so -finstrumenter -g -O0 thread_memtest.c -lpthread -o thread_memtest 5 | # clang -g -O2 thread_memtest.c -lpthread -o thread_memtest-pthread 6 | 7 | clean: 8 | rm -f thread_memtest.native thread_memtestnew.bc thread_memtest.bc thread_memtest-afterinstrument.bc thread_memtest-afterinstrument.ll thread_memtest.ll thread_memtest.s 9 | # gcc thread_memtest.s -Llibrary -lsheriff -o thread_memtest.native 10 | # clang -O0 -emit-llvm thread_memtest.c -S -o thread_memtest.ll 11 | -------------------------------------------------------------------------------- /runtime/objectinfo.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef SHERIFF_OBJECTINFO_H 4 | #define SHERIFF_OBJECTINFO_H 5 | 6 | #include "xdefines.h" 7 | 8 | class ObjectInfo { 9 | public: 10 | // Whether this is a heap object 11 | bool isHeapObject; 12 | bool hasPotentialFS; 13 | int accessThreads; // False sharing type, inter-objects or inner-object 14 | int times; 15 | unsigned long words; 16 | long invalidations; 17 | unsigned long totalWrites; 18 | unsigned long totalAccesses; 19 | unsigned long unitlength; 20 | unsigned long totallength; 21 | unsigned long * start; 22 | unsigned long * stop; 23 | void * winfo; 24 | union { 25 | // Used for globals only. 26 | void * symbol; 27 | 28 | // Callsite information. 29 | unsigned long callsite[CALL_SITE_DEPTH]; 30 | } u; 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/binheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _BINHEAP_H_ 4 | #define _BINHEAP_H_ 5 | 6 | #include 7 | 8 | 9 | template 10 | class BinHeap { 11 | public: 12 | 13 | inline void * malloc (size_t sz) { 14 | // Find bin. 15 | int bin = findBin (sz); 16 | void * ptr = myHeaps[bin].malloc (sz); 17 | return ptr; 18 | } 19 | 20 | inline void free (void * ptr) { 21 | size_t sz = Super::size (ptr); 22 | int bin = findBin (sz); 23 | myHeaps[bin].free (ptr); 24 | } 25 | 26 | private: 27 | 28 | inline int findBin (size_t sz) { 29 | int i; 30 | for (i = 0; i < NumBins; i++) { 31 | if (Bins[i] >= sz) { 32 | break; 33 | } 34 | } 35 | return i; 36 | } 37 | 38 | Super myHeaps[NumBins + 1]; 39 | 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /runtime/heaplayers/util/bitindex.cpp: -------------------------------------------------------------------------------- 1 | #include "bitindex.h" 2 | 3 | // Definitions of static members of BitIndex. 4 | 5 | int BitIndex::index32[32]; 6 | unsigned long BitIndex::on[32]; 7 | unsigned long BitIndex::off[32]; 8 | unsigned long BitIndex::lgtable[16]; 9 | 10 | // Implementations. 11 | 12 | BitIndex::BitIndex (void) 13 | { 14 | setup(); 15 | } 16 | 17 | 18 | void BitIndex::setup (void) 19 | { 20 | int t[] = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3}; 21 | int i; 22 | for (i = 0; i < 32; i++) { 23 | index32[ (debruijn32 << i) >> 27 ] = i; 24 | } 25 | for (i = 0; i < 16; i++) { 26 | lgtable[i] = t[i]; 27 | } 28 | for (i = 0; i < 32; i++) { 29 | on[i] = 1 << i; 30 | off[i] = ~on[i]; 31 | } 32 | } 33 | 34 | 35 | 36 | // One instance of BitIndex so everything will work. 37 | 38 | static BitIndex _hiddenBitIndex; 39 | -------------------------------------------------------------------------------- /runtime/x.log: -------------------------------------------------------------------------------- 1 | This is pdfeTeX, Version 3.141592-1.21a-2.2 (Web2C 7.5.4) (format=pdflatex 2012.8.24) 12 SEP 2013 10:34 2 | entering extended mode 3 | **main 4 | (/usr/share/texmf/tex/latex/tools/x.tex 5 | ! Interruption. 6 | 7 | \begingroup 8 | l.1 9 | %% 10 | ? x 11 | 12 | Here is how much of TeX's memory you used: 13 | 8 strings out of 94500 14 | 203 string characters out of 1176766 15 | 48348 words of memory out of 1000000 16 | 3273 multiletter control sequences out of 10000+50000 17 | 3640 words of font info for 14 fonts, out of 500000 for 2000 18 | 580 hyphenation exceptions out of 1000 19 | 3i,0n,1p,11b,6s stack positions out of 1500i,500n,5000p,200000b,5000s 20 | PDF statistics: 21 | 0 PDF objects out of 300000 22 | 0 named destinations out of 131072 23 | 1 words of extra memory for PDF output out of 65536 24 | No pages of output. 25 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/lazyheap.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _LAZYHEAP_H_ 4 | #define _LAZYHEAP_H_ 5 | 6 | template 7 | class LazyHeap { 8 | public: 9 | 10 | LazyHeap (void) 11 | : initialized (0) 12 | {} 13 | 14 | ~LazyHeap (void) { 15 | if (initialized) { 16 | delete lazyheap; 17 | } 18 | } 19 | 20 | inline void * malloc (size_t sz) { 21 | return getHeap()->malloc (sz); 22 | } 23 | inline void free (void * ptr) { 24 | getHeap()->free (ptr); 25 | } 26 | inline void clear (void) { 27 | if (initialized) { 28 | getHeap()->clear(); 29 | } 30 | } 31 | 32 | private: 33 | 34 | SuperHeap * getHeap (void) { 35 | if (!initialized) { 36 | lazyheap = new SuperHeap; 37 | initialized = 1; 38 | } 39 | return lazyheap; 40 | } 41 | 42 | bool initialized; 43 | SuperHeap * lazyheap; 44 | }; 45 | 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /runtime/heaplayers/sbrkheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _SBRKHEAP_H_ 4 | #define _SBRKHEAP_H_ 5 | 6 | #ifdef WIN32 7 | 8 | // If we're using Windows, we'll need to link in sbrk.c, 9 | // a replacement for sbrk(). 10 | 11 | extern "C" void * sbrk (size_t sz); 12 | 13 | #endif 14 | 15 | /* 16 | * @class SbrkHeap 17 | * @brief A source heap that is a thin wrapper over sbrk. 18 | * 19 | * As it stands, memory cannot be returned to sbrk(). 20 | * This is not a significant limitation, since only memory 21 | * at the end of the break point can ever be returned anyway. 22 | */ 23 | 24 | namespace HL { 25 | 26 | class SbrkHeap { 27 | public: 28 | SbrkHeap (void) 29 | {} 30 | 31 | inline void * malloc (size_t sz) { 32 | return sbrk(sz); 33 | } 34 | 35 | inline void free (void *) { } 36 | inline int remove (void *) { return 0; } 37 | }; 38 | 39 | } 40 | 41 | 42 | #endif 43 | 44 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/counteddictionary.h: -------------------------------------------------------------------------------- 1 | #ifndef _COUNTEDDICTIONARY_H_ 2 | #define _COUNTEDDICTIONARY_H_ 3 | 4 | template 5 | class CountedDictionary : public Dict { 6 | public: 7 | class Entry : public Dict::Entry {}; 8 | 9 | __forceinline CountedDictionary (void) 10 | : num (0) 11 | {} 12 | 13 | __forceinline void clear (void) { 14 | num = 0; 15 | Dict::clear(); 16 | } 17 | 18 | __forceinline Entry * get (void) { 19 | Entry * e = (Entry *) Dict::get(); 20 | if (e) { 21 | --num; 22 | } 23 | return e; 24 | } 25 | 26 | __forceinline Entry * remove (void) { 27 | Entry * e = (Entry *) Dict::remove(); 28 | if (e) { 29 | --num; 30 | } 31 | return e; 32 | } 33 | 34 | __forceinline void insert (Entry * e) { 35 | Dict::insert (e); 36 | ++num; 37 | } 38 | 39 | __forceinline int getNumber (void) const { 40 | return num; 41 | } 42 | 43 | private: 44 | int num; 45 | }; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /runtime/heaplayers/hldefines.h: -------------------------------------------------------------------------------- 1 | #ifndef _HLDEFINES_H_ 2 | #define _HLDEFINES_H_ 3 | 4 | /* 5 | * @file hldefines.h 6 | * @brief Defines macros used throughout Heap Layers. 7 | * 8 | */ 9 | 10 | // Define HL_EXECUTABLE_HEAP as 1 if you want that (i.e., you're doing 11 | // dynamic code generation). 12 | 13 | #define HL_EXECUTABLE_HEAP 0 14 | 15 | #if defined(_MSC_VER) 16 | 17 | // Microsoft Visual Studio 18 | #pragma inline_depth(255) 19 | #define INLINE __forceinline 20 | #define inline __forceinline 21 | #define NO_INLINE __declspec(noinline) 22 | #pragma warning(disable: 4530) 23 | #define MALLOC_FUNCTION 24 | #define RESTRICT 25 | 26 | #elif defined(__GNUC__) 27 | 28 | // GNU C 29 | 30 | #define NO_INLINE __attribute__ ((noinline)) 31 | #define INLINE inline 32 | #define MALLOC_FUNCTION __attribute__((malloc)) 33 | #define RESTRICT __restrict__ 34 | 35 | #else 36 | 37 | // All others 38 | 39 | #define NO_INLINE 40 | #define INLINE inline 41 | #define MALLOC_FUNCTION 42 | #define RESTRICT 43 | 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /paper/PPoPP-2014/table.tex: -------------------------------------------------------------------------------- 1 | \begin{table*}[ht!] 2 | {\centering\begin{tabular}{l|r|r|r|r|r}\hline 3 | {\bf \small Benchmark} & {\bf \small Source Code} & {\bf \small New} & {\bf \small Without Prediction} &{\bf \small With Prediction} & {\bf \small Improvement} \\ 4 | \hline 5 | \small \textbf{histogram} & {\small histogram-pthread.c:213} & \cmark{} &\cmark{} & \cmark{} & 46.22\%\\ 6 | \small \textbf{linear\_regression} & {\small linear\_regression-pthread.c:133} & & & \cmark{} & 1206.93\ 7 | %\\ 8 | \small \textbf{reverse\_index} & {\small reverseindex-pthread.c:511} & & \cmark{} & \cmark{} & 0.09\%\\\small \textbf{word\_count} & {\small word\_count-pthread.c:136} & & \cmark{} & \cmark{} & 0.14\%\\ 9 | \hline 10 | \small \textbf{streamcluster} & {\small streamcluster.cpp:985} & & \cmark{} & \cmark{} &7.52\% \\ 11 | \small \textbf{streamcluster} & {\small streamcluster.cpp:1907} & \cmark{} & \cmark{} & \cmark{} & 4.77\%\\ 12 | \hline 13 | \end{tabular} 14 | \caption{Detection results of \Predator{} on Phoenix and PARSEC benchmark suites. \label{table:detection 15 | }} 16 | } 17 | \end{table*} 18 | 19 | -------------------------------------------------------------------------------- /paper/PPoPP-2014/futurework.tex: -------------------------------------------------------------------------------- 1 | \label{sec:futurework} 2 | 3 | We have identified several directions along which \Predator{} could be enhanced. 4 | 5 | \paragraph{Use Across the Software Stack.} 6 | \Predator{}'s architecture should in principle let it detect and predict false sharing in the entire software stack, including hypervisors, operating systems, libraries, and applications using different threading libraries. 7 | 8 | \paragraph{Improved Performance.} 9 | \Predator{} currently imposes approximately $6\times$ performance overhead. In the current implementation, every memory access is instrumented with a library call to notify the runtime system. A library call entails not only normal function call overhead but also Global Offset Table (GOT) and/or Procedure Linkage Table (PLT) lookup overhead. We plan to improve \Predator{}'s performance by inserting relevant code directly, rather than via function calls. 10 | 11 | \paragraph{Suggest Fixes.} Finally, we would like to enhance \Predator{}'s reporting. We believe that leveraging memory trace information will make it possible for \Predator{} to prescribe fixes to the programmer to help them eliminate false sharing. 12 | 13 | -------------------------------------------------------------------------------- /runtime/heaplayers/debugheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | 4 | #ifndef _DEBUGHEAP_H_ 5 | #define _DEBUGHEAP_H_ 6 | 7 | #include 8 | 9 | /** 10 | * 11 | * 12 | */ 13 | 14 | namespace HL { 15 | 16 | template 18 | class DebugHeap : public Super { 19 | private: 20 | 21 | enum { CANARY = 0xdeadbeef }; 22 | 23 | public: 24 | 25 | // Fill with A's. 26 | inline void * malloc (size_t sz) { 27 | // Add a guard area at the end. 28 | void * ptr; 29 | ptr = Super::malloc (sz + sizeof(unsigned long)); 30 | memset (ptr, 'A', sz); 31 | *((unsigned long *) ((char *) ptr + sz)) = (unsigned long) CANARY; 32 | assert (Super::getSize(ptr) >= sz); 33 | return ptr; 34 | } 35 | 36 | // Fill with F's. 37 | inline void free (void * ptr) { 38 | char * b = (char *) ptr; 39 | size_t sz = Super::getSize(ptr); 40 | // Check for the canary. 41 | unsigned long storedCanary = *((unsigned long *) b + sz - sizeof(unsigned long)); 42 | if (storedCanary != CANARY) { 43 | abort(); 44 | } 45 | memset (ptr, freeChar, sz); 46 | Super::free (ptr); 47 | } 48 | }; 49 | 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /runtime/xplock.h: -------------------------------------------------------------------------------- 1 | #ifndef SHERIFF_XPLOCK_H 2 | #define SHERIFF_XPLOCK_H 3 | 4 | #if !defined(_WIN32) 5 | #include 6 | #include 7 | #include 8 | #include 9 | #endif 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "internalheap.h" 16 | 17 | /** 18 | * @class xplock 19 | * @brief A cross-process lock. 20 | * 21 | * @author Emery Berger 22 | */ 23 | 24 | // Use secret hidden APIs to avoid mallocs... 25 | 26 | class xplock { 27 | public: 28 | 29 | xplock (void) { 30 | // Instantiate the lock structure inside a shared mmap. 31 | _lock = (pthread_mutex_t *) 32 | mmap (NULL, xdefines::PageSize, 33 | PROT_READ | PROT_WRITE, 34 | MAP_SHARED | MAP_ANONYMOUS, -1, 0); 35 | 36 | pthread_mutex_init(_lock, NULL); 37 | } 38 | 39 | /// @brief Lock the lock. 40 | void lock() { 41 | pthread_mutex_lock(_lock); 42 | } 43 | 44 | /// @brief Unlock the lock. 45 | void unlock() { 46 | pthread_mutex_unlock(_lock); 47 | } 48 | 49 | private: 50 | 51 | /// A pointer to the lock. 52 | pthread_mutex_t * _lock; 53 | }; 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/kingsmodheap.h: -------------------------------------------------------------------------------- 1 | #ifndef _KINGSMODHEAP_H_ 2 | #define _KINGSMODHEAP_H_ 3 | 4 | #include "segheap.h" 5 | 6 | /* KingsMod (segregated fits) allocator */ 7 | 8 | namespace KingsMod { 9 | 10 | inline size_t class2Size (int i); 11 | 12 | inline int pow2Class (size_t sz) { 13 | static size_t sizeTable[] = {8UL, 16UL, 24UL, 32UL, 40UL, 48UL, 56UL, 72UL, 80UL, 96UL, 120UL, 144UL, 168UL, 200UL, 240UL, 288UL, 344UL, 416UL, 496UL, 592UL, 712UL, 856UL, 1024UL, 1232UL, 1472UL, 1768UL, 2120UL, 2544UL, 3048UL, 3664UL}; 14 | int c = 0; 15 | while (c < 30 && sz < sizeTable[c]) { 16 | c++; 17 | } 18 | return c; 19 | } 20 | 21 | inline size_t class2Size (int i) { 22 | assert (i >= 0); 23 | assert (i < 30); 24 | static size_t sizeTable[] = {8UL, 16UL, 24UL, 32UL, 40UL, 48UL, 56UL, 72UL, 80UL, 96UL, 120UL, 144UL, 168UL, 200UL, 240UL, 288UL, 344UL, 416UL, 496UL, 592UL, 712UL, 856UL, 1024UL, 1232UL, 1472UL, 1768UL, 2120UL, 2544UL, 3048UL, 3664UL}; 25 | return sizeTable[i]; 26 | } 27 | 28 | }; 29 | 30 | 31 | template 32 | class KingsModHeap : public SegHeap<29, KingsMod::pow2Class, KingsMod::class2Size, PerClassHeap, PerClassHeap> {}; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /paper/PPoPP-2014/conclusion.tex: -------------------------------------------------------------------------------- 1 | \label{sec:conclusion} 2 | This paper introduces \emph{predictive false sharing detection}, and presents a prototype system that performs this detection called \Predator{}. By collecting and analyzing information through instrumented reads and writes, the runtime system detects false sharing based on cache invalidations and only reports those potentially causing severe performance degradation. 3 | \Predator{} predicts potential false sharing that could be caused by a change of hardware cache line size or the starting addresses of objects. By identifying latent false sharing problems that can occur in the wild but which are unobserved in the test environment, \Predator{} overcomes a key limitation of 4 | all previous false sharing detection approaches. 5 | 6 | Our evaluation shows that \Predator{} can effectively detect and predict several previously unknown and existing false sharing problems in two popular benchmark suites, Phoenix and PARSEC. We also evaluate \Predator{} on six real applications. 7 | It successfully detects two known false sharing problems inside MySQL and the Boost library. 8 | Fixing these false sharing problems improves performance by $6\times$ and $40\%$, respectively. 9 | 10 | % Availability. 11 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/multiheap.h: -------------------------------------------------------------------------------- 1 | #ifndef _MULTIHEAP_H_ 2 | #define _MULTIHEAP_H_ 3 | 4 | #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) 5 | #ifndef WIN32 6 | #define WIN32 1 7 | #endif 8 | #include 9 | #include 10 | #endif 11 | 12 | template 13 | class MultiHeap : public Super { 14 | public: 15 | 16 | inline void * malloc (size_t sz) { 17 | // Hash the thread id. 18 | // We assume that it's impossible for two threads to collide. 19 | int tid = getThreadId() % NumHeaps; 20 | void * ptr = mySuper[tid].malloc (sz + sizeof(double)); 21 | *((int *) ptr) = tid; 22 | void * newPtr = (void *) ((double *) ptr + 1); 23 | return newPtr; 24 | } 25 | 26 | inline void free (void * ptr) { 27 | // Return the object to its own heap. 28 | void * originalPtr = (void *) ((double *) ptr - 1); 29 | int heapIndex = *((int *) originalPtr); 30 | // FIX ME! A 'cache' would be nice here... 31 | // FIX ME! We need a lock here. 32 | mySuper[heapIndex].free (originalPtr); 33 | } 34 | 35 | private: 36 | 37 | Super mySuper[NumHeaps]; 38 | 39 | int getThreadId (void) { 40 | #if WIN32 41 | return GetCurrentThreadId(); 42 | #endif 43 | } 44 | 45 | }; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /runtime/heaplayers/freelistheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _FREELISTHEAP_H_ 4 | #define _FREELISTHEAP_H_ 5 | 6 | /** 7 | * @class FreelistHeap 8 | * @brief Manage freed memory on a linked list. 9 | * @warning This is for one "size class" only. 10 | * 11 | * Note that the linked list is threaded through the freed objects, 12 | * meaning that such objects must be at least the size of a pointer. 13 | */ 14 | 15 | #include "freesllist.h" 16 | #include 17 | 18 | namespace HL { 19 | 20 | template 21 | class FreelistHeap : public SuperHeap { 22 | public: 23 | 24 | FreelistHeap (void) 25 | { 26 | } 27 | 28 | inline void * malloc (size_t sz) { 29 | // Check the free list first. 30 | void * ptr = _freelist.get(); 31 | // If it's empty, get more memory; 32 | // otherwise, advance the free list pointer. 33 | if (ptr == 0) { 34 | ptr = SuperHeap::malloc (sz); 35 | } 36 | return ptr; 37 | } 38 | 39 | inline void free (void * ptr) { 40 | if (ptr == 0) { 41 | return; 42 | } 43 | _freelist.insert (ptr); 44 | } 45 | 46 | inline void clear (void) { 47 | void * ptr; 48 | while (ptr = _freelist.get()) { 49 | SuperHeap::free (ptr); 50 | } 51 | } 52 | 53 | private: 54 | 55 | FreeSLList _freelist; 56 | 57 | }; 58 | 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /runtime/heaplayers/freesllist.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _FREESLLIST_H_ 4 | #define _FREESLLIST_H_ 5 | 6 | #include 7 | 8 | /** 9 | * @class FreeSLList 10 | * @brief A "memory neutral" singly-linked list, 11 | * 12 | * Uses the free space in objects to store 13 | * the pointers. 14 | */ 15 | 16 | 17 | class FreeSLList { 18 | public: 19 | 20 | inline void clear (void) { 21 | head.next = NULL; 22 | } 23 | 24 | class Entry; 25 | 26 | /// Get the head of the list. 27 | inline Entry * get (void) { 28 | const Entry * e = head.next; 29 | if (e == NULL) { 30 | return NULL; 31 | } 32 | head.next = e->next; 33 | return const_cast(e); 34 | } 35 | 36 | inline Entry * remove (void) { 37 | const Entry * e = head.next; 38 | if (e == NULL) { 39 | return NULL; 40 | } 41 | head.next = e->next; 42 | return const_cast(e); 43 | } 44 | 45 | inline void insert (void * e) { 46 | Entry * entry = reinterpret_cast(e); 47 | entry->next = head.next; 48 | head.next = entry; 49 | } 50 | 51 | class Entry { 52 | public: 53 | Entry (void) 54 | : next (NULL) 55 | {} 56 | Entry * next; 57 | #if 0 58 | private: 59 | Entry (const Entry&); 60 | Entry& operator=(const Entry&); 61 | #endif 62 | }; 63 | 64 | private: 65 | Entry head; 66 | }; 67 | 68 | 69 | #endif 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /runtime/heaplayers/profileheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _PROFILEHEAP_H_ 4 | #define _PROFILEHEAP_H_ 5 | 6 | 7 | #include 8 | 9 | extern int memRequested; 10 | extern int maxMemRequested; 11 | 12 | // Maintain & print memory usage info. 13 | // Requires a superheap with the size() method (e.g., SizeHeap). 14 | 15 | template 16 | class ProfileHeap : public super { 17 | public: 18 | 19 | ProfileHeap (void) 20 | { 21 | memRequested = 0; 22 | maxMemRequested = 0; 23 | } 24 | 25 | ~ProfileHeap (void) 26 | { 27 | if (maxMemRequested > 0) { 28 | stats(); 29 | } 30 | } 31 | 32 | inline void * malloc (size_t sz) { 33 | void * ptr = super::malloc (sz); 34 | // Notice that we use the size reported by the allocator 35 | // for the object rather than the requested size. 36 | memRequested += super::getSize(ptr); 37 | if (memRequested > maxMemRequested) { 38 | maxMemRequested = memRequested; 39 | } 40 | return ptr; 41 | } 42 | 43 | inline void free (void * ptr) { 44 | memRequested -= super::getSize (ptr); 45 | super::free (ptr); 46 | } 47 | 48 | private: 49 | void stats (void) { 50 | printf ("Heap: %d\n", HeapNumber); 51 | printf ("Max memory requested = %d\n", maxMemRequested); 52 | printf ("Memory still in use = %d\n", memRequested); 53 | } 54 | 55 | int memRequested; 56 | int maxMemRequested; 57 | 58 | }; 59 | 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /runtime/finetime.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | Copyright (C) 2011 University of Massachusetts Amherst. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | */ 21 | 22 | #ifndef SHERIFF_FINETIME_H 23 | #define SHERIFF_FINETIME_H 24 | 25 | /* 26 | * @file finetime.h 27 | * @brief Fine timing management based on rdtsc. 28 | * @author Ting Yang 29 | * @author Tongping Liu 30 | */ 31 | 32 | 33 | extern "C" { 34 | 35 | struct timeinfo { 36 | unsigned long low; 37 | unsigned long high; 38 | }; 39 | 40 | void start (struct timeinfo *ti); 41 | double stop (struct timeinfo * begin, struct timeinfo * end); 42 | unsigned long elapsed2ms(double elapsed); 43 | 44 | }; 45 | #endif /* __TIME_H__ */ 46 | -------------------------------------------------------------------------------- /runtime/heaplayers/hybridheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _HYBRIDHEAP_H_ 4 | #define _HYBRIDHEAP_H_ 5 | 6 | #include 7 | #include "sassert.h" 8 | #include "hldefines.h" 9 | 10 | /** 11 | * @class HybridHeap 12 | * Objects no bigger than BigSize are allocated and freed to SmallHeap. 13 | * Bigger objects are passed on to the super heap. 14 | */ 15 | 16 | namespace HL { 17 | 18 | template 19 | class HybridHeap : public SmallHeap { 20 | public: 21 | 22 | HybridHeap (void) 23 | { 24 | } 25 | 26 | enum { Alignment = ((int) SmallHeap::Alignment < (int) BigHeap::Alignment) ? 27 | (int) SmallHeap::Alignment : 28 | (int) BigHeap::Alignment }; 29 | 30 | MALLOC_FUNCTION INLINE void * malloc (size_t sz) { 31 | if (sz <= BigSize) { 32 | return SmallHeap::malloc (sz); 33 | } else { 34 | return slowPath (sz); 35 | } 36 | } 37 | 38 | inline void free (void * ptr) { 39 | if (SmallHeap::getSize(ptr) <= BigSize) { 40 | SmallHeap::free (ptr); 41 | } else { 42 | bm.free (ptr); 43 | } 44 | } 45 | 46 | inline void clear (void) { 47 | bm.clear(); 48 | SmallHeap::clear(); 49 | } 50 | 51 | 52 | private: 53 | 54 | MALLOC_FUNCTION NO_INLINE 55 | void * slowPath (size_t sz) { 56 | return bm.malloc (sz); 57 | } 58 | 59 | 60 | HL::sassert<(BigSize > 0)> checkBigSizeNonZero; 61 | 62 | BigHeap bm; 63 | }; 64 | 65 | } 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /runtime/heaplayers/nullheap.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2003 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | #ifndef _NULLHEAP_H_ 28 | #define _NULLHEAP_H_ 29 | 30 | #include 31 | 32 | /** 33 | * @class NullHeap 34 | * @brief A source heap that does nothing. 35 | */ 36 | 37 | namespace HL { 38 | 39 | class NullHeap { 40 | public: 41 | inline void * malloc (size_t) const { return 0; } 42 | inline void free (void *) const {} 43 | inline int remove (void *) const { return 0; } 44 | inline void clear (void) const {} 45 | inline size_t getSize (void *) const { return 0; } 46 | }; 47 | 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /runtime/heaplayers/perclassheap.h: -------------------------------------------------------------------------------- 1 | #ifndef _PERCLASSHEAP_H 2 | #define _PERCLASSHEAP_H 3 | 4 | #include 5 | 6 | /** 7 | * @class PerClassHeap 8 | * @brief Enable the use of one heap for all class memory allocation. 9 | * 10 | * This class contains one instance of the SuperHeap argument. The 11 | * example below shows how to make a subclass of Foo that uses a 12 | * FreelistHeap to manage its memory, overloading operators new and 13 | * delete. 14 | * 15 | * 16 | * class NewFoo : public Foo, PerClassHeap > {}; 17 | * 18 | */ 19 | 20 | namespace HL { 21 | 22 | template 23 | class PerClassHeap { 24 | public: 25 | inline void * operator new (size_t sz) { 26 | return getHeap()->malloc (sz); 27 | } 28 | inline void operator delete (void * ptr) { 29 | getHeap()->free (ptr); 30 | } 31 | inline void * operator new[] (size_t sz) { 32 | return getHeap()->malloc (sz); 33 | } 34 | inline void operator delete[] (void * ptr) { 35 | getHeap()->free (ptr); 36 | } 37 | // For some reason, g++ needs placement new to be overridden 38 | // as well, at least in conjunction with use of the STL. 39 | // Otherwise, this should be superfluous. 40 | inline void * operator new (size_t sz, void * p) { return p; } 41 | inline void * operator new[] (size_t sz, void * p) { return p; } 42 | 43 | private: 44 | inline static SuperHeap * getHeap (void) { 45 | static SuperHeap theHeap; 46 | return &theHeap; 47 | } 48 | }; 49 | 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/theap.h: -------------------------------------------------------------------------------- 1 | #ifndef _THEAP_H_ 2 | #define _THEAP_H_ 3 | 4 | // A general threshold-based heap. 5 | 6 | // Threshold layer. 7 | // Once we have more than Threshold bytes on our freelist, 8 | // return memory to the superheap. 9 | 10 | // The class argument FH should be some freelist heap that subclasses NullHeap. 11 | 12 | template 13 | class THeap : public SuperHeap { 14 | public: 15 | THeap (void) 16 | : total (0) 17 | {} 18 | 19 | ~THeap (void) 20 | {} 21 | 22 | inline void * malloc (size_t sz) { 23 | void * ptr; 24 | ptr = fHeap.malloc (sz); 25 | if (ptr == NULL) { 26 | // We have no memory on our freelist. 27 | // Get it from the superheap. 28 | ptr = SuperHeap::malloc (sz); 29 | } else { 30 | total -= size(ptr); 31 | // printf ("total = %d\n", total); 32 | } 33 | assert (size(ptr) >= sz); 34 | return ptr; 35 | } 36 | 37 | inline void free (void * ptr) { 38 | if (total < Threshold) { 39 | // printf ("FREE TO FREELIST.\n"); 40 | total += size(ptr); 41 | fHeap.free (ptr); 42 | //printf ("total = %d\n", total); 43 | } else { 44 | // Dump the freelist heap. 45 | void * p = fHeap.malloc (1); 46 | while (p != NULL) { 47 | SuperHeap::free (p); 48 | p = fHeap.malloc (1); 49 | } 50 | SuperHeap::free (ptr); 51 | total = 0; 52 | } 53 | } 54 | 55 | private: 56 | // Provide a free list that will return NULL if it is out of memory. 57 | FH fHeap; 58 | int total; 59 | }; 60 | 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /runtime/heaplayers/boundedfreelistheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _BOUNDEDFREELISTHEAP_H_ 4 | #define _BOUNDEDFREELISTHEAP_H_ 5 | 6 | // Beware -- this is for one "size class" only!! 7 | 8 | template 9 | class BoundedFreeListHeap : public Super { 10 | public: 11 | 12 | BoundedFreeListHeap (void) 13 | : nObjects (0), 14 | myFreeList (NULL) 15 | {} 16 | 17 | ~BoundedFreeListHeap (void) 18 | { 19 | clear(); 20 | } 21 | 22 | inline void * malloc (size_t sz) { 23 | // Check the free list first. 24 | void * ptr = myFreeList; 25 | if (ptr == NULL) { 26 | ptr = Super::malloc (sz); 27 | } else { 28 | myFreeList = myFreeList->next; 29 | } 30 | return ptr; 31 | } 32 | 33 | inline void free (void * ptr) { 34 | if (nObjects < numObjects) { 35 | // Add this object to the free list. 36 | ((freeObject *) ptr)->next = myFreeList; 37 | myFreeList = (freeObject *) ptr; 38 | nObjects++; 39 | } else { 40 | clear(); 41 | // Super::free (ptr); 42 | } 43 | } 44 | 45 | inline void clear (void) { 46 | // Delete everything on the free list. 47 | void * ptr = myFreeList; 48 | while (ptr != NULL) { 49 | void * oldptr = ptr; 50 | ptr = (void *) ((freeObject *) ptr)->next; 51 | Super::free (oldptr); 52 | } 53 | myFreeList = NULL; 54 | nObjects = 0; 55 | } 56 | 57 | private: 58 | 59 | class freeObject { 60 | public: 61 | freeObject * next; 62 | }; 63 | 64 | int nObjects; 65 | freeObject * myFreeList; 66 | }; 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /runtime/heaplayers/util/recursivelock.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _RECURSIVELOCK_H_ 4 | #define _RECURSIVELOCK_H_ 5 | 6 | /** 7 | * @class RecursiveLockType 8 | * @brief Implements a recursive lock using some base lock representation. 9 | * @param BaseLock The base lock representation. 10 | */ 11 | 12 | #include "cpuinfo.h" 13 | 14 | namespace HL { 15 | 16 | template 17 | class RecursiveLockType : public BaseLock { 18 | public: 19 | 20 | inline RecursiveLockType (void); 21 | 22 | inline void lock (void); 23 | inline void unlock (void); 24 | 25 | private: 26 | int tid; /// The lock owner's thread id. -1 if unlocked. 27 | int count; /// The recursion depth of the lock. 28 | }; 29 | 30 | 31 | }; 32 | 33 | template 34 | HL::RecursiveLockType::RecursiveLockType (void) 35 | : tid (-1), 36 | count (0) 37 | {} 38 | 39 | template 40 | void HL::RecursiveLockType::lock (void) { 41 | int currthread = CPUInfo::getThreadId(); 42 | if (tid == currthread) { 43 | count++; 44 | } else { 45 | BaseLock::lock(); 46 | tid = currthread; 47 | count++; 48 | } 49 | } 50 | 51 | template 52 | void HL::RecursiveLockType::unlock (void) { 53 | int currthread = CPUInfo::getThreadId(); 54 | if (tid == currthread) { 55 | count--; 56 | if (count == 0) { 57 | tid = -1; 58 | BaseLock::unlock(); 59 | } 60 | } else { 61 | // We tried to unlock it but we didn't lock it! 62 | // This should never happen. 63 | assert (0); 64 | abort(); 65 | } 66 | } 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /runtime/heaplayers/bins4k.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #if !defined(_BINS4K_H_) 4 | #define _BINS4K_H_ 5 | 6 | #include "bins.h" 7 | #include "sassert.h" 8 | 9 | namespace HL { 10 | 11 | template 12 | class bins { 13 | 14 | public: 15 | bins (void) {} 16 | 17 | enum { NUM_BINS = 33 }; 18 | enum { BIG_OBJECT = 4096 - sizeof(Header) }; 19 | 20 | static const size_t _bins[NUM_BINS]; 21 | 22 | static inline int getSizeClass (size_t sz) { 23 | assert (sz <= BIG_OBJECT); 24 | if (sz < 8) { 25 | return 0; 26 | } else if (sz <= 128) { 27 | return ((sz + 7) >> 3) - 1; 28 | } else { 29 | return slowLookupSizeClass (sz); 30 | } 31 | } 32 | 33 | static inline size_t getClassSize (const int i) { 34 | assert (i >= 0); 35 | assert (i < NUM_BINS); 36 | return _bins[i]; 37 | } 38 | 39 | private: 40 | 41 | static int slowLookupSizeClass (const size_t sz) { 42 | // Find the size class for a given object size 43 | // (the smallest i such that _bins[i] >= sz). 44 | int sizeclass = 0; 45 | while (_bins[sizeclass] < sz) 46 | { 47 | sizeclass++; 48 | assert (sizeclass < NUM_BINS); 49 | } 50 | return sizeclass; 51 | } 52 | 53 | sassert<(BIG_OBJECT > 0)> verifyHeaderSize; 54 | 55 | }; 56 | } 57 | 58 | template 59 | const size_t HL::bins::_bins[NUM_BINS] = {8UL, 16UL, 24UL, 32UL, 40UL, 48UL, 56UL, 64UL, 72UL, 80UL, 88UL, 96UL, 104UL, 112UL, 120UL, 128UL, 152UL, 176UL, 208UL, 248UL, 296UL, 352UL, 416UL, 496UL, 592UL, 704UL, 856UL, 1024UL, 1224UL, 1712UL, 2048UL, 3416UL, 4096UL - sizeof(Header)}; 60 | 61 | #endif 62 | 63 | -------------------------------------------------------------------------------- /runtime/heaplayers/lockedheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2003 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | #ifndef _LOCKEDHEAP_H_ 28 | #define _LOCKEDHEAP_H_ 29 | 30 | #include "guard.h" 31 | 32 | namespace HL { 33 | 34 | template 35 | class LockedHeap : public Super { 36 | public: 37 | 38 | inline void * malloc (size_t sz) { 39 | Guard l (thelock); 40 | return Super::malloc (sz); 41 | } 42 | 43 | inline void free (void * ptr) { 44 | Guard l (thelock); 45 | Super::free (ptr); 46 | } 47 | 48 | inline void lock (void) { 49 | thelock.lock(); 50 | } 51 | 52 | inline void unlock (void) { 53 | thelock.unlock(); 54 | } 55 | 56 | private: 57 | LockType thelock; 58 | }; 59 | 60 | } 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/emptychunkheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _LAZYSLOTHEAP_H_ 4 | #define _LAZYSLOTHEAP_H_ 5 | 6 | /* 7 | This heap manages memory in units of Chunks. 8 | malloc returns a slot within a chunk, 9 | while free returns slots back to a chunk. 10 | 11 | Once a chunk is COMPLETELY empty, it is returned to the superheap. 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | template 18 | class LazySlotHeap : public Super { 19 | public: 20 | 21 | LazySlotHeap (void) 22 | : myChunk (new (Super::malloc (sz)) Chunk()) 23 | {} 24 | 25 | ~LazySlotHeap (void) 26 | { 27 | // Give up our chunk. 28 | Super::free (myChunk); 29 | } 30 | 31 | inline void * malloc (size_t sz) { 32 | assert (sz == chunkSize); 33 | void * ptr = myChunk->getSlot(); 34 | if (ptr == NULL) { 35 | myChunk = new (Super::malloc (sz)) Chunk(); 36 | ptr = myChunk->getSlot(); 37 | assert (ptr != NULL); 38 | } 39 | return ; 40 | } 41 | 42 | inline void free (void * ptr) { 43 | /// Return a slot to its chunk. 44 | Chunk * ch = Chunk::getChunk (ptr); 45 | ch->putSlot (ptr); 46 | // Once the chunk is completely empty, free it. 47 | if (ch->getNumSlotsAvailable() == ch->getNumSlots()) { 48 | if (ch == myChunk) { 49 | // If this was 'our' chunk, get another one. 50 | myChunk = new (Super::malloc (sz)) Chunk(); 51 | } 52 | Super::free (ch); 53 | } 54 | } 55 | 56 | private: 57 | 58 | Chunk * myChunk; 59 | 60 | }; 61 | 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/cartesianheap.h: -------------------------------------------------------------------------------- 1 | #ifndef _CARTESIANHEAP_H_ 2 | #define _CARTESIANHEAP_H_ 3 | 4 | //#include "heaplayers.h" 5 | //#include "treap.h" 6 | 7 | // NB: All objects are rounded up to at least the size of a treap node 8 | // (around 24 bytes on a 32-bit architecture). 9 | 10 | template 11 | class CartesianHeap : public SuperHeap { 12 | 13 | // Provide a freelist wrapper for treap nodes. 14 | class MyTreap : public Treap { 15 | public: 16 | // class Node : public PerClassHeap::Node, FreelistHeap > {}; 17 | }; 18 | 19 | public: 20 | 21 | ~CartesianHeap (void) { 22 | // FIX ME 23 | // free everything from the treap. 24 | } 25 | 26 | void * malloc (size_t sz) { 27 | // Round sz up. 28 | sz = (sz < sizeof(MyTreap::Node)) ? sizeof(MyTreap::Node) : sz; 29 | MyTreap::Node * n = (MyTreap::Node *) treap.lookupGreater (sz); 30 | if (n != NULL) { 31 | assert (n->getValue() == (void *) n); 32 | void * ptr = n->getValue(); 33 | treap.remove (n); 34 | // delete n; // onto a freelist 35 | return ptr; 36 | } else { 37 | return SuperHeap::malloc (sz); 38 | } 39 | } 40 | 41 | void free (void * ptr) { 42 | // MyTreap::Node * n = new MyTreap::Node; // from a freelist 43 | // cout << "n = " << (void *) n << endl; 44 | MyTreap::Node * n = (MyTreap::Node *) ptr; 45 | treap.insert (n, getSize(ptr), ptr, (unsigned int) ptr); 46 | } 47 | 48 | // Removes a pointer from the treap. 49 | void remove (void * ptr) { 50 | treap.remove ((MyTreap::Node *) ptr); 51 | } 52 | 53 | private: 54 | 55 | MyTreap treap; 56 | 57 | }; 58 | 59 | #endif // _CARTESIANHEAP_H_ 60 | -------------------------------------------------------------------------------- /runtime/heaplayers/leamallocheap.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2003 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | #ifndef _LEAMALLOCHEAP_H_ 28 | #define _LEAMALLOCHEAP_H_ 29 | 30 | #include 31 | 32 | /** 33 | * @class LeaMallocHeap 34 | * @brief A "source heap" that uses the Lea allocator. 35 | */ 36 | 37 | extern "C" void * dlmalloc (size_t); 38 | extern "C" void dlfree (void *); 39 | extern "C" size_t dlmalloc_usable_size (void *); 40 | 41 | namespace HL { 42 | 43 | class LeaMallocHeap { 44 | public: 45 | inline void * malloc (size_t sz) { 46 | void * ptr = dlmalloc (sz); 47 | return ptr; 48 | } 49 | 50 | inline void free (void * p) { 51 | dlfree (p); 52 | } 53 | 54 | inline size_t getSize (const void * p) { 55 | return dlmalloc_usable_size ((void *) p); 56 | } 57 | }; 58 | 59 | }; 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /paper/PPoPP-2014/abstract.tex: -------------------------------------------------------------------------------- 1 | False sharing is a notorious problem for multithreaded applications 2 | that can drastically degrade both performance and 3 | scalability. Existing approaches can precisely identify 4 | the sources of false sharing, but only report false 5 | sharing actually observed during execution; they do not generalize 6 | across executions. Because false sharing is extremely sensitive to 7 | object layout, these detectors can easily miss false sharing problems 8 | that can arise due to slight differences in memory allocation order or 9 | object placement decisions by the compiler. In addition, they cannot 10 | predict the impact of false sharing on hardware with different cache 11 | line sizes. 12 | 13 | This paper presents \Predator{}, a predictive software-based false 14 | sharing detector. \Predator{} generalizes from a single execution to 15 | precisely predict false sharing that is latent in the current 16 | execution. \predator{} tracks accesses within a range that could lead 17 | to false sharing given different object placement. It also tracks 18 | accesses within 19 | \emph{virtual cache lines}, contiguous memory ranges that span actual 20 | hardware cache lines, to predict sharing on hardware platforms with 21 | larger cache line sizes. For each, it reports the exact program 22 | location of predicted false sharing problems, ranked by their 23 | projected impact on performance. We evaluate \Predator{} across a 24 | range of benchmarks and actual applications. \Predator{} identifies 25 | problems undetectable with previous tools, including two 26 | previously-unknown false sharing problems, with no false 27 | positives. \Predator{} is able to immediately locate false sharing problems in MySQL and the 28 | Boost library that had eluded detection for years. 29 | -------------------------------------------------------------------------------- /runtime/heaplayers/util/winlock.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _WINLOCK_H_ 4 | #define _WINLOCK_H_ 5 | 6 | #if defined(_WIN32) 7 | 8 | #include 9 | 10 | /** 11 | * @class WinLockType 12 | * @brief Locking using Win32 mutexes. 13 | * 14 | * Note that this lock type detects whether we are running on a 15 | * multiprocessor. If not, then we do not use atomic operations. 16 | */ 17 | 18 | #if 1 19 | 20 | namespace HL { 21 | 22 | class WinLockType { 23 | public: 24 | 25 | WinLockType (void) 26 | : mutex (0) 27 | {} 28 | 29 | ~WinLockType (void) 30 | { 31 | mutex = 0; 32 | } 33 | 34 | inline void lock (void) { 35 | #if 1 36 | // We're on a multiprocessor - use atomic operations. 37 | while (InterlockedExchange ((long *) &mutex, 1) != 0) 38 | Sleep (0); 39 | #endif 40 | } 41 | 42 | inline void unlock (void) { 43 | mutex = 0; 44 | // InterlockedExchange (&mutex, 0); 45 | } 46 | 47 | private: 48 | unsigned int mutex; 49 | bool onMultiprocessor (void) { 50 | SYSTEM_INFO infoReturn[1]; 51 | GetSystemInfo (infoReturn); 52 | if (infoReturn->dwNumberOfProcessors == 1) { 53 | return FALSE; 54 | } else { 55 | return TRUE; 56 | } 57 | } 58 | }; 59 | 60 | }; 61 | 62 | #else 63 | 64 | #include 65 | 66 | class WinLockType { 67 | public: 68 | 69 | WinLockType (void) 70 | { 71 | InitializeCriticalSection(&mutex); 72 | } 73 | 74 | ~WinLockType (void) 75 | { 76 | DeleteCriticalSection(&mutex); 77 | } 78 | 79 | inline void lock (void) { 80 | EnterCriticalSection(&mutex); 81 | } 82 | 83 | inline void unlock (void) { 84 | LeaveCriticalSection(&mutex); 85 | } 86 | 87 | private: 88 | CRITICAL_SECTION mutex; 89 | }; 90 | 91 | #endif 92 | 93 | #endif 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /runtime/heaplayers/exceptionheap.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2003 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | #ifndef _EXCEPTION_HEAP 28 | #define _EXCEPTION_HEAP 29 | 30 | #include 31 | #include 32 | 33 | class std::bad_alloc; 34 | 35 | namespace HL { 36 | 37 | template 38 | class ExceptionHeap : public Super { 39 | public: 40 | inline void * malloc (size_t sz) throw (std::bad_alloc) { 41 | void * ptr = Super::malloc (sz); 42 | if (ptr == NULL) { 43 | throw new std::bad_alloc; 44 | } 45 | return ptr; 46 | } 47 | }; 48 | 49 | 50 | template 51 | class CatchExceptionHeap : public Super { 52 | public: 53 | inline void * malloc (size_t sz) { 54 | void * ptr; 55 | try { 56 | ptr = Super::malloc (sz); 57 | } catch (std::bad_alloc) { 58 | ptr = NULL; 59 | } 60 | return ptr; 61 | } 62 | }; 63 | 64 | }; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /runtime/heaplayers/util/fred.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | #ifndef _FRED_H_ 4 | #define _FRED_H_ 5 | 6 | /// A thread-wrapper of childlike simplicity :). 7 | 8 | #if defined(_WIN32) 9 | 10 | #include 11 | #include 12 | 13 | #elif defined(__SVR4) 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #else 20 | 21 | #include 22 | #include 23 | 24 | #endif 25 | 26 | namespace HL { 27 | 28 | extern "C" typedef void * (*ThreadFunctionType) (void *); 29 | 30 | class Fred { 31 | public: 32 | 33 | Fred (void) { 34 | #if !defined(_WIN32) 35 | pthread_attr_init (&attr); 36 | #endif 37 | } 38 | 39 | ~Fred (void) { 40 | #if !defined(_WIN32) 41 | pthread_attr_destroy (&attr); 42 | #endif 43 | } 44 | 45 | void create (ThreadFunctionType function, void * arg) { 46 | #if defined(_WIN32) 47 | t = CreateThread (0, 0, (LPTHREAD_START_ROUTINE) *function, (LPVOID) arg, 0, 0); 48 | #else 49 | pthread_create (&t, &attr, function, arg); 50 | #endif 51 | } 52 | 53 | void join (void) { 54 | #if defined(_WIN32) 55 | WaitForSingleObject (t, INFINITE); 56 | #else 57 | pthread_join (t, NULL); 58 | #endif 59 | } 60 | 61 | static void yield (void) { 62 | #if defined(_WIN32) 63 | Sleep (0); 64 | #elif defined(__SVR4) 65 | thr_yield(); 66 | #else 67 | sched_yield(); 68 | #endif 69 | } 70 | 71 | 72 | static void setConcurrency (int n) { 73 | #if defined(_WIN32) 74 | #elif defined(__SVR4) 75 | thr_setconcurrency (n); 76 | #else 77 | pthread_setconcurrency (n); 78 | #endif 79 | } 80 | 81 | 82 | private: 83 | #if defined(_WIN32) 84 | typedef HANDLE FredType; 85 | #else 86 | typedef pthread_t FredType; 87 | pthread_attr_t attr; 88 | #endif 89 | 90 | FredType t; 91 | }; 92 | 93 | } 94 | 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/combineheap.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2003 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | #ifndef _COMBINEHEAP_H_ 28 | #define _COMBINEHEAP_H_ 29 | 30 | 31 | /** 32 | * @class CombineHeap 33 | * @brief Combines MallocHeap and FreeHeap: MallocHeap for malloc, FreeHeap for the rest 34 | */ 35 | 36 | namespace HL { 37 | 38 | template 39 | class CombineHeap : public FreeHeap { 40 | 41 | public: 42 | 43 | inline void * malloc (size_t sz) { 44 | return mallocheap.malloc (sz); 45 | } 46 | 47 | MallocHeap& getMallocHeap (void) { 48 | return mallocheap; 49 | } 50 | 51 | inline void clear (void) { 52 | mallocheap.clear(); 53 | FreeHeap::clear(); 54 | } 55 | 56 | inline void free (void * ptr) { 57 | printf ("combineheap: free %x, sz = %d!\n", ptr, getSize(ptr)); 58 | FreeHeap::free (ptr); 59 | } 60 | 61 | private: 62 | MallocHeap mallocheap; 63 | 64 | }; 65 | 66 | }; 67 | 68 | #endif 69 | 70 | -------------------------------------------------------------------------------- /runtime/heaplayers/util/posixlock.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2003 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | #ifndef _POSIXLOCK_H_ 28 | #define _POSIXLOCK_H_ 29 | 30 | #if !defined(_WIN32) 31 | 32 | #include 33 | 34 | /** 35 | * @class PosixLockType 36 | * @brief Locking using POSIX mutex objects. 37 | */ 38 | 39 | namespace HL { 40 | 41 | class PosixLockType { 42 | public: 43 | 44 | PosixLockType (void) 45 | { 46 | int r = pthread_mutex_init (&mutex, NULL); 47 | if (r) { 48 | throw 0; 49 | } 50 | } 51 | 52 | ~PosixLockType (void) 53 | { 54 | pthread_mutex_destroy (&mutex); 55 | } 56 | 57 | void lock (void) { 58 | pthread_mutex_lock (&mutex); 59 | } 60 | 61 | void unlock (void) { 62 | pthread_mutex_unlock (&mutex); 63 | } 64 | 65 | private: 66 | union { 67 | pthread_mutex_t mutex; 68 | double _dummy[sizeof(pthread_mutex_t)/sizeof(double) + 1]; 69 | }; 70 | }; 71 | 72 | } 73 | 74 | #endif 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /runtime/privateheap.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | Copyright (c) 2011, University of Massachusetts Amherst. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | */ 21 | 22 | #ifndef _PRIVATEHEAP_H_ 23 | #define _PRIVATEHEAP_H_ 24 | #include "stdio.h" 25 | #include "string.h" 26 | /** 27 | * @file privateheap.h 28 | * @brief A private heap for internal allocation needs. Basically, those memory won't be seen by others. 29 | * @author Emery Berger 30 | * @author Tongping Liu 31 | * 32 | */ 33 | 34 | extern "C" { 35 | void * dlmalloc (size_t sz); 36 | void dlfree (void *); 37 | size_t dlmalloc_usable_size (void *); 38 | void * dlrealloc(void * ptr, size_t sz); 39 | } 40 | 41 | class privateheap { 42 | public: 43 | 44 | virtual ~privateheap (void) {} 45 | 46 | static void * malloc (size_t sz) { 47 | return dlmalloc (sz); 48 | } 49 | 50 | static void free (void * ptr) { 51 | dlfree (ptr); 52 | } 53 | 54 | static size_t getSize (void * ptr) { 55 | return dlmalloc_usable_size (ptr); 56 | } 57 | 58 | static void * realloc(void * ptr, size_t sz) { 59 | return dlrealloc(ptr, sz); 60 | } 61 | }; 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/topslotheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _TOPSLOTHEAP_H_ 4 | #define _TOPSLOTHEAP_H_ 5 | 6 | #include 7 | 8 | #include "bigchunk.h" 9 | 10 | /* 11 | TopSlotHeap. 12 | 13 | malloc returns objects of size chunkSize. 14 | 15 | free returns objects of size chunkSize. 16 | 17 | */ 18 | 19 | template 20 | class TopSlotHeap : public Super { 21 | public: 22 | 23 | TopSlotHeap (void) 24 | : myChunks (NULL) 25 | {} 26 | 27 | // Get a chunkSize object. 28 | inline void * malloc (size_t sz); 29 | 30 | // Free a chunkSize object. 31 | inline void free (void * ptr); 32 | 33 | protected: 34 | 35 | virtual inline void localFree (void * ptr); 36 | 37 | 38 | private: 39 | 40 | BigChunk * myChunks; 41 | 42 | }; 43 | 44 | 45 | template 46 | void * TopSlotHeap::malloc (size_t sz) 47 | { 48 | assert (sz <= chunkSize); 49 | if (myChunks == NULL) { 50 | return new (Super::malloc (chunkSize)) BigChunk; 51 | } else { 52 | printf ("Recycled a chunk.\n"); 53 | BigChunk * ch = myChunks; 54 | myChunks = myChunks->getNext(); 55 | ch->setNext (NULL); 56 | ch->setHeap (NULL); 57 | return ch; 58 | } 59 | } 60 | 61 | 62 | template 63 | void TopSlotHeap::free (void * ptr) { 64 | printf ("Freed a chunk.\n"); 65 | BigChunk * ch = (BigChunk *) ptr; 66 | ch->setNext (myChunks); 67 | ch->setHeap (this); 68 | myChunks = ch; 69 | } 70 | 71 | 72 | template 73 | void TopSlotHeap::localFree (void * ptr) { 74 | free (ptr); 75 | } 76 | 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /runtime/xglobals.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | Copyright (c) 2008-12, University of Massachusetts Amherst. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | */ 21 | 22 | /* 23 | * @file xglobals.h 24 | * @brief Management the globals of applications, here we donot care about those globals of libc.so and libpthread.so. 25 | * @author Tongping Liu 26 | */ 27 | 28 | #ifndef _XGLOBALS_H_ 29 | #define _XGLOBALS_H_ 30 | 31 | #include "xdefines.h" 32 | #include "selfmap.h" 33 | 34 | /// @class xglobals 35 | /// @brief Maps the globals region onto a persistent store. 36 | class xglobals { 37 | public: 38 | 39 | 40 | xglobals () 41 | { 42 | // fprintf(stderr, "GLOBALS_START is %x\n", GLOBALS_START); 43 | } 44 | 45 | void initialize(void) { 46 | // We check those mappings to find out existing globals. 47 | int numb; 48 | int i; 49 | 50 | // Trying to get information about different text segmensts. 51 | selfmap::getInstance().getTextRegions(); 52 | 53 | // Trying to get the information of global regions 54 | selfmap::getInstance().getGlobalRegion((void **)&globalStart, (void **)&globalEnd); 55 | } 56 | 57 | private: 58 | }; 59 | 60 | #endif 61 | 62 | -------------------------------------------------------------------------------- /runtime/heaplayers/addheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _ADDHEAP_H_ 4 | #define _ADDHEAP_H_ 5 | 6 | /* 7 | 8 | Heap Layers: An Extensible Memory Allocation Infrastructure 9 | 10 | Copyright (C) 2000-2003 by Emery Berger 11 | http://www.cs.umass.edu/~emery 12 | emery@cs.umass.edu 13 | 14 | This program is free software; you can redistribute it and/or modify 15 | it under the terms of the GNU General Public License as published by 16 | the Free Software Foundation; either version 2 of the License, or 17 | (at your option) any later version. 18 | 19 | This program is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License 25 | along with this program; if not, write to the Free Software 26 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | 28 | */ 29 | 30 | // Reserve space for a class in the head of every allocated object. 31 | 32 | #include 33 | 34 | namespace HL { 35 | 36 | template 37 | class AddHeap : public Super { 38 | public: 39 | 40 | inline void * malloc (size_t sz) { 41 | void * ptr = Super::malloc (sz + align(sizeof(Add))); 42 | void * newPtr = (void *) align ((size_t) ((Add *) ptr + 1)); 43 | return ptr; 44 | } 45 | 46 | inline void free (void * ptr) { 47 | void * origPtr = (void *) ((Add *) ptr - 1); 48 | Super::free (origPtr); 49 | } 50 | 51 | inline size_t getSize (void * ptr) { 52 | void * origPtr = (void *) ((Add *) ptr - 1); 53 | return Super::getSize (origPtr); 54 | } 55 | 56 | private: 57 | static inline size_t align (size_t sz) { 58 | return (sz + (sizeof(double) - 1)) & ~(sizeof(double) - 1); 59 | } 60 | 61 | }; 62 | 63 | }; 64 | #endif 65 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/strictslotheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _LAZYSLOTHEAP_H_ 4 | #define _LAZYSLOTHEAP_H_ 5 | 6 | /* 7 | This heap manages memory in units of Chunks. 8 | malloc returns a slot within a chunk, 9 | while free returns slots back to a chunk. 10 | 11 | We completely exhaust the first chunk before we ever get another one. 12 | Once a chunk is COMPLETELY empty, it is returned to the superheap. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | #include "chunk.h" 19 | 20 | template 21 | class LazySlotHeap : public Super { 22 | public: 23 | 24 | LazySlotHeap (void) 25 | : myChunk (new (Super::malloc (chunkSize)) Chunk()) 26 | {} 27 | 28 | virtual ~LazySlotHeap (void) 29 | { 30 | // Give up our chunk. 31 | Super::free (myChunk); 32 | } 33 | 34 | inline void * malloc (size_t sz) { 35 | assert (sz <= chunkSize); 36 | void * ptr = myChunk->getSlot(); 37 | if (ptr == NULL) { 38 | myChunk = new (Super::malloc (chunkSize)) Chunk(); 39 | ptr = myChunk->getSlot(); 40 | assert (ptr != NULL); 41 | } 42 | return ptr; 43 | } 44 | 45 | inline void free (void * ptr) { 46 | /// Return a slot to its chunk. 47 | Chunk * ch = Chunk::getChunk (ptr); 48 | ch->putSlot (ptr); 49 | // Once the chunk is completely empty, free it. 50 | if (ch->getNumSlotsAvailable() == ch->getNumSlots()) { 51 | if (ch == myChunk) { 52 | // If this was 'our' chunk, get another one. 53 | myChunk = new (Super::malloc (chunkSize)) Chunk(); 54 | } 55 | Super::free (ch); 56 | } 57 | } 58 | 59 | protected: 60 | 61 | inline static size_t size (void * ptr) 62 | { 63 | return slotSize; 64 | } 65 | 66 | 67 | private: 68 | 69 | Chunk * myChunk; 70 | 71 | }; 72 | 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /runtime/heaplayers/oneheap.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2003 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | #ifndef _ONEHEAP_H_ 28 | #define _ONEHEAP_H_ 29 | 30 | // 31 | // Wrap a single instance of a heap. 32 | // 33 | 34 | namespace HL { 35 | 36 | template 37 | class OneHeap { 38 | public: 39 | OneHeap (void) 40 | : theHeap (getHeap()) 41 | {} 42 | 43 | inline void * malloc (const size_t sz) { 44 | return theHeap->malloc (sz); 45 | } 46 | inline void free (void * ptr) { 47 | theHeap->free (ptr); 48 | } 49 | inline int remove (void * ptr) { 50 | return theHeap->remove (ptr); 51 | } 52 | inline void clear (void) { 53 | theHeap->clear(); 54 | } 55 | inline size_t getSize (void * ptr) { 56 | return theHeap->getSize (ptr); 57 | } 58 | 59 | enum { Alignment = SuperHeap::Alignment }; 60 | 61 | private: 62 | 63 | SuperHeap * theHeap; 64 | 65 | inline static SuperHeap * getHeap (void) { 66 | static SuperHeap theHeap; 67 | return &theHeap; 68 | } 69 | // SuperHeap theHeap; 70 | }; 71 | 72 | } 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /runtime/heaplayers/staticheap.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2003 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | /* 28 | 29 | StaticHeap: manage a fixed range of memory. 30 | 31 | */ 32 | 33 | #ifndef _STATICHEAP_H_ 34 | #define _STATICHEAP_H_ 35 | 36 | namespace HL { 37 | 38 | template 39 | class StaticHeap { 40 | public: 41 | 42 | StaticHeap (void) 43 | : ptr (&buf[0]), 44 | remaining (MemorySize) 45 | {} 46 | 47 | enum { Alignment = 1 }; 48 | 49 | inline void * malloc (size_t sz) { 50 | if (remaining < sz) { 51 | return NULL; 52 | } 53 | void * p = ptr; 54 | ptr += sz; 55 | remaining -= sz; 56 | return p; 57 | } 58 | 59 | void free (void *) {} 60 | int remove (void *) { return 0; } 61 | 62 | int isValid (void * ptr) { 63 | return (((size_t) ptr >= (size_t) buf) && 64 | ((size_t) ptr < (size_t) buf)); 65 | } 66 | 67 | private: 68 | 69 | #if 1 70 | // Disable copying and assignment. 71 | StaticHeap (const StaticHeap&); 72 | StaticHeap& operator= (const StaticHeap&); 73 | #endif 74 | 75 | char buf[MemorySize]; 76 | char * ptr; 77 | size_t remaining; 78 | }; 79 | 80 | }; 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /runtime/cachepredict.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | /* 21 | * @file Cachepredict.h 22 | * @brief The information about cache prediction. 23 | * @author Tongping Liu 24 | */ 25 | 26 | 27 | #ifndef _CACHEPREDICT_H_ 28 | #define _CACHEPREDICT_H_ 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #if !defined(_WIN32) 35 | #include 36 | #include 37 | #include 38 | #endif 39 | 40 | #include //sort 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include "xdefines.h" 47 | #include "list.h" 48 | 49 | class cachepredict { 50 | public: 51 | cachepredict() 52 | { 53 | } 54 | 55 | ~cachepredict (void) { 56 | } 57 | 58 | void init(void) { 59 | _predictions = 0; 60 | } 61 | 62 | // Check whether we need prediction 63 | inline bool hasPrediction(void) { 64 | return (_predictions > 0 ? true : false); 65 | } 66 | 67 | void handleAccess(int tindex, void * addr, eAccessType type) { 68 | if(_predictions == 0) { 69 | return; 70 | } 71 | 72 | 73 | 74 | } 75 | 76 | private: 77 | // how much predictions 78 | int _predictions; 79 | 80 | // All predictions are appended into this list. 81 | list_t _predictList; 82 | }; 83 | 84 | #endif 85 | 86 | -------------------------------------------------------------------------------- /runtime/libfuncs.h: -------------------------------------------------------------------------------- 1 | #ifndef _REAL_H_ 2 | #define _REAL_H_ 3 | 4 | #include 5 | 6 | #define WRAP(x) _real_##x 7 | 8 | // libc functions 9 | extern void* (*WRAP(mmap))(void*, size_t, int, int, int, off_t); 10 | extern void* (*WRAP(malloc))(size_t); 11 | extern void (*WRAP(free))(void *); 12 | extern void* (*WRAP(realloc))(void *, size_t); 13 | extern void* (*WRAP(memalign))(size_t, size_t); 14 | extern size_t (*WRAP(malloc_usable_size))(void *); 15 | extern ssize_t (*WRAP(read))(int, void*, size_t); 16 | extern ssize_t (*WRAP(write))(int, const void*, size_t); 17 | extern int (*WRAP(sigwait))(const sigset_t*, int*); 18 | 19 | // pthread basics 20 | extern int (*WRAP(pthread_create))(pthread_t*, const pthread_attr_t*, void *(*)(void*), void*); 21 | extern int (*WRAP(pthread_cancel))(pthread_t); 22 | extern int (*WRAP(pthread_join))(pthread_t, void**); 23 | extern int (*WRAP(pthread_exit))(void*); 24 | 25 | // pthread mutexes 26 | extern int (*WRAP(pthread_mutexattr_init))(pthread_mutexattr_t*); 27 | extern int (*WRAP(pthread_mutex_init))(pthread_mutex_t*, const pthread_mutexattr_t*); 28 | extern int (*WRAP(pthread_mutex_lock))(pthread_mutex_t*); 29 | extern int (*WRAP(pthread_mutex_unlock))(pthread_mutex_t*); 30 | extern int (*WRAP(pthread_mutex_trylock))(pthread_mutex_t*); 31 | extern int (*WRAP(pthread_mutex_destroy))(pthread_mutex_t*); 32 | 33 | // pthread condition variables 34 | extern int (*WRAP(pthread_condattr_init))(pthread_condattr_t*); 35 | extern int (*WRAP(pthread_cond_init))(pthread_cond_t*, pthread_condattr_t*); 36 | extern int (*WRAP(pthread_cond_wait))(pthread_cond_t*, pthread_mutex_t*); 37 | extern int (*WRAP(pthread_cond_signal))(pthread_cond_t*); 38 | extern int (*WRAP(pthread_cond_broadcast))(pthread_cond_t*); 39 | extern int (*WRAP(pthread_cond_destroy))(pthread_cond_t*); 40 | 41 | // pthread barriers 42 | extern int (*WRAP(pthread_barrier_init))(pthread_barrier_t*, pthread_barrierattr_t*, unsigned int); 43 | extern int (*WRAP(pthread_barrier_wait))(pthread_barrier_t*); 44 | extern int (*WRAP(pthread_barrier_destroy))(pthread_barrier_t*); 45 | 46 | void init_real_functions(); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/slotheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _SLOTHEAP_H_ 4 | #define _SLOTHEAP_H_ 5 | 6 | // NOTE: All size requests to malloc must be identical! 7 | 8 | /* 9 | 10 | A "slot" allocator. 11 | 12 | All allocations come from a fixed-size chunk of memory 13 | that is carved into a number of pieces. 14 | 15 | The "chunk" class must support the following methods: 16 | 17 | void * getSlot (void); // Returns NULL if there is no slot left. 18 | void putSlot (void *); // Puts a slot back into its chunk. 19 | 20 | */ 21 | 22 | #include 23 | 24 | #include "chunkheap.h" 25 | 26 | /* A "slot" heap. 27 | 28 | This heap reserves exactly one "chunk" that is divided into 29 | a number of fixed-size slots. When the chunk is used up, 30 | the heap requests another one. */ 31 | 32 | template 33 | class SlotInterface; 34 | 35 | template 36 | class SlotHeap : public SlotInterface >{}; 37 | 38 | template 39 | class SlotInterface : public Super { 40 | public: 41 | 42 | SlotInterface (void) 43 | : currentChunk (new (Super::malloc(chunkSize)) Chunk) 44 | {} 45 | 46 | inline void * malloc (size_t sz) { 47 | assert (sz == slotSize); 48 | // Use up all of the slots in one chunk, 49 | // and get another chunk if we need one. 50 | void * ptr = currentChunk->getSlot(); 51 | if (ptr == NULL) { 52 | // This chunk is empty -- get another one. 53 | currentChunk = new (Super::malloc(chunkSize)) Chunk; 54 | ptr = currentChunk->getSlot(); 55 | } 56 | assert (ptr != NULL); 57 | return ptr; 58 | } 59 | 60 | inline void free (void * ptr) { 61 | // If this object belongs to "our" chunk, 62 | // free it directly; otherwise, pass it up. 63 | if (getChunk(ptr) == currentChunk) { 64 | currentChunk->putSlot (ptr); 65 | } else { 66 | Super::free (ptr); 67 | } 68 | } 69 | 70 | private: 71 | 72 | Chunk * currentChunk; 73 | 74 | }; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /runtime/heaplayers/mallocheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2005 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | #ifndef _MALLOCHEAP_H_ 28 | #define _MALLOCHEAP_H_ 29 | 30 | #include 31 | 32 | #if defined(__SVR4) 33 | extern "C" size_t malloc_usable_size (void *); 34 | #else 35 | extern "C" size_t malloc_usable_size (void *) throw (); 36 | #endif 37 | 38 | #if defined(_WIN32) || defined(linux) 39 | #include 40 | #elif defined(__APPLE__) 41 | #include 42 | #endif 43 | 44 | /** 45 | * @class mallocHeap 46 | * @brief A "source heap" that uses malloc and free. 47 | */ 48 | 49 | namespace HL { 50 | 51 | class mallocHeap { 52 | public: 53 | 54 | ~mallocHeap (void) {} 55 | 56 | inline void * malloc (size_t sz) { 57 | return ::malloc (sz); 58 | } 59 | 60 | 61 | inline void free (void * ptr) { 62 | ::free (ptr); 63 | } 64 | 65 | #if defined(_MSC_VER) 66 | inline size_t getSize (void * ptr) { 67 | return ::_msize (ptr); 68 | } 69 | #elif defined(__GNUC__) && !defined(__SVR4) 70 | inline size_t getSize (void * ptr) { 71 | return ::malloc_usable_size (ptr); 72 | } 73 | #elif defined(__APPLE__) 74 | inline size_t getSize (void * ptr) { 75 | return ::malloc_size (ptr); 76 | } 77 | #endif 78 | 79 | }; 80 | 81 | }; 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /paper/PPoPP-2014/issues.tex: -------------------------------------------------------------------------------- 1 | (1) Maybe user should have a option to check those false sharing inside stack variables. 2 | (2) Should we use a thread index instead to save some spaces? Also, maybe it is better for the performance. 3 | Generally, we will not have two threads that are accessing the same subheap. However, we may have to use 4 | the pthread\_t for comparison since it is unique? but actually it is not. 5 | We should use the unique heap in order to avoid the lock usage and overlapping (Diehard problem). In Diehard, 6 | two threads can use the same heap every time. 7 | Also, we may introduce the current pointer in the thread library so that we can know corresponding information quickly. 8 | whenever all children threads has been exited, then we should possibly update the 9 | So we should use a 10 | 11 | (3) Should we have an internal heap which also use tid to index their subheap. 12 | (4) When there are multiple files there, how we can instrument every file one by one? Design a makefile to do this automatically. 13 | 14 | (a) Inserting the into clang so that we do not need to change the make file for each files. 15 | (b) We will keep track of each read/write accesses instead of only checking once for each basic block. 16 | 17 | 18 | Improving the performance step by step 19 | (1) Avoiding using the singleton if we can use the simple variable. 20 | (2) Trying to use the sampling (100 instructions we only sample one). 21 | 22 | (4) How to sample those accesses. We donot want to loose those cache invalidations. 23 | So for each cache line, we are using the cache line based sampling mechanism. 24 | In the non-sampling phase, we will not update everything. 25 | 26 | However, there is a per-thread based sampling. For example, we only sample those accesses in the 27 | first 500 over 1000 accesses. However, we may lost a lot of interleaving accesses by doing this. 28 | 29 | If we are using the system level accessCount, for example, updating this shared accesses can cause a lot of 30 | invalidations - which cause a lot of performance problem by using the shared account. 31 | 32 | Also, we should try to implement those very basic accesses incremental in the first level instead of inside a very deep level. 33 | 34 | 35 | -------------------------------------------------------------------------------- /runtime/heaplayers/stats.h: -------------------------------------------------------------------------------- 1 | #ifndef _HLSTATS_H_ 2 | #define _HLSTATS_H_ 3 | 4 | #include 5 | 6 | template 7 | class InUseHeap : public SuperHeap { 8 | private: 9 | typedef std::map mapType; 10 | public: 11 | InUseHeap (void) 12 | : inUse (0), 13 | maxInUse (0) 14 | {} 15 | void * malloc (size_t sz) { 16 | void * ptr = SuperHeap::malloc (sz); 17 | if (ptr != NULL) { 18 | inUse += sz; 19 | if (maxInUse < inUse) { 20 | maxInUse = inUse; 21 | } 22 | allocatedObjects.insert (std::pair(ptr, sz)); 23 | } 24 | return ptr; 25 | } 26 | void free (void * ptr) { 27 | mapType::iterator i; 28 | i = allocatedObjects.find (ptr); 29 | if (i == allocatedObjects.end()) { 30 | // oops -- called free on object i didn't allocate. 31 | assert (0); 32 | } 33 | inUse -= (*i).second; 34 | allocatedObjects.erase (i); 35 | SuperHeap::free (ptr); 36 | } 37 | 38 | int getInUse (void) const { 39 | return inUse; 40 | } 41 | int getMaxInUse (void) const { 42 | return maxInUse; 43 | } 44 | private: 45 | int inUse; 46 | int maxInUse; 47 | mapType allocatedObjects; 48 | }; 49 | 50 | 51 | template 52 | class AllocatedHeap : public SuperHeap { 53 | public: 54 | AllocatedHeap (void) 55 | : allocated (0), 56 | maxAllocated (0) 57 | {} 58 | void * malloc (size_t sz) { 59 | void * ptr = SuperHeap::malloc (sz); 60 | if (ptr != NULL) { 61 | allocated += getSize(ptr); 62 | if (maxAllocated < allocated) { 63 | maxAllocated = allocated; 64 | } 65 | } 66 | return ptr; 67 | } 68 | void free (void * ptr) { 69 | allocated -= getSize(ptr); 70 | SuperHeap::free (ptr); 71 | } 72 | 73 | int getAllocated (void) const { 74 | return allocated; 75 | } 76 | int getMaxAllocated (void) const { 77 | return maxAllocated; 78 | } 79 | private: 80 | int allocated; 81 | int maxAllocated; 82 | }; 83 | 84 | 85 | template 86 | class StatsHeap : public SuperHeap { 87 | public: 88 | ~StatsHeap (void) { 89 | printf ("In use = %d, allocated = %d\n", getInUse(), getAllocated()); 90 | printf ("Max in use = %d, max allocated = %d\n", getMaxInUse(), getMaxAllocated()); 91 | } 92 | }; 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /runtime/mm.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 , University of Massachusetts Amherst. 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | #ifndef _MM_H_ 20 | #define _MM_H_ 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | class MM { 30 | public: 31 | #define ALIGN_TO_CACHELINE(size) (size%64 == 0 ? size:(size+64)/64*64) 32 | 33 | static void mmapDeallocate (void * ptr, size_t sz) { 34 | munmap(ptr, sz); 35 | } 36 | 37 | static void * mmapAllocateShared (size_t sz, 38 | void * startaddr = NULL, 39 | int fd = -1) 40 | { 41 | return allocate (true, sz, fd, startaddr); 42 | } 43 | 44 | static void * mmapAllocatePrivate (size_t sz, 45 | void * startaddr = NULL, 46 | int fd = -1) 47 | { 48 | return allocate (false, sz, fd, startaddr); 49 | } 50 | 51 | private: 52 | 53 | static void * allocate (bool isShared, 54 | size_t sz, 55 | int fd, 56 | void * startaddr) 57 | { 58 | int protInfo = PROT_READ | PROT_WRITE; 59 | int sharedInfo = isShared ? MAP_SHARED : MAP_PRIVATE; 60 | sharedInfo |= ((fd == -1) ? MAP_ANONYMOUS : 0); 61 | sharedInfo |= ((startaddr != NULL) ? MAP_FIXED : 0); 62 | 63 | void * ptr = mmap(startaddr, sz, protInfo, sharedInfo, fd, 0); 64 | if(ptr == MAP_FAILED) { 65 | fprintf(stderr, "Couldn't do mmap %s : startaddr %p, sz %lx\n", strerror(errno), startaddr, sz); 66 | abort(); 67 | } 68 | 69 | return ptr; 70 | } 71 | 72 | }; 73 | 74 | #endif /* _MM_H_ */ 75 | 76 | -------------------------------------------------------------------------------- /runtime/heaplayers/stats.cpp: -------------------------------------------------------------------------------- 1 | // Report stats. 2 | 3 | #include 4 | 5 | #include "timer.h" 6 | 7 | struct mallinfo { 8 | int arena; /* non-mmapped space allocated from system */ 9 | int ordblks; /* number of free chunks */ 10 | int smblks; /* number of fastbin blocks */ 11 | int hblks; /* number of mmapped regions */ 12 | int hblkhd; /* space in mmapped regions */ 13 | int usmblks; /* maximum total allocated space */ 14 | int fsmblks; /* space available in freed fastbin blocks */ 15 | int uordblks; /* total allocated space */ 16 | int fordblks; /* total free space */ 17 | int keepcost; /* top-most, releasable (via malloc_trim) space */ 18 | }; 19 | 20 | #if 1 21 | extern "C" struct mallinfo dlmallinfo (void); 22 | #endif 23 | extern "C" void mstats (void); // for Kingsley malloc. 24 | extern "C" void dlmalloc_stats (void); // for Doug Lea malloc. 25 | extern "C" void * sbrk (long); 26 | extern "C" void malloc_stats (void); // for Doug Lea malloc. 27 | 28 | int masMem;// FIX ME 29 | 30 | 31 | int totalAllocated; 32 | int maxAllocated; 33 | int totalRequested; 34 | int maxRequested; 35 | 36 | class TimeItAll { 37 | public: 38 | TimeItAll (void) { 39 | totalAllocated = 0; 40 | maxAllocated = 0; 41 | t.start(); 42 | // FIX ME 43 | masMem = 0; 44 | #ifdef WIN32 45 | initSpace = (long) sbrk(0); 46 | //initSpace = CommittedSpace(); 47 | #endif 48 | } 49 | 50 | ~TimeItAll (void) { 51 | t.stop(); 52 | #if 0 53 | struct mallinfo mi = dlmallinfo(); 54 | printf ("Doug Lea Memory allocated = {total} %d, {non-mmapped} %d\n", mi.usmblks, mi.arena); 55 | #endif 56 | double elapsed = (double) t; 57 | printf ("Time elapsed = %f\n", elapsed); 58 | printf ("Max allocated = %d\n", maxAllocated); 59 | printf ("Max requested = %d\n", maxRequested); 60 | printf ("Frag = %lf\n", (double) maxAllocated / (double) maxRequested); 61 | #ifdef WIN32 62 | printf ("init space = %ld\n", initSpace); 63 | printf ("Sbrk report: %ld\n", (long) sbrk(0)); 64 | #if 0 65 | size_t diff = (size_t) wsbrk(8); 66 | cout << "diff1 = " << diff << endl; 67 | diff -= initSpace - 8; 68 | cout << "diff = " << diff << endl; 69 | #endif 70 | #endif 71 | malloc_stats(); 72 | fflush (stdout); 73 | // dlmalloc_stats(); 74 | } 75 | private: 76 | Timer t; 77 | #ifdef WIN32 78 | long initSpace; 79 | #endif 80 | }; 81 | 82 | TimeItAll timer; 83 | -------------------------------------------------------------------------------- /runtime/heaplayers/adapt.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2003 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | 28 | #ifndef _ADAPT_H_ 29 | #define _ADAPT_H_ 30 | 31 | /** 32 | * @class AdaptHeap 33 | * @brief Maintains dictionary entries through freed objects. 34 | * Sample dictionaries include DLList and SLList. 35 | */ 36 | 37 | namespace HL { 38 | 39 | template 40 | class AdaptHeap : public SuperHeap { 41 | public: 42 | 43 | /// Allocate an object (remove from the dictionary). 44 | inline void * malloc (const size_t) { 45 | void * ptr = (Entry *) dict.get(); 46 | return ptr; 47 | } 48 | 49 | /// Deallocate the object (return to the dictionary). 50 | inline void free (void * ptr) { 51 | Entry * entry = (Entry *) ptr; 52 | dict.insert (entry); 53 | } 54 | 55 | /// Remove an object from the dictionary. 56 | inline int remove (void * ptr) { 57 | dict.remove ((Entry *) ptr); 58 | return 1; 59 | } 60 | 61 | /// Clear the dictionary. 62 | inline void clear (void) { 63 | Entry * ptr; 64 | while ((ptr = (Entry *) dict.get()) != NULL) { 65 | SuperHeap::free (ptr); 66 | } 67 | dict.clear(); 68 | SuperHeap::clear(); 69 | } 70 | 71 | 72 | private: 73 | 74 | /// The dictionary object. 75 | Dictionary dict; 76 | 77 | class Entry : public Dictionary::Entry {}; 78 | }; 79 | 80 | } 81 | 82 | #endif // _ADAPT_H_ 83 | -------------------------------------------------------------------------------- /runtime/heaplayers/adaptheap.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2003 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | 28 | #ifndef _ADAPT_H_ 29 | #define _ADAPT_H_ 30 | 31 | /** 32 | * @class AdaptHeap 33 | * @brief Maintains dictionary entries through freed objects. 34 | * Sample dictionaries include DLList and SLList. 35 | */ 36 | 37 | namespace HL { 38 | 39 | template 40 | class AdaptHeap : public SuperHeap { 41 | public: 42 | 43 | /// Allocate an object (remove from the dictionary). 44 | inline void * malloc (const size_t) { 45 | void * ptr = (Entry *) dict.get(); 46 | return ptr; 47 | } 48 | 49 | /// Deallocate the object (return to the dictionary). 50 | inline void free (void * ptr) { 51 | Entry * entry = (Entry *) ptr; 52 | dict.insert (entry); 53 | } 54 | 55 | /// Remove an object from the dictionary. 56 | inline int remove (void * ptr) { 57 | dict.remove ((Entry *) ptr); 58 | return 1; 59 | } 60 | 61 | /// Clear the dictionary. 62 | inline void clear (void) { 63 | Entry * ptr; 64 | while ((ptr = (Entry *) dict.get()) != NULL) { 65 | SuperHeap::free (ptr); 66 | } 67 | dict.clear(); 68 | SuperHeap::clear(); 69 | } 70 | 71 | 72 | private: 73 | 74 | /// The dictionary object. 75 | Dictionary dict; 76 | 77 | class Entry : public Dictionary::Entry {}; 78 | }; 79 | 80 | } 81 | 82 | #endif // _ADAPT_H_ 83 | -------------------------------------------------------------------------------- /runtime/heaplayers/ansiwrapper.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _ANSIWRAPPER_H_ 4 | #define _ANSIWRAPPER_H_ 5 | 6 | #include 7 | #include 8 | 9 | /* 10 | * @class ANSIWrapper 11 | * @brief Provide ANSI C behavior for malloc & free. 12 | * 13 | * Implements all prescribed ANSI behavior, including zero-sized 14 | * requests & aligned request sizes to a double word (or long word). 15 | */ 16 | 17 | namespace HL { 18 | 19 | template 20 | class ANSIWrapper : public SuperHeap { 21 | public: 22 | 23 | ANSIWrapper (void) 24 | {} 25 | 26 | inline void * malloc (size_t sz) { 27 | if (sz < 2 * sizeof(size_t)) { 28 | // Make sure it's at least big enough to hold two pointers (and 29 | // conveniently enough, that's at least the size of a double, as 30 | // required by ANSI). 31 | sz = 2 * sizeof(size_t); 32 | } 33 | sz = align(sz); 34 | void * ptr = SuperHeap::malloc (sz); 35 | return ptr; 36 | } 37 | 38 | inline void free (void * ptr) { 39 | if (ptr != 0) { 40 | SuperHeap::free (ptr); 41 | } 42 | } 43 | 44 | inline void * calloc (const size_t s1, const size_t s2) { 45 | void * ptr = malloc (s1 * s2); 46 | if (ptr) { 47 | memset (ptr, 0, s1 * s2); 48 | } 49 | return ptr; 50 | } 51 | 52 | inline void * realloc (void * ptr, const size_t sz) { 53 | if (ptr == 0) { 54 | return malloc (sz); 55 | } 56 | if (sz == 0) { 57 | free (ptr); 58 | return 0; 59 | } 60 | size_t objSize = getSize (ptr); 61 | if (objSize == sz) { 62 | return ptr; 63 | } 64 | 65 | // Allocate a new block of size sz. 66 | void * buf = malloc (sz); 67 | 68 | // Copy the contents of the original object 69 | // up to the size of the new block. 70 | 71 | size_t minSize = (objSize < sz) ? objSize : sz; 72 | if (buf) { 73 | memcpy (buf, ptr, minSize); 74 | } 75 | 76 | // Free the old block. 77 | free (ptr); 78 | return buf; 79 | } 80 | 81 | inline size_t getSize (void * ptr) { 82 | if (ptr) { 83 | return SuperHeap::getSize (ptr); 84 | } else { 85 | return 0; 86 | } 87 | } 88 | 89 | private: 90 | inline static size_t align (size_t sz) { 91 | return (sz + (sizeof(double) - 1)) & ~(sizeof(double) - 1); 92 | } 93 | 94 | }; 95 | 96 | } 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /runtime/Makefile: -------------------------------------------------------------------------------- 1 | SOURCE_DIR = . 2 | INCLUDE_DIR = . 3 | 4 | #SOURCE_DIR = source 5 | #INCLUDE_DIR = include 6 | 7 | SRCS = $(SOURCE_DIR)/libdefault.cpp \ 8 | $(SOURCE_DIR)/libfuncs.cpp \ 9 | $(SOURCE_DIR)/dlmalloc.c \ 10 | $(SOURCE_DIR)/finetime.c 11 | 12 | INCS = $(INCLUDE_DIR)/xdefines.h \ 13 | $(INCLUDE_DIR)/selfmap.h \ 14 | $(INCLUDE_DIR)/xrun.h \ 15 | $(INCLUDE_DIR)/xmemory.h \ 16 | $(INCLUDE_DIR)/xmapping.h \ 17 | $(INCLUDE_DIR)/objectheader.h \ 18 | $(INCLUDE_DIR)/xoneheap.h \ 19 | $(INCLUDE_DIR)/xpheap.h \ 20 | $(INCLUDE_DIR)/callsite.h \ 21 | $(INCLUDE_DIR)/report.h \ 22 | $(INCLUDE_DIR)/cachetrack.h \ 23 | $(INCLUDE_DIR)/privateheap.h \ 24 | $(INCLUDE_DIR)/atomic.h \ 25 | $(INCLUDE_DIR)/elfinfo.h \ 26 | $(INCLUDE_DIR)/xthread.h \ 27 | $(INCLUDE_DIR)/finetime.h \ 28 | $(INCLUDE_DIR)/mm.h 29 | 30 | DEPS = $(SRCS) $(INCS) 31 | 32 | CXX = g++ -g -O2 -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/detect -I$(INCLUDE_DIR)/heap -I$(INCLUDE_DIR)/util -I$(INCLUDE_DIR)/sync 33 | 34 | # Detection on 32bit 35 | # CXX = g++ -DSSE_SUPPORT -m32 -DX86_32BIT -O3 -fno-omit-frame-pointer -DDETECT_FALSE_SHARING 36 | # Detection on 64bit 37 | #CXX = g++ -DSSE_SUPPORT -m64 -fno-omit-frame-pointer -DDETECT_FALSE_SHARING 38 | 39 | 40 | # -march=core2 -msse3 -DSSE_SUPPORT 41 | #CFLAGS = -Wall -msse3 -DSSE_SUPPORT -fno-omit-frame-pointer 42 | #CFLAGS = -fno-omit-frame-pointer -DPREDICTION 43 | CFLAGS = -fno-omit-frame-pointer -DPREDICTION -DCENTRALIZED_BIG_HEAP -DUSING_SIGUSR2 44 | #-DOUTPUT_WORD_ACCESSES 45 | #CFLAGS = -fno-omit-frame-pointer -DPREDICTION -DOUTPUT_WORD_ACCESSES 46 | #-DIMPROVE_PERF 47 | #-DOUTPUT_WORD_ACCESSES 48 | #CFLAGS = -fno-omit-frame-pointer 49 | CFLAGS32 = $(CFLAGS) -m32 -DX86_32BIT # -O3 50 | CFLAGS64 = $(CFLAGS) #-m64 # -O3 51 | #CFLAGS64 = $(CFLAGS) -m64 # -O3 52 | 53 | INCLUDE_DIRS = -I. -I./heaplayers -I./heaplayers/util 54 | 55 | #GET_CHARACTERISTICS 56 | 57 | TARGETS = libdefault64.so 58 | #TARGETS = libdefault32.so libdefault64.so 59 | 60 | all: $(TARGETS) 61 | 62 | libdefault32.so: $(DEPS) 63 | $(CXX) $(CFLAGS32) $(INCLUDE_DIRS) -shared -fPIC -D'CUSTOM_PREFIX(x)=default_##x' $(SRCS) -o libdefault32.so -ldl -lpthread 64 | 65 | libdefault64.so: $(DEPS) 66 | $(CXX) $(CFLAGS64) $(INCLUDE_DIRS) -shared -fPIC -D'CUSTOM_PREFIX(x)=default_##x' $(SRCS) -o libdefault64.so -ldl -lpthread 67 | 68 | clean: 69 | rm -f $(TARGETS) 70 | 71 | -------------------------------------------------------------------------------- /runtime/heaplayers/sizethreadheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _SIZETHREADHEAP_H_ 4 | #define _SIZETHREADHEAP_H_ 5 | 6 | #include 7 | 8 | template 9 | class SizeThreadHeap : public Super { 10 | public: 11 | 12 | inline void * malloc (size_t sz) { 13 | // Add room for a size field & a thread field. 14 | // Both of these must fit in a double. 15 | assert (sizeof(st) <= sizeof(double)); 16 | st * ptr = (st *) Super::malloc (sz + sizeof(double)); 17 | // Store the requested size. 18 | ptr->size = sz; 19 | assert (getOrigPtr(ptr + 1) == ptr); 20 | return (void *) (ptr + 1); 21 | } 22 | 23 | inline void free (void * ptr) { 24 | void * origPtr = (void *) getOrigPtr(ptr); 25 | Super::free (origPtr); 26 | } 27 | 28 | static inline volatile int getThreadId (void); 29 | 30 | static inline size_t& size (void * ptr) { 31 | return getOrigPtr(ptr)->size; 32 | } 33 | 34 | static inline int& thread (void * ptr) { 35 | return getOrigPtr(ptr)->tid; 36 | } 37 | 38 | private: 39 | 40 | typedef struct _st { 41 | size_t size; 42 | int tid; 43 | } st; 44 | 45 | static inline st * getOrigPtr (void * ptr) { 46 | return (st *) ((double *) ptr - 1); 47 | } 48 | 49 | }; 50 | 51 | 52 | 53 | // A platform-dependent way to get a thread id. 54 | 55 | // Include the necessary platform-dependent crud. 56 | #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) 57 | #ifndef WIN32 58 | #define WIN32 1 59 | #endif 60 | #include 61 | #include 62 | #endif 63 | 64 | template 65 | inline volatile int 66 | SizeThreadHeap::getThreadId (void) { 67 | #if defined(WIN32) 68 | return GetCurrentThreadId(); 69 | #endif 70 | #if defined(__BEOS__) 71 | return find_thread(0); 72 | #endif 73 | #if defined(__linux) 74 | // Consecutive thread id's in Linux are 1024 apart; 75 | // dividing off the 1024 gives us an appropriate thread id. 76 | return (int) pthread_self() >> 10; // (>> 10 = / 1024) 77 | #endif 78 | #if defined(__SVR4) 79 | return (int) lwp_self(); 80 | #endif 81 | #if defined(POSIX) 82 | return (int) pthread_self(); 83 | #endif 84 | #if USE_SPROC 85 | // This hairiness has the same effect as calling getpid(), 86 | // but it's MUCH faster since it avoids making a system call 87 | // and just accesses the sproc-local data directly. 88 | int pid = (int) PRDA->sys_prda.prda_sys.t_pid; 89 | return pid; 90 | #endif 91 | } 92 | 93 | 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /runtime/heaplayers/util/bitindex.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | /** 4 | * @file bitindex.h 5 | * 6 | * Bit-access operations, including msb and lsb. 7 | * @author Emery Berger (emery@cs.umass.edu) 8 | */ 9 | 10 | // lsb is due to Leiserson, Prokop, Randall (MIT). 11 | // msb is also a fast implementation of floor(lg_2). 12 | 13 | #ifndef _BITINDEX_H_ 14 | #define _BITINDEX_H_ 15 | 16 | #include 17 | 18 | namespace HL { 19 | 20 | class BitIndex { 21 | private: 22 | 23 | enum { debruijn32 = 0x077CB531UL }; 24 | static int index32[32]; 25 | static unsigned long lgtable[16]; 26 | static unsigned long on[32]; 27 | static unsigned long off[32]; 28 | 29 | void setup (void); 30 | 31 | public: 32 | 33 | BitIndex (void); 34 | ~BitIndex (void) {} 35 | 36 | // Set bit_index in b (to 1). 37 | static void set (unsigned long &b, int index) 38 | { 39 | assert (index >= 0); 40 | assert (index < 32); 41 | b |= on[index]; 42 | } 43 | 44 | // Reset bit_index in b (set it to 0). 45 | static void reset (unsigned long &b, int index) 46 | { 47 | assert (index >= 0); 48 | assert (index < 32); 49 | b &= off[index]; 50 | } 51 | 52 | // Find the least-significant bit. 53 | static int lsb (unsigned long b) 54 | { 55 | //#if 0 56 | #if 0 // i386 57 | // Intel x86 code. 58 | register unsigned long index = 0; 59 | if (b > 0) { 60 | asm ("bsfl %1, %0" : "=r" (index) : "r" (b)); 61 | } 62 | return index; 63 | #else 64 | b &= (unsigned long) -((signed long) b); 65 | b *= debruijn32; 66 | b >>= 27; 67 | return index32[b]; 68 | #endif 69 | } 70 | 71 | // Find the most-significant bit. 72 | static int msb (unsigned long b) 73 | { 74 | #if 0 // i386 75 | // Intel x86 code. 76 | register unsigned long index = 0; 77 | if (b > 0) { 78 | asm ("bsrl %1, %0" : "=r" (index) : "r" (b)); 79 | } 80 | return index; 81 | #else 82 | int l = 0; 83 | // b < 2^32 84 | if (b >= 65536) { 85 | l += 16; 86 | b >>= 16; 87 | } 88 | // b < 2^16 89 | if (b >= 256) { 90 | l += 8; 91 | b >>= 8; 92 | } 93 | // b < 2^8 94 | if (b >= 16) { 95 | l += 4; 96 | b >>= 4; 97 | } 98 | return l + lgtable[b]; 99 | #endif 100 | } 101 | 102 | 103 | }; 104 | 105 | }; 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /runtime/heaplayers/sizeownerheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2003 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | #ifndef _SIZEOWNERHEAP_H_ 28 | #define _SIZEOWNERHEAP_H_ 29 | 30 | #include 31 | 32 | #include "addheap.h" 33 | 34 | /** 35 | * @class SizeOwnerHeap 36 | * @brief Adds object size and owner heap information. 37 | */ 38 | 39 | namespace HL { 40 | 41 | template 42 | class SizeOwner { 43 | public: 44 | union { 45 | struct { 46 | size_t size; 47 | Heap * owner; 48 | } s; 49 | double dummy; 50 | }; 51 | }; 52 | 53 | template 54 | class SizeOwnerHeap : public AddHeap, Super> { 55 | private: 56 | 57 | typedef AddHeap, Super> SuperHeap; 58 | 59 | public: 60 | 61 | inline void * malloc (size_t sz) { 62 | void * ptr = SuperHeap::malloc (sz); 63 | // Store the requested size. 64 | SizeOwner * so = (SizeOwner *) ptr; 65 | so->s.size = sz; 66 | so->s.owner = this; 67 | // Store the owner. 68 | return (void *) (so + 1); 69 | } 70 | 71 | inline void free (void * ptr) { 72 | void * origPtr = (void *) ((SizeOwner *) ptr - 1); 73 | SuperHeap::free (origPtr); 74 | } 75 | 76 | static inline Super * owner (void * ptr) { 77 | SizeOwner * so = (SizeOwner *) ptr - 1; 78 | return so->s.owner; 79 | } 80 | 81 | static inline size_t size (void * ptr) { 82 | SizeOwner * so = (SizeOwner *) ptr - 1; 83 | return so->s.size; 84 | } 85 | }; 86 | 87 | }; 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /runtime/hashfuncs.h: -------------------------------------------------------------------------------- 1 | 2 | // -*- C++ -*- 3 | 4 | /* 5 | Copyright (c) 2012, University of Massachusetts Amherst. 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | */ 22 | 23 | /* 24 | * @file hashfuncs.h 25 | * @brief Some functions related to hash table. 26 | * @author Tongping Liu 27 | */ 28 | #ifndef __HASHFUNCS_H__ 29 | #define __HASHFUNCS_H__ 30 | 31 | #include "list.h" 32 | 33 | class HashFuncs { 34 | public: 35 | // The following functions are stole from stl library 36 | static size_t hashString(const void * start, size_t len) { 37 | unsigned long __h = 0; 38 | char * __s = (char *)start; 39 | int i; 40 | 41 | for ( ; i <= len; i++, ++__s) 42 | __h = 5*__h + *__s; 43 | 44 | return size_t(__h); 45 | } 46 | 47 | static size_t hashInt(const int x, size_t len) { 48 | return x; 49 | } 50 | 51 | static size_t hashLong(long x, size_t len) { 52 | return x; 53 | } 54 | 55 | static size_t hashUnsignedlong(unsigned long x, size_t len) { 56 | return x; 57 | } 58 | 59 | static size_t hashAddr(void * addr, size_t len) { 60 | unsigned long key = (unsigned long)addr; 61 | key ^= (key << 15) ^ 0xcd7dcd7d; 62 | key ^= (key >> 10); 63 | key ^= (key << 3); 64 | key ^= (key >> 6); 65 | key ^= (key << 2) + (key << 14); 66 | key ^= (key >> 16); 67 | return key; 68 | } 69 | 70 | static bool compareAddr(void * addr1, void * addr2, size_t len) { 71 | return addr1 == addr2; 72 | } 73 | 74 | static bool compareInt(int var1, int var2, size_t len) { 75 | return var1 == var2; 76 | } 77 | 78 | static bool compareString(const char * str1, const char * str2, size_t len) { 79 | return strncmp(str1, str2, len) == 0; 80 | } 81 | 82 | }; 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /runtime/elfinfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 University of Massachusetts Amherst. 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | /* 21 | * @file elfinfo.h 22 | * @brief elf info, borrowed from Linux. 23 | * @author Tongping Liu 24 | */ 25 | 26 | 27 | #ifndef __ELFINFO_H__ 28 | #define __ELFINFO_H__ 29 | 30 | 31 | #include 32 | 33 | #ifdef X86_32BIT 34 | #define Elf_Ehdr Elf32_Ehdr 35 | #define Elf_Shdr Elf32_Shdr 36 | #define Elf_Sym Elf32_Sym 37 | #define Elf_Addr Elf32_Addr 38 | #define Elf_Section Elf32_Section 39 | 40 | #define ELF_ST_BIND(x) ((x) >> 4) 41 | #define ELF_ST_TYPE(x) (((unsigned int) x) & 0xf) 42 | 43 | #define Elf_Rel Elf32_Rel 44 | #define Elf_Rela Elf32_Rela 45 | #define ELF_R_SYM ELF32_R_SYM 46 | #define ELF_R_TYPE ELF32_R_TYPE 47 | 48 | struct elf_info { 49 | unsigned long size; 50 | Elf_Ehdr * hdr; 51 | Elf32_Shdr * sechdrs; 52 | Elf32_Sym * symtab_start; 53 | Elf32_Sym * symtab_stop; 54 | const char *strtab; 55 | }; 56 | #else 57 | #define Elf_Ehdr Elf64_Ehdr 58 | #define Elf_Shdr Elf64_Shdr 59 | #define Elf_Sym Elf64_Sym 60 | #define Elf_Addr Elf64_Addr 61 | #define Elf_Section Elf64_Section 62 | 63 | #define ELF_ST_BIND(x) ((x) >> 4) 64 | #define ELF_ST_TYPE(x) (((unsigned int) x) & 0xf) 65 | 66 | #define Elf_Rel Elf64_Rel 67 | #define Elf_Rela Elf64_Rela 68 | #define ELF_R_SYM ELF64_R_SYM 69 | #define ELF_R_TYPE ELF64_R_TYPE 70 | 71 | struct elf_info { 72 | unsigned long size; 73 | Elf_Ehdr * hdr; 74 | Elf64_Shdr * sechdrs; 75 | Elf64_Sym * symtab_start; 76 | Elf64_Sym * symtab_stop; 77 | const char *strtab; 78 | }; 79 | 80 | #endif 81 | 82 | #endif /* __ELFINFO_H__ */ 83 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/sizethreadheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _SIZETHREADHEAP_H_ 4 | #define _SIZETHREADHEAP_H_ 5 | 6 | #include 7 | 8 | template 9 | class SizeThreadHeap : public Super { 10 | public: 11 | 12 | inline void * malloc (size_t sz) { 13 | // Add room for a size field & a thread field. 14 | // Both of these must fit in a double. 15 | assert (sizeof(st) <= sizeof(double)); 16 | st * ptr = (st *) Super::malloc (sz + sizeof(double)); 17 | // Store the requested size. 18 | ptr->size = sz; 19 | assert (getOrigPtr(ptr + 1) == ptr); 20 | return (void *) (ptr + 1); 21 | } 22 | 23 | inline void free (void * ptr) { 24 | void * origPtr = (void *) getOrigPtr(ptr); 25 | Super::free (origPtr); 26 | } 27 | 28 | static inline volatile int getThreadId (void); 29 | 30 | static inline size_t& size (void * ptr) { 31 | return getOrigPtr(ptr)->size; 32 | } 33 | 34 | static inline int& thread (void * ptr) { 35 | return getOrigPtr(ptr)->tid; 36 | } 37 | 38 | private: 39 | 40 | typedef struct _st { 41 | size_t size; 42 | int tid; 43 | } st; 44 | 45 | static inline st * getOrigPtr (void * ptr) { 46 | return (st *) ((double *) ptr - 1); 47 | } 48 | 49 | }; 50 | 51 | 52 | 53 | // A platform-dependent way to get a thread id. 54 | 55 | // Include the necessary platform-dependent crud. 56 | #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) 57 | #ifndef WIN32 58 | #define WIN32 1 59 | #endif 60 | #include 61 | #include 62 | #endif 63 | 64 | template 65 | inline volatile int 66 | SizeThreadHeap::getThreadId (void) { 67 | #if defined(WIN32) 68 | return GetCurrentThreadId(); 69 | #endif 70 | #if defined(__BEOS__) 71 | return find_thread(0); 72 | #endif 73 | #if defined(__linux) 74 | // Consecutive thread id's in Linux are 1024 apart; 75 | // dividing off the 1024 gives us an appropriate thread id. 76 | return (int) pthread_self() >> 10; // (>> 10 = / 1024) 77 | #endif 78 | #if defined(__SVR4) 79 | return (int) lwp_self(); 80 | #endif 81 | #if defined(POSIX) // FIX ME?? 82 | return (int) pthread_self(); 83 | #endif 84 | #if USE_SPROC // FIX ME 85 | // This hairiness has the same effect as calling getpid(), 86 | // but it's MUCH faster since it avoids making a system call 87 | // and just accesses the sproc-local data directly. 88 | int pid = (int) PRDA->sys_prda.prda_sys.t_pid; 89 | return pid; 90 | #endif 91 | } 92 | 93 | 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /runtime/objectheader.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | Copyright (C) 2011 University of Massachusetts Amherst. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | */ 21 | 22 | #ifndef SHERIFF_OBJECTHEADER_H 23 | #define SHERIFF_OBJECTHEADER_H 24 | 25 | /* 26 | * @file objectheader.h 27 | * @brief Heap object header, keeping track of size and callsite. 28 | * @author Emery Berger 29 | * @author Tongping Liu 30 | */ 31 | #include "callsite.h" 32 | 33 | class objectHeader { 34 | public: 35 | enum { MAGIC = 0xCAFEBABE }; 36 | 37 | objectHeader (size_t sz) 38 | : _size (sz), 39 | _magic (MAGIC) 40 | { 41 | } 42 | 43 | size_t getSize () { sanityCheck(); return _size; } 44 | size_t getSizeWithoutChecking () { return _size; } 45 | 46 | bool isValidObject() { 47 | // FIXME: _size should be multiple of 8s according to our heap implementation. 48 | // return (_size % 8 == 0)? true : false; 49 | return _magic == MAGIC; 50 | } 51 | 52 | inline void * getObjectStart(void) { 53 | return (void *)((intptr_t)&_magic + sizeof(objectHeader)); 54 | } 55 | 56 | inline void * getObjectEnd(void) { 57 | return (void *)((intptr_t)&_magic + sizeof(objectHeader) + getSizeWithoutChecking()); 58 | } 59 | 60 | inline void * getCallsiteAddr(void) { 61 | return &_callsite; 62 | } 63 | 64 | private: 65 | 66 | bool sanityCheck (void) { 67 | #ifndef NDEBUG 68 | if (_magic != MAGIC) { 69 | fprintf (stderr, "Sanity check failed in process %d. Current _magic %lx at %p\n", getpid(), _magic, &_magic); 70 | ::abort(); 71 | } 72 | #endif 73 | return true; 74 | } 75 | 76 | size_t _magic; 77 | size_t _size; 78 | CallSite _callsite; 79 | }; 80 | 81 | #endif /* SHERIFF_OBJECTHEADER_H */ 82 | -------------------------------------------------------------------------------- /runtime/heaplayers/fifofreelist.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _FIFOFREELIST_H_ 4 | #define _FIFOFREELIST_H_ 5 | 6 | #include 7 | 8 | #ifdef NDEBUG 9 | #define IFDEBUG(x) 10 | #else 11 | #define IFDEBUG(x) x 12 | #endif 13 | 14 | 15 | template 16 | class FIFOFreelistHeap : public SuperHeap { 17 | public: 18 | 19 | FIFOFreelistHeap (void) 20 | IFDEBUG(: nObjects (0)) 21 | { 22 | head.next = &tail; 23 | tail.next = &tail; 24 | assert (isEmpty()); 25 | } 26 | 27 | ~FIFOFreelistHeap (void) 28 | { 29 | // printf ("Adios free list.\n"); 30 | // Delete everything on the free list. 31 | freeObject * ptr = head.next; 32 | while (ptr != &tail) { 33 | void * oldptr = ptr; 34 | ptr = ptr->next; 35 | SuperHeap::free (oldptr); 36 | } 37 | } 38 | 39 | inline void * malloc (size_t sz) { 40 | assert (isValid()); 41 | // Check the free list first. 42 | freeObject * ptr = head.next; 43 | if (ptr == &tail) { 44 | assert (nObjects == 0); 45 | assert (isEmpty()); 46 | ptr = (freeObject *) SuperHeap::malloc (sz); 47 | } else { 48 | assert (nObjects > 0); 49 | head.next = ptr->next; 50 | if (head.next == &tail) { 51 | tail.next = &tail; 52 | } 53 | IFDEBUG (nObjects--); 54 | } 55 | assert (isValid()); 56 | return (void *) ptr; 57 | } 58 | 59 | inline void free (void * ptr) { 60 | assert (isValid()); 61 | // Add this object to the free list. 62 | assert (ptr != NULL); 63 | IFDEBUG (nObjects++); 64 | freeObject * p = (freeObject *) ptr; 65 | p->next = &tail; 66 | tail.next->next = p; 67 | tail.next = p; 68 | if (head.next == &tail) { 69 | head.next = p; 70 | } 71 | assert (!isEmpty()); 72 | assert (isValid()); 73 | } 74 | 75 | private: 76 | 77 | int isValid (void) { 78 | // Make sure every object is the right size. 79 | freeObject * ptr = head.next; 80 | if (ptr != &tail) { 81 | size_t sz = SuperHeap::getSize(ptr); 82 | while (ptr != &tail) { 83 | void * oldptr = ptr; 84 | ptr = ptr->next; 85 | assert (SuperHeap::getSize(oldptr) >= sz); 86 | } 87 | } 88 | return 1; 89 | } 90 | 91 | int isEmpty (void) { 92 | return (head.next == &tail); 93 | } 94 | 95 | class freeObject { 96 | public: 97 | freeObject * prev; 98 | freeObject * next; 99 | }; 100 | 101 | freeObject head, tail; 102 | IFDEBUG (int nObjects); 103 | }; 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/fifofreelist.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _FIFOFREELIST_H_ 4 | #define _FIFOFREELIST_H_ 5 | 6 | #include 7 | 8 | #ifdef NDEBUG 9 | #define IFDEBUG(x) 10 | #else 11 | #define IFDEBUG(x) x 12 | #endif 13 | 14 | 15 | template 16 | class FIFOFreelistHeap : public SuperHeap { 17 | public: 18 | 19 | FIFOFreelistHeap (void) 20 | IFDEBUG(: nObjects (0)) 21 | { 22 | head.next = &tail; 23 | tail.next = &tail; 24 | assert (isEmpty()); 25 | } 26 | 27 | ~FIFOFreelistHeap (void) 28 | { 29 | // printf ("Adios free list.\n"); 30 | // Delete everything on the free list. 31 | freeObject * ptr = head.next; 32 | while (ptr != &tail) { 33 | void * oldptr = ptr; 34 | ptr = ptr->next; 35 | SuperHeap::free (oldptr); 36 | } 37 | } 38 | 39 | inline void * malloc (size_t sz) { 40 | assert (isValid()); 41 | // Check the free list first. 42 | freeObject * ptr = head.next; 43 | if (ptr == &tail) { 44 | assert (nObjects == 0); 45 | assert (isEmpty()); 46 | ptr = (freeObject *) SuperHeap::malloc (sz); 47 | } else { 48 | assert (nObjects > 0); 49 | head.next = ptr->next; 50 | if (head.next == &tail) { 51 | tail.next = &tail; 52 | } 53 | IFDEBUG (nObjects--); 54 | } 55 | assert (isValid()); 56 | return (void *) ptr; 57 | } 58 | 59 | inline void free (void * ptr) { 60 | assert (isValid()); 61 | // Add this object to the free list. 62 | assert (ptr != NULL); 63 | IFDEBUG (nObjects++); 64 | freeObject * p = (freeObject *) ptr; 65 | p->next = &tail; 66 | tail.next->next = p; 67 | tail.next = p; 68 | if (head.next == &tail) { 69 | head.next = p; 70 | } 71 | assert (!isEmpty()); 72 | assert (isValid()); 73 | } 74 | 75 | private: 76 | 77 | int isValid (void) { 78 | // Make sure every object is the right size. 79 | freeObject * ptr = head.next; 80 | if (ptr != &tail) { 81 | size_t sz = SuperHeap::getSize(ptr); 82 | while (ptr != &tail) { 83 | void * oldptr = ptr; 84 | ptr = ptr->next; 85 | assert (SuperHeap::getSize(oldptr) >= sz); 86 | } 87 | } 88 | return 1; 89 | } 90 | 91 | int isEmpty (void) { 92 | return (head.next == &tail); 93 | } 94 | 95 | class freeObject { 96 | public: 97 | freeObject * prev; 98 | freeObject * next; 99 | }; 100 | 101 | freeObject head, tail; 102 | IFDEBUG (int nObjects); 103 | }; 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /runtime/heaplayers/fifodlfreelist.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _FIFODLFREELIST_H_ 4 | #define _FIFODLFREELIST_H_ 5 | 6 | #include 7 | 8 | template 9 | class FIFODLFreelistHeap : public Super { 10 | public: 11 | 12 | FIFODLFreelistHeap (void) 13 | { 14 | head.prev = &head; 15 | head.next = &tail; 16 | tail.prev = &head; 17 | tail.next = &tail; 18 | assert (isEmpty()); 19 | } 20 | 21 | ~FIFODLFreelistHeap (void) 22 | { 23 | // Delete everything on the free list. 24 | freeObject * ptr = head.next; 25 | while (ptr != &tail) { 26 | void * oldptr = ptr; 27 | ptr = ptr->next; 28 | Super::free (oldptr); 29 | } 30 | } 31 | 32 | inline void * malloc (size_t sz) { 33 | //printf ("flist malloc %d\n", sz); 34 | // Check the free list first. 35 | freeObject * ptr = tail.prev; 36 | if (ptr == &head) { 37 | assert (isEmpty()); 38 | ptr = (freeObject *) Super::malloc (sz); 39 | } else { 40 | ptr->prev->next = &tail; 41 | tail.prev = ptr->prev; 42 | #if 0 43 | ptr->prev = NULL; 44 | ptr->next = NULL; 45 | #endif 46 | } 47 | assert (getSize(ptr) >= sz); 48 | assert (getSize(ptr) >= sizeof(freeObject)); 49 | return (void *) ptr; 50 | } 51 | 52 | inline void free (void * ptr) { 53 | // Add this object to the free list. 54 | assert (ptr != NULL); 55 | freeObject * p = (freeObject *) ptr; 56 | p->next = head.next; 57 | p->next->prev = p; 58 | p->prev = &head; 59 | head.next = p; 60 | assert (!isEmpty()); 61 | } 62 | 63 | #if 0 64 | // Returns the entire linked list of freed objects. 65 | inline void * multimalloc (size_t sz) { 66 | freeObject * ptr = head.next; 67 | ptr->prev = NULL; 68 | tail.prev->next = NULL; 69 | head.next = &tail; 70 | tail.prev = &head; 71 | return ptr; 72 | } 73 | #endif 74 | 75 | inline static void remove (void * rptr) 76 | { 77 | freeObject * p = (freeObject *) rptr; 78 | assert (p->next != NULL); 79 | assert (p->prev != NULL); 80 | p->prev->next = p->next; 81 | p->next->prev = p->prev; 82 | p->prev = p->next = NULL; 83 | } 84 | 85 | 86 | private: 87 | 88 | int isEmpty (void) { 89 | return (head.next == &tail); 90 | } 91 | 92 | class freeObject { 93 | public: 94 | freeObject * prev; 95 | freeObject * next; 96 | }; 97 | 98 | freeObject head, tail; 99 | }; 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /runtime/spinlock.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | Copyright (c) 2012-2013, University of Massachusetts Amherst. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | */ 21 | 22 | /* 23 | * @file: spinlock.h 24 | * @brief: spinlock used internally. 25 | * @author: Tongping Liu 26 | * Note: Some references: http://locklessinc.com/articles/locks/ 27 | */ 28 | #ifndef __SPINLOCK_H__ 29 | #define __SPINLOCK_H__ 30 | 31 | #include "atomic.h" 32 | 33 | class spinlock { 34 | public: 35 | spinlock() { 36 | _lock = 0; 37 | } 38 | 39 | void init(void) { 40 | _lock = 0; 41 | } 42 | 43 | // Lock 44 | void lock(void) { 45 | #if 0 46 | int cnt = 0; 47 | 48 | while (atomic_test_and_set(&lock)) { 49 | if (cnt < MAX_SPIN_COUNT) { 50 | cnt++; 51 | } 52 | cnt = 0; 53 | } 54 | #endif 55 | #if 0 56 | #define SPIN_SLEEP_DURATION 5000001 57 | #define MAX_SPIN_COUNT 10000 58 | 59 | int cnt = 0; 60 | struct timespec tm; 61 | 62 | while (atomic_test_and_set(&_lock)) { 63 | if (cnt < MAX_SPIN_COUNT) { 64 | cnt++; 65 | } else { 66 | tm.tv_sec = 0; 67 | tm.tv_nsec = SPIN_SLEEP_DURATION; 68 | syscall(__NR_nanosleep, &tm, NULL); 69 | cnt = 0; 70 | } 71 | } 72 | 73 | #else 74 | // fprintf(stderr, "Thread %d:try to lock\n", getThreadIndex()); 75 | while (atomic_test_and_set(&_lock)) { 76 | //while(_lock) { 77 | // There is no need to check the _lock since it could be inside the register 78 | /* Pause instruction to prevent excess processor bus usage */ 79 | atomic_cpuRelax(); 80 | } 81 | // fprintf(stderr, "Thread %d: get lock\n", getThreadIndex()); 82 | #endif 83 | } 84 | 85 | void unlock(void) { 86 | _lock = 0; 87 | atomic_memoryBarrier(); 88 | } 89 | 90 | private: 91 | volatile unsigned long _lock; 92 | }; 93 | 94 | #endif /* __SPINLOCK_H__ */ 95 | 96 | -------------------------------------------------------------------------------- /runtime/heaplayers/util/sllist.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2003 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | #ifndef _SLLIST_H_ 28 | #define _SLLIST_H_ 29 | 30 | #include 31 | 32 | /** 33 | * @class SLList 34 | * @brief A "memory neutral" singly-linked list. 35 | * @author Emery Berger 36 | */ 37 | 38 | namespace HL { 39 | 40 | class SLList { 41 | public: 42 | 43 | inline SLList (void) { 44 | clear(); 45 | } 46 | 47 | class Entry; 48 | 49 | /// Clear the list. 50 | inline void clear (void) { 51 | head.next = NULL; 52 | } 53 | 54 | /// Get the head of the list. 55 | inline Entry * get (void) { 56 | const Entry * e = head.next; 57 | if (e == NULL) { 58 | return NULL; 59 | } 60 | head.next = e->next; 61 | return (Entry *) e; 62 | } 63 | 64 | private: 65 | 66 | /** 67 | * @brief Remove one item from the list. 68 | * @warning This method aborts the program if called. 69 | */ 70 | inline void remove (Entry *) { 71 | abort(); 72 | } 73 | 74 | public: 75 | 76 | /// Inserts an entry into the head of the list. 77 | inline void insert (Entry * e) { 78 | e->next = head.next; 79 | head.next = e; 80 | } 81 | 82 | /// An entry in the list. 83 | class Entry { 84 | public: 85 | inline Entry (void) 86 | : next (NULL) 87 | {} 88 | // private: 89 | // Entry * prev; 90 | public: 91 | Entry * next; 92 | }; 93 | 94 | private: 95 | 96 | /// The head of the list. 97 | Entry head; 98 | 99 | }; 100 | 101 | } 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /runtime/heaplayers/sizeheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2007 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | #ifndef _SIZEHEAP_H_ 28 | #define _SIZEHEAP_H_ 29 | 30 | /** 31 | * @file sizeheap.h 32 | * @brief Contains UseSizeHeap and SizeHeap. 33 | */ 34 | 35 | #include 36 | #include 37 | 38 | #include "addheap.h" 39 | 40 | /** 41 | * @class UseSizeHeap 42 | * @brief Adds a getSize method to access the size of an allocated object. 43 | * @see SizeHeap 44 | */ 45 | 46 | namespace HL { 47 | 48 | template 49 | class UseSizeHeap : public Super { 50 | public: 51 | 52 | inline static size_t getSize (const void * ptr) { 53 | return ((freeObject *) ptr - 1)->getSize(); 54 | } 55 | 56 | protected: 57 | class freeObject { 58 | public: 59 | freeObject (size_t sz) 60 | : _size (sz) 61 | {} 62 | size_t getSize (void) const { 63 | return _size; 64 | } 65 | private: 66 | union { 67 | size_t _size; 68 | double _dummy; // for alignment. 69 | }; 70 | }; 71 | }; 72 | 73 | /** 74 | * @class SizeHeap 75 | * @brief Allocates extra room for the size of an object. 76 | */ 77 | 78 | template 79 | class SizeHeap : public UseSizeHeap { 80 | typedef typename UseSizeHeap::freeObject freeObject; 81 | public: 82 | inline void * malloc (const size_t sz) { 83 | freeObject * ptr = new (SuperHeap::malloc (sz + sizeof(freeObject))) 84 | freeObject (sz); 85 | void * obj = (void *) (ptr + 1); 86 | size_t size = UseSizeHeap::getSize(obj); 87 | assert (size >= sz); 88 | return obj; 89 | } 90 | inline void free (void * ptr) { 91 | SuperHeap::free (((freeObject *) ptr) - 1); 92 | } 93 | }; 94 | 95 | }; 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /runtime/callsite.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | Copyright (C) 2011 University of Massachusetts Amherst. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | */ 21 | 22 | /* 23 | * @file callsite.h 24 | * @brief Management about callsite for heap objects. 25 | * @author Tongping Liu 26 | */ 27 | 28 | #ifndef SHERIFF_CALLSITE_H 29 | #define SHERIFF_CALLSITE_H 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | class CallSite { 38 | public: 39 | CallSite() { 40 | for (int i = 0; i < CALL_SITE_DEPTH; i++) { 41 | _callsite[i] = 0; 42 | } 43 | } 44 | 45 | unsigned long getItem(unsigned int index) 46 | { 47 | assert (index < CALL_SITE_DEPTH); 48 | return _callsite[index]; 49 | } 50 | 51 | unsigned long getDepth() 52 | { 53 | return CALL_SITE_DEPTH; 54 | } 55 | 56 | void print() 57 | { 58 | printf("ALLOCATION CALL SITE: "); 59 | for(int i = 0; i < CALL_SITE_DEPTH; i++) { 60 | printf("%lx\t", _callsite[i]); 61 | } 62 | printf("\n"); 63 | } 64 | 65 | void fetch(void) { 66 | void * array[10]; 67 | int size; 68 | int log = 0; 69 | 70 | // PRDBG("Try to get backtrace with array %p\n", array); 71 | if(!isBacktrace) { 72 | isBacktrace = true; 73 | // get void*'s for all entries on the stack 74 | size = backtrace(array, 11); 75 | isBacktrace = false; 76 | 77 | for(int i = 0; i < size; i++) { 78 | unsigned long addr = (unsigned long)array[i]; 79 | //fprintf(stderr, "textStart %lx textEnd %lx addr %lx at log %d\n", textStart, textEnd, addr, log); 80 | if(addr >= textStart && addr <= textEnd) { 81 | _callsite[log++] = addr; 82 | if(log == CALL_SITE_DEPTH) { 83 | break; 84 | } 85 | } 86 | } 87 | } 88 | } 89 | 90 | unsigned long _callsite[CALL_SITE_DEPTH]; 91 | }; 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /runtime/heaplayers/gnuwrapper.cpp: -------------------------------------------------------------------------------- 1 | #ifndef __GNUC__ 2 | #error "This file requires the GNU compiler." 3 | #endif 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define CUSTOM_PREFIX(n) _custom##n 11 | #include "libhoard.cpp" 12 | 13 | extern "C" { 14 | 15 | void * CUSTOM_PREFIX(malloc) (size_t); 16 | void CUSTOM_PREFIX(free) (void *); 17 | void * CUSTOM_PREFIX(realloc) (void *, size_t); 18 | void * CUSTOM_PREFIX(memalign) (size_t, size_t); 19 | 20 | static void my_init_hook (void); 21 | 22 | // New hooks for allocation functions. 23 | static void * my_malloc_hook (size_t, const void *); 24 | static void my_free_hook (void *, const void *); 25 | static void * my_realloc_hook (void *, size_t, const void *); 26 | static void * my_memalign_hook (size_t, size_t, const void *); 27 | 28 | // Store the old hooks just in case. 29 | static void * (*old_malloc_hook) (size_t, const void *); 30 | static void (*old_free_hook) (void *, const void *); 31 | static void *(*old_realloc_hook)(void *ptr, size_t size, const void *caller); 32 | static void *(*old_memalign_hook)(size_t alignment, size_t size, const void *caller); 33 | 34 | void (*__malloc_initialize_hook) (void) = my_init_hook; 35 | 36 | static void my_init_hook (void) { 37 | // Store the old hooks. 38 | old_malloc_hook = __malloc_hook; 39 | old_free_hook = __free_hook; 40 | old_realloc_hook = __realloc_hook; 41 | old_memalign_hook = __memalign_hook; 42 | 43 | // Point the hooks to the replacement functions. 44 | __malloc_hook = my_malloc_hook; 45 | __free_hook = my_free_hook; 46 | __realloc_hook = my_realloc_hook; 47 | __memalign_hook = my_memalign_hook; 48 | 49 | } 50 | 51 | // static size_t counter = 0; 52 | 53 | static void * my_malloc_hook (size_t size, const void * caller) { 54 | void * result; 55 | // fprintf (stderr, "malloc\n"); 56 | #if 0 57 | counter++; 58 | if (counter > 900000) 59 | abort(); 60 | #endif 61 | result = CUSTOM_PREFIX(malloc) (size); 62 | return result; 63 | } 64 | 65 | static void my_free_hook (void * ptr, const void * caller) { 66 | CUSTOM_PREFIX(free) (ptr); 67 | } 68 | 69 | static void * my_realloc_hook (void * ptr, size_t size, const void * caller) { 70 | return CUSTOM_PREFIX(realloc) (ptr, size); 71 | } 72 | 73 | static void * my_memalign_hook (size_t size, size_t alignment, const void * caller) { 74 | return CUSTOM_PREFIX(memalign) (size, alignment); 75 | } 76 | 77 | #if 0 78 | void finalizer (void) __attribute__((destructor)); 79 | 80 | void finalizer (void) { 81 | printf ("counter = %d\n", counter); 82 | } 83 | #endif 84 | 85 | } 86 | 87 | -------------------------------------------------------------------------------- /runtime/heaplayers/unique.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _UNIQUEHEAP_H_ 4 | #define _UNIQUEHEAP_H_ 5 | 6 | #include 7 | #include 8 | 9 | /** 10 | * 11 | * @class UniqueHeap 12 | * @brief Instantiates one instance of a class used for every malloc & free. 13 | * @author Emery Berger 14 | * 15 | */ 16 | 17 | template 18 | class UniqueHeap { 19 | public: 20 | 21 | /** 22 | * Ensure that the super heap gets created, 23 | * and add a reference for every instance of unique heap. 24 | */ 25 | UniqueHeap (void) 26 | { 27 | volatile SuperHeap * forceCreationOfSuperHeap = getSuperHeap(); 28 | addRef(); 29 | } 30 | 31 | /** 32 | * @brief Delete one reference to the unique heap. 33 | * When the number of references goes to zero, 34 | * delete the super heap. 35 | */ 36 | ~UniqueHeap (void) { 37 | int r = delRef(); 38 | if (r <= 0) { 39 | getSuperHeap()->SuperHeap::~SuperHeap(); 40 | } 41 | } 42 | 43 | // The remaining public methods are just 44 | // thin wrappers that route calls to the static object. 45 | 46 | inline void * malloc (size_t sz) { 47 | return getSuperHeap()->malloc (sz); 48 | } 49 | 50 | inline void free (void * ptr) { 51 | getSuperHeap()->free (ptr); 52 | } 53 | 54 | inline size_t getSize (void * ptr) { 55 | return getSuperHeap()->getSize (ptr); 56 | } 57 | 58 | inline int remove (void * ptr) { 59 | return getSuperHeap()->remove (ptr); 60 | } 61 | 62 | inline void clear (void) { 63 | getSuperHeap()->clear(); 64 | } 65 | 66 | #if 0 67 | inline int getAllocated (void) { 68 | return getSuperHeap()->getAllocated(); 69 | } 70 | 71 | inline int getMaxAllocated (void) { 72 | return getSuperHeap()->getMaxAllocated(); 73 | } 74 | 75 | inline int getMaxInUse (void) { 76 | return getSuperHeap()->getMaxInUse(); 77 | } 78 | #endif 79 | 80 | private: 81 | 82 | /// Add one reference. 83 | void addRef (void) { 84 | getRefs() += 1; 85 | } 86 | 87 | /// Delete one reference count. 88 | int delRef (void) { 89 | getRefs() -= 1; 90 | return getRefs(); 91 | } 92 | 93 | /// Internal accessor for reference count. 94 | int& getRefs (void) { 95 | static int numRefs = 0; 96 | return numRefs; 97 | } 98 | 99 | SuperHeap * getSuperHeap (void) { 100 | static char superHeapBuffer[sizeof(SuperHeap)]; 101 | static SuperHeap * aSuperHeap = (SuperHeap *) (new ((char *) &superHeapBuffer) SuperHeap); 102 | return aSuperHeap; 103 | } 104 | 105 | void doNothing (Child *) {} 106 | }; 107 | 108 | 109 | #endif // _UNIQUE_H_ 110 | -------------------------------------------------------------------------------- /runtime/xoneheap.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | Author: Emery Berger, http://www.cs.umass.edu/~emery 5 | 6 | Copyright (c) 2007-8 Emery Berger, University of Massachusetts Amherst. 7 | 8 | This program is free software; you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation; either version 2 of the License, or 11 | (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | 22 | */ 23 | 24 | #ifndef _XONEHEAP_H_ 25 | #define _XONEHEAP_H_ 26 | 27 | /** 28 | * @class xoneheap 29 | * @brief Wraps a single heap instance. 30 | * 31 | * @author Emery Berger 32 | */ 33 | 34 | template 35 | class xoneheap { 36 | public: 37 | xoneheap() { 38 | //fprintf(stderr, "xoneheap constructor.\n"); 39 | } 40 | void * initialize(size_t size, size_t metasize) { return getHeap()->initialize(size, metasize); } 41 | void finalize (void * end) { getHeap()->finalize(end); } 42 | #if 0 43 | void cleanup() { getHeap()->cleanup(); } 44 | 45 | bool FSSuspect(void * addr, size_t size) { return getHeap()->FSSuspect(addr, size); } 46 | void handleAccess(void * addr, int bytes, eAccessType type) { return getHeap()->handleAccess(addr, bytes, type); } 47 | 48 | void reportFalseSharing(void) { return getHeap()->reportFalseSharing(getHeapPosition()); } 49 | bool inRange (void * ptr) { return getHeap()->inRange(ptr); } 50 | #endif 51 | // Get heap start and end, this is used to check range. 52 | void * getHeapStart(void) { return getHeap()->getHeapStart(); } 53 | void * getHeapEnd(void) { return getHeap()->getHeapEnd(); } 54 | void * getHeapPosition(void) { return getHeap()->getHeapPosition(); } 55 | 56 | bool nop() { return getHeap()->nop(); } 57 | 58 | 59 | void * malloc (size_t sz) { return getHeap()->malloc(sz); } 60 | void free (void * ptr) { getHeap()->free(ptr); } 61 | size_t getSize (void * ptr) { return getHeap()->getSize(ptr); } 62 | 63 | private: 64 | 65 | SourceHeap * getHeap (void) { 66 | static char heapbuf[sizeof(SourceHeap)]; 67 | static SourceHeap * _heap = new (heapbuf) SourceHeap; 68 | //fprintf (stderr, "heap is in %p\n", _heap); 69 | return _heap; 70 | } 71 | 72 | }; 73 | 74 | 75 | #endif // _XONEHEAP_H_ 76 | -------------------------------------------------------------------------------- /runtime/heaplayers/threadspecificheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _THREADHEAP_H_ 4 | #define _THREADHEAP_H_ 5 | 6 | #include 7 | #include 8 | 9 | /* 10 | 11 | A ThreadHeap comprises NumHeaps "per-thread" heaps. 12 | 13 | To pick a per-thread heap, the current thread id is hashed (mod NumHeaps). 14 | 15 | malloc gets memory from its hashed per-thread heap. 16 | free returns memory to its hashed per-thread heap. 17 | 18 | (This allows the per-thread heap to determine the return 19 | policy -- 'pure private heaps', 'private heaps with ownership', 20 | etc.) 21 | 22 | NB: We assume that the thread heaps are 'locked' as needed. */ 23 | 24 | 25 | template 26 | class ThreadHeap : public PerThreadHeap { 27 | public: 28 | 29 | ThreadHeap (void) 30 | { 31 | } 32 | 33 | inline void * malloc (size_t sz) { 34 | int tid = getThreadId() % NumHeaps; 35 | return getHeap(tid)->malloc (sz); 36 | } 37 | 38 | inline void free (void * ptr) { 39 | int tid = getThreadId() % NumHeaps; 40 | getHeap(tid)->free (ptr); 41 | } 42 | 43 | 44 | private: 45 | 46 | // Access the given heap within the buffer. 47 | PerThreadHeap * getHeap (int index) { 48 | assert (index >= 0); 49 | assert (index < NumHeaps); 50 | return &ptHeaps[index]; 51 | } 52 | 53 | // Get a suitable thread id number. 54 | inline static volatile int getThreadId (void); 55 | 56 | PerThreadHeap ptHeaps[NumHeaps]; 57 | 58 | }; 59 | 60 | 61 | // A platform-dependent way to get a thread id. 62 | 63 | // Include the necessary platform-dependent crud. 64 | #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) 65 | #ifndef WIN32 66 | #define WIN32 1 67 | #endif 68 | #include 69 | #include 70 | #endif 71 | 72 | template 73 | inline volatile int 74 | ThreadHeap::getThreadId (void) { 75 | #if WIN32 76 | return GetCurrentThreadId(); 77 | #endif 78 | #if defined(__BEOS__) 79 | return find_thread(0); 80 | #endif 81 | #if defined(__linux) 82 | // Consecutive thread id's in Linux are 1024 apart; 83 | // dividing off the 1024 gives us an appropriate thread id. 84 | return (int) pthread_self() >> 10; // (>> 10 = / 1024) 85 | #endif 86 | #if defined(__SVR4) 87 | return (int) lwp_self(); 88 | #endif 89 | #if defined(POSIX) 90 | return (int) pthread_self(); 91 | #endif 92 | #if USE_SPROC 93 | // This hairiness has the same effect as calling getpid(), 94 | // but it's MUCH faster since it avoids making a system call 95 | // and just accesses the sproc-local data directly. 96 | int pid = (int) PRDA->sys_prda.prda_sys.t_pid; 97 | return pid; 98 | #endif 99 | } 100 | 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/lazyslotheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _LAZYSLOTHEAP_H_ 4 | #define _LAZYSLOTHEAP_H_ 5 | 6 | /* 7 | This heap manages memory in units of Chunks. 8 | malloc returns a slot within a chunk, 9 | while free returns slots back to a chunk. 10 | 11 | We completely exhaust the first chunk before we ever get another one. 12 | Once a chunk (except for our current one) is COMPLETELY empty, it is returned to the superheap. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | #include "chunk.h" 19 | 20 | 21 | template 22 | class LazySlotHeap : public Super { 23 | public: 24 | 25 | LazySlotHeap (void) 26 | : myChunk (new (Super::malloc (chunkSize)) Chunk()) 27 | {} 28 | 29 | ~LazySlotHeap (void) 30 | { 31 | // Give up our chunk. 32 | Super::free (myChunk); 33 | } 34 | 35 | inline void * malloc (size_t sz) { 36 | assert (sz <= slotSize); 37 | void * ptr = myChunk->getSlot(); 38 | if (ptr == NULL) { 39 | myChunk = new (Super::malloc (chunkSize)) Chunk(); 40 | ptr = myChunk->getSlot(); 41 | assert (ptr != NULL); 42 | } 43 | return ptr; 44 | } 45 | 46 | inline void free (void * ptr) { 47 | /// Return a slot to its chunk. 48 | Chunk * ch = Chunk::getChunk (ptr); 49 | ch->putSlot (ptr); 50 | // check if it's completely empty. If so, free it. 51 | if (ch != myChunk) { 52 | // Once the chunk is completely empty, free it. 53 | if (ch->getNumSlotsAvailable() == ch->getNumSlots()) { 54 | Super::free (ch); 55 | } 56 | } 57 | 58 | #if 0 59 | // If this chunk isn't the one we're currently holding, 60 | // free it. NB: It is NOT guaranteed to be empty! 61 | if (ch != myChunk) { 62 | Super::free (ch); 63 | } 64 | #endif 65 | #if 0 66 | template 67 | class StrictSlotHeap : public LazySlotHeap { 68 | public: 69 | inline void free (void * ptr) { 70 | /// Return a slot to its chunk. 71 | Chunk * ch = Chunk::getChunk (ptr); 72 | ch->putSlot (ptr); 73 | // check if it's completely empty. If so, free it. 74 | if (ch != myChunk) { 75 | // Once the chunk is completely empty, free it. 76 | if (ch->getNumSlotsAvailable() == ch->getNumSlots()) { 77 | Super::free (ch); 78 | } 79 | } 80 | } 81 | 82 | }; 83 | #endif 84 | 85 | } 86 | 87 | inline static size_t size (void * ptr) 88 | { 89 | return slotSize; 90 | } 91 | 92 | 93 | protected: 94 | 95 | Chunk * myChunk; 96 | 97 | }; 98 | 99 | 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /runtime/heaplayers/firstfitheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _FIRSTFITHEAP_H_ 4 | #define _FIRSTFITHEAP_H_ 5 | 6 | template 7 | class FirstFitHeap : public Super { 8 | public: 9 | 10 | FirstFitHeap (void) 11 | : myFreeList (NULL) 12 | #ifndef NDEBUG 13 | ,nObjects (0) 14 | #endif 15 | { 16 | assert (classInvariant()); 17 | } 18 | 19 | ~FirstFitHeap (void) 20 | { 21 | #if 1 22 | // Delete everything on the free list. 23 | void * ptr = myFreeList; 24 | while (ptr != NULL) { 25 | // assert (nObjects > 0); 26 | assert (ptr != NULL); 27 | void * oldptr = ptr; 28 | ptr = (void *) ((freeObject *) ptr)->next; 29 | Super::free (oldptr); 30 | #ifndef NDEBUG 31 | --nObjects; 32 | #endif 33 | } 34 | #endif 35 | } 36 | 37 | inline void * malloc (size_t sz) { 38 | // Check the free list first. 39 | assert (classInvariant()); 40 | void * ptr = myFreeList; 41 | if (ptr == NULL) { 42 | assert (nObjects == 0); 43 | ptr = Super::malloc (sz); 44 | } else { 45 | assert (nObjects > 0); 46 | freeObject * p = myFreeList; 47 | freeObject * prev = NULL; 48 | while ((p != NULL) && (getSize((void *) p) < sz)) { 49 | prev = p; 50 | p = p->next; 51 | } 52 | if (p == NULL) { 53 | ptr = Super::malloc (sz); 54 | } else { 55 | assert (getSize((void *) p) >= sz); 56 | if (prev == NULL) { 57 | myFreeList = p->next; 58 | } else { 59 | assert (prev->next == p); 60 | prev->next = p->next; 61 | } 62 | #ifndef NDEBUG 63 | nObjects--; 64 | #endif 65 | ptr = p; 66 | } 67 | } 68 | assert (classInvariant()); 69 | return ptr; 70 | } 71 | 72 | inline void free (void * ptr) { 73 | // Add this object to the free list. 74 | assert (ptr != NULL); 75 | assert (classInvariant()); 76 | #ifndef NDEBUG 77 | nObjects++; 78 | #endif 79 | freeObject * p = myFreeList; 80 | freeObject * prev = NULL; 81 | // Insert the object "in order". 82 | #if 1 83 | while ((p != NULL) & (p <= ptr)) { 84 | prev = p; 85 | p = p->next; 86 | } 87 | #endif 88 | if (prev == NULL) { 89 | ((freeObject *) ptr)->next = myFreeList; 90 | myFreeList = (freeObject *) ptr; 91 | } else { 92 | ((freeObject *) ptr)->next = prev->next; 93 | prev->next = (freeObject *) ptr; 94 | } 95 | assert (classInvariant()); 96 | } 97 | 98 | private: 99 | 100 | int classInvariant (void) { 101 | return (((myFreeList == NULL) && (nObjects == 0)) 102 | || ((myFreeList != NULL) && (nObjects > 0))); 103 | } 104 | 105 | class freeObject { 106 | public: 107 | freeObject * next; 108 | }; 109 | 110 | freeObject * myFreeList; 111 | #ifndef NDEBUG 112 | int nObjects; 113 | #endif 114 | 115 | }; 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /runtime/internalheap.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | Copyright (C) 2011 University of Massachusetts Amherst. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | */ 21 | 22 | #ifndef _INTERNALHEAP_H_ 23 | #define _INTERNALHEAP_H_ 24 | 25 | #include "xdefines.h" 26 | #include "sourceinternalheap.h" 27 | #include "xoneheap.h" 28 | #include "xpheap.h" 29 | /** 30 | * @file InternalHeap.h 31 | * @brief A shared heap for internal allocation needs. 32 | * @author Tongping Liu 33 | * 34 | */ 35 | class InternalHeap 36 | { 37 | public: 38 | InternalHeap() 39 | { 40 | } 41 | 42 | ~InternalHeap (void) {} 43 | 44 | // Just one accessor. Why? We don't want more than one (singleton) 45 | // and we want access to it neatly encapsulated here, for use by the 46 | // signal handler. 47 | static InternalHeap& getInstance (void) { 48 | static void * buf[sizeof(InternalHeap)]; 49 | static InternalHeap * theOneTrueObject = new (buf) InternalHeap(); 50 | return *theOneTrueObject; 51 | } 52 | 53 | void initialize(void) { 54 | _heap.initialize(xdefines::INTERNALHEAP_SIZE); 55 | } 56 | 57 | void checkMagic(void * ptr) { 58 | unsigned long * magicWord = (unsigned long *)((intptr_t)ptr - sizeof(objectHeader)); 59 | 60 | if(*magicWord != 0xCAFEBABE) { 61 | fprintf(stderr, "@@@@@@@@@@@@@@@@@@@@@@@@@magicWord %lx at address %p with ptr %p@@@@@@@@@@@@@@@@@@@@@@\n", *magicWord, magicWord, ptr); 62 | } 63 | } 64 | 65 | void * malloc (size_t sz) { 66 | void * ptr = NULL; 67 | ptr = _heap.malloc (getThreadIndex(), sz); 68 | 69 | // checkMagic(ptr); 70 | return ptr; 71 | } 72 | 73 | void free (void * ptr) { 74 | _heap.free (getThreadIndex(), ptr); 75 | // fprintf(stderr, "@@@@@@@@@@@@free checking on ptr %p@@@@@@@@\n", ptr); 76 | // checkMagic(ptr); 77 | } 78 | 79 | private: 80 | xpheap >_heap; 81 | }; 82 | 83 | 84 | class InternalHeapAllocator { 85 | public: 86 | inline void * malloc (size_t sz) { 87 | return InternalHeap::getInstance().malloc(sz); 88 | } 89 | 90 | inline void free (void * ptr) { 91 | return InternalHeap::getInstance().free(ptr); 92 | } 93 | }; 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /runtime/handleAccessInline.h: -------------------------------------------------------------------------------- 1 | #ifndef __HANDLE_ACCESS_H__ 2 | #define __HANDLE_ACCESS_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define ATOMIC_INCREMENT_AND_RETURN 9 | #define THRESHOLD_TRACK_DETAILS (10000) 10 | #define INVOKE_DETAILED_TRACKING (THRESHOLD_TRACK_DETAILS-1) 11 | #define MAX_USER_SPACE (0xC0000000) 12 | #define CACHE_STATUS_BASE (0x200000000000) 13 | #define CACHE_TRACKING_BASE (0x200080000000) 14 | #define SAMPLE_ACCESSES_EACH_INTERVAL THRESHOLD_TRACK_DETAILS 15 | #define SAMPLE_INTERVAL (100 * SAMPLE_ACCESSES_EACH_INTERVAL) 16 | 17 | // There are 3 cases of handle accesses: 18 | // 1. 0 - do nothing 19 | // 2. 1 - call 20 | extern void allocCacheTrack(unsigned long index); 21 | extern void handleAccess(unsigned long addr, unsigned long size, int isWrite); 22 | //extern __attribute__ ((always_inline)) inline unsigned long atomic_increment_and_return(volatile unsigned long * obj); 23 | //extern __attribute__ ((always_inline)) inline int handleAccessBefore(unsigned long addr, int isWrite, int typesize); 24 | // __attribute__ ((weak)); 25 | //__attribute__ ((always_inline)) inline unsigned long atomic_increment_and_return(volatile unsigned long * obj) { 26 | __attribute__ ((always_inline)) inline unsigned long atomic_increment_and_return(volatile unsigned long * obj) { 27 | unsigned long i = 1; 28 | asm volatile("lock; xadd %0, %1" 29 | : "+r" (i), "+m" (*obj) 30 | : : "memory"); 31 | return i; 32 | } 33 | 34 | __attribute__ ((always_inline)) inline int handleAccessBefore(unsigned long addr, int isWrite, int typesize) { 35 | int result = 0; 36 | 37 | // We only care those acesses of global and heap. 38 | if(addr > MAX_USER_SPACE) { 39 | return 0; 40 | } 41 | 42 | unsigned long cindex = addr >> 6; 43 | unsigned long * cacheWrites = (unsigned long *)CACHE_STATUS_BASE; 44 | unsigned long * cacheTrackings = (unsigned long *)CACHE_TRACKING_BASE; 45 | 46 | unsigned long * status = (unsigned long *)&cacheWrites[cindex]; 47 | unsigned long totalWrites = *status; 48 | if(totalWrites < THRESHOLD_TRACK_DETAILS) { 49 | // Only update writes 50 | if(isWrite == 1) { 51 | totalWrites = atomic_increment_and_return(status); 52 | if(totalWrites == INVOKE_DETAILED_TRACKING) { 53 | allocCacheTrack(cindex); 54 | result = 1; 55 | } 56 | } 57 | } 58 | else { 59 | // Update the access counter and we only calling the callback when it is necessary 60 | unsigned long tracking = cacheTrackings[cindex]; 61 | if(tracking != 0) { 62 | unsigned long * access = (unsigned long *)(tracking); 63 | *access += 1; 64 | if(*access%SAMPLE_INTERVAL <= SAMPLE_ACCESSES_EACH_INTERVAL) { 65 | handleAccess(addr, typesize>>3, isWrite); 66 | } 67 | } 68 | } 69 | 70 | return 1; 71 | // printf("hihi, it is a test with result %d isWrite %d address %lx\n", result, isWrite, addr); 72 | } 73 | #ifdef __cplusplus 74 | }; /* end of extern "C" */ 75 | #endif 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /runtime/heaplayers/localmallocheap.h: -------------------------------------------------------------------------------- 1 | #ifndef _LOCALMALLOCHEAP_H_ 2 | #define _LOCALMALLOCHEAP_H_ 3 | 4 | #include 5 | 6 | #include "ansiwrapper.h" 7 | #include "sizeheap.h" 8 | #include "staticheap.h" 9 | 10 | extern "C" { 11 | size_t malloc_usable_size (void *); 12 | 13 | typedef void * mallocFunction (size_t); 14 | typedef void freeFunction (void *); 15 | typedef size_t msizeFunction (void *); 16 | 17 | typedef void exitFunction (int); 18 | exitFunction * trueExitFunction; 19 | } 20 | 21 | namespace HL { 22 | 23 | class LocalMallocHeap { 24 | public: 25 | 26 | LocalMallocHeap (void) 27 | : freefn (NULL), 28 | msizefn (NULL), 29 | mallocfn (NULL), 30 | firsttime (true) 31 | {} 32 | 33 | inline void * malloc (size_t sz) { 34 | if (firsttime) { 35 | 36 | firsttime = false; 37 | 38 | // We haven't initialized anything yet. 39 | // Initialize all of the malloc shim functions. 40 | 41 | freefn = (freeFunction *) dlsym (RTLD_NEXT, "free"); 42 | msizefn = (msizeFunction *) dlsym (RTLD_NEXT, "malloc_usable_size"); 43 | trueExitFunction = (exitFunction *) dlsym (RTLD_NEXT, "exit"); 44 | mallocfn = (mallocFunction *) dlsym (RTLD_NEXT, "malloc"); 45 | 46 | if (!(freefn && msizefn && trueExitFunction && mallocfn)) { 47 | fprintf (stderr, "Serious problem!\n"); 48 | abort(); 49 | } 50 | 51 | assert (freefn); 52 | assert (msizefn); 53 | assert (trueExitFunction); 54 | assert (mallocfn); 55 | 56 | // Go get some memory from malloc! 57 | return (*mallocfn)(sz); 58 | } 59 | 60 | // Now, once we have mallocfn resolved, we can use it. 61 | // Otherwise, we're still in dlsym-land, and have to use our local heap. 62 | 63 | if (mallocfn) { 64 | return (*mallocfn)(sz); 65 | } else { 66 | void * ptr = localHeap.malloc (sz); 67 | assert (ptr); 68 | return ptr; 69 | } 70 | } 71 | 72 | inline void free (void * ptr) { 73 | if (mallocfn) { 74 | if (localHeap.isValid (ptr)) { 75 | // We got a pointer to the temporary allocation buffer. 76 | localHeap.free (ptr); 77 | } else { 78 | (*freefn)(ptr); 79 | } 80 | } 81 | } 82 | 83 | inline size_t getSize (void * ptr) { 84 | if (localHeap.isValid (ptr)) { 85 | return localHeap.getSize (ptr); 86 | } else if (mallocfn) { 87 | return (*msizefn)(ptr); 88 | } else { 89 | // This should never happen. 90 | return 0; 91 | } 92 | } 93 | 94 | private: 95 | 96 | bool firsttime; /// True iff we haven't initialized the shim functions. 97 | 98 | // Shim functions below. 99 | 100 | freeFunction * freefn; 101 | msizeFunction * msizefn; 102 | mallocFunction * mallocfn; 103 | 104 | /// The local heap (for use while we are in dlsym, installing the 105 | /// shim functions). Hopefully 64K is enough... 106 | 107 | ANSIWrapper > > localHeap; 108 | 109 | }; 110 | 111 | } 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /runtime/finetime.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 University of Massachusetts Amherst. 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | /* 21 | * @file finetime.c 22 | * @brief Fine timing management based on rdtsc. 23 | * @author Ting Yang 24 | * @author Tongping Liu 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #include "finetime.h" 31 | double cpu_freq = 2327507.08008; // FIX ME What? 32 | 33 | void __get_time(struct timeinfo * ti) 34 | { 35 | unsigned int tlow, thigh; 36 | 37 | asm volatile ("rdtsc" 38 | : "=a"(tlow), 39 | "=d"(thigh)); 40 | 41 | ti->low = tlow; 42 | ti->high = thigh; 43 | } 44 | 45 | double __count_elapse(struct timeinfo * start, struct timeinfo * stop) 46 | { 47 | double elapsed = 0.0; 48 | 49 | elapsed = (double)(stop->low - start->low) + (double)(UINT_MAX)*(double)(stop->high - start->high); 50 | if (stop->low < start->low) 51 | elapsed -= (double)UINT_MAX; 52 | 53 | return elapsed; 54 | } 55 | 56 | double get_elapse (struct timeinfo * start, struct timeinfo * stop) 57 | { 58 | double elapse = 0.0; 59 | elapse = __count_elapse(start, stop); 60 | 61 | return elapse; 62 | } 63 | 64 | /* The following functions are exported to user application. Normally, a special case about using this file is like this. 65 | start(); 66 | ***** 67 | elapse = stop(); 68 | 69 | time = elapsed2us(); 70 | */ 71 | 72 | void start(struct timeinfo *ti) 73 | { 74 | /* Clear the start_ti and stop_ti */ 75 | __get_time(ti); 76 | return; 77 | } 78 | 79 | /* 80 | * Stop timing. 81 | */ 82 | double stop(struct timeinfo * begin, struct timeinfo * end) 83 | { 84 | double elapse = 0.0; 85 | struct timeinfo stop_ti; 86 | 87 | if (end == NULL) { 88 | __get_time(&stop_ti); 89 | elapse = get_elapse(begin, &stop_ti); 90 | } 91 | else { 92 | __get_time(end); 93 | elapse = get_elapse(begin, end); 94 | } 95 | 96 | return elapse; 97 | } 98 | 99 | /* Provide a function to turn the elapse time to microseconds. */ 100 | unsigned long elapsed2ms(double elapsed) 101 | { 102 | unsigned long ms; 103 | // ms =(unsigned long)(elapsed*1000000.0/cpu_freq); 104 | ms =(unsigned long)(elapsed/cpu_freq); 105 | return(ms); 106 | } 107 | -------------------------------------------------------------------------------- /runtime/heaplayers/chunkheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _CHUNKHEAP_H_ 4 | #define _CHUNKHEAP_H_ 5 | 6 | /* 7 | 8 | Heap Layers: An Extensible Memory Allocation Infrastructure 9 | 10 | Copyright (C) 2000-2003 by Emery Berger 11 | http://www.cs.umass.edu/~emery 12 | emery@cs.umass.edu 13 | 14 | This program is free software; you can redistribute it and/or modify 15 | it under the terms of the GNU General Public License as published by 16 | the Free Software Foundation; either version 2 of the License, or 17 | (at your option) any later version. 18 | 19 | This program is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License 25 | along with this program; if not, write to the Free Software 26 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 | 28 | */ 29 | 30 | #include 31 | 32 | /** 33 | * @class ChunkHeap 34 | * @brief Allocates memory from the superheap in chunks. 35 | * @param ChunkSize The minimum size for allocating memory from the superheap. 36 | */ 37 | 38 | namespace HL { 39 | 40 | template 41 | class ChunkHeap : public SuperHeap { 42 | public: 43 | 44 | inline ChunkHeap (void) 45 | : buffer (NULL), 46 | eob (NULL) 47 | {} 48 | 49 | inline void * malloc (const size_t sz) { 50 | void * ptr = buffer; 51 | buffer += sz; 52 | if (buffer <= eob) { 53 | assert (eob != NULL); 54 | assert ((size_t) (eob - (char *) ptr + 1) >= sz); 55 | return ptr; 56 | } 57 | buffer -= sz; // we didn't succeed, back up 58 | return getMoreMemory(sz); 59 | } 60 | 61 | inline void clear (void) { 62 | buffer = NULL; 63 | eob = NULL; 64 | SuperHeap::clear (); 65 | } 66 | 67 | private: 68 | 69 | // Disabled. 70 | inline int remove (void *); 71 | 72 | void * getMoreMemory (size_t sz) { 73 | assert (sz > 0); 74 | // Round sz to the next chunk size. 75 | size_t reqSize = (((sz-1) / ChunkSize) + 1) * ChunkSize; 76 | char * buf = (char *) SuperHeap::malloc (reqSize); 77 | if (buf == NULL) { 78 | return NULL; 79 | } 80 | // If the current end of buffer is not the same as the new buffer, 81 | // reset the buffer pointer. 82 | if (eob != buf) { 83 | buffer = buf; 84 | } 85 | else { 86 | // we still have a bit leftover at the end of previous buffer 87 | reqSize += eob - buffer; 88 | } 89 | eob = buffer + reqSize; 90 | 91 | void * ptr = buffer; 92 | buffer += sz; 93 | return ptr; 94 | } 95 | 96 | /// The current allocation buffer. 97 | char * buffer; 98 | 99 | /// The end of the buffer. 100 | char * eob; 101 | }; 102 | 103 | } 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /paper/PPoPP-2014/Makefile: -------------------------------------------------------------------------------- 1 | MAIN = main 2 | 3 | PDFLATEX = pdflatex -halt-on-error -interaction nonstopmode 4 | BIBTEX = bibtex 5 | PATCH = patch -p0 -t 6 | 7 | R ?= 78a25fcd17d0b310ba837d55fd62ed2dff0b1083 8 | # HEAD 9 | DIFF_DIR = .diff.$(R) 10 | OLDVERSION_DIR = .oldversion.$(R) 11 | CHANGES_FILE = .changes.$(R).diff 12 | 13 | SIDE_EFFECTS = $(MAIN).pdf $(MAIN).out $(MAIN).aux $(MAIN).bbl $(MAIN).blg $(MAIN).log diff.pdf \ 14 | $(wildcard diff.*) $(wildcard oldversion.*) $(wildcard changes.*) 15 | 16 | FILES = $(filter-out $(SIDE_EFFECTS), $(wildcard *)) 17 | TEX_FILES = $(wildcard *.tex) 18 | NONTEX_FILES = $(filter-out $(TEX_FILES), $(FILES)) 19 | 20 | OLD_FILES = $(addprefix $(OLDVERSION_DIR)/, $(FILES)) 21 | OLD_TEX_FILES = $(addprefix $(OLDVERSION_DIR/, $(TEX_FILES)) 22 | OLD_NONTEX_FILES = $(addprefix $(OLDVERSION_DIR/, $(NONTEX_FILES)) 23 | 24 | DIFF_FILES = $(addprefix $(DIFF_DIR)/, $(FILES)) 25 | DIFF_TEX_FILES = $(addprefix $(DIFF_DIR)/, $(TEX_FILES)) 26 | DIFF_NONTEX_FILES = $(addprefix $(DIFF_DIR)/, $(NONTEX_FILES)) 27 | 28 | all: $(MAIN).pdf $(MAIN).bbl 29 | 30 | clean: 31 | @rm -f $(MAIN).pdf $(MAIN).out $(MAIN).aux $(MAIN).bbl $(MAIN).blg $(MAIN).log 32 | @rm -rf diff.pdf .oldversion.* .diff.* .changes.* 33 | 34 | $(MAIN).pdf: $(wildcard *.tex) 35 | @echo "[MAIN] Running pdflatex" 36 | @$(PDFLATEX) $(MAIN).tex | tail 37 | 38 | $(MAIN).bbl: $(wildcard *.bib) 39 | @echo "[MAIN] Running bibtex" 40 | @$(BIBTEX) $(MAIN).aux 41 | 42 | @echo "[MAIN] Updating document references" 43 | @$(PDFLATEX) $(MAIN).tex > /dev/null 44 | @$(PDFLATEX) $(MAIN).tex > /dev/null 45 | 46 | diff: diff.pdf 47 | 48 | diff.pdf: $(DIFF_DIR)/$(MAIN).pdf $(DIFF_DIR)/$(MAIN).bbl 49 | @cp $(DIFF_DIR)/$(MAIN).pdf diff.pdf 50 | 51 | $(DIFF_DIR)/$(MAIN).pdf: $(DIFF_NONTEX_FILES) $(DIFF_DIR)/$(MAIN).tex 52 | @echo "[DIFF] Running pdflatex" 53 | @cd $(DIFF_DIR); $(PDFLATEX) $(MAIN).tex | tail 54 | 55 | $(DIFF_DIR)/$(MAIN).bbl: $(wildcard $(DIFF_DIR)/*.bib) 56 | @echo "[DIFF] Running bibtex" 57 | @cd $(DIFF_DIR); $(BIBTEX) $(MAIN).aux 58 | @echo "[DIFF] Updating document references" 59 | @cd $(DIFF_DIR); $(PDFLATEX) $(MAIN).tex > /dev/null 60 | @cd $(DIFF_DIR); $(PDFLATEX) $(MAIN).tex > /dev/null 61 | 62 | $(DIFF_DIR)/$(MAIN).tex: oldversion_dummy 63 | @echo "[DIFF] Running latexdiff" 64 | @mkdir -p $(DIFF_DIR) 65 | @latexdiff --flatten $(OLDVERSION_DIR)/$(MAIN).tex $(MAIN).tex > $@ 2> /dev/null 66 | 67 | $(DIFF_NONTEX_FILES): oldversion_dummy 68 | @echo "[DIFF] Copying $(notdir $@) to diff workspace" 69 | @mkdir -p $(DIFF_DIR) 70 | @cp -R $(notdir $@) $@ 71 | 72 | oldversion_dummy: $(CHANGES_FILE) 73 | @echo "[DIFF] Copying files to old version workspace" 74 | @mkdir -p $(OLDVERSION_DIR) 75 | @cp -R $(FILES) $(OLDVERSION_DIR)/ 76 | @echo "[DIFF] Applying changes to old version workspace" 77 | @$(PATCH) -R -d $(OLDVERSION_DIR) -i ../$(CHANGES_FILE) 78 | 79 | $(CHANGES_FILE): $(FILES) 80 | ifeq ($(R),HEAD) 81 | @echo "[DIFF] Using local checkout to compute changes" 82 | @git diff 78a25fcd17d0b310ba837d55fd62ed2dff0b1083 *.tex > $@ 83 | else 84 | @echo "[DIFF] Fetching changes from repository" 85 | @git diff $(R) > $@ 86 | endif 87 | -------------------------------------------------------------------------------- /runtime/heaplayers/utility.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _UTILITY_H_ 4 | #define _UTILITY_H_ 5 | 6 | /** 7 | * @file utility.h 8 | * @brief Convenient wrappers that let us new up & delete objects from heaps. 9 | * 10 | * 11 | * Example:
12 | * 13 | * 14 | * Heap h;
15 | *
16 | * Foo * foo;
17 | * newObject (foo,h); // instead of: foo = new Foo;
18 | * deleteObject (foo,h); // instead of: delete foo;
19 | *
20 | * Foo * foo2;
21 | * newArray (foo2, 10, h); // instead of: foo2 = new Foo[10];
22 | * deleteArray (foo2, h); // instead of: delete [] foo2;
23 | * 24 | */ 25 | 26 | #include 27 | 28 | 29 | // Construct an object on a given heap. 30 | class newObject { 31 | public: 32 | template 33 | inline void operator() (Object*& o, Heap& h) const { 34 | o = new (h.malloc (sizeof(Object))) Object; 35 | } 36 | 37 | template 38 | inline void operator() (Object*& o, const A1& a1, Heap& h) const { 39 | o = new (h.malloc (sizeof(Object))) Object (a1); 40 | } 41 | 42 | template 43 | inline void operator() (Object*& o, const A1& a1, const A2& a2, Heap& h) const { 44 | o = new (h.malloc (sizeof(Object))) Object (a1, a2); 45 | } 46 | 47 | template 48 | inline void operator() (Object*& o, const A1& a1, const A2& a2, const A3& a3, Heap& h) const { 49 | o = new (h.malloc (sizeof(Object))) Object (a1, a2, a3); 50 | } 51 | }; 52 | 53 | 54 | // Delete an object to a given heap. 55 | class deleteObject { 56 | public: 57 | template 58 | inline void operator()(Object*& o, Heap& h) { 59 | o->~Object(); 60 | h.free (o); 61 | } 62 | }; 63 | 64 | 65 | class newArray { 66 | public: 67 | template 68 | inline void operator() (Object*& o, unsigned int n, Heap& h) const { 69 | // Store the number of array elements in the beginning of the space. 70 | double * ptr = (double *) h.malloc (sizeof(Object) * n + sizeof(double)); 71 | *((unsigned int *) ptr) = n; 72 | // Initialize every element. 73 | ptr++; 74 | Object * ptr2 = (Object *) ptr; 75 | // Save the pointer to the start of the array. 76 | o = ptr2; 77 | // Now iterate and construct every object in place. 78 | for (unsigned int i = 0; i < n; i++) { 79 | new ((void *) ptr2) Object; 80 | ptr2++; 81 | } 82 | } 83 | }; 84 | 85 | 86 | class deleteArray { 87 | public: 88 | template 89 | inline void operator()(Object*& o, Heap& h) const { 90 | unsigned int n = *((unsigned int *) ((double *) o - 1)); 91 | Object * optr = o; 92 | // Call the destructor on every element in the array. 93 | for (unsigned int i = 0; i < n; i++) { 94 | optr->~Object(); 95 | optr++; 96 | } 97 | // Free the array. 98 | h.free ((void *) ((double *) o - 1)); 99 | } 100 | }; 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /runtime/heaplayers/slopheap.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2003 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | 28 | #ifndef _SLOPHEAP_H_ 29 | #define _SLOPHEAP_H_ 30 | 31 | /** 32 | * @class SlopHeap 33 | * 34 | * SlopHeap is designed to guarantee that you always have an extra N bytes 35 | * available after the most recent malloc. This is necessary for the current 36 | * coalescing support, which can look past the last allocated object. 37 | * 38 | * @param SuperHeap The parent heap. 39 | * @param SLOP The amount of extra memory required, in bytes. 40 | */ 41 | 42 | namespace HL { 43 | 44 | template 45 | class SlopHeap : public SuperHeap { 46 | public: 47 | SlopHeap (void) 48 | : remaining (0), 49 | ptr (NULL) 50 | {} 51 | 52 | inline void * malloc (const size_t nbytes) { 53 | 54 | // Put the usual case up front. 55 | if (nbytes <= remaining) { 56 | remaining -= nbytes; 57 | char * p = ptr; 58 | ptr += nbytes; 59 | return (void *) p; 60 | } 61 | 62 | // 63 | // We don't have enough space to satisfy the current 64 | // request, so get more memory. 65 | // 66 | 67 | return getMoreMemory(nbytes); 68 | } 69 | 70 | inline void clear (void) { 71 | ptr = NULL; 72 | remaining = 0; 73 | SuperHeap::clear (); 74 | } 75 | 76 | inline void free (void *) {} 77 | 78 | private: 79 | 80 | // Disabled. 81 | inline int remove (void *); 82 | 83 | void * getMoreMemory (size_t nbytes) { 84 | char * newptr = (char *) SuperHeap::malloc (nbytes + SLOP); 85 | 86 | if (newptr == NULL) { 87 | return NULL; 88 | } 89 | 90 | // 91 | // If this new memory is contiguous with the previous one, 92 | // reclaim the "slop". 93 | // 94 | 95 | if ((ptr != NULL) && (ptr + remaining + SLOP == newptr)) { 96 | remaining += SLOP; 97 | } else { 98 | ptr = newptr; 99 | remaining = 0; 100 | } 101 | char * p = ptr; 102 | ptr += nbytes; 103 | 104 | return (void *) p; 105 | } 106 | 107 | char * ptr; 108 | size_t remaining; 109 | 110 | }; 111 | 112 | } 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/multimalloc.h: -------------------------------------------------------------------------------- 1 | #ifndef _MULTIMALLOC_H_ 2 | #define _MULTIMALLOC_H_ 3 | 4 | #include 5 | 6 | #include 7 | 8 | 9 | #include "dynarray.h" 10 | #include "stack.h" 11 | 12 | 13 | template 14 | class MultiMalloc : public SuperHeap { 15 | public: 16 | 17 | 18 | MultiMalloc (void) { 19 | //f.open ("multimalloc.log"); 20 | } 21 | 22 | ~MultiMalloc (void) { 23 | //f.close (); 24 | } 25 | 26 | // Sets ptr to a list of up to num objects of size sz 27 | // and returns how many free objects ptr points to. 28 | int multimalloc (int num, size_t sz, void *& ptr) 29 | { 30 | //f << "multimalloc from " << this << endl << flush; 31 | // printf ("multimalloc\n"); 32 | assert (num > 0); 33 | if (stk.empty()) { 34 | #if 0 35 | //f << "malloc " << num << ", " << sz << "\n" << flush; 36 | ptr = SuperHeap::malloc (sz); 37 | assert (size(ptr) >= sz); 38 | assert (sz >= sizeof(FreeObject *)); 39 | FreeObject * p = (FreeObject *) ptr; 40 | for (int i = 1; i < num; i++) { 41 | p->next = (FreeObject *) SuperHeap::malloc (sz); 42 | p = p->next; 43 | assert (size(p) >= sz); 44 | } 45 | p->next = NULL; 46 | #else 47 | size_t sz1 = align(sz + sizeof(double)); 48 | ptr = SuperHeap::malloc (num * sz1); // Allow room for size & thread info. 49 | ptr = (double *) ptr + 1; 50 | FreeObject * p = (FreeObject *) ptr; 51 | for (int i = 0; i < num - 1; i++) { 52 | size(p) = sz; 53 | FreeObject * next = (FreeObject *) (((unsigned long) p) + sz1); 54 | p->next = next; 55 | p = p->next; 56 | } 57 | size(p) = sz; 58 | p->next = NULL; 59 | assert (size(p) + ((unsigned long) p) <= ((unsigned long) ptr + num * sz1)); 60 | #endif 61 | 62 | #ifndef NDEBUG 63 | p = (FreeObject *) ptr; 64 | int c = 0; 65 | while (p != NULL) { 66 | c++; 67 | p = p->next; 68 | } 69 | assert (c == num); 70 | #endif 71 | return num; 72 | } else { 73 | // Pop off some memory from the stack. 74 | assert (!stk.empty()); 75 | np v = stk.pop(); 76 | // JUST FOR CHECKING -- 77 | assert (v.num == num); 78 | ptr = v.ptr; 79 | assert (v.num > 0); 80 | assert (size(ptr) >= sz); 81 | //f << "multimalloc " << v.num << ", " << sz << "\n" << flush; 82 | return v.num; 83 | } 84 | } 85 | 86 | // Frees all num items pointed to by ptr. 87 | void multifree (int num, void * ptr) 88 | { 89 | // printf ("multifree\n"); 90 | np v; 91 | //f << "multifree " << num << ", size = " << size(ptr) << "\n" << flush; 92 | v.num = num; 93 | v.ptr = ptr; 94 | stk.push (v); 95 | } 96 | 97 | private: 98 | 99 | MultiMalloc (const MultiMalloc&); 100 | MultiMalloc& operator=(const MultiMalloc&); 101 | 102 | class np { 103 | public: 104 | int num; 105 | void * ptr; 106 | }; 107 | 108 | class FreeObject { 109 | public: 110 | FreeObject * next; 111 | }; 112 | 113 | void * malloc (size_t); 114 | void free (void *); 115 | 116 | Stack > stk; 117 | //ofstream f; 118 | 119 | static inline size_t align (size_t sz) { 120 | return (sz + (sizeof(double) - 1)) & ~(sizeof(double) - 1); 121 | } 122 | 123 | }; 124 | 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /runtime/cacheinfo.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | */ 19 | 20 | /* 21 | * @file cacheinfo.h 22 | * @brief Detailed information about read/write access on specified cache. 23 | * @author Tongping Liu 24 | */ 25 | 26 | 27 | #ifndef _CACHEINFO_H_ 28 | #define _CACHEINFO_H_ 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #if !defined(_WIN32) 35 | #include 36 | #include 37 | #include 38 | #endif 39 | 40 | #include //sort 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include "xdefines.h" 47 | #include "cachehistogram.h" 48 | 49 | using namespace std; 50 | 51 | class cacheinfo { 52 | public: 53 | cacheinfo() 54 | { 55 | 56 | } 57 | 58 | ~cacheinfo (void) { 59 | } 60 | 61 | void initialize(void * start, size_t sz) { 62 | if(start == NULL) { 63 | assert(0); 64 | } 65 | 66 | _cacheStart = (char *)start; 67 | _cacheEnd = _cacheStart + sz; 68 | 69 | // See explanation of cachehistogram. 70 | // we want to avoid the checking of empty table 71 | // so it is possible that eery cache line will have invalidation 72 | // even it is not happening. 73 | _invalidations = -1; 74 | _histogram.init(); 75 | } 76 | 77 | // Check the cache line level's invalidation 78 | bool handleAccess(int tindex, char * addr, eAccessType type) { 79 | bool reportFalseSharing = false; 80 | 81 | // In the prediction, cacheStart and cacheEnd is not irregular 82 | // we only update corresponding cache line. 83 | if(addr >= _cacheStart && addr <= _cacheEnd) { 84 | if(_histogram.updateHistogram(tindex, type)) { 85 | // fprintf(stderr, "handleAccess invalidations %p at cacheline %p\n", _invalidations, _cacheStart); 86 | if(_invalidations != 0 && _invalidations%1000 == 0) { 87 | reportFalseSharing = true; 88 | } 89 | _invalidations++; 90 | } 91 | } 92 | 93 | return reportFalseSharing; 94 | } 95 | 96 | long invalidations(void) { 97 | return _invalidations; 98 | } 99 | 100 | char * getCacheStart(void) { 101 | return _cacheStart; 102 | } 103 | 104 | private: 105 | // How many invalidations happens in this cache line. 106 | //unsigned long _invalidations; 107 | long _invalidations; 108 | cachehistogram _histogram; 109 | char * _cacheStart; 110 | char * _cacheEnd; 111 | }; 112 | 113 | #endif 114 | 115 | -------------------------------------------------------------------------------- /runtime/heaplayers/experimental/batchheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _BATCHHEAP_H_ 4 | #define _BATCHHEAP_H_ 5 | 6 | #include 7 | 8 | 9 | template 10 | class MultiMalloc : public SuperHeap { 11 | public: 12 | // Sets ptr to a list of up to num objects of size sz 13 | // and returns how many free objects ptr points to. 14 | int multimalloc (int num, size_t sz, void *& ptr) 15 | { 16 | int i = 0; 17 | ptr = (freeObject *) SuperHeap::malloc (sz); 18 | freeObject * p = (freeObject *) ptr; 19 | if (ptr != NULL) { 20 | for (i = 1; i < num; i++) { 21 | p->next = (freeObject *) SuperHeap::malloc (sz); 22 | if (p->next == NULL) 23 | break; 24 | p = p->next; 25 | } 26 | p->next = NULL; 27 | } 28 | return i; 29 | } 30 | 31 | // Frees all num items pointed to by ptr 32 | // and sets ptr to NULL. 33 | void multifree (int num, void *& ptr) 34 | { 35 | freeObject * p; 36 | freeObject * prev = (freeObject *) ptr; 37 | for (int i = 0; i < num; i++) { 38 | p = prev->next; 39 | SuperHeap::free (prev); 40 | prev = p; 41 | } 42 | ptr = NULL; 43 | } 44 | 45 | private: 46 | 47 | class freeObject { 48 | public: 49 | freeObject * next; 50 | }; 51 | 52 | 53 | }; 54 | 55 | 56 | template 57 | class BatchHeap : public SuperHeap { 58 | public: 59 | 60 | BatchHeap (void) 61 | : nObjects (0) 62 | { 63 | freeList[0] = NULL; 64 | freeList[1] = NULL; 65 | } 66 | 67 | 68 | ~BatchHeap (void) { 69 | if (nObjects <= BatchNumber) { 70 | SuperHeap::multifree (nObjects, (void *&) freeList[0]); 71 | } else { 72 | SuperHeap::multifree (BatchNumber, (void *&) freeList[0]); 73 | SuperHeap::multifree (nObjects - BatchNumber, (void *&) freeList[1]); 74 | } 75 | } 76 | 77 | inline void * malloc (size_t sz) { 78 | if (nObjects == 0) { 79 | // Obtain BatchNumber objects if we're out. 80 | nObjects = SuperHeap::multimalloc (BatchNumber, sz, (void *&) freeList[0]); 81 | } 82 | assert (nObjects >= 1); 83 | freeObject * ptr; 84 | if (nObjects > BatchNumber) { 85 | freeObject *& head = freeList[1]; 86 | ptr = head; 87 | nObjects--; 88 | head = head->next; 89 | return (void *) ptr; 90 | } else { 91 | freeObject *& head = freeList[0]; 92 | ptr = head; 93 | nObjects--; 94 | head = head->next; 95 | return (void *) ptr; 96 | } 97 | } 98 | 99 | inline void free (void * ptr) { 100 | if (nObjects <= BatchNumber) { 101 | freeObject *& head = freeList[0]; 102 | ((freeObject *) ptr)->next = head; 103 | head = (freeObject *) ptr; 104 | } else { 105 | freeObject *& head = freeList[1]; 106 | ((freeObject *) ptr)->next = head; 107 | head = (freeObject *) ptr; 108 | } 109 | nObjects++; 110 | if (nObjects == 2 * BatchNumber) { 111 | // Free half of them. 112 | assert (freeList[1] != NULL); 113 | SuperHeap::multifree (BatchNumber, (void *&) freeList[1]); 114 | } 115 | } 116 | 117 | private: 118 | 119 | class freeObject { 120 | public: 121 | freeObject * next; 122 | }; 123 | 124 | int nObjects; 125 | 126 | // The first free list holds the first BatchNumber objects, 127 | // while the second free list holds the rest. 128 | freeObject * freeList[2]; 129 | }; 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /paper/PPoPP-2014/discuss.tex: -------------------------------------------------------------------------------- 1 | \label{sec:discussion} 2 | 3 | \subsection{Instrumentation Selection} 4 | \label{sec:instrumentationtradeoff} 5 | Dynamic binary instrumentation and compiler-based instrumentation are two alternative approaches for performing instrumentation~\cite{Instrumentation}. They exhibit different tradeoffs of performance and generality. Dynamic binary instrumentors, such as Valgrind~\cite{Valgrind}, Pin~\cite{Pin}, and DynamoRIO~\cite{DynamoRIO}, typically analyze the program's code just before execution in order to insert instrumentation. They introduce significant performance overhead, mostly caused by run-time encoding and decoding, but the fact that they operate directly on binaries makes them extremely convenient. By contrast, compiler instrumentation inserts instrumentation in the compilation phase, which requires re-compilation of all source code. 6 | \Predator{} employs compiler-based instrumentation both because of its better performance and its greater flexibility, as discussed in Section~\ref{sec:selectinstrumentation}. 7 | 8 | \subsection{Effectiveness} 9 | Several factors can affect \Predator{}'s ability to identify false sharing. 10 | 11 | \begin{figure}[!t] 12 | \centering 13 | \includegraphics[width=3.4in]{fig/sample} 14 | %\includegraphics{fig/potential.pdf} 15 | \caption{Sampling rate sensitivity (execution time).} 16 | \label{fig:sample} 17 | \end{figure} 18 | 19 | \paragraph{Different Inputs.} Different inputs trigger distinct executions of a program. If a specific input does not exercise the code with false sharing problems, \Predator{} cannot necessarily detect them. However, \Predator{} does generalize over inputs to find latent false sharing problems on those exercised code. When any reasonably representative set of inputs are exercised, as is required by any testing regime, \Predator{} can effectively predict false sharing. 20 | 21 | \paragraph{Input Size.} Input size may affect detection results. As discussed in Section~\ref{optimization}, \Predator{} introduces several threshold values to reduce tracking overhead, which can be adjusted as needed. If the input size is so small that it cannot generate enough false sharing events to cross the predefined thresholds, then the detection mechanism will not be triggered. In such cases, \Predator{} will miss actual cases of false sharing. However, realistically large inputs should be enough to trigger \Predator{}'s detection mechanisms. In our experience, running applications for at least 150 seconds is sufficient to expose false sharing problems. 22 | 23 | \paragraph{Hardware Independence.} \Predator{}'s compiler-based approach make it independent of the underlying hardware platform. This approach increases generality, but may lead it to over-report false sharing. \Predator{} conservatively assumes that different threads are running on different cores and detects false sharing problems based on possible cache invalidations. However, if multiple threads involved in false sharing are on the same core, then there will be no performance impact. 24 | 25 | %\subsection{Prediction Limitations} 26 | %\Predator{} can accurately and precisely predict a false sharing problem even when it does not occur. But \Predator{} cannot predict a false sharing problem if the code with false sharing is not exercised at all. Also, \Predator{} may miss potential false sharing problems between two objects brought by a different compiler or memory allocator. 27 | -------------------------------------------------------------------------------- /runtime/xrun.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | Author: Emery Berger, http://www.cs.umass.edu/~emery 5 | 6 | Copyright (c) 2007-12 Emery Berger, University of Massachusetts Amherst. 7 | 8 | This program is free software; you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation; either version 2 of the License, or 11 | (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 | 22 | */ 23 | 24 | /* 25 | * @file xrun.h 26 | * @brief The main engine for consistency management, etc. 27 | * @author Emery Berger 28 | * @author Tongping Liu 29 | */ 30 | 31 | #ifndef SHERIFF_XRUN_H 32 | #define SHERIFF_XRUN_H 33 | 34 | #include "xdefines.h" 35 | #include "xthread.h" 36 | 37 | // memory 38 | #include "xmemory.h" 39 | #include "internalheap.h" 40 | 41 | // Grace utilities 42 | #include "atomic.h" 43 | 44 | class xrun { 45 | 46 | private: 47 | 48 | xrun() 49 | : _memory (xmemory::getInstance()) 50 | { 51 | } 52 | 53 | public: 54 | 55 | static xrun& getInstance() { 56 | static char buf[sizeof(xrun)]; 57 | static xrun * theOneTrueObject = new (buf) xrun(); 58 | 59 | return *theOneTrueObject; 60 | } 61 | 62 | /// @brief Initialize the system. 63 | void initialize() 64 | { 65 | installSignalHandler(); 66 | InternalHeap::getInstance().initialize(); 67 | xthread::getInstance().initialize(); 68 | // Initialize the memory (install the memory handler) 69 | _memory.initialize(); 70 | // fprintf(stderr, "in the init of xrun, finishing xmemoy\n"); 71 | } 72 | 73 | void finalize (void) 74 | { 75 | fprintf(stderr, "Finalizing, check the false sharing problem now.\n"); 76 | // If the tid was set, it means that this instance was 77 | // initialized: end the transaction (at the end of main()). 78 | _memory.finalize(); 79 | } 80 | 81 | /// @brief Install a handler for KILL signals. 82 | void installSignalHandler() { 83 | // Now set up a signal handler for SIGINT events. 84 | struct sigaction siga; 85 | 86 | // Point to the handler function. 87 | //siga.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART | SA_NODEFER; 88 | siga.sa_flags = SA_RESTART | SA_NODEFER; 89 | //fprintf(stderr, "install signale handler %d\n", __LINE__); 90 | 91 | siga.sa_handler = xmemory::sigHandler; 92 | if (sigaction(SIGINT, &siga, NULL) == -1) { 93 | perror ("installing SIGINT failed\n"); 94 | exit (-1); 95 | } 96 | #ifdef USING_SIGUSR2 97 | if (sigaction(SIGUSR2, &siga, NULL) == -1) { 98 | perror ("installing SIGINT failed\n"); 99 | exit (-1); 100 | } 101 | #endif 102 | } 103 | 104 | private: 105 | 106 | int _tid; 107 | 108 | /// The memory manager (for both heap and globals). 109 | xmemory& _memory; 110 | }; 111 | 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /runtime/handleAccess.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define ATOMIC_INCREMENT_AND_RETURN 9 | #define THRESHOLD_TRACK_DETAILS (10000) 10 | #define INVOKE_DETAILED_TRACKING (THRESHOLD_TRACK_DETAILS-1) 11 | #define MAX_USER_SPACE (0x240000000) 12 | #define CACHE_STATUS_BASE (0x200000000000) 13 | #define CACHE_TRACKING_BASE (0x200080000000) 14 | #define SAMPLE_ACCESSES_EACH_INTERVAL THRESHOLD_TRACK_DETAILS 15 | #define SAMPLE_INTERVAL (100 * SAMPLE_ACCESSES_EACH_INTERVAL) 16 | 17 | // There are 3 cases of handle accesses: 18 | // 1. 0 - do nothing 19 | // 2. 1 - call 20 | extern void allocCacheTrack(unsigned long index); 21 | extern void handleAccess(unsigned long addr, unsigned long size, int isWrite); 22 | //extern __attribute__ ((always_inline)) inline unsigned long atomic_increment_and_return(volatile unsigned long * obj); 23 | //extern __attribute__ ((always_inline)) inline int handleAccessBefore(unsigned long addr, int isWrite, int typesize); 24 | // __attribute__ ((weak)); 25 | //__attribute__ ((always_inline)) inline unsigned long atomic_increment_and_return(volatile unsigned long * obj) { 26 | //__attribute__ ((always_inline)) 27 | inline unsigned long atomic_increment_and_return(volatile unsigned long * obj) { 28 | unsigned long i = 1; 29 | asm volatile("lock; xadd %0, %1" 30 | : "+r" (i), "+m" (*obj) 31 | : : "memory"); 32 | return i; 33 | } 34 | 35 | void handleAccessBefore(unsigned long addr, int isWrite, int typesize); 36 | 37 | //__attribute__ ((always_inline)) 38 | inline void handleAccessBefore(unsigned long addr, int isWrite, int typesize) { 39 | // We only care those acesses of global and heap. 40 | if(addr > MAX_USER_SPACE) { 41 | return; 42 | } 43 | 44 | //if(isWrite == 1) 45 | //printf("handleAccessBefore: addr %lx isWRite %d typeSize %d\n", addr, isWrite, typesize); 46 | 47 | unsigned long cindex = addr >> 6; 48 | unsigned long * cacheWrites = (unsigned long *)CACHE_STATUS_BASE; 49 | unsigned long * cacheTrackings = (unsigned long *)CACHE_TRACKING_BASE; 50 | 51 | unsigned long * status = (unsigned long *)&cacheWrites[cindex]; 52 | unsigned long totalWrites = *status; 53 | if(totalWrites < THRESHOLD_TRACK_DETAILS) { 54 | // Only update writes 55 | if(isWrite == 1) { 56 | totalWrites = 1; 57 | asm volatile("lock; xadd %0, %1" 58 | : "+r" (totalWrites), "+m" (*status) 59 | : : "memory"); 60 | // totalWrites = atomic_increment_and_return(status); 61 | if(totalWrites == INVOKE_DETAILED_TRACKING) { 62 | // fprintf(stderr, "totalWrites %ld at addr %lx allocCacheTrack. index %ld\n", totalWrites, addr, cindex); 63 | allocCacheTrack(cindex); 64 | } 65 | } 66 | } 67 | else { 68 | // Update the access counter and we only calling the callback when it is necessary 69 | unsigned long tracking = cacheTrackings[cindex]; 70 | if(tracking != 0) { 71 | unsigned long * access = (unsigned long *)(tracking); 72 | *access += 1; 73 | //fprintf(stderr, "Address %lx Access address %p\n", addr, access); 74 | if(*access%SAMPLE_INTERVAL <= SAMPLE_ACCESSES_EACH_INTERVAL) { 75 | handleAccess(addr, typesize, isWrite); 76 | } 77 | } 78 | } 79 | 80 | return; 81 | // printf("hihi, it is a test with result %d isWrite %d address %lx\n", result, isWrite, addr); 82 | } 83 | #ifdef __cplusplus 84 | }; /* end of extern "C" */ 85 | #endif 86 | 87 | -------------------------------------------------------------------------------- /runtime/heaplayers/sbrk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Sbrk implementation for Win32 by Emery Berger, http://www.cs.utexas.edu/users/emery */ 6 | 7 | void * sbrk (long size) { 8 | 9 | /* Reserve up to 1 GB of RAM */ 10 | /* 11 | We pre-reserve a very large chunk of memory 12 | and commit pages as we go. */ 13 | 14 | #define PRE_RESERVE 1024 * 1024 * 1024 15 | 16 | static long remainingReserved = PRE_RESERVE; 17 | 18 | static int initialized = 0; 19 | static char * currentPosition = NULL; 20 | static char * nextPage = NULL; 21 | static long remainingCommitted = 0; 22 | static long pageSize; 23 | void * p; 24 | 25 | if (!initialized) { 26 | 27 | /* 28 | Do one-time initialization stuff: 29 | get the page size from the system, 30 | reserve a large range of memory, 31 | and initialize the appropriate variables. 32 | 33 | */ 34 | 35 | SYSTEM_INFO sSysInfo; 36 | LPVOID base; 37 | GetSystemInfo(&sSysInfo); 38 | 39 | pageSize = sSysInfo.dwPageSize; 40 | 41 | /* Reserve pages in the process's virtual address space. */ 42 | 43 | #if 1 44 | base = VirtualAlloc(NULL, remainingReserved, MEM_RESERVE, PAGE_NOACCESS); 45 | #else 46 | base = VirtualAlloc(NULL, remainingReserved, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 47 | remainingCommitted = PRE_RESERVE; 48 | #endif 49 | 50 | if (base == NULL ) 51 | exit (1); /* VirtualAlloc reserve failed */ 52 | 53 | currentPosition = nextPage = (char *) base; 54 | initialized = 1; 55 | } 56 | 57 | if (size < 0) { 58 | 59 | #if 0 60 | /* Uncommit pages if possible. 61 | Round the size down to a multiple of the page size, 62 | and decommit those pages. 63 | */ 64 | 65 | 66 | int bytesToUncommit = (-size & ~(pageSize - 1)); 67 | 68 | if (bytesToUncommit > PRE_RESERVE - remainingReserved) { 69 | /* Error -- the user has tried to free memory that we never 70 | even reserved. */ 71 | return currentPosition; 72 | } 73 | 74 | if (bytesToUncommit > 0) { 75 | 76 | int result = VirtualFree (nextPage - bytesToUncommit, bytesToUncommit, MEM_DECOMMIT); 77 | if (result == 0) { 78 | /* Error -- don't change a thing. */ 79 | return currentPosition; 80 | } 81 | remainingCommitted -= bytesToUncommit; 82 | } 83 | 84 | currentPosition -= size; 85 | remainingReserved += size; 86 | #endif 87 | return currentPosition; 88 | 89 | } 90 | 91 | if (size > 0) { 92 | void * p; 93 | if (size > remainingCommitted) { 94 | 95 | /* Commit some more pages. 96 | We round up to an even number of pages. 97 | Note that page size must be a power of two. 98 | */ 99 | 100 | int bytesToCommit = (size - remainingCommitted + pageSize - 1) & ~(pageSize - 1); 101 | int * result; 102 | 103 | result = VirtualAlloc((LPVOID) nextPage, bytesToCommit, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 104 | 105 | if (result == NULL ) 106 | exit (1); /* VirtualAlloc commit failed */ 107 | 108 | nextPage += bytesToCommit; 109 | remainingCommitted += bytesToCommit; 110 | } 111 | 112 | p = currentPosition; 113 | currentPosition += size; 114 | remainingCommitted -= size; 115 | remainingReserved -= size; 116 | return p; 117 | } 118 | 119 | assert (size == 0); 120 | return currentPosition; 121 | 122 | } 123 | -------------------------------------------------------------------------------- /runtime/bigheap.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | Copyright (c) 2011, University of Massachusetts Amherst. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; either version 2 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | 20 | */ 21 | 22 | /* 23 | * @file xpheap.h 24 | * @brief A heap optimized to reduce the likelihood of false sharing. 25 | * @author Tongping Liu 26 | */ 27 | 28 | #ifndef _BIGHEAP_H_ 29 | #define _BIGHEAP_H_ 30 | 31 | #include "kingsleyheap.h" 32 | #include "objectheader.h" 33 | #include "xdefines.h" 34 | 35 | typedef struct { 36 | // Blocks in this size class. 37 | int index; 38 | void * blocks[xdefines::NUM_HEAPS]; 39 | } bigHeapClass; 40 | 41 | class bigheap 42 | { 43 | 44 | public: 45 | bigheap() { 46 | } 47 | 48 | /// @brief Initialize the system. 49 | void initialize() 50 | { 51 | _totalBlocks = xdefines::MAX_THREADS; 52 | _totalClasses = xdefines::BIG_HEAP_SIZE_CLASSES; 53 | _minSize = xdefines::BIG_HEAP_CHUNK_SIZE; 54 | 55 | pthread_mutex_init(&_lock, NULL); 56 | 57 | for(int i = 0; i < _totalClasses; i++) { 58 | _classes[i].index = 0; 59 | } 60 | } 61 | 62 | // Get size classes 63 | size_t getSizeClass(size_t sz) { 64 | size_t thisClass = Kingsley::size2Class(sz)-17; 65 | //printf("thisClass is %d\n", thisClass); 66 | assert(thisClass < _totalClasses); 67 | return thisClass; 68 | } 69 | 70 | // Record this entry. It can be failed if the cache is full. 71 | bool free(void * ptr, size_t sz) { 72 | bool result = false; 73 | size_t sizeclass = getSizeClass(sz); 74 | bigHeapClass * myClass = &_classes[sizeclass]; 75 | 76 | global_lock(); 77 | 78 | if(myClass->index < _totalBlocks) { 79 | myClass->blocks[myClass->index] = ptr; 80 | result = true; 81 | myClass->index++; 82 | } 83 | 84 | global_unlock(); 85 | 86 | return result; 87 | } 88 | 89 | // Allocate a thread index under the protection of global lock 90 | void * malloc(size_t size) { 91 | void * ptr = NULL; 92 | 93 | size_t sizeclass = getSizeClass(size); 94 | bigHeapClass * myClass = &_classes[sizeclass]; 95 | 96 | global_lock(); 97 | 98 | if(myClass->index > 0) { 99 | ptr = myClass->blocks[--myClass->index]; 100 | } 101 | 102 | global_unlock(); 103 | return ptr; 104 | } 105 | 106 | 107 | private: 108 | /// @brief Lock the lock. 109 | void global_lock(void) { 110 | pthread_mutex_lock(&_lock); 111 | } 112 | 113 | /// @brief Unlock the lock. 114 | void global_unlock(void) { 115 | pthread_mutex_unlock(&_lock); 116 | } 117 | 118 | // fprintf(stderr, "remove thread %p with thread index %d\n", thread, thread->index); 119 | pthread_mutex_t _lock; 120 | size_t _totalBlocks; 121 | size_t _totalClasses; 122 | size_t _minSize; 123 | bigHeapClass _classes[xdefines::BIG_HEAP_SIZE_CLASSES]; 124 | }; 125 | 126 | #endif // _BIGHEAP_H_ 127 | 128 | 129 | -------------------------------------------------------------------------------- /runtime/heaplayers/kingsleyheap.h: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | 3 | /* 4 | 5 | Heap Layers: An Extensible Memory Allocation Infrastructure 6 | 7 | Copyright (C) 2000-2003 by Emery Berger 8 | http://www.cs.umass.edu/~emery 9 | emery@cs.umass.edu 10 | 11 | This program is free software; you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation; either version 2 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program; if not, write to the Free Software 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | */ 26 | 27 | #ifndef _KINGSLEYHEAP_H_ 28 | #define _KINGSLEYHEAP_H_ 29 | 30 | #include "segheap.h" 31 | 32 | /** 33 | * @file kingsleyheap.h 34 | * @brief Classes to implement a Kingsley (power-of-two, segregated fits) allocator. 35 | */ 36 | 37 | /** 38 | * @namespace Kingsley 39 | * @brief Functions to implement KingsleyHeap. 40 | */ 41 | 42 | 43 | 44 | namespace Kingsley { 45 | 46 | size_t class2Size (const int i); 47 | 48 | #if defined(__sparc) && defined(__GNUC__) 49 | inline int popc (int v) { 50 | int r; 51 | asm volatile ("popc %1, %0" 52 | : "=r" (r) 53 | : "r" (v)); 54 | return r; 55 | } 56 | #endif 57 | 58 | /** 59 | * A speed optimization: 60 | * we use this array to quickly return the size class of objects 61 | * from 8 to 128 bytes. 62 | */ 63 | const int cl[16] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 }; 64 | 65 | inline int size2Class (size_t sz) { 66 | #if defined(__sparc) && defined(__GNUC__) 67 | // Adapted from _Hacker's Delight_, by Henry Warren (p.80) 68 | size_t x = sz; 69 | x = x | (x >> 1); 70 | x = x | (x >> 2); 71 | x = x | (x >> 4); 72 | x = x | (x >> 8); 73 | x = x | (x >> 16); 74 | return popc(x) - 3; 75 | #else 76 | if (sz < sizeof(double)) { 77 | sz = sizeof(double); 78 | } 79 | if (sz <= 128 ) { 80 | int index = (sz - 1) >> 3; 81 | int c = cl[index]; 82 | assert (class2Size(c) >= sz); 83 | return c; 84 | } else { 85 | // 86 | // We know that the object is more than 128 bytes long, 87 | // so we can avoid iterating 5 times. 88 | // 89 | int c = 5; 90 | size_t sz1 = ((sz - 1) >> 5); 91 | while (sz1 > 7) { 92 | sz1 >>= 1; 93 | c++; 94 | } 95 | assert (class2Size(c) >= sz); 96 | return c; 97 | } 98 | #endif 99 | 100 | } 101 | 102 | inline size_t class2Size (const int i) { 103 | return (size_t) (1UL << (i+3)); 104 | } 105 | 106 | enum { NUMBINS = 29 }; 107 | 108 | }; 109 | 110 | /** 111 | * @class KingsleyHeap 112 | * @brief The Kingsley-style allocator. 113 | * @param PerClassHeap The heap to use for each size class. 114 | * @param BigHeap The heap for "large" objects. 115 | * @see Kingsley 116 | */ 117 | 118 | namespace HL { 119 | 120 | template 121 | class KingsleyHeap : 122 | public StrictSegHeap {}; 127 | 128 | }; 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /runtime/heaplayers/threadheap.h: -------------------------------------------------------------------------------- 1 | /* -*- C++ -*- */ 2 | 3 | #ifndef _THREADHEAP_H_ 4 | #define _THREADHEAP_H_ 5 | 6 | #include 7 | #include 8 | 9 | #if !defined(_WIN32) 10 | #include 11 | #endif 12 | 13 | #if defined(__SVR4) // Solaris 14 | extern "C" unsigned int lwp_self(void); 15 | #endif 16 | 17 | /* 18 | 19 | A ThreadHeap comprises NumHeaps "per-thread" heaps. 20 | 21 | To pick a per-thread heap, the current thread id is hashed (mod NumHeaps). 22 | 23 | malloc gets memory from its hashed per-thread heap. 24 | free returns memory to its hashed per-thread heap. 25 | 26 | (This allows the per-thread heap to determine the return 27 | policy -- 'pure private heaps', 'private heaps with ownership', 28 | etc.) 29 | 30 | NB: We assume that the thread heaps are 'locked' as needed. */ 31 | 32 | namespace HL { 33 | 34 | template 35 | class ThreadHeap : public PerThreadHeap { 36 | public: 37 | 38 | inline void * malloc (size_t sz) { 39 | int tid = getThreadId() % NumHeaps; 40 | assert (tid >= 0); 41 | assert (tid < NumHeaps); 42 | return getHeap(tid)->malloc (sz); 43 | } 44 | 45 | inline void free (void * ptr) { 46 | int tid = getThreadId() % NumHeaps; 47 | assert (tid >= 0); 48 | assert (tid < NumHeaps); 49 | getHeap(tid)->free (ptr); 50 | } 51 | 52 | inline size_t getSize (void * ptr) { 53 | int tid = getThreadId() % NumHeaps; 54 | assert (tid >= 0); 55 | assert (tid < NumHeaps); 56 | return getHeap(tid)->getSize (ptr); 57 | } 58 | 59 | 60 | private: 61 | 62 | // Access the given heap within the buffer. 63 | inline PerThreadHeap * getHeap (int index) { 64 | assert (index >= 0); 65 | assert (index < NumHeaps); 66 | return &ptHeaps[index]; 67 | } 68 | 69 | // Get a suitable thread id number. 70 | inline static volatile int getThreadId (void); 71 | 72 | PerThreadHeap ptHeaps[NumHeaps]; 73 | 74 | }; 75 | 76 | } 77 | 78 | 79 | // A platform-dependent way to get a thread id. 80 | 81 | // Include the necessary platform-dependent crud. 82 | #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) 83 | #ifndef WIN32 84 | #define WIN32 1 85 | #endif 86 | #include 87 | #include 88 | #endif 89 | 90 | template 91 | inline volatile int 92 | HL::ThreadHeap::getThreadId (void) { 93 | #if defined(WIN32) 94 | // It looks like thread id's are always multiples of 4, so... 95 | int tid = GetCurrentThreadId() >> 2; 96 | // Now hash in some of the first bits. 97 | // return (tid & ~(1024-1)) ^ tid; 98 | return tid; 99 | #endif 100 | #if defined(__BEOS__) 101 | return find_thread(0); 102 | #endif 103 | #if defined(__linux) 104 | // Consecutive thread id's in Linux are 1024 apart; 105 | // dividing off the 1024 gives us an appropriate thread id. 106 | return (int) pthread_self() >> 10; // (>> 10 = / 1024) 107 | #endif 108 | #if defined(__SVR4) 109 | // printf ("lwp_self = %d\n", (int) lwp_self()); 110 | return (int) lwp_self(); 111 | #endif 112 | #if defined(__APPLE__) 113 | return (int) pthread_self(); 114 | #endif 115 | #if defined(POSIX) 116 | return (int) pthread_self(); 117 | #endif 118 | #if USE_SPROC 119 | // This hairiness has the same effect as calling getpid(), 120 | // but it's MUCH faster since it avoids making a system call 121 | // and just accesses the sproc-local data directly. 122 | int pid = (int) PRDA->sys_prda.prda_sys.t_pid; 123 | return pid; 124 | #endif 125 | } 126 | 127 | 128 | #endif 129 | --------------------------------------------------------------------------------