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