1*51c0b2f7Stbbdev /* 2*51c0b2f7Stbbdev Copyright (c) 2005-2020 Intel Corporation 3*51c0b2f7Stbbdev 4*51c0b2f7Stbbdev Licensed under the Apache License, Version 2.0 (the "License"); 5*51c0b2f7Stbbdev you may not use this file except in compliance with the License. 6*51c0b2f7Stbbdev You may obtain a copy of the License at 7*51c0b2f7Stbbdev 8*51c0b2f7Stbbdev http://www.apache.org/licenses/LICENSE-2.0 9*51c0b2f7Stbbdev 10*51c0b2f7Stbbdev Unless required by applicable law or agreed to in writing, software 11*51c0b2f7Stbbdev distributed under the License is distributed on an "AS IS" BASIS, 12*51c0b2f7Stbbdev WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*51c0b2f7Stbbdev See the License for the specific language governing permissions and 14*51c0b2f7Stbbdev limitations under the License. 15*51c0b2f7Stbbdev */ 16*51c0b2f7Stbbdev 17*51c0b2f7Stbbdev 18*51c0b2f7Stbbdev #define __TBB_NO_IMPLICIT_LINKAGE 1 19*51c0b2f7Stbbdev 20*51c0b2f7Stbbdev #if _USRDLL 21*51c0b2f7Stbbdev #include "common/utils_assert.h" 22*51c0b2f7Stbbdev #include <stdlib.h> // for NULL 23*51c0b2f7Stbbdev 24*51c0b2f7Stbbdev const char *globalCallMsg = "A TBB allocator function call is resolved into wrong implementation."; 25*51c0b2f7Stbbdev 26*51c0b2f7Stbbdev #if _WIN32||_WIN64 27*51c0b2f7Stbbdev // must be defined in DLL for linker to not drop the dependency on the DLL. 28*51c0b2f7Stbbdev extern "C" { 29*51c0b2f7Stbbdev extern __declspec(dllexport) void *scalable_malloc(size_t); 30*51c0b2f7Stbbdev extern __declspec(dllexport) void scalable_free (void *); 31*51c0b2f7Stbbdev extern __declspec(dllexport) void safer_scalable_free (void *, void (*)(void*)); 32*51c0b2f7Stbbdev extern __declspec(dllexport) void *scalable_realloc(void *, size_t); 33*51c0b2f7Stbbdev extern __declspec(dllexport) void *safer_scalable_realloc(void *, size_t, void *); 34*51c0b2f7Stbbdev extern __declspec(dllexport) void *scalable_calloc(size_t, size_t); 35*51c0b2f7Stbbdev extern __declspec(dllexport) int scalable_posix_memalign(void **, size_t, size_t); 36*51c0b2f7Stbbdev extern __declspec(dllexport) void *scalable_aligned_malloc(size_t, size_t); 37*51c0b2f7Stbbdev extern __declspec(dllexport) void *scalable_aligned_realloc(void *, size_t, size_t); 38*51c0b2f7Stbbdev extern __declspec(dllexport) void *safer_scalable_aligned_realloc(void *, size_t, size_t, void *); 39*51c0b2f7Stbbdev extern __declspec(dllexport) void scalable_aligned_free(void *); 40*51c0b2f7Stbbdev extern __declspec(dllexport) size_t scalable_msize(void *); 41*51c0b2f7Stbbdev extern __declspec(dllexport) size_t safer_scalable_msize (void *, size_t (*)(void*)); 42*51c0b2f7Stbbdev } 43*51c0b2f7Stbbdev #endif 44*51c0b2f7Stbbdev 45*51c0b2f7Stbbdev // Those functions must not be called instead of presented in dynamic library. 46*51c0b2f7Stbbdev extern "C" void *scalable_malloc(size_t) 47*51c0b2f7Stbbdev { 48*51c0b2f7Stbbdev ASSERT(0, globalCallMsg); 49*51c0b2f7Stbbdev return NULL; 50*51c0b2f7Stbbdev } 51*51c0b2f7Stbbdev extern "C" void scalable_free (void *) 52*51c0b2f7Stbbdev { 53*51c0b2f7Stbbdev ASSERT(0, globalCallMsg); 54*51c0b2f7Stbbdev } 55*51c0b2f7Stbbdev extern "C" void safer_scalable_free (void *, void (*)(void*)) 56*51c0b2f7Stbbdev { 57*51c0b2f7Stbbdev ASSERT(0, globalCallMsg); 58*51c0b2f7Stbbdev } 59*51c0b2f7Stbbdev extern "C" void *scalable_realloc(void *, size_t) 60*51c0b2f7Stbbdev { 61*51c0b2f7Stbbdev ASSERT(0, globalCallMsg); 62*51c0b2f7Stbbdev return NULL; 63*51c0b2f7Stbbdev } 64*51c0b2f7Stbbdev extern "C" void *safer_scalable_realloc(void *, size_t, void *) 65*51c0b2f7Stbbdev { 66*51c0b2f7Stbbdev ASSERT(0, globalCallMsg); 67*51c0b2f7Stbbdev return NULL; 68*51c0b2f7Stbbdev } 69*51c0b2f7Stbbdev extern "C" void *scalable_calloc(size_t, size_t) 70*51c0b2f7Stbbdev { 71*51c0b2f7Stbbdev ASSERT(0, globalCallMsg); 72*51c0b2f7Stbbdev return NULL; 73*51c0b2f7Stbbdev } 74*51c0b2f7Stbbdev extern "C" int scalable_posix_memalign(void **, size_t, size_t) 75*51c0b2f7Stbbdev { 76*51c0b2f7Stbbdev ASSERT(0, globalCallMsg); 77*51c0b2f7Stbbdev return 0; 78*51c0b2f7Stbbdev } 79*51c0b2f7Stbbdev extern "C" void *scalable_aligned_malloc(size_t, size_t) 80*51c0b2f7Stbbdev { 81*51c0b2f7Stbbdev ASSERT(0, globalCallMsg); 82*51c0b2f7Stbbdev return NULL; 83*51c0b2f7Stbbdev } 84*51c0b2f7Stbbdev extern "C" void *scalable_aligned_realloc(void *, size_t, size_t) 85*51c0b2f7Stbbdev { 86*51c0b2f7Stbbdev ASSERT(0, globalCallMsg); 87*51c0b2f7Stbbdev return NULL; 88*51c0b2f7Stbbdev } 89*51c0b2f7Stbbdev extern "C" void *safer_scalable_aligned_realloc(void *, size_t, size_t, void *) 90*51c0b2f7Stbbdev { 91*51c0b2f7Stbbdev ASSERT(0, globalCallMsg); 92*51c0b2f7Stbbdev return NULL; 93*51c0b2f7Stbbdev } 94*51c0b2f7Stbbdev extern "C" void scalable_aligned_free(void *) 95*51c0b2f7Stbbdev { 96*51c0b2f7Stbbdev ASSERT(0, globalCallMsg); 97*51c0b2f7Stbbdev } 98*51c0b2f7Stbbdev extern "C" size_t scalable_msize(void *) 99*51c0b2f7Stbbdev { 100*51c0b2f7Stbbdev ASSERT(0, globalCallMsg); 101*51c0b2f7Stbbdev return 0; 102*51c0b2f7Stbbdev } 103*51c0b2f7Stbbdev extern "C" size_t safer_scalable_msize (void *, size_t (*)(void*)) 104*51c0b2f7Stbbdev { 105*51c0b2f7Stbbdev ASSERT(0, globalCallMsg); 106*51c0b2f7Stbbdev return 0; 107*51c0b2f7Stbbdev } 108*51c0b2f7Stbbdev 109*51c0b2f7Stbbdev int main() {} 110*51c0b2f7Stbbdev 111*51c0b2f7Stbbdev #else // _USRDLL 112*51c0b2f7Stbbdev 113*51c0b2f7Stbbdev // harness_defs.h must be included before tbb_stddef.h to overcome exception-dependent 114*51c0b2f7Stbbdev // system headers that come from tbb_stddef.h 115*51c0b2f7Stbbdev #if __TBB_WIN8UI_SUPPORT || __TBB_MIC_OFFLOAD 116*51c0b2f7Stbbdev // The test does not work if dynamic load is unavailable. 117*51c0b2f7Stbbdev // For MIC offload, it fails because liboffload brings libiomp which observes and uses the fake scalable_* calls. 118*51c0b2f7Stbbdev #else 119*51c0b2f7Stbbdev #include "common/test.h" 120*51c0b2f7Stbbdev #include "common/memory_usage.h" 121*51c0b2f7Stbbdev #include "common/utils_dynamic_libs.h" 122*51c0b2f7Stbbdev #include "common/utils_assert.h" 123*51c0b2f7Stbbdev #include "common/utils_report.h" 124*51c0b2f7Stbbdev #include <cstring> // memset 125*51c0b2f7Stbbdev 126*51c0b2f7Stbbdev extern "C" { 127*51c0b2f7Stbbdev #if _WIN32||_WIN64 128*51c0b2f7Stbbdev extern __declspec(dllimport) 129*51c0b2f7Stbbdev #endif 130*51c0b2f7Stbbdev void *scalable_malloc(size_t); 131*51c0b2f7Stbbdev } 132*51c0b2f7Stbbdev 133*51c0b2f7Stbbdev struct Run { 134*51c0b2f7Stbbdev void operator()( std::size_t /*id*/ ) const { 135*51c0b2f7Stbbdev 136*51c0b2f7Stbbdev void* (*malloc_ptr)(std::size_t); 137*51c0b2f7Stbbdev void (*free_ptr)(void*); 138*51c0b2f7Stbbdev 139*51c0b2f7Stbbdev void* (*aligned_malloc_ptr)(size_t size, size_t alignment); 140*51c0b2f7Stbbdev void (*aligned_free_ptr)(void*); 141*51c0b2f7Stbbdev 142*51c0b2f7Stbbdev const char* actual_name; 143*51c0b2f7Stbbdev utils::LIBRARY_HANDLE lib = utils::OpenLibrary(actual_name = MALLOCLIB_NAME1); 144*51c0b2f7Stbbdev if (!lib) lib = utils::OpenLibrary(actual_name = MALLOCLIB_NAME2); 145*51c0b2f7Stbbdev if (!lib) { 146*51c0b2f7Stbbdev REPORT("Can't load " MALLOCLIB_NAME1 " or " MALLOCLIB_NAME2 "\n"); 147*51c0b2f7Stbbdev exit(1); 148*51c0b2f7Stbbdev } 149*51c0b2f7Stbbdev utils::GetAddress(lib, "scalable_malloc", malloc_ptr); 150*51c0b2f7Stbbdev utils::GetAddress(lib, "scalable_free", free_ptr); 151*51c0b2f7Stbbdev utils::GetAddress(lib, "scalable_aligned_malloc", aligned_malloc_ptr); 152*51c0b2f7Stbbdev utils::GetAddress(lib, "scalable_aligned_free", aligned_free_ptr); 153*51c0b2f7Stbbdev 154*51c0b2f7Stbbdev for (size_t sz = 1024; sz <= 10*1024 ; sz*=10) { 155*51c0b2f7Stbbdev void *p1 = aligned_malloc_ptr(sz, 16); 156*51c0b2f7Stbbdev std::memset(p1, 0, sz); 157*51c0b2f7Stbbdev aligned_free_ptr(p1); 158*51c0b2f7Stbbdev } 159*51c0b2f7Stbbdev 160*51c0b2f7Stbbdev void *p = malloc_ptr(100); 161*51c0b2f7Stbbdev std::memset(p, 1, 100); 162*51c0b2f7Stbbdev free_ptr(p); 163*51c0b2f7Stbbdev 164*51c0b2f7Stbbdev utils::CloseLibrary(lib); 165*51c0b2f7Stbbdev #if _WIN32 || _WIN64 166*51c0b2f7Stbbdev ASSERT(GetModuleHandle(actual_name), 167*51c0b2f7Stbbdev "allocator library must not be unloaded"); 168*51c0b2f7Stbbdev #else 169*51c0b2f7Stbbdev ASSERT(dlsym(RTLD_DEFAULT, "scalable_malloc"), 170*51c0b2f7Stbbdev "allocator library must not be unloaded"); 171*51c0b2f7Stbbdev #endif 172*51c0b2f7Stbbdev } 173*51c0b2f7Stbbdev }; 174*51c0b2f7Stbbdev 175*51c0b2f7Stbbdev //! \brief \ref error_guessing 176*51c0b2f7Stbbdev TEST_CASE("test unload lib") { 177*51c0b2f7Stbbdev int i; 178*51c0b2f7Stbbdev std::ptrdiff_t memory_leak = 0; 179*51c0b2f7Stbbdev 180*51c0b2f7Stbbdev // warm-up run 181*51c0b2f7Stbbdev utils::NativeParallelFor( 1, Run() ); 182*51c0b2f7Stbbdev 183*51c0b2f7Stbbdev { 184*51c0b2f7Stbbdev /* 1st call to GetMemoryUsage() allocate some memory, 185*51c0b2f7Stbbdev but it seems memory consumption stabilized after this. 186*51c0b2f7Stbbdev */ 187*51c0b2f7Stbbdev utils::GetMemoryUsage(); 188*51c0b2f7Stbbdev std::size_t memory_in_use = utils::GetMemoryUsage(); 189*51c0b2f7Stbbdev std::size_t memory_check = utils::GetMemoryUsage(); 190*51c0b2f7Stbbdev REQUIRE_MESSAGE(memory_in_use == memory_check, 191*51c0b2f7Stbbdev "Memory consumption should not increase after 1st GetMemoryUsage() call"); 192*51c0b2f7Stbbdev } 193*51c0b2f7Stbbdev { 194*51c0b2f7Stbbdev // expect that memory consumption stabilized after several runs 195*51c0b2f7Stbbdev for (i=0; i<3; i++) { 196*51c0b2f7Stbbdev std::size_t memory_in_use = utils::GetMemoryUsage(); 197*51c0b2f7Stbbdev for (int j=0; j<10; j++) 198*51c0b2f7Stbbdev utils::NativeParallelFor( 1, Run() ); 199*51c0b2f7Stbbdev memory_leak = utils::GetMemoryUsage() - memory_in_use; 200*51c0b2f7Stbbdev if (memory_leak == 0) // possibly too strong? 201*51c0b2f7Stbbdev break; 202*51c0b2f7Stbbdev } 203*51c0b2f7Stbbdev } 204*51c0b2f7Stbbdev if(3==i) { 205*51c0b2f7Stbbdev // not stabilized, could be leak 206*51c0b2f7Stbbdev REPORT( "Error: memory leak of up to %ld bytes\n", static_cast<long>(memory_leak)); 207*51c0b2f7Stbbdev exit(1); 208*51c0b2f7Stbbdev } 209*51c0b2f7Stbbdev 210*51c0b2f7Stbbdev } 211*51c0b2f7Stbbdev 212*51c0b2f7Stbbdev #endif /* __TBB_WIN8UI_SUPPORT */ 213*51c0b2f7Stbbdev 214*51c0b2f7Stbbdev #endif // _USRDLL 215