151c0b2f7Stbbdev /*
2*c21e688aSSergey Zheltov     Copyright (c) 2005-2022 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 #define __TBB_NO_IMPLICIT_LINKAGE 1
1851c0b2f7Stbbdev 
1951c0b2f7Stbbdev #if _USRDLL
2051c0b2f7Stbbdev 
2151c0b2f7Stbbdev #include <stdlib.h>
2251c0b2f7Stbbdev #include "common/config.h"
2351c0b2f7Stbbdev #include "common/utils_assert.h"
2451c0b2f7Stbbdev #include "tbb/scalable_allocator.h"
2551c0b2f7Stbbdev 
2651c0b2f7Stbbdev #if _WIN32||_WIN64
2751c0b2f7Stbbdev extern "C" {
2851c0b2f7Stbbdev     extern __declspec(dllexport) void callDll();
2951c0b2f7Stbbdev }
3051c0b2f7Stbbdev #endif
3151c0b2f7Stbbdev 
callDll()3251c0b2f7Stbbdev extern "C" void callDll()
3351c0b2f7Stbbdev {
3451c0b2f7Stbbdev     static const int NUM = 20;
3551c0b2f7Stbbdev     void *ptrs[NUM];
3651c0b2f7Stbbdev 
3751c0b2f7Stbbdev     for (int i=0; i<NUM; i++) {
3851c0b2f7Stbbdev         ptrs[i] = scalable_malloc(i*1024);
3957f524caSIlya Isaev         ASSERT(ptrs[i], nullptr);
4051c0b2f7Stbbdev     }
4151c0b2f7Stbbdev     for (int i=0; i<NUM; i++)
4251c0b2f7Stbbdev         scalable_free(ptrs[i]);
4351c0b2f7Stbbdev }
4451c0b2f7Stbbdev 
main()4551c0b2f7Stbbdev int main() {}
4651c0b2f7Stbbdev 
4751c0b2f7Stbbdev 
4851c0b2f7Stbbdev #else // _USRDLL
49a080baf9SAlex #include "common/config.h"
5051c0b2f7Stbbdev // FIXME: fix the test to support Windows* 8 Store Apps mode.
51a080baf9SAlex // For sanitizers, it fails because RUNPATH is lost: https://github.com/google/sanitizers/issues/1219
527941f880SIlya Isaev #if !__TBB_WIN8UI_SUPPORT && !(__GNUC__ && __GNUC__ < 10 && __TBB_USE_SANITIZERS) && __TBB_DYNAMIC_LOAD_ENABLED
5351c0b2f7Stbbdev 
5451c0b2f7Stbbdev #define __TBB_NO_IMPLICIT_LINKAGE 1
5551c0b2f7Stbbdev #include "common/test.h"
5651c0b2f7Stbbdev #include "common/utils.h"
5751c0b2f7Stbbdev #include "common/utils_dynamic_libs.h"
5851c0b2f7Stbbdev #include "common/utils_report.h"
5951c0b2f7Stbbdev #include "common/memory_usage.h"
6051c0b2f7Stbbdev #include "common/spin_barrier.h"
6151c0b2f7Stbbdev 
627941f880SIlya Isaev 
6351c0b2f7Stbbdev class UseDll {
6451c0b2f7Stbbdev     utils::FunctionAddress run;
6551c0b2f7Stbbdev public:
UseDll(utils::FunctionAddress runPtr)6651c0b2f7Stbbdev     UseDll(utils::FunctionAddress runPtr) : run(runPtr) { }
operator ()(std::size_t) const6751c0b2f7Stbbdev     void operator()( std::size_t /*id*/ ) const {
6851c0b2f7Stbbdev         (*run)();
6951c0b2f7Stbbdev     }
7051c0b2f7Stbbdev };
7151c0b2f7Stbbdev 
LoadThreadsUnload()7251c0b2f7Stbbdev void LoadThreadsUnload()
7351c0b2f7Stbbdev {
7451c0b2f7Stbbdev     utils::LIBRARY_HANDLE lib =
7551c0b2f7Stbbdev         utils::OpenLibrary(TEST_LIBRARY_NAME("_test_malloc_used_by_lib"));
7651c0b2f7Stbbdev     ASSERT(lib, "Can't load " TEST_LIBRARY_NAME("_test_malloc_used_by_lib"));
7751c0b2f7Stbbdev     utils::NativeParallelFor(std::size_t(4), UseDll(utils::GetAddress(lib, "callDll")));
7851c0b2f7Stbbdev     utils::CloseLibrary(lib);
7951c0b2f7Stbbdev }
8051c0b2f7Stbbdev 
8151c0b2f7Stbbdev struct UnloadCallback {
8251c0b2f7Stbbdev     utils::LIBRARY_HANDLE lib;
8351c0b2f7Stbbdev 
operator ()UnloadCallback8451c0b2f7Stbbdev     void operator() () const {
8551c0b2f7Stbbdev         utils::CloseLibrary(lib);
8651c0b2f7Stbbdev     }
8751c0b2f7Stbbdev };
8851c0b2f7Stbbdev 
8951c0b2f7Stbbdev struct RunWithLoad {
9051c0b2f7Stbbdev     static utils::SpinBarrier startBarr, endBarr;
9151c0b2f7Stbbdev     static UnloadCallback unloadCallback;
9251c0b2f7Stbbdev     static utils::FunctionAddress runPtr;
9351c0b2f7Stbbdev 
operator ()RunWithLoad9451c0b2f7Stbbdev     void operator()(std::size_t id) const {
9551c0b2f7Stbbdev         if (!id) {
9651c0b2f7Stbbdev             utils::LIBRARY_HANDLE lib =
9751c0b2f7Stbbdev                 utils::OpenLibrary(TEST_LIBRARY_NAME("_test_malloc_used_by_lib"));
9851c0b2f7Stbbdev             ASSERT(lib, "Can't load " TEST_LIBRARY_NAME("_test_malloc_used_by_lib"));
9951c0b2f7Stbbdev             runPtr = utils::GetAddress(lib, "callDll");
10051c0b2f7Stbbdev             unloadCallback.lib = lib;
10151c0b2f7Stbbdev         }
10251c0b2f7Stbbdev         startBarr.wait();
10351c0b2f7Stbbdev         (*runPtr)();
10451c0b2f7Stbbdev         endBarr.wait(unloadCallback);
10551c0b2f7Stbbdev     }
10651c0b2f7Stbbdev };
10751c0b2f7Stbbdev 
10851c0b2f7Stbbdev utils::SpinBarrier RunWithLoad::startBarr{}, RunWithLoad::endBarr{};
10951c0b2f7Stbbdev UnloadCallback RunWithLoad::unloadCallback;
11051c0b2f7Stbbdev utils::FunctionAddress RunWithLoad::runPtr;
11151c0b2f7Stbbdev 
ThreadsLoadUnload()11251c0b2f7Stbbdev void ThreadsLoadUnload() {
11351c0b2f7Stbbdev     constexpr std::size_t threads = 4;
11451c0b2f7Stbbdev 
11551c0b2f7Stbbdev     RunWithLoad::startBarr.initialize(threads);
11651c0b2f7Stbbdev     RunWithLoad::endBarr.initialize(threads);
11751c0b2f7Stbbdev     RunWithLoad body{};
11851c0b2f7Stbbdev     utils::NativeParallelFor(threads, body);
11951c0b2f7Stbbdev }
12051c0b2f7Stbbdev 
12151c0b2f7Stbbdev //! \brief \ref error_guessing
12251c0b2f7Stbbdev TEST_CASE("use test as lib") {
12351c0b2f7Stbbdev     const int ITERS = 20;
12451c0b2f7Stbbdev     int i;
12551c0b2f7Stbbdev     std::ptrdiff_t memory_leak = 0;
12651c0b2f7Stbbdev 
12751c0b2f7Stbbdev     utils::GetMemoryUsage();
12851c0b2f7Stbbdev 
12951c0b2f7Stbbdev     for (int run = 0; run < 2; run++) {
13051c0b2f7Stbbdev         // expect that memory consumption stabilized after several runs
13151c0b2f7Stbbdev         for (i = 0; i < ITERS; i++) {
13251c0b2f7Stbbdev             std::size_t memory_in_use = utils::GetMemoryUsage();
13351c0b2f7Stbbdev             if (run) {
13451c0b2f7Stbbdev                 LoadThreadsUnload();
13551c0b2f7Stbbdev             } else {
13651c0b2f7Stbbdev                 ThreadsLoadUnload();
13751c0b2f7Stbbdev             }
13851c0b2f7Stbbdev             memory_leak = utils::GetMemoryUsage() - memory_in_use;
13951c0b2f7Stbbdev             if (memory_leak == 0)  // possibly too strong?
14051c0b2f7Stbbdev                 break;
14151c0b2f7Stbbdev         }
14251c0b2f7Stbbdev         if(i==ITERS) {
14351c0b2f7Stbbdev             // not stabilized, could be leak
14451c0b2f7Stbbdev             REPORT( "Error: memory leak of up to %ld bytes\n", static_cast<long>(memory_leak));
14551c0b2f7Stbbdev             WARN(false);
14651c0b2f7Stbbdev         }
14751c0b2f7Stbbdev     }
14851c0b2f7Stbbdev }
149a080baf9SAlex #endif /* Unsupported configurations */
15051c0b2f7Stbbdev #endif // _USRDLL
151