151c0b2f7Stbbdev /*
2*b15aabb3Stbbdev     Copyright (c) 2005-2021 Intel Corporation
351c0b2f7Stbbdev 
451c0b2f7Stbbdev     Licensed under the Apache License, Version 2.0 (the "License");
551c0b2f7Stbbdev     you may not use this file except in compliance with the License.
651c0b2f7Stbbdev     You may obtain a copy of the License at
751c0b2f7Stbbdev 
851c0b2f7Stbbdev         http://www.apache.org/licenses/LICENSE-2.0
951c0b2f7Stbbdev 
1051c0b2f7Stbbdev     Unless required by applicable law or agreed to in writing, software
1151c0b2f7Stbbdev     distributed under the License is distributed on an "AS IS" BASIS,
1251c0b2f7Stbbdev     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1351c0b2f7Stbbdev     See the License for the specific language governing permissions and
1451c0b2f7Stbbdev     limitations under the License.
1551c0b2f7Stbbdev */
1651c0b2f7Stbbdev 
1751c0b2f7Stbbdev 
1851c0b2f7Stbbdev #define __TBB_NO_IMPLICIT_LINKAGE 1
1951c0b2f7Stbbdev 
2051c0b2f7Stbbdev #if _USRDLL
2151c0b2f7Stbbdev #include "common/utils_assert.h"
2251c0b2f7Stbbdev #include <stdlib.h> // for NULL
2351c0b2f7Stbbdev 
2451c0b2f7Stbbdev const char *globalCallMsg = "A TBB allocator function call is resolved into wrong implementation.";
2551c0b2f7Stbbdev 
2651c0b2f7Stbbdev #if _WIN32||_WIN64
2751c0b2f7Stbbdev // must be defined in DLL for linker to not drop the dependency on the DLL.
2851c0b2f7Stbbdev extern "C" {
2951c0b2f7Stbbdev     extern __declspec(dllexport) void *scalable_malloc(size_t);
3051c0b2f7Stbbdev     extern __declspec(dllexport) void scalable_free (void *);
3151c0b2f7Stbbdev     extern __declspec(dllexport) void safer_scalable_free (void *, void (*)(void*));
3251c0b2f7Stbbdev     extern __declspec(dllexport) void *scalable_realloc(void *, size_t);
3351c0b2f7Stbbdev     extern __declspec(dllexport) void *safer_scalable_realloc(void *, size_t, void *);
3451c0b2f7Stbbdev     extern __declspec(dllexport) void *scalable_calloc(size_t, size_t);
3551c0b2f7Stbbdev     extern __declspec(dllexport) int scalable_posix_memalign(void **, size_t, size_t);
3651c0b2f7Stbbdev     extern __declspec(dllexport) void *scalable_aligned_malloc(size_t, size_t);
3751c0b2f7Stbbdev     extern __declspec(dllexport) void *scalable_aligned_realloc(void *, size_t, size_t);
3851c0b2f7Stbbdev     extern __declspec(dllexport) void *safer_scalable_aligned_realloc(void *, size_t, size_t, void *);
3951c0b2f7Stbbdev     extern __declspec(dllexport) void scalable_aligned_free(void *);
4051c0b2f7Stbbdev     extern __declspec(dllexport) size_t scalable_msize(void *);
4151c0b2f7Stbbdev     extern __declspec(dllexport) size_t safer_scalable_msize (void *, size_t (*)(void*));
4251c0b2f7Stbbdev }
4351c0b2f7Stbbdev #endif
4451c0b2f7Stbbdev 
4551c0b2f7Stbbdev // Those functions must not be called instead of presented in dynamic library.
4651c0b2f7Stbbdev extern "C" void *scalable_malloc(size_t)
4751c0b2f7Stbbdev {
4851c0b2f7Stbbdev     ASSERT(0, globalCallMsg);
4951c0b2f7Stbbdev     return NULL;
5051c0b2f7Stbbdev }
5151c0b2f7Stbbdev extern "C" void scalable_free (void *)
5251c0b2f7Stbbdev {
5351c0b2f7Stbbdev     ASSERT(0, globalCallMsg);
5451c0b2f7Stbbdev }
5551c0b2f7Stbbdev extern "C" void safer_scalable_free (void *, void (*)(void*))
5651c0b2f7Stbbdev {
5751c0b2f7Stbbdev     ASSERT(0, globalCallMsg);
5851c0b2f7Stbbdev }
5951c0b2f7Stbbdev extern "C" void *scalable_realloc(void *, size_t)
6051c0b2f7Stbbdev {
6151c0b2f7Stbbdev     ASSERT(0, globalCallMsg);
6251c0b2f7Stbbdev     return NULL;
6351c0b2f7Stbbdev }
6451c0b2f7Stbbdev extern "C" void *safer_scalable_realloc(void *, size_t, void *)
6551c0b2f7Stbbdev {
6651c0b2f7Stbbdev     ASSERT(0, globalCallMsg);
6751c0b2f7Stbbdev     return NULL;
6851c0b2f7Stbbdev }
6951c0b2f7Stbbdev extern "C" void *scalable_calloc(size_t, size_t)
7051c0b2f7Stbbdev {
7151c0b2f7Stbbdev     ASSERT(0, globalCallMsg);
7251c0b2f7Stbbdev     return NULL;
7351c0b2f7Stbbdev }
7451c0b2f7Stbbdev extern "C" int scalable_posix_memalign(void **, size_t, size_t)
7551c0b2f7Stbbdev {
7651c0b2f7Stbbdev     ASSERT(0, globalCallMsg);
7751c0b2f7Stbbdev     return 0;
7851c0b2f7Stbbdev }
7951c0b2f7Stbbdev extern "C" void *scalable_aligned_malloc(size_t, size_t)
8051c0b2f7Stbbdev {
8151c0b2f7Stbbdev     ASSERT(0, globalCallMsg);
8251c0b2f7Stbbdev     return NULL;
8351c0b2f7Stbbdev }
8451c0b2f7Stbbdev extern "C" void *scalable_aligned_realloc(void *, size_t, size_t)
8551c0b2f7Stbbdev {
8651c0b2f7Stbbdev     ASSERT(0, globalCallMsg);
8751c0b2f7Stbbdev     return NULL;
8851c0b2f7Stbbdev }
8951c0b2f7Stbbdev extern "C" void *safer_scalable_aligned_realloc(void *, size_t, size_t, void *)
9051c0b2f7Stbbdev {
9151c0b2f7Stbbdev     ASSERT(0, globalCallMsg);
9251c0b2f7Stbbdev     return NULL;
9351c0b2f7Stbbdev }
9451c0b2f7Stbbdev extern "C" void scalable_aligned_free(void *)
9551c0b2f7Stbbdev {
9651c0b2f7Stbbdev     ASSERT(0, globalCallMsg);
9751c0b2f7Stbbdev }
9851c0b2f7Stbbdev extern "C" size_t scalable_msize(void *)
9951c0b2f7Stbbdev {
10051c0b2f7Stbbdev     ASSERT(0, globalCallMsg);
10151c0b2f7Stbbdev     return 0;
10251c0b2f7Stbbdev }
10351c0b2f7Stbbdev extern "C" size_t safer_scalable_msize (void *, size_t (*)(void*))
10451c0b2f7Stbbdev {
10551c0b2f7Stbbdev     ASSERT(0, globalCallMsg);
10651c0b2f7Stbbdev     return 0;
10751c0b2f7Stbbdev }
10851c0b2f7Stbbdev 
10951c0b2f7Stbbdev int main() {}
11051c0b2f7Stbbdev 
11151c0b2f7Stbbdev #else  // _USRDLL
11251c0b2f7Stbbdev 
11351c0b2f7Stbbdev // harness_defs.h must be included before tbb_stddef.h to overcome exception-dependent
11451c0b2f7Stbbdev // system headers that come from tbb_stddef.h
11551c0b2f7Stbbdev #if __TBB_WIN8UI_SUPPORT || __TBB_MIC_OFFLOAD
11651c0b2f7Stbbdev // The test does not work if dynamic load is unavailable.
11751c0b2f7Stbbdev // For MIC offload, it fails because liboffload brings libiomp which observes and uses the fake scalable_* calls.
11849e08aacStbbdev #else /* !(__TBB_WIN8UI_SUPPORT || __TBB_MIC_OFFLOAD) */
11951c0b2f7Stbbdev #include "common/test.h"
12051c0b2f7Stbbdev #include "common/memory_usage.h"
12151c0b2f7Stbbdev #include "common/utils_dynamic_libs.h"
12251c0b2f7Stbbdev #include "common/utils_assert.h"
12351c0b2f7Stbbdev #include "common/utils_report.h"
12451c0b2f7Stbbdev #include <cstring> // memset
12551c0b2f7Stbbdev 
12651c0b2f7Stbbdev extern "C" {
12751c0b2f7Stbbdev #if _WIN32||_WIN64
12851c0b2f7Stbbdev     extern __declspec(dllimport)
12951c0b2f7Stbbdev #endif
13051c0b2f7Stbbdev     void *scalable_malloc(size_t);
13151c0b2f7Stbbdev }
13251c0b2f7Stbbdev 
13351c0b2f7Stbbdev struct Run {
13451c0b2f7Stbbdev     void operator()( std::size_t /*id*/ ) const {
13551c0b2f7Stbbdev 
13651c0b2f7Stbbdev         void* (*malloc_ptr)(std::size_t);
13751c0b2f7Stbbdev         void (*free_ptr)(void*);
13851c0b2f7Stbbdev 
13951c0b2f7Stbbdev         void* (*aligned_malloc_ptr)(size_t size, size_t alignment);
14051c0b2f7Stbbdev         void  (*aligned_free_ptr)(void*);
14151c0b2f7Stbbdev 
14251c0b2f7Stbbdev         const char* actual_name;
14351c0b2f7Stbbdev         utils::LIBRARY_HANDLE lib = utils::OpenLibrary(actual_name = MALLOCLIB_NAME1);
14451c0b2f7Stbbdev         if (!lib)      lib = utils::OpenLibrary(actual_name = MALLOCLIB_NAME2);
14551c0b2f7Stbbdev         if (!lib) {
14651c0b2f7Stbbdev             REPORT("Can't load " MALLOCLIB_NAME1 " or " MALLOCLIB_NAME2 "\n");
14751c0b2f7Stbbdev             exit(1);
14851c0b2f7Stbbdev         }
14951c0b2f7Stbbdev         utils::GetAddress(lib, "scalable_malloc", malloc_ptr);
15051c0b2f7Stbbdev         utils::GetAddress(lib, "scalable_free", free_ptr);
15151c0b2f7Stbbdev         utils::GetAddress(lib, "scalable_aligned_malloc", aligned_malloc_ptr);
15251c0b2f7Stbbdev         utils::GetAddress(lib, "scalable_aligned_free", aligned_free_ptr);
15351c0b2f7Stbbdev 
15451c0b2f7Stbbdev         for (size_t sz = 1024; sz <= 10*1024 ; sz*=10) {
15551c0b2f7Stbbdev             void *p1 = aligned_malloc_ptr(sz, 16);
15651c0b2f7Stbbdev             std::memset(p1, 0, sz);
15751c0b2f7Stbbdev             aligned_free_ptr(p1);
15851c0b2f7Stbbdev         }
15951c0b2f7Stbbdev 
16051c0b2f7Stbbdev         void *p = malloc_ptr(100);
16151c0b2f7Stbbdev         std::memset(p, 1, 100);
16251c0b2f7Stbbdev         free_ptr(p);
16351c0b2f7Stbbdev 
16451c0b2f7Stbbdev         utils::CloseLibrary(lib);
16551c0b2f7Stbbdev #if _WIN32 || _WIN64
16651c0b2f7Stbbdev         ASSERT(GetModuleHandle(actual_name),
16751c0b2f7Stbbdev                "allocator library must not be unloaded");
16851c0b2f7Stbbdev #else
16951c0b2f7Stbbdev         ASSERT(dlsym(RTLD_DEFAULT, "scalable_malloc"),
17051c0b2f7Stbbdev                "allocator library must not be unloaded");
17151c0b2f7Stbbdev #endif
17251c0b2f7Stbbdev     }
17351c0b2f7Stbbdev };
17451c0b2f7Stbbdev 
17551c0b2f7Stbbdev //! \brief \ref error_guessing
17651c0b2f7Stbbdev TEST_CASE("test unload lib") {
17751c0b2f7Stbbdev     std::ptrdiff_t memory_leak = 0;
17851c0b2f7Stbbdev 
17951c0b2f7Stbbdev     // warm-up run
18051c0b2f7Stbbdev     utils::NativeParallelFor( 1, Run() );
18151c0b2f7Stbbdev 
18251c0b2f7Stbbdev     {
18351c0b2f7Stbbdev         /* 1st call to GetMemoryUsage() allocate some memory,
18451c0b2f7Stbbdev            but it seems memory consumption stabilized after this.
18551c0b2f7Stbbdev         */
18651c0b2f7Stbbdev         utils::GetMemoryUsage();
18751c0b2f7Stbbdev         std::size_t memory_in_use = utils::GetMemoryUsage();
18851c0b2f7Stbbdev         std::size_t memory_check = utils::GetMemoryUsage();
18951c0b2f7Stbbdev         REQUIRE_MESSAGE(memory_in_use == memory_check,
19051c0b2f7Stbbdev             "Memory consumption should not increase after 1st GetMemoryUsage() call");
19151c0b2f7Stbbdev     }
19251c0b2f7Stbbdev     {
19351c0b2f7Stbbdev         // expect that memory consumption stabilized after several runs
19449e08aacStbbdev         for (;;) {
19551c0b2f7Stbbdev             std::size_t memory_in_use = utils::GetMemoryUsage();
19651c0b2f7Stbbdev             for (int j=0; j<10; j++)
19751c0b2f7Stbbdev                 utils::NativeParallelFor( 1, Run() );
19851c0b2f7Stbbdev             memory_leak = utils::GetMemoryUsage() - memory_in_use;
19949e08aacStbbdev             if (memory_leak == 0)
20049e08aacStbbdev                 return;
20151c0b2f7Stbbdev         }
20251c0b2f7Stbbdev     }
20351c0b2f7Stbbdev }
20451c0b2f7Stbbdev 
20549e08aacStbbdev #endif /* !(__TBB_WIN8UI_SUPPORT || __TBB_MIC_OFFLOAD) */
20651c0b2f7Stbbdev 
20751c0b2f7Stbbdev #endif // _USRDLL
208