| /* |
| Copyright 2005-2010 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 <stdio.h> |
| #if _WIN32 || _WIN64 |
| #include <windows.h> |
| #else |
| #include <dlfcn.h> |
| #endif |
| #include <tbb/tbb_stddef.h> |
| #define HARNESS_NO_PARSE_COMMAND_LINE 1 |
| #include "harness.h" |
| #include "harness_memory.h" |
| |
| #if TBB_USE_DEBUG |
| #define SUFFIX1 "_debug" |
| #define SUFFIX2 |
| #else |
| #define SUFFIX1 |
| #define SUFFIX2 "_debug" |
| #endif /* TBB_USE_DEBUG */ |
| |
| #if _WIN32||_WIN64 |
| #define PREFIX |
| #define EXT ".dll" |
| #else |
| #define PREFIX "lib" |
| #if __APPLE__ |
| #define EXT ".dylib" |
| #elif __linux__ |
| #define EXT __TBB_STRING(.so.TBB_COMPATIBLE_INTERFACE_VERSION) |
| #elif __FreeBSD__ || __sun |
| #define EXT ".so" |
| #else |
| #error Unknown OS |
| #endif |
| #endif |
| |
| // Form the names of the TBB memory allocator binaries. |
| #define MALLOCLIB_NAME1 PREFIX "tbbmalloc" SUFFIX1 EXT |
| #define MALLOCLIB_NAME2 PREFIX "tbbmalloc" SUFFIX2 EXT |
| |
| #if _WIN32 || _WIN64 |
| #define LIBRARY_HANDLE HMODULE |
| #define LOAD_LIBRARY(name) LoadLibrary((name)) |
| #else |
| #define LIBRARY_HANDLE void* |
| #define LOAD_LIBRARY(name) dlopen((name), RTLD_NOW|RTLD_GLOBAL) |
| #endif |
| |
| struct Run { |
| void operator()( int /*id*/ ) const { |
| void* (*malloc_ptr)(size_t); |
| void (*free_ptr)(void*); |
| |
| const char* actual_name; |
| LIBRARY_HANDLE lib = LOAD_LIBRARY(actual_name = MALLOCLIB_NAME1); |
| if (!lib) lib = LOAD_LIBRARY(actual_name = MALLOCLIB_NAME2); |
| if (!lib) { |
| REPORT("Can't load " MALLOCLIB_NAME1 " or " MALLOCLIB_NAME2 "\n"); |
| exit(1); |
| } |
| #if _WIN32 || _WIN64 |
| // casts at both sides are to soothe MinGW compiler |
| (void *&)malloc_ptr = (void*)GetProcAddress(lib, "scalable_malloc"); |
| (void *&)free_ptr = (void*)GetProcAddress(lib, "scalable_free"); |
| #else |
| (void *&)malloc_ptr = dlsym(lib, "scalable_malloc"); |
| (void *&)free_ptr = dlsym(lib, "scalable_free"); |
| #endif |
| if (!malloc_ptr || !free_ptr) { |
| REPORT("Can't find scalable_(malloc|free) in %s \n", actual_name); |
| exit(1); |
| } |
| |
| void *p = malloc_ptr(100); |
| memset(p, 1, 100); |
| free_ptr(p); |
| |
| #if _WIN32 || _WIN64 |
| BOOL ret = FreeLibrary(lib); |
| ASSERT(ret, "FreeLibrary must be successful"); |
| ASSERT(GetModuleHandle(actual_name), |
| "allocator library must not be unloaded"); |
| #else |
| int ret = dlclose(lib); |
| ASSERT(ret == 0, "dlclose must be successful"); |
| ASSERT(dlsym(RTLD_DEFAULT, "scalable_malloc"), |
| "allocator library must not be unloaded"); |
| #endif |
| } |
| }; |
| |
| int TestMain () { |
| int i; |
| ptrdiff_t memory_leak; |
| |
| // warm-up run |
| NativeParallelFor( 1, Run() ); |
| /* 1st call to GetMemoryUsage() allocate some memory, |
| but it seems memory consumption stabilized after this. |
| */ |
| GetMemoryUsage(); |
| size_t memory_in_use = GetMemoryUsage(); |
| ASSERT(memory_in_use == GetMemoryUsage(), |
| "Memory consumption should not increase after 1st GetMemoryUsage() call"); |
| |
| // expect that memory consumption stabilized after several runs |
| for (i=0; i<3; i++) { |
| size_t memory_in_use = GetMemoryUsage(); |
| for (int j=0; j<10; j++) |
| NativeParallelFor( 1, Run() ); |
| memory_leak = GetMemoryUsage() - memory_in_use; |
| if (memory_leak == 0) // possibly too strong? |
| break; |
| } |
| if(3==i) { |
| // not stabilized, could be leak |
| REPORT( "Error: memory leak of up to %ld bytes\n", static_cast<long>(memory_leak)); |
| exit(1); |
| } |
| |
| return Harness::Done; |
| } |