[8735] New memory allocator for MaNGOS, based on Intel Threading Building Blocks library. Performance gains depend greatly on OS you use!

You should add two libraries into your server binaries:
tbb.so/tbbmalloc.so on *nix and tbb(_debug).dll/tbbmalloc(_debug).dll on Windows!!!

Define USE_STANDARD_MALLOC while compiling 'framework' project to use OS' default memory allocator!

Signed-off-by: Ambal <pogrebniak@gala.net>
This commit is contained in:
Ambal 2009-10-26 00:58:55 +02:00
parent 9e4b833054
commit a2ed351365
235 changed files with 52785 additions and 432 deletions

View file

@ -0,0 +1,120 @@
/*
Copyright 2005-2009 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks.
Threading Building Blocks is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
Threading Building Blocks is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Threading Building Blocks; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
As a special exception, you may use this file as part of a free software
library without restriction. Specifically, if other files instantiate
templates or use macros or inline functions from this file, or you compile
this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered by
the GNU General Public License.
*/
#ifndef _TBB_malloc_Customize_H_
#define _TBB_malloc_Customize_H_
/* Thread shutdown notification callback */
/* redefine the name of the callback to meet TBB requirements
for externally visible names of service functions */
#define mallocThreadShutdownNotification __TBB_mallocThreadShutdownNotification
#define mallocProcessShutdownNotification __TBB_mallocProcessShutdownNotification
extern "C" void mallocThreadShutdownNotification(void *);
extern "C" void mallocProcessShutdownNotification(void);
// customizing MALLOC_ASSERT macro
#include "tbb/tbb_stddef.h"
#define MALLOC_ASSERT(assertion, message) __TBB_ASSERT(assertion, message)
#ifndef MALLOC_DEBUG
#define MALLOC_DEBUG TBB_USE_DEBUG
#endif
#include "tbb/tbb_machine.h"
#if DO_ITT_NOTIFY
#include "tbb/itt_notify.h"
#define MALLOC_ITT_SYNC_PREPARE(pointer) ITT_NOTIFY(sync_prepare, (pointer))
#define MALLOC_ITT_SYNC_ACQUIRED(pointer) ITT_NOTIFY(sync_acquired, (pointer))
#define MALLOC_ITT_SYNC_RELEASING(pointer) ITT_NOTIFY(sync_releasing, (pointer))
#define MALLOC_ITT_SYNC_CANCEL(pointer) ITT_NOTIFY(sync_cancel, (pointer))
#else
#define MALLOC_ITT_SYNC_PREPARE(pointer) ((void)0)
#define MALLOC_ITT_SYNC_ACQUIRED(pointer) ((void)0)
#define MALLOC_ITT_SYNC_RELEASING(pointer) ((void)0)
#define MALLOC_ITT_SYNC_CANCEL(pointer) ((void)0)
#endif
//! Stripped down version of spin_mutex.
/** Instances of MallocMutex must be declared in memory that is zero-initialized.
There are no constructors. This is a feature that lets it be
used in situations where the mutex might be used while file-scope constructors
are running.
There are no methods "acquire" or "release". The scoped_lock must be used
in a strict block-scoped locking pattern. Omitting these methods permitted
further simplication. */
class MallocMutex {
unsigned char value;
//! Deny assignment
void operator=( MallocMutex& MallocMutex );
public:
class scoped_lock {
const unsigned char value;
MallocMutex& mutex;
public:
scoped_lock( MallocMutex& m ) : value( __TBB_LockByte(m.value)), mutex(m) {}
~scoped_lock() { __TBB_store_with_release(mutex.value, value); }
};
friend class scoped_lock;
};
inline intptr_t AtomicIncrement( volatile intptr_t& counter ) {
return __TBB_FetchAndAddW( &counter, 1 )+1;
}
inline uintptr_t AtomicAdd( volatile uintptr_t& counter, uintptr_t value ) {
return __TBB_FetchAndAddW( &counter, value );
}
inline intptr_t AtomicCompareExchange( volatile intptr_t& location, intptr_t new_value, intptr_t comparand) {
return __TBB_CompareAndSwapW( &location, new_value, comparand );
}
#define USE_DEFAULT_MEMORY_MAPPING 1
// To support malloc replacement with LD_PRELOAD
#include "proxy.h"
#if MALLOC_LD_PRELOAD
#define malloc_proxy __TBB_malloc_proxy
extern "C" void * __TBB_malloc_proxy(size_t) __attribute__ ((weak));
#else
const bool malloc_proxy = false;
#endif
namespace rml {
namespace internal {
void init_tbbmalloc();
} } // namespaces
#define MALLOC_EXTRA_INITIALIZATION rml::internal::init_tbbmalloc()
#endif /* _TBB_malloc_Customize_H_ */

View file

@ -0,0 +1,97 @@
/*
Copyright 2005-2009 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks.
Threading Building Blocks is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
Threading Building Blocks is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Threading Building Blocks; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
As a special exception, you may use this file as part of a free software
library without restriction. Specifically, if other files instantiate
templates or use macros or inline functions from this file, or you compile
this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered by
the GNU General Public License.
*/
#ifndef _itt_common_malloc_LifoQueue_H_
#define _itt_common_malloc_LifoQueue_H_
#include "TypeDefinitions.h"
#include <string.h> // for memset()
//! Checking the synchronization method
/** FINE_GRAIN_LOCKS is the only variant for now; should be defined for LifoQueue */
#ifndef FINE_GRAIN_LOCKS
#define FINE_GRAIN_LOCKS
#endif
namespace rml {
namespace internal {
class LifoQueue {
public:
inline LifoQueue();
inline void push(void** ptr);
inline void* pop(void);
private:
void * top;
#ifdef FINE_GRAIN_LOCKS
MallocMutex lock;
#endif /* FINE_GRAIN_LOCKS */
};
#ifdef FINE_GRAIN_LOCKS
/* LifoQueue assumes zero initialization so a vector of it can be created
* by just allocating some space with no call to constructor.
* On Linux, it seems to be necessary to avoid linking with C++ libraries.
*
* By usage convention there is no race on the initialization. */
LifoQueue::LifoQueue( ) : top(NULL)
{
// MallocMutex assumes zero initialization
memset(&lock, 0, sizeof(MallocMutex));
}
void LifoQueue::push( void **ptr )
{
MallocMutex::scoped_lock scoped_cs(lock);
*ptr = top;
top = ptr;
}
void * LifoQueue::pop( )
{
void **result=NULL;
{
MallocMutex::scoped_lock scoped_cs(lock);
if (!top) goto done;
result = (void **) top;
top = *result;
}
*result = NULL;
done:
return result;
}
#endif /* FINE_GRAIN_LOCKS */
} // namespace internal
} // namespace rml
#endif /* _itt_common_malloc_LifoQueue_H_ */

View file

