1/*
2 Copyright (c) 2005-2019 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#if _USRDLL
18
19#include <stdlib.h>
20#include "harness_defs.h"
21#include "tbb/scalable_allocator.h"
22#if __TBB_SOURCE_DIRECTLY_INCLUDED
23#include "../tbbmalloc/tbbmalloc_internal_api.h"
24#endif
25
26#define HARNESS_CUSTOM_MAIN 1
27#define HARNESS_NO_PARSE_COMMAND_LINE 1
28#include "harness.h"
29#include "harness_assert.h"
30
31#if _WIN32||_WIN64
32extern "C" {
33 extern __declspec(dllexport) void callDll();
34}
35#endif
36
37extern "C" void callDll()
38{
39 static const int NUM = 20;
40 void *ptrs[NUM];
41
42 for (int i=0; i<NUM; i++) {
43 ptrs[i] = scalable_malloc(i*1024);
44 ASSERT(ptrs[i], NULL);
45 }
46 for (int i=0; i<NUM; i++)
47 scalable_free(ptrs[i]);
48}
49
50#if __TBB_SOURCE_DIRECTLY_INCLUDED
51
52struct RegisterProcessShutdownNotification {
53 ~RegisterProcessShutdownNotification() {
54 __TBB_mallocProcessShutdownNotification();
55 }
56};
57
58static RegisterProcessShutdownNotification reg;
59
60#endif
61
62#else // _USRDLL
63
64#define __TBB_NO_IMPLICIT_LINKAGE 1
65#include "harness_dynamic_libs.h"
66#if __TBB_WIN8UI_SUPPORT
67// FIXME: fix the test to support Windows* 8 Store Apps mode.
68#define HARNESS_SKIP_TEST 1
69#endif
70#define HARNESS_NO_PARSE_COMMAND_LINE 1
71#include "harness.h"
72
73#if !HARNESS_SKIP_TEST
74
75#include "harness_memory.h"
76#include "harness_tbb_independence.h"
77#include "harness_barrier.h"
78
79class UseDll {
80 Harness::FunctionAddress run;
81public:
82 UseDll(Harness::FunctionAddress runPtr) : run(runPtr) { }
83 void operator()( int /*id*/ ) const {
84 (*run)();
85 }
86};
87
88void LoadThreadsUnload()
89{
90 Harness::LIBRARY_HANDLE lib =
91 Harness::OpenLibrary(TEST_LIBRARY_NAME("test_malloc_used_by_lib_dll"));
92 ASSERT(lib, "Can't load " TEST_LIBRARY_NAME("test_malloc_used_by_lib_dll"));
93 NativeParallelFor( 4, UseDll( Harness::GetAddress(lib, "callDll") ) );
94 Harness::CloseLibrary(lib);
95}
96
97struct UnloadCallback {
98 Harness::LIBRARY_HANDLE lib;
99
100 void operator() () const {
101 Harness::CloseLibrary(lib);
102 }
103};
104
105struct RunWithLoad : NoAssign {
106 static Harness::SpinBarrier startBarr, endBarr;
107 static UnloadCallback unloadCallback;
108 static Harness::FunctionAddress runPtr;
109
110 void operator()(int id) const {
111 if (!id) {
112 Harness::LIBRARY_HANDLE lib =
113 Harness::OpenLibrary(TEST_LIBRARY_NAME("test_malloc_used_by_lib_dll"));
114 ASSERT(lib, "Can't load " TEST_LIBRARY_NAME("test_malloc_used_by_lib_dll"));
115 runPtr = Harness::GetAddress(lib, "callDll");
116 unloadCallback.lib = lib;
117 }
118 startBarr.wait();
119 (*runPtr)();
120 endBarr.wait(unloadCallback);
121 }
122};
123
124Harness::SpinBarrier RunWithLoad::startBarr, RunWithLoad::endBarr;
125UnloadCallback RunWithLoad::unloadCallback;
126Harness::FunctionAddress RunWithLoad::runPtr;
127
128void ThreadsLoadUnload()
129{
130 const int threads = 4;
131
132 RunWithLoad::startBarr.initialize(threads);
133 RunWithLoad::endBarr.initialize(threads);
134 NativeParallelFor(threads, RunWithLoad());
135}
136
137int TestMain () {
138 const int ITERS = 20;
139 int i;
140 std::ptrdiff_t memory_leak = 0;
141
142 GetMemoryUsage();
143
144 for (int run = 0; run<2; run++) {
145 // expect that memory consumption stabilized after several runs
146 for (i=0; i<ITERS; i++) {
147 std::size_t memory_in_use = GetMemoryUsage();
148 if (run)
149 LoadThreadsUnload();
150 else
151 ThreadsLoadUnload();
152 memory_leak = GetMemoryUsage() - memory_in_use;
153 if (memory_leak == 0) // possibly too strong?
154 break;
155 }
156 if(i==ITERS) {
157 // not stabilized, could be leak
158 REPORT( "Error: memory leak of up to %ld bytes\n", static_cast<long>(memory_leak));
159 exit(1);
160 }
161 }
162
163 return Harness::Done;
164}
165
166#endif /* HARNESS_SKIP_TEST */
167#endif // _USRDLL
168