@ -0,0 +1,101 @@
/*
Copyright 2005-2009 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks.
Threading Building Blocks is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
Threading Building Blocks is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Threading Building Blocks; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
As a special exception, you may use this file as part of a free software
library without restriction. Specifically, if other files instantiate
templates or use macros or inline functions from this file, or you compile
this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered by
the GNU General Public License.
*/
#ifndef _itt_shared_malloc_MapMemory_H
#define _itt_shared_malloc_MapMemory_H
#if __linux__ || __APPLE__ || __sun || __FreeBSD__
#if __sun && !defined(_XPG4_2)
// To have void* as mmap's 1st argument
#define _XPG4_2 1
#define XPG4_WAS_DEFINED 1
#endif
#include <sys/mman.h>
#if XPG4_WAS_DEFINED
#undef _XPG4_2
#undef XPG4_WAS_DEFINED
#endif
#define MEMORY_MAPPING_USES_MALLOC 0
void* MapMemory (size_t bytes)
{
void* result = 0;
#ifndef MAP_ANONYMOUS
// Mac OS* X defines MAP_ANON, which is deprecated in Linux.
#define MAP_ANONYMOUS MAP_ANON
#endif /* MAP_ANONYMOUS */
result = mmap(result, bytes, (PROT_READ | PROT_WRITE), MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
return result==MAP_FAILED? 0: result;
}
int UnmapMemory(void *area, size_t bytes)
{
return munmap(area, bytes);
}
#elif _WIN32 || _WIN64
#include <windows.h>
#define MEMORY_MAPPING_USES_MALLOC 0
void* MapMemory (size_t bytes)
{
/* Is VirtualAlloc thread safe? */
return VirtualAlloc(NULL, bytes, (MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN), PAGE_READWRITE);
}
int UnmapMemory(void *area, size_t bytes)
{
BOOL result = VirtualFree(area, 0, MEM_RELEASE);
return !result;
}
#else
#include <stdlib.h>
#define MEMORY_MAPPING_USES_MALLOC 1
void* MapMemory (size_t bytes)
{
return malloc( bytes );
}
int UnmapMemory(void *area, size_t bytes)
{
free( area );
return 0;
}
#endif /* OS dependent */
#if MALLOC_CHECK_RECURSION && MEMORY_MAPPING_USES_MALLOC
#error Impossible to protect against malloc recursion when memory mapping uses malloc.
#endif
#endif /* _itt_shared_malloc_MapMemory_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,137 @@
/*
Copyright 2005-2009 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks.
Threading Building Blocks is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
Threading Building Blocks is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Threading Building Blocks; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
As a special exception, you may use this file as part of a free software
library without restriction. Specifically, if other files instantiate
templates or use macros or inline functions from this file, or you compile
this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered by
the GNU General Public License.
*/
#define MAX_THREADS 1024
#define NUM_OF_BINS 30
#define ThreadCommonCounters NUM_OF_BINS
enum counter_type {
allocBlockNew = 0,
allocBlockPublic,
allocBumpPtrUsed,
allocFreeListUsed,
allocPrivatized,
examineEmptyEnough,
examineNotEmpty,
freeRestoreBumpPtr,
freeByOtherThread,
freeToActiveBlock,
freeToInactiveBlock,
freeBlockPublic,
freeBlockBack,
MaxCounters
};
enum common_counter_type {
allocNewLargeObj = 0,
allocCachedLargeObj,
cacheLargeObj,
freeLargeObj,
lockPublicFreeList,
freeToOtherThread
};
#if COLLECT_STATISTICS
/* Statistics reporting callback registred via a static object dtor
on Posix or DLL_PROCESS_DETACH on Windows.
*/
static bool reportAllocationStatistics;
struct bin_counters {
int counter[MaxCounters];
};
static bin_counters statistic[MAX_THREADS][NUM_OF_BINS+1]; //zero-initialized;
static inline int STAT_increment(int thread, int bin, int ctr)
{
return reportAllocationStatistics && thread < MAX_THREADS ? ++(statistic[thread][bin].counter[ctr]) : 0;
}
static inline void initStatisticsCollection() {
#if defined(MALLOCENV_COLLECT_STATISTICS)
if (NULL != getenv(MALLOCENV_COLLECT_STATISTICS))
reportAllocationStatistics = true;
#endif
}
#else
#define STAT_increment(a,b,c) ((void)0)
#endif /* COLLECT_STATISTICS */
static inline void STAT_print(int thread)
{
#if COLLECT_STATISTICS
if (!reportAllocationStatistics)
return;
char filename[100];
#if USE_PTHREAD
sprintf(filename, "stat_ScalableMalloc_proc%04d_thr%04d.log", getpid(), thread);
#else
sprintf(filename, "stat_ScalableMalloc_thr%04d.log", thread);
#endif
FILE* outfile = fopen(filename, "w");
for(int i=0; i<NUM_OF_BINS; ++i)
{
bin_counters& ctrs = statistic[thread][i];
fprintf(outfile, "Thr%04d Bin%02d", thread, i);
fprintf(outfile, ": allocNewBlocks %5d", ctrs.counter[allocBlockNew]);
fprintf(outfile, ", allocPublicBlocks %5d", ctrs.counter[allocBlockPublic]);
fprintf(outfile, ", restoreBumpPtr %5d", ctrs.counter[freeRestoreBumpPtr]);
fprintf(outfile, ", privatizeCalled %10d", ctrs.counter[allocPrivatized]);
fprintf(outfile, ", emptyEnough %10d", ctrs.counter[examineEmptyEnough]);
fprintf(outfile, ", notEmptyEnough %10d", ctrs.counter[examineNotEmpty]);
fprintf(outfile, ", freeBlocksPublic %5d", ctrs.counter[freeBlockPublic]);
fprintf(outfile, ", freeBlocksBack %5d", ctrs.counter[freeBlockBack]);
fprintf(outfile, "\n");
}
for(int i=0; i<NUM_OF_BINS; ++i)
{
bin_counters& ctrs = statistic[thread][i];
fprintf(outfile, "Thr%04d Bin%02d", thread, i);
fprintf(outfile, ": allocBumpPtr %10d", ctrs.counter[allocBumpPtrUsed]);
fprintf(outfile, ", allocFreeList %10d", ctrs.counter[allocFreeListUsed]);
fprintf(outfile, ", freeToActiveBlk %10d", ctrs.counter[freeToActiveBlock]);
fprintf(outfile, ", freeToInactive %10d", ctrs.counter[freeToInactiveBlock]);
fprintf(outfile, ", freedByOther %10d", ctrs.counter[freeByOtherThread]);
fprintf(outfile, "\n");
}
bin_counters& ctrs = statistic[thread][ThreadCommonCounters];
fprintf(outfile, "Thr%04d common counters", thread);
fprintf(outfile, ": allocNewLargeObject %5d", ctrs.counter[allocNewLargeObj]);
fprintf(outfile, ": allocCachedLargeObject %5d", ctrs.counter[allocCachedLargeObj]);
fprintf(outfile, ", cacheLargeObject %5d", ctrs.counter[cacheLargeObj]);
fprintf(outfile, ", freeLargeObject %5d", ctrs.counter[freeLargeObj]);
fprintf(outfile, ", lockPublicFreeList %5d", ctrs.counter[lockPublicFreeList]);
fprintf(outfile, ", freeToOtherThread %10d", ctrs.counter[freeToOtherThread]);
fprintf(outfile, "\n");
fclose(outfile);
#endif
}

View file

@ -0,0 +1,104 @@
/*
Copyright 2005-2009 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks.
Threading Building Blocks is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
Threading Building Blocks is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Threading Building Blocks; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
As a special exception, you may use this file as part of a free software
library without restriction. Specifically, if other files instantiate
templates or use macros or inline functions from this file, or you compile
this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered by
the GNU General Public License.
*/
#ifndef _itt_shared_malloc_TypeDefinitions_H_
#define _itt_shared_malloc_TypeDefinitions_H_
// Define preprocessor symbols used to determine architecture
#if _WIN32||_WIN64
# if defined(_M_AMD64)
# define __ARCH_x86_64 1
# elif defined(_M_IA64)
# define __ARCH_ipf 1
# elif defined(_M_IX86)||defined(__i386__) // the latter for MinGW support
# define __ARCH_x86_32 1
# else
# error Unknown processor architecture for Windows
# endif
# define USE_WINTHREAD 1
#else /* Assume generic Unix */
# if __x86_64__
# define __ARCH_x86_64 1
# elif __ia64__
# define __ARCH_ipf 1
# elif __i386__ || __i386
# define __ARCH_x86_32 1
# else
# define __ARCH_other 1
# endif
# define USE_PTHREAD 1
#endif
// Include files containing declarations of intptr_t and uintptr_t
#include <stddef.h> // size_t
#if _MSC_VER
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif
namespace rml {
namespace internal {
extern bool original_malloc_found;
extern void* (*original_malloc_ptr)(size_t);
extern void (*original_free_ptr)(void*);
} } // namespaces
//! PROVIDE YOUR OWN Customize.h IF YOU FEEL NECESSARY
#include "Customize.h"
/*
* Functions to align an integer down or up to the given power of two,
* and test for such an alignment, and for power of two.
*/
template<typename T>
static inline T alignDown(T arg, uintptr_t alignment) {
return T( (uintptr_t)arg & ~(alignment-1));
}
template<typename T>
static inline T alignUp (T arg, uintptr_t alignment) {
return T(((uintptr_t)arg+(alignment-1)) & ~(alignment-1));
// /*is this better?*/ return (((uintptr_t)arg-1) | (alignment-1)) + 1;
}
template<typename T>
static inline bool isAligned(T arg, uintptr_t alignment) {
return 0==((uintptr_t)arg & (alignment-1));
}
static inline bool isPowerOfTwo(uintptr_t arg) {
return arg && (0==(arg & (arg-1)));
}
static inline bool isPowerOfTwoMultiple(uintptr_t arg, uintptr_t divisor) {
// Divisor is assumed to be a power of two (which is valid for current uses).
MALLOC_ASSERT( isPowerOfTwo(divisor), "Divisor should be a power of two" );
return arg && (0==(arg & (arg-divisor)));
}
#endif /* _itt_shared_malloc_TypeDefinitions_H_ */

View file

@ -0,0 +1,70 @@
/*
Copyright 2005-2009 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks.
Threading Building Blocks is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
Threading Building Blocks is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Threading Building Blocks; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
As a special exception, you may use this file as part of a free software
library without restriction. Specifically, if other files instantiate
templates or use macros or inline functions from this file, or you compile
this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered by
the GNU General Public License.
*/
{
global:
scalable_calloc;
scalable_free;
scalable_malloc;
scalable_realloc;
scalable_posix_memalign;
scalable_aligned_malloc;
scalable_aligned_realloc;
scalable_aligned_free;
__TBB_internal_calloc;
__TBB_internal_free;
__TBB_internal_malloc;
__TBB_internal_realloc;
__TBB_internal_posix_memalign;
scalable_msize;
local:
/* TBB symbols */
*3rml8internal*;
*3tbb*;
*__TBB*;
__itt_*;
ITT_DoOneTimeInitialization;
TBB_runtime_interface_version;
/* Intel Compiler (libirc) symbols */
__intel_*;
_intel_*;
get_memcpy_largest_cachelinesize;
get_memcpy_largest_cache_size;
get_mem_ops_method;
init_mem_ops_method;
irc__get_msg;
irc__print;
override_mem_ops_method;
set_memcpy_largest_cachelinesize;
set_memcpy_largest_cache_size;
};

View file

@ -0,0 +1,59 @@
/*
Copyright 2005-2009 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks.
Threading Building Blocks is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
Threading Building Blocks is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Threading Building Blocks; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
As a special exception, you may use this file as part of a free software
library without restriction. Specifically, if other files instantiate
templates or use macros or inline functions from this file, or you compile
this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered by
the GNU General Public License.
*/
{
global:
calloc;
free;
malloc;
realloc;
posix_memalign;
memalign;
valloc;
pvalloc;
mallinfo;
mallopt;
__TBB_malloc_proxy;
__TBB_internal_find_original_malloc;
_ZdaPv; /* next ones are new/delete */
_ZdaPvRKSt9nothrow_t;
_ZdlPv;
_ZdlPvRKSt9nothrow_t;
_Znaj;
_ZnajRKSt9nothrow_t;
_Znwj;
_ZnwjRKSt9nothrow_t;
local:
/* TBB symbols */
*3rml8internal*;
*3tbb*;
*__TBB*;
};

View file

@ -0,0 +1,59 @@
/*
Copyright 2005-2009 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks.
Threading Building Blocks is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
Threading Building Blocks is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Threading Building Blocks; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
As a special exception, you may use this file as part of a free software
library without restriction. Specifically, if other files instantiate
templates or use macros or inline functions from this file, or you compile
this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered by
the GNU General Public License.
*/
{
global:
calloc;
free;
malloc;
realloc;
posix_memalign;
memalign;
valloc;
pvalloc;
mallinfo;
mallopt;
__TBB_malloc_proxy;
__TBB_internal_find_original_malloc;
_ZdaPv; /* next ones are new/delete */
_ZdaPvRKSt9nothrow_t;
_ZdlPv;
_ZdlPvRKSt9nothrow_t;
_Znam;
_ZnamRKSt9nothrow_t;
_Znwm;
_ZnwmRKSt9nothrow_t;
local:
/* TBB symbols */
*3rml8internal*;
*3tbb*;
*__TBB*;
};

View file

@ -0,0 +1,59 @@
/*
Copyright 2005-2009 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks.
Threading Building Blocks is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
Threading Building Blocks is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Threading Building Blocks; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
As a special exception, you may use this file as part of a free software
library without restriction. Specifically, if other files instantiate
templates or use macros or inline functions from this file, or you compile
this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered by
the GNU General Public License.
*/
{
global:
calloc;
free;
malloc;
realloc;
posix_memalign;
memalign;
valloc;
pvalloc;
mallinfo;
mallopt;
__TBB_malloc_proxy;
__TBB_internal_find_original_malloc;
_ZdaPv; /* next ones are new/delete */
_ZdaPvRKSt9nothrow_t;
_ZdlPv;
_ZdlPvRKSt9nothrow_t;
_Znam;
_ZnamRKSt9nothrow_t;
_Znwm;
_ZnwmRKSt9nothrow_t;
local:
/* TBB symbols */
*3rml8internal*;
*3tbb*;
*__TBB*;
};

View file

@ -0,0 +1,36 @@
# Copyright 2005-2009 Intel Corporation. All Rights Reserved.
#
# This file is part of Threading Building Blocks.
#
# Threading Building Blocks is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public License
# version 2 as published by the Free Software Foundation.
#
# Threading Building Blocks is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Threading Building Blocks; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# As a special exception, you may use this file as part of a free software
# library without restriction. Specifically, if other files instantiate
# templates or use macros or inline functions from this file, or you compile
# this file and link it with other files to produce an executable, this
# file does not by itself cause the resulting executable to be covered by
# the GNU General Public License. This exception does not however
# invalidate any other reasons why the executable file might be covered by
# the GNU General Public License.
# MemoryAllocator.cpp
_scalable_calloc
_scalable_free
_scalable_malloc
_scalable_realloc
_scalable_posix_memalign
_scalable_aligned_malloc
_scalable_aligned_realloc
_scalable_aligned_free
_scalable_msize

View file

@ -0,0 +1,36 @@
# Copyright 2005-2009 Intel Corporation. All Rights Reserved.
#
# This file is part of Threading Building Blocks.
#
# Threading Building Blocks is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public License
# version 2 as published by the Free Software Foundation.
#
# Threading Building Blocks is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Threading Building Blocks; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# As a special exception, you may use this file as part of a free software
# library without restriction. Specifically, if other files instantiate
# templates or use macros or inline functions from this file, or you compile
# this file and link it with other files to produce an executable, this
# file does not by itself cause the resulting executable to be covered by
# the GNU General Public License. This exception does not however
# invalidate any other reasons why the executable file might be covered by
# the GNU General Public License.
# MemoryAllocator.cpp
_scalable_calloc
_scalable_free
_scalable_malloc
_scalable_realloc
_scalable_posix_memalign
_scalable_aligned_malloc
_scalable_aligned_realloc
_scalable_aligned_free
_scalable_msize

View file

@ -0,0 +1,434 @@
/*
Copyright 2005-2009 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks.
Threading Building Blocks is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
Threading Building Blocks is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Threading Building Blocks; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
As a special exception, you may use this file as part of a free software
library without restriction. Specifically, if other files instantiate
templates or use macros or inline functions from this file, or you compile
this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered by
the GNU General Public License.
*/
#include "proxy.h"
#if MALLOC_LD_PRELOAD
/*** service functions and variables ***/
#include <unistd.h> // for sysconf
#include <dlfcn.h>
static long memoryPageSize;
static inline void initPageSize()
{
memoryPageSize = sysconf(_SC_PAGESIZE);
}
/* For the expected behaviour (i.e., finding malloc/free/etc from libc.so,
not from ld-linux.so) dlsym(RTLD_NEXT) should be called from
a LD_PRELOADed library, not another dynamic library.
So we have to put find_original_malloc here.
*/
extern "C" bool __TBB_internal_find_original_malloc(int num, const char *names[],
void *ptrs[])
{
for (int i=0; i<num; i++)
if (NULL == (ptrs[i] = dlsym (RTLD_NEXT, names[i])))
return false;
return true;
}
/* __TBB_malloc_proxy used as a weak symbol by libtbbmalloc for:
1) detection that the proxy library is loaded
2) check that dlsym("malloc") found something different from our replacement malloc
*/
extern "C" void *__TBB_malloc_proxy() __attribute__ ((alias ("malloc")));
#ifndef __THROW
#define __THROW
#endif
/*** replacements for malloc and the family ***/
extern "C" {
void *malloc(size_t size) __THROW
{
return __TBB_internal_malloc(size);
}
void * calloc(size_t num, size_t size) __THROW
{
return __TBB_internal_calloc(num, size);
}
void free(void *object) __THROW
{
__TBB_internal_free(object);
}
void * realloc(void* ptr, size_t sz) __THROW
{
return __TBB_internal_realloc(ptr, sz);
}
int posix_memalign(void **memptr, size_t alignment, size_t size) __THROW
{
return __TBB_internal_posix_memalign(memptr, alignment, size);
}
/* The older *NIX interface for aligned allocations;
it's formally substituted by posix_memalign and deprecated,
so we do not expect it to cause cyclic dependency with C RTL. */
void * memalign(size_t alignment, size_t size) __THROW
{
return scalable_aligned_malloc(size, alignment);
}
/* valloc allocates memory aligned on a page boundary */
void * valloc(size_t size) __THROW
{
if (! memoryPageSize) initPageSize();
return scalable_aligned_malloc(size, memoryPageSize);
}
/* pvalloc allocates smallest set of complete pages which can hold
the requested number of bytes. Result is aligned on page boundary. */
void * pvalloc(size_t size) __THROW
{
if (! memoryPageSize) initPageSize();
// align size up to the page size
size = ((size-1) | (memoryPageSize-1)) + 1;
return scalable_aligned_malloc(size, memoryPageSize);
}
int mallopt(int /*param*/, int /*value*/) __THROW
{
return 1;
}
} /* extern "C" */
#if __linux__
#include <malloc.h>
#include <string.h> // for memset
extern "C" struct mallinfo mallinfo() __THROW
{
struct mallinfo m;
memset(&m, 0, sizeof(struct mallinfo));
return m;
}
#endif /* __linux__ */
/*** replacements for global operators new and delete ***/
#include <new>
void * operator new(size_t sz) throw (std::bad_alloc) {
void *res = scalable_malloc(sz);
if (NULL == res) throw std::bad_alloc();
return res;
}
void* operator new[](size_t sz) throw (std::bad_alloc) {
void *res = scalable_malloc(sz);
if (NULL == res) throw std::bad_alloc();
return res;
}
void operator delete(void* ptr) throw() {
scalable_free(ptr);
}
void operator delete[](void* ptr) throw() {
scalable_free(ptr);
}
void* operator new(size_t sz, const std::nothrow_t&) throw() {
return scalable_malloc(sz);
}
void* operator new[](std::size_t sz, const std::nothrow_t&) throw() {
return scalable_malloc(sz);
}
void operator delete(void* ptr, const std::nothrow_t&) throw() {
scalable_free(ptr);
}
void operator delete[](void* ptr, const std::nothrow_t&) throw() {
scalable_free(ptr);
}
#endif /* MALLOC_LD_PRELOAD */
#ifdef _WIN32
#include <windows.h>
#include <stdio.h>
#include "tbb_function_replacement.h"
void safer_scalable_free2( void *ptr)
{
safer_scalable_free( ptr, NULL );
}
// we do not support _expand();
void* safer_expand( void *, size_t )
{
return NULL;
}
#define __TBB_QV(EXP) #EXP
#define __TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(CRTLIB)\
void (*orig_free_##CRTLIB)(void*); \
void safer_scalable_free_##CRTLIB( void *ptr) \
{ \
safer_scalable_free( ptr, orig_free_##CRTLIB ); \
} \
\
size_t (*orig_msize_##CRTLIB)(void*); \
size_t safer_scalable_msize_##CRTLIB( void *ptr) \
{ \
return safer_scalable_msize( ptr, orig_msize_##CRTLIB ); \
} \
\
void* safer_scalable_realloc_##CRTLIB( void *ptr, size_t size ) \
{ \
orig_ptrs func_ptrs = {orig_free_##CRTLIB, orig_msize_##CRTLIB}; \
return safer_scalable_realloc( ptr, size, &func_ptrs ); \
} \
\
void* safer_scalable_aligned_realloc_##CRTLIB( void *ptr, size_t size, size_t aligment ) \
{ \
orig_ptrs func_ptrs = {orig_free_##CRTLIB, orig_msize_##CRTLIB}; \
return safer_scalable_aligned_realloc( ptr, size, aligment, &func_ptrs ); \
}
#if _WIN64
#define __TBB_ORIG_ALLOCATOR_REPLACEMENT_CALL(CRT_VER)\
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ## d.dll), "free", (FUNCPTR)safer_scalable_free_ ## CRT_VER ## d, 9, (FUNCPTR*)&orig_free_ ## CRT_VER ## d ); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ##.dll), "free", (FUNCPTR)safer_scalable_free_ ## CRT_VER, 0, NULL ); \
orig_free_ ## CRT_VER = NULL; \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ## d.dll), "_msize",(FUNCPTR)safer_scalable_msize_ ## CRT_VER ## d, 9, (FUNCPTR*)&orig_msize_ ## CRT_VER ## d ); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ##.dll), "_msize",(FUNCPTR)safer_scalable_msize_ ## CRT_VER, 7, (FUNCPTR*)&orig_msize_ ## CRT_VER ); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ## d.dll), "realloc", (FUNCPTR)safer_scalable_realloc_ ## CRT_VER ## d, 0, NULL); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ##.dll), "realloc", (FUNCPTR)safer_scalable_realloc_ ## CRT_VER, 0, NULL); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ## d.dll), "_aligned_free", (FUNCPTR)safer_scalable_free_ ## CRT_VER ## d, 0, NULL); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ##.dll), "_aligned_free", (FUNCPTR)safer_scalable_free_ ## CRT_VER, 0, NULL); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ## d.dll), "_aligned_realloc",(FUNCPTR)safer_scalable_aligned_realloc_ ## CRT_VER ## d, 0, NULL); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ##.dll), "_aligned_realloc",(FUNCPTR)safer_scalable_aligned_realloc_ ## CRT_VER, 0, NULL);
#else
#define __TBB_ORIG_ALLOCATOR_REPLACEMENT_CALL(CRT_VER)\
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ## d.dll), "free", (FUNCPTR)safer_scalable_free_ ## CRT_VER ## d, 5, (FUNCPTR*)&orig_free_ ## CRT_VER ## d ); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ##.dll), "free", (FUNCPTR)safer_scalable_free_ ## CRT_VER, 7, (FUNCPTR*)&orig_free_ ## CRT_VER ); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ## d.dll), "_msize",(FUNCPTR)safer_scalable_msize_ ## CRT_VER ## d, 5, (FUNCPTR*)&orig_msize_ ## CRT_VER ## d ); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ##.dll), "_msize",(FUNCPTR)safer_scalable_msize_ ## CRT_VER, 7, (FUNCPTR*)&orig_msize_ ## CRT_VER ); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ## d.dll), "realloc", (FUNCPTR)safer_scalable_realloc_ ## CRT_VER ## d, 0, NULL); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ##.dll), "realloc", (FUNCPTR)safer_scalable_realloc_ ## CRT_VER, 0, NULL); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ## d.dll), "_aligned_free", (FUNCPTR)safer_scalable_free_ ## CRT_VER ## d, 0, NULL); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ##.dll), "_aligned_free", (FUNCPTR)safer_scalable_free_ ## CRT_VER, 0, NULL); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ## d.dll), "_aligned_realloc",(FUNCPTR)safer_scalable_aligned_realloc_ ## CRT_VER ## d, 0, NULL); \
ReplaceFunctionWithStore( __TBB_QV(CRT_VER ##.dll), "_aligned_realloc",(FUNCPTR)safer_scalable_aligned_realloc_ ## CRT_VER, 0, NULL);
#endif
__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr70d);
__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr70);
__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr71d);
__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr71);
__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr80d);
__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr80);
__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr90d);
__TBB_ORIG_ALLOCATOR_REPLACEMENT_WRAPPER(msvcr90);
/*** replacements for global operators new and delete ***/
#include <new>
#if _MSC_VER && !defined(__INTEL_COMPILER)
#pragma warning( push )
#pragma warning( disable : 4290 )
#endif
void * operator_new(size_t sz) throw (std::bad_alloc) {
void *res = scalable_malloc(sz);
if (NULL == res) throw std::bad_alloc();
return res;
}
void* operator_new_arr(size_t sz) throw (std::bad_alloc) {
void *res = scalable_malloc(sz);
if (NULL == res) throw std::bad_alloc();
return res;
}
void operator_delete(void* ptr) throw() {
safer_scalable_free2(ptr);
}
#if _MSC_VER && !defined(__INTEL_COMPILER)
#pragma warning( pop )
#endif
void operator_delete_arr(void* ptr) throw() {
safer_scalable_free2(ptr);
}
void* operator_new_t(size_t sz, const std::nothrow_t&) throw() {
return scalable_malloc(sz);
}
void* operator_new_arr_t(std::size_t sz, const std::nothrow_t&) throw() {
return scalable_malloc(sz);
}
void operator_delete_t(void* ptr, const std::nothrow_t&) throw() {
safer_scalable_free2(ptr);
}
void operator_delete_arr_t(void* ptr, const std::nothrow_t&) throw() {
safer_scalable_free2(ptr);
}
const char* modules_to_replace[] = {
"msvcr80d.dll",
"msvcr80.dll",
"msvcr90d.dll",
"msvcr90.dll",
"msvcr70d.dll",
"msvcr70.dll",
"msvcr71d.dll",
"msvcr71.dll",
};
/*
We need to replace following functions:
malloc
calloc
_aligned_malloc
_expand (by dummy implementation)
??2@YAPAXI@Z operator new (ia32)
??_U@YAPAXI@Z void * operator new[] (size_t size) (ia32)
??3@YAXPAX@Z operator delete (ia32)
??_V@YAXPAX@Z operator delete[] (ia32)
??2@YAPEAX_K@Z void * operator new(unsigned __int64) (intel64)
??_V@YAXPEAX@Z void * operator new[](unsigned __int64) (intel64)
??3@YAXPEAX@Z operator delete (intel64)
??_V@YAXPEAX@Z operator delete[] (intel64)
??2@YAPAXIABUnothrow_t@std@@@Z void * operator new (size_t sz, const std::nothrow_t&) throw() (optional)
??_U@YAPAXIABUnothrow_t@std@@@Z void * operator new[] (size_t sz, const std::nothrow_t&) throw() (optional)
and these functions have runtime-specific replacement:
realloc
free
_msize
_aligned_realloc
_aligned_free
*/
typedef struct FRData_t {
//char *_module;
const char *_func;
FUNCPTR _fptr;
FRR_ON_ERROR _on_error;
} FRDATA;
FRDATA routines_to_replace[] = {
{ "malloc", (FUNCPTR)scalable_malloc, FRR_FAIL },
{ "calloc", (FUNCPTR)scalable_calloc, FRR_FAIL },
{ "_aligned_malloc", (FUNCPTR)scalable_aligned_malloc, FRR_FAIL },
{ "_expand", (FUNCPTR)safer_expand, FRR_IGNORE },
#if _WIN64
{ "??2@YAPEAX_K@Z", (FUNCPTR)operator_new, FRR_FAIL },
{ "??_U@YAPEAX_K@Z", (FUNCPTR)operator_new_arr, FRR_FAIL },
{ "??3@YAXPEAX@Z", (FUNCPTR)operator_delete, FRR_FAIL },
{ "??_V@YAXPEAX@Z", (FUNCPTR)operator_delete_arr, FRR_FAIL },
#else
{ "??2@YAPAXI@Z", (FUNCPTR)operator_new, FRR_FAIL },
{ "??_U@YAPAXI@Z", (FUNCPTR)operator_new_arr, FRR_FAIL },
{ "??3@YAXPAX@Z", (FUNCPTR)operator_delete, FRR_FAIL },
{ "??_V@YAXPAX@Z", (FUNCPTR)operator_delete_arr, FRR_FAIL },
#endif
{ "??2@YAPAXIABUnothrow_t@std@@@Z", (FUNCPTR)operator_new_t, FRR_IGNORE },
{ "??_U@YAPAXIABUnothrow_t@std@@@Z", (FUNCPTR)operator_new_arr_t, FRR_IGNORE }
};
#ifndef UNICODE
void ReplaceFunctionWithStore( const char*dllName, const char *funcName, FUNCPTR newFunc, UINT opcodesNumber, FUNCPTR* origFunc )
#else
void ReplaceFunctionWithStore( const wchar_t *dllName, const char *funcName, FUNCPTR newFunc, UINT opcodesNumber, FUNCPTR* origFunc )
#endif
{
FRR_TYPE type = ReplaceFunction( dllName, funcName, newFunc, opcodesNumber, origFunc );
if (type == FRR_NODLL) return;
if ( type != FRR_OK )
{
fprintf(stderr, "Failed to replace function %s in module %s\n",
funcName, dllName);
exit(1);
}
}
void doMallocReplacement()
{
int i,j;
// Replace functions without storing original code
int modules_to_replace_count = sizeof(modules_to_replace) / sizeof(modules_to_replace[0]);
int routines_to_replace_count = sizeof(routines_to_replace) / sizeof(routines_to_replace[0]);
for ( j=0; j<modules_to_replace_count; j++ )
for (i = 0; i < routines_to_replace_count; i++)
{
FRR_TYPE type = ReplaceFunction( modules_to_replace[j], routines_to_replace[i]._func, routines_to_replace[i]._fptr, NULL, NULL );
if (type == FRR_NODLL) break;
if (type != FRR_OK && routines_to_replace[i]._on_error==FRR_FAIL)
{
fprintf(stderr, "Failed to replace function %s in module %s\n",
routines_to_replace[i]._func, modules_to_replace[j]);
exit(1);
}
}
// Replace functions and keep backup of original code (separate for each runtime)
__TBB_ORIG_ALLOCATOR_REPLACEMENT_CALL(msvcr70)
__TBB_ORIG_ALLOCATOR_REPLACEMENT_CALL(msvcr71)
__TBB_ORIG_ALLOCATOR_REPLACEMENT_CALL(msvcr80)
__TBB_ORIG_ALLOCATOR_REPLACEMENT_CALL(msvcr90)
}
extern "C" BOOL WINAPI DllMain( HINSTANCE hInst, DWORD callReason, LPVOID reserved )
{
if ( callReason==DLL_PROCESS_ATTACH && reserved && hInst ) {
#if TBBMALLOC_USE_TBB_FOR_ALLOCATOR_ENV_CONTROLLED
char pinEnvVariable[50];
if( GetEnvironmentVariable("TBBMALLOC_USE_TBB_FOR_ALLOCATOR", pinEnvVariable, 50))
{
doMallocReplacement();
}
#else
doMallocReplacement();
#endif
}
return TRUE;
}
// Just to make the linker happy and link the DLL to the application
extern "C" __declspec(dllexport) void __TBB_malloc_proxy()
{
}
#endif //_WIN32

View file

@ -0,0 +1,72 @@
/*
Copyright 2005-2009 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks.
Threading Building Blocks is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
Threading Building Blocks is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Threading Building Blocks; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
As a special exception, you may use this file as part of a free software
library without restriction. Specifically, if other files instantiate
templates or use macros or inline functions from this file, or you compile
this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered by
the GNU General Public License.
*/
#ifndef _TBB_malloc_proxy_H_
#define _TBB_malloc_proxy_H_
#if __linux__
#define MALLOC_LD_PRELOAD 1
#endif
// MALLOC_LD_PRELOAD depends on MALLOC_CHECK_RECURSION stuff
#if __linux__ || __APPLE__ || __sun || __FreeBSD__ || MALLOC_LD_PRELOAD
#define MALLOC_CHECK_RECURSION 1
#endif
#include <stddef.h>
extern "C" {
void * scalable_malloc(size_t size);
void * scalable_calloc(size_t nobj, size_t size);
void scalable_free(void *ptr);
void * scalable_realloc(void* ptr, size_t size);
void * scalable_aligned_malloc(size_t size, size_t alignment);
void * scalable_aligned_realloc(void* ptr, size_t size, size_t alignment);
int scalable_posix_memalign(void **memptr, size_t alignment, size_t size);
size_t scalable_msize(void *ptr);
void safer_scalable_free( void *ptr, void (*original_free)(void*));
void * safer_scalable_realloc( void *ptr, size_t, void* );
void * safer_scalable_aligned_realloc( void *ptr, size_t, size_t, void* );
size_t safer_scalable_msize( void *ptr, size_t (*orig_msize_crt80d)(void*));
void * __TBB_internal_malloc(size_t size);
void * __TBB_internal_calloc(size_t num, size_t size);
void __TBB_internal_free(void *ptr);
void * __TBB_internal_realloc(void* ptr, size_t sz);
int __TBB_internal_posix_memalign(void **memptr, size_t alignment, size_t size);
bool __TBB_internal_find_original_malloc(int num, const char *names[], void *table[]);
} // extern "C"
// Struct with original free() and _msize() pointers
struct orig_ptrs {
void (*orig_free) (void*);
size_t (*orig_msize)(void*);
};
#endif /* _TBB_malloc_proxy_H_ */

View file

@ -0,0 +1,396 @@
/*
Copyright 2005-2009 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks.
Threading Building Blocks is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
Threading Building Blocks is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Threading Building Blocks; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
As a special exception, you may use this file as part of a free software
library without restriction. Specifically, if other files instantiate
templates or use macros or inline functions from this file, or you compile
this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered by
the GNU General Public License.
*/
//We works on windows only
#ifdef _WIN32
#define _CRT_SECURE_NO_DEPRECATE 1
#include <windows.h>
#include <new>
#include "tbb_function_replacement.h"
inline UINT_PTR Ptr2Addrint(LPVOID ptr)
{
Int2Ptr i2p;
i2p.lpv = ptr;
return i2p.uip;
}
inline LPVOID Addrint2Ptr(UINT_PTR ptr)
{
Int2Ptr i2p;
i2p.uip = ptr;
return i2p.lpv;
}
// Is the distance between addr1 and addr2 smaller than dist
inline bool IsInDistance(UINT_PTR addr1, UINT_PTR addr2, __int64 dist)
{
__int64 diff = addr1>addr2 ? addr1-addr2 : addr2-addr1;
return diff<dist;
}
/*
* When inserting a probe in 64 bits process the distance between the insertion
* point and the target may be bigger than 2^32. In this case we are using
* indirect jump through memory where the offset to this memory location
* is smaller than 2^32 and it contains the absolute address (8 bytes).
*
* This class is used to hold the pages used for the above trampolines.
* Since this utility will be used to replace malloc functions this implementation
* doesn't allocate memory dynamically.
*
* The struct MemoryBuffer holds the data about a page in the memory used for
* replacing functions in Intel64 where the target is too far to be replaced
* with a short jump. All the calculations of m_base and m_next are in a multiple
* of SIZE_OF_ADDRESS (which is 8 in Win64).
*/
class MemoryProvider {
private:
struct MemoryBuffer {
UINT_PTR m_base; // base address of the buffer
UINT_PTR m_next; // next free location in the buffer
DWORD m_size; // size of buffer
// Default constructor
MemoryBuffer() : m_base(0), m_next(0), m_size(0) {}
// Constructor
MemoryBuffer(void *base, DWORD size)
{
m_base = Ptr2Addrint(base);
m_next = m_base;
m_size = size;
}
};
MemoryBuffer *CreateBuffer(UINT_PTR addr)
{
// No more room in the pages database
if (m_lastBuffer - m_pages == MAX_NUM_BUFFERS)
return 0;
void *newAddr = Addrint2Ptr(addr);
// Get information for the region which the given address belongs to
MEMORY_BASIC_INFORMATION memInfo;
if (VirtualQuery(newAddr, &memInfo, sizeof(memInfo)) != sizeof(memInfo))
return 0;
for(;;) {
// The new address to check is beyond the current region and aligned to allocation size
newAddr = Addrint2Ptr( (Ptr2Addrint(memInfo.BaseAddress) + memInfo.RegionSize + m_allocSize) & ~(UINT_PTR)(m_allocSize-1) );
// Check that the address is in the right distance.
// VirtualAlloc can only round the address down; so it will remain in the right distance
if (!IsInDistance(addr, Ptr2Addrint(newAddr), MAX_DISTANCE))
break;
if (VirtualQuery(newAddr, &memInfo, sizeof(memInfo)) != sizeof(memInfo))
break;
if (memInfo.State == MEM_FREE && memInfo.RegionSize >= m_allocSize)
{
// Found a free region, try to allocate a page in this region
void *newPage = VirtualAlloc(newAddr, m_allocSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
if (!newPage)
break;
// Add the new page to the pages database
MemoryBuffer *pBuff = new (m_lastBuffer) MemoryBuffer(newPage, m_allocSize);
++m_lastBuffer;
return pBuff;
}
}
// Failed to find a buffer in the distance
return 0;
}
public:
MemoryProvider()
{
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
m_allocSize = sysInfo.dwAllocationGranularity;
m_lastBuffer = &m_pages[0];
}
// We can't free the pages in the destructor because the trampolines
// are using these memory locations and a replaced function might be called
// after the destructor was called.
~MemoryProvider()
{
}
// Return a memory location in distance less than 2^31 from input address
UINT_PTR GetLocation(UINT_PTR addr)
{
MemoryBuffer *pBuff = m_pages;
for (; pBuff<m_lastBuffer && IsInDistance(pBuff->m_next, addr, MAX_DISTANCE); ++pBuff)
{
if (pBuff->m_next < pBuff->m_base + pBuff->m_size)
{
UINT_PTR loc = pBuff->m_next;
pBuff->m_next += MAX_PROBE_SIZE;
return loc;
}
}
pBuff = CreateBuffer(addr);
if(!pBuff)
return 0;
UINT_PTR loc = pBuff->m_next;
pBuff->m_next += MAX_PROBE_SIZE;
return loc;
}
private:
MemoryBuffer m_pages[MAX_NUM_BUFFERS];
MemoryBuffer *m_lastBuffer;
DWORD m_allocSize;
};
static MemoryProvider memProvider;
// Insert jump relative instruction to the input address
// RETURN: the size of the trampoline or 0 on failure
static DWORD InsertTrampoline32(void *inpAddr, void *targetAddr, UINT opcodesNumber, FUNCPTR* storedAddr)
{
UINT_PTR srcAddr = Ptr2Addrint(inpAddr);
UINT_PTR tgtAddr = Ptr2Addrint(targetAddr);
// Check that the target fits in 32 bits
if (!IsInDistance(srcAddr, tgtAddr, MAX_DISTANCE))
return 0;
UINT_PTR offset;
UINT offset32;
UCHAR *codePtr = (UCHAR *)inpAddr;
// If requested, store original function code
if ( storedAddr ){
UINT_PTR strdAddr = memProvider.GetLocation(srcAddr);
if (!strdAddr)
return 0;
*storedAddr = (FUNCPTR)Addrint2Ptr(strdAddr);
// Set 'executable' flag for original instructions in the new place
DWORD pageFlags = PAGE_EXECUTE_READWRITE;
if (!VirtualProtect(*storedAddr, MAX_PROBE_SIZE, pageFlags, &pageFlags)) return 0;
// Copy original instructions to the new place
memcpy(*storedAddr, codePtr, opcodesNumber);
// Set jump to the code after replacement
offset = srcAddr - strdAddr - SIZE_OF_RELJUMP;
offset32 = (UINT)((offset & 0xFFFFFFFF));
*((UCHAR*)*storedAddr+opcodesNumber) = 0xE9;
memcpy(((UCHAR*)*storedAddr+opcodesNumber+1), &offset32, sizeof(offset32));
}
// The following will work correctly even if srcAddr>tgtAddr, as long as
// address difference is less than 2^31, which is guaranteed by IsInDistance.
offset = tgtAddr - srcAddr - SIZE_OF_RELJUMP;
offset32 = (UINT)(offset & 0xFFFFFFFF);
// Insert the jump to the new code
*codePtr = 0xE9;
memcpy(codePtr+1, &offset32, sizeof(offset32));
// Fill the rest with NOPs to correctly see disassembler of old code in debugger.
for( unsigned i=SIZE_OF_RELJUMP; i<opcodesNumber; i++ ){
*(codePtr+i) = 0x90;
}
return SIZE_OF_RELJUMP;
}
// This function is called when the offset doesn't fit in 32 bits
// 1 Find and allocate a page in the small distance (<2^31) from input address
// 2 Put jump RIP relative indirect through the address in the close page
// 3 Put the absolute address of the target in the allocated location
// RETURN: the size of the trampoline or 0 on failure
static DWORD InsertTrampoline64(void *inpAddr, void *targetAddr, UINT opcodesNumber, FUNCPTR* storedAddr)
{
UINT_PTR srcAddr = Ptr2Addrint(inpAddr);
UINT_PTR tgtAddr = Ptr2Addrint(targetAddr);
// Get a location close to the source address
UINT_PTR location = memProvider.GetLocation(srcAddr);
if (!location)
return 0;
UINT_PTR offset;
UINT offset32;
UCHAR *codePtr = (UCHAR *)inpAddr;
// Fill the location
UINT_PTR *locPtr = (UINT_PTR *)Addrint2Ptr(location);
*locPtr = tgtAddr;
// If requested, store original function code
if( storedAddr ){
UINT_PTR strdAddr = memProvider.GetLocation(srcAddr);
if (!strdAddr)
return 0;
*storedAddr = (FUNCPTR)Addrint2Ptr(strdAddr);
// Set 'executable' flag for original instructions in the new place
DWORD pageFlags = PAGE_EXECUTE_READWRITE;
if (!VirtualProtect(*storedAddr, MAX_PROBE_SIZE, pageFlags, &pageFlags)) return 0;
// Copy original instructions to the new place
memcpy(*storedAddr, codePtr, opcodesNumber);
// Set jump to the code after replacement. It is within the distance of relative jump!
offset = srcAddr - strdAddr - SIZE_OF_RELJUMP;
offset32 = (UINT)((offset & 0xFFFFFFFF));
*((UCHAR*)*storedAddr+opcodesNumber) = 0xE9;
memcpy(((UCHAR*)*storedAddr+opcodesNumber+1), &offset32, sizeof(offset32));
}
// Fill the buffer
offset = location - srcAddr - SIZE_OF_INDJUMP;
offset32 = (UINT)(offset & 0xFFFFFFFF);
*(codePtr) = 0xFF;
*(codePtr+1) = 0x25;
memcpy(codePtr+2, &offset32, sizeof(offset32));
// Fill the rest with NOPs to correctly see disassembler of old code in debugger.
for( unsigned i=SIZE_OF_INDJUMP; i<opcodesNumber; i++ ){
*(codePtr+i) = 0x90;
}
return SIZE_OF_INDJUMP;
}
// Insert a jump instruction in the inpAddr to the targetAddr
// 1. Get the memory protection of the page containing the input address
// 2. Change the memory protection to writable
// 3. Call InsertTrampoline32 or InsertTrampoline64
// 4. Restore memory protection
// RETURN: FALSE on failure, TRUE on success
static bool InsertTrampoline(void *inpAddr, void *targetAddr, UINT opcodesNumber, FUNCPTR* origFunc)
{
DWORD probeSize;
// Change page protection to EXECUTE+WRITE
DWORD origProt = 0;
if (!VirtualProtect(inpAddr, MAX_PROBE_SIZE, PAGE_EXECUTE_WRITECOPY, &origProt))
return FALSE;
probeSize = InsertTrampoline32(inpAddr, targetAddr, opcodesNumber, origFunc);
if (!probeSize)
probeSize = InsertTrampoline64(inpAddr, targetAddr, opcodesNumber, origFunc);
// Restore original protection
VirtualProtect(inpAddr, MAX_PROBE_SIZE, origProt, &origProt);
if (!probeSize)
return FALSE;
FlushInstructionCache(GetCurrentProcess(), inpAddr, probeSize);
FlushInstructionCache(GetCurrentProcess(), origFunc, probeSize);
return TRUE;
}
// Routine to replace the functions
// TODO: replace opcodesNumber with opcodes and opcodes number to check if we replace right code.
FRR_TYPE ReplaceFunctionA(const char *dllName, const char *funcName, FUNCPTR newFunc, UINT opcodesNumber, FUNCPTR* origFunc)
{
// Cache the results of the last search for the module
// Assume that there was no DLL unload between
static char cachedName[MAX_PATH+1];
static HMODULE cachedHM = 0;
if (!dllName || !*dllName)
return FRR_NODLL;
if (!cachedHM || strncmp(dllName, cachedName, MAX_PATH) != 0)
{
// Find the module handle for the input dll
HMODULE hModule = GetModuleHandleA(dllName);
if (hModule == 0)
{
// Couldn't find the module with the input name
cachedHM = 0;
return FRR_NODLL;
}
cachedHM = hModule;
strncpy(cachedName, dllName, MAX_PATH);
}
FARPROC inpFunc = GetProcAddress(cachedHM, funcName);
if (inpFunc == 0)
{
// Function was not found
return FRR_NOFUNC;
}
if (!InsertTrampoline((void*)inpFunc, (void*)newFunc, opcodesNumber, origFunc)){
// Failed to insert the trampoline to the target address
return FRR_FAILED;
}
return FRR_OK;
}
FRR_TYPE ReplaceFunctionW(const wchar_t *dllName, const char *funcName, FUNCPTR newFunc, UINT opcodesNumber, FUNCPTR* origFunc)
{
// Cache the results of the last search for the module
// Assume that there was no DLL unload between
static wchar_t cachedName[MAX_PATH+1];
static HMODULE cachedHM = 0;
if (!dllName || !*dllName)
return FRR_NODLL;
if (!cachedHM || wcsncmp(dllName, cachedName, MAX_PATH) != 0)
{
// Find the module handle for the input dll
HMODULE hModule = GetModuleHandleW(dllName);
if (hModule == 0)
{
// Couldn't find the module with the input name
cachedHM = 0;
return FRR_NODLL;
}
cachedHM = hModule;
wcsncpy(cachedName, dllName, MAX_PATH);
}
FARPROC inpFunc = GetProcAddress(cachedHM, funcName);
if (inpFunc == 0)
{
// Function was not found
return FRR_NOFUNC;
}
if (!InsertTrampoline((void*)inpFunc, (void*)newFunc, opcodesNumber, origFunc)){
// Failed to insert the trampoline to the target address
return FRR_FAILED;
}
return FRR_OK;
}
#endif //_WIN32

View file

@ -0,0 +1,84 @@
/*
Copyright 2005-2009 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks.
Threading Building Blocks is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
Threading Building Blocks is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Threading Building Blocks; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
As a special exception, you may use this file as part of a free software
library without restriction. Specifically, if other files instantiate
templates or use macros or inline functions from this file, or you compile
this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered by
the GNU General Public License.
*/
#ifndef __TBB_function_replacement_H
#define __TBB_function_replacement_H
typedef enum {
FRR_OK, /* Succeeded in replacing the function */
FRR_NODLL, /* The requested DLL was not found */
FRR_NOFUNC, /* The requested function was not found */
FRR_FAILED, /* The function replacement request failed */
} FRR_TYPE;
typedef enum {
FRR_FAIL, /* Required function */
FRR_IGNORE, /* optional function */
} FRR_ON_ERROR;
typedef void (*FUNCPTR)();
#ifndef UNICODE
#define ReplaceFunction ReplaceFunctionA
#else
#define ReplaceFunction ReplaceFunctionW
#endif //UNICODE
FRR_TYPE ReplaceFunctionA(const char *dllName, const char *funcName, FUNCPTR newFunc, UINT opcodesNumber, FUNCPTR* origFunc=NULL);
FRR_TYPE ReplaceFunctionW(const wchar_t *dllName, const char *funcName, FUNCPTR newFunc, UINT opcodesNumber, FUNCPTR* origFunc=NULL);
// Utilities to convert between ADDRESS and LPVOID
union Int2Ptr {
UINT_PTR uip;
LPVOID lpv;
};
inline UINT_PTR Ptr2Addrint(LPVOID ptr);
inline LPVOID Addrint2Ptr(UINT_PTR ptr);
// Use this value as the maximum size the trampoline region
const int MAX_PROBE_SIZE = 32;
// The size of a jump relative instruction "e9 00 00 00 00"
const int SIZE_OF_RELJUMP = 5;
// The size of jump RIP relative indirect "ff 25 00 00 00 00"
const int SIZE_OF_INDJUMP = 6;
// The size of address we put in the location (in Intel64)
const int SIZE_OF_ADDRESS = 8;
// The max distance covered in 32 bits: 2^31 - 1 - C
// where C should not be smaller than the size of a probe.
// The latter is important to correctly handle "backward" jumps.
const __int64 MAX_DISTANCE = (((__int64)1 << 31) - 1) - MAX_PROBE_SIZE;
// The maximum number of distinct buffers in memory
const int MAX_NUM_BUFFERS = 256;
#endif //__TBB_function_replacement_H

View file

@ -0,0 +1,189 @@
/*
Copyright 2005-2009 Intel Corporation. All Rights Reserved.
This file is part of Threading Building Blocks.
Threading Building Blocks is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
Threading Building Blocks is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Threading Building Blocks; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
As a special exception, you may use this file as part of a free software
library without restriction. Specifically, if other files instantiate
templates or use macros or inline functions from this file, or you compile
this file and link it with other files to produce an executable, this
file does not by itself cause the resulting executable to be covered by
the GNU General Public License. This exception does not however
invalidate any other reasons why the executable file might be covered by
the GNU General Public License.
*/
#include "TypeDefinitions.h" // Customize.h and proxy.h get included
#include "tbb/itt_notify.cpp"
#if MALLOC_CHECK_RECURSION
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#if __sun
#include <string.h> /* for memset */
#include <errno.h>
#endif
#if MALLOC_LD_PRELOAD
extern "C" {
void safer_scalable_free( void*, void (*)(void*) );
void * safer_scalable_realloc( void*, size_t, void* );
bool __TBB_internal_find_original_malloc(int num, const char *names[], void *table[]) __attribute__ ((weak));
}
#endif /* MALLOC_LD_PRELOAD */
#endif /* MALLOC_CHECK_RECURSION */
namespace rml {
namespace internal {
#if MALLOC_CHECK_RECURSION
void* (*original_malloc_ptr)(size_t) = 0;
void (*original_free_ptr)(void*) = 0;
static void* (*original_calloc_ptr)(size_t,size_t) = 0;
static void* (*original_realloc_ptr)(void*,size_t) = 0;
#endif /* MALLOC_CHECK_RECURSION */
#if __TBB_NEW_ITT_NOTIFY
extern "C"
#endif
void ITT_DoOneTimeInitialization() {} // required for itt_notify.cpp to work
#if DO_ITT_NOTIFY
/** Caller is responsible for ensuring this routine is called exactly once. */
void MallocInitializeITT() {
#if __TBB_NEW_ITT_NOTIFY
tbb::internal::__TBB_load_ittnotify();
#else
bool success = false;
// Check if we are running under control of VTune.
if( GetBoolEnvironmentVariable("KMP_FOR_TCHECK") || GetBoolEnvironmentVariable("KMP_FOR_TPROFILE") ) {
// Yes, we are under control of VTune. Check for libittnotify library.
success = dynamic_link( LIBITTNOTIFY_NAME, ITT_HandlerTable, 5 );
}
if (!success){
for (int i = 0; i < 5; i++)
*ITT_HandlerTable[i].handler = NULL;
}
#endif /* !__TBB_NEW_ITT_NOTIFY */
}
#endif /* DO_ITT_NOTIFY */
void init_tbbmalloc() {
#if MALLOC_LD_PRELOAD
if (malloc_proxy && __TBB_internal_find_original_malloc) {
const char *alloc_names[] = { "malloc", "free", "realloc", "calloc"};
void *orig_alloc_ptrs[4];
if (__TBB_internal_find_original_malloc(4, alloc_names, orig_alloc_ptrs)) {
(void *&)original_malloc_ptr = orig_alloc_ptrs[0];
(void *&)original_free_ptr = orig_alloc_ptrs[1];
(void *&)original_realloc_ptr = orig_alloc_ptrs[2];
(void *&)original_calloc_ptr = orig_alloc_ptrs[3];
MALLOC_ASSERT( original_malloc_ptr!=malloc_proxy,
"standard malloc not found" );
/* It's workaround for a bug in GNU Libc 2.9 (as it shipped with Fedora 10).
1st call to libc's malloc should be not from threaded code.
*/
original_free_ptr(original_malloc_ptr(1024));
original_malloc_found = 1;
}
}
#endif /* MALLOC_LD_PRELOAD */
#if DO_ITT_NOTIFY
MallocInitializeITT();
#endif
}
#if !(_WIN32||_WIN64)
struct RegisterProcessShutdownNotification {
~RegisterProcessShutdownNotification() {
mallocProcessShutdownNotification();
}
};
static RegisterProcessShutdownNotification reg;
#endif
#if MALLOC_CHECK_RECURSION
bool original_malloc_found;
#if MALLOC_LD_PRELOAD
extern "C" {
void * __TBB_internal_malloc(size_t size)
{
return scalable_malloc(size);
}
void * __TBB_internal_calloc(size_t num, size_t size)
{
return scalable_calloc(num, size);
}
int __TBB_internal_posix_memalign(void **memptr, size_t alignment, size_t size)
{
return scalable_posix_memalign(memptr, alignment, size);
}
void* __TBB_internal_realloc(void* ptr, size_t sz)
{
return safer_scalable_realloc(ptr, sz, (void*&)original_realloc_ptr);
}
void __TBB_internal_free(void *object)
{
safer_scalable_free(object, original_free_ptr);
}
} /* extern "C" */
#endif /* MALLOC_LD_PRELOAD */
#endif /* MALLOC_CHECK_RECURSION */
} } // namespaces
#ifdef _WIN32
#include <windows.h>
extern "C" BOOL WINAPI DllMain( HINSTANCE hInst, DWORD callReason, LPVOID )
{
if (callReason==DLL_THREAD_DETACH)
{
mallocThreadShutdownNotification(NULL);
}
else if (callReason==DLL_PROCESS_DETACH)
{
mallocProcessShutdownNotification();
}
return TRUE;
}
#endif //_WIN32

View file

@ -0,0 +1,129 @@
// Copyright 2005-2009 Intel Corporation. All Rights Reserved.
//
// This file is part of Threading Building Blocks.
//
// Threading Building Blocks is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// version 2 as published by the Free Software Foundation.
//
// Threading Building Blocks is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Threading Building Blocks; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
// Microsoft Visual C++ generated resource script.
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include <winresrc.h>
#define ENDL "\r\n"
#include "../tbb/tbb_version.h"
#define TBBMALLOC_VERNUMBERS TBB_VERSION_MAJOR, TBB_VERSION_MINOR, __TBB_VERSION_YMD
#define TBBMALLOC_VERSION __TBB_STRING(TBBMALLOC_VERNUMBERS)
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Neutral resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
#ifdef _WIN32
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
// manifest integration
#ifdef TBB_MANIFEST
#include "winuser.h"
2 RT_MANIFEST tbbmanifest.exe.manifest
#endif
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION TBBMALLOC_VERNUMBERS
PRODUCTVERSION TBB_VERNUMBERS
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004b0"
BEGIN
VALUE "CompanyName", "Intel Corporation\0"
VALUE "FileDescription", "Scalable Allocator library\0"
VALUE "FileVersion", TBBMALLOC_VERSION "\0"
//what is it? VALUE "InternalName", "tbbmalloc\0"
VALUE "LegalCopyright", "Copyright 2005-2009 Intel Corporation. All Rights Reserved.\0"
VALUE "LegalTrademarks", "\0"
#ifndef TBB_USE_DEBUG
VALUE "OriginalFilename", "tbbmalloc.dll\0"
#else
VALUE "OriginalFilename", "tbbmalloc_debug.dll\0"
#endif
VALUE "ProductName", "Intel(R) Threading Building Blocks for Windows\0"
VALUE "ProductVersion", TBB_VERSION "\0"
VALUE "Comments", TBB_VERSION_STRINGS "\0"
VALUE "PrivateBuild", "\0"
VALUE "SpecialBuild", "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 1200
END
END
#endif // Neutral resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View file

@ -0,0 +1,37 @@
/*
Copyright 2005-2009 Intel Corporation. All Rights Reserved.
The source code contained or described herein and all documents related
to the source code ("Material") are owned by Intel Corporation or its
suppliers or licensors. Title to the Material remains with Intel
Corporation or its suppliers and licensors. The Material is protected
by worldwide copyright laws and treaty provisions. No part of the
Material may be used, copied, reproduced, modified, published, uploaded,
posted, transmitted, distributed, or disclosed in any way without
Intel's prior express written permission.
No license under any patent, copyright, trade secret or other
intellectual property right is granted to or conferred upon you by
disclosure or delivery of the Materials, either expressly, by
implication, inducement, estoppel or otherwise. Any license under such
intellectual property rights must be express and approved by Intel in
writing.
*/
{
global:
scalable_calloc;
scalable_free;
scalable_malloc;
scalable_realloc;
scalable_posix_memalign;
scalable_aligned_malloc;
scalable_aligned_realloc;
scalable_aligned_free;
safer_scalable_free;
safer_scalable_realloc;
scalable_msize;
safer_scalable_msize;
safer_scalable_aligned_realloc;
local:*;
};

View file

@ -0,0 +1,42 @@
; Copyright 2005-2009 Intel Corporation. All Rights Reserved.
;
; This file is part of Threading Building Blocks.
;
; Threading Building Blocks is free software; you can redistribute it
; and/or modify it under the terms of the GNU General Public License
; version 2 as published by the Free Software Foundation.
;
; Threading Building Blocks is distributed in the hope that it will be
; useful, but WITHOUT ANY WARRANTY; without even the implied warranty
; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with Threading Building Blocks; if not, write to the Free Software
; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
;
; As a special exception, you may use this file as part of a free software
; library without restriction. Specifically, if other files instantiate
; templates or use macros or inline functions from this file, or you compile
; this file and link it with other files to produce an executable, this
; file does not by itself cause the resulting executable to be covered by
; the GNU General Public License. This exception does not however
; invalidate any other reasons why the executable file might be covered by
; the GNU General Public License.
EXPORTS
; MemoryAllocator.cpp
scalable_calloc
scalable_free
scalable_malloc
scalable_realloc
scalable_posix_memalign
scalable_aligned_malloc
scalable_aligned_realloc
scalable_aligned_free
safer_scalable_free
safer_scalable_realloc
scalable_msize
safer_scalable_msize
safer_scalable_aligned_realloc

View file

@ -0,0 +1,42 @@
; Copyright 2005-2009 Intel Corporation. All Rights Reserved.
;
; This file is part of Threading Building Blocks.
;
; Threading Building Blocks is free software; you can redistribute it
; and/or modify it under the terms of the GNU General Public License
; version 2 as published by the Free Software Foundation.
;
; Threading Building Blocks is distributed in the hope that it will be
; useful, but WITHOUT ANY WARRANTY; without even the implied warranty
; of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with Threading Building Blocks; if not, write to the Free Software
; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
;
; As a special exception, you may use this file as part of a free software
; library without restriction. Specifically, if other files instantiate
; templates or use macros or inline functions from this file, or you compile
; this file and link it with other files to produce an executable, this
; file does not by itself cause the resulting executable to be covered by
; the GNU General Public License. This exception does not however
; invalidate any other reasons why the executable file might be covered by
; the GNU General Public License.
EXPORTS
; MemoryAllocator.cpp
scalable_calloc
scalable_free
scalable_malloc
scalable_realloc
scalable_posix_memalign
scalable_aligned_malloc
scalable_aligned_realloc
scalable_aligned_free
safer_scalable_free
safer_scalable_realloc
scalable_msize
safer_scalable_msize
safer_scalable_aligned_realloc