1 /*
2 Copyright (c) 2005-2020 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
32 extern "C" {
33 extern __declspec(dllexport) void callDll();
34 }
35 #endif
36
callDll()37 extern "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
52 struct RegisterProcessShutdownNotification {
~RegisterProcessShutdownNotificationRegisterProcessShutdownNotification53 ~RegisterProcessShutdownNotification() {
54 __TBB_mallocProcessShutdownNotification();
55 }
56 };
57
58 static 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
79 class UseDll {
80 Harness::FunctionAddress run;
81 public:
UseDll(Harness::FunctionAddress runPtr)82 UseDll(Harness::FunctionAddress runPtr) : run(runPtr) { }
operator ()(int) const83 void operator()( int /*id*/ ) const {
84 (*run)();
85 }
86 };
87
LoadThreadsUnload()88 void 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
97 struct UnloadCallback {
98 Harness::LIBRARY_HANDLE lib;
99
operator ()UnloadCallback100 void operator() () const {
101 Harness::CloseLibrary(lib);
102 }
103 };
104
105 struct RunWithLoad : NoAssign {
106 static Harness::SpinBarrier startBarr, endBarr;
107 static UnloadCallback unloadCallback;
108 static Harness::FunctionAddress runPtr;
109
operator ()RunWithLoad110 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
124 Harness::SpinBarrier RunWithLoad::startBarr, RunWithLoad::endBarr;
125 UnloadCallback RunWithLoad::unloadCallback;
126 Harness::FunctionAddress RunWithLoad::runPtr;
127
ThreadsLoadUnload()128 void ThreadsLoadUnload()
129 {
130 const int threads = 4;
131
132 RunWithLoad::startBarr.initialize(threads);
133 RunWithLoad::endBarr.initialize(threads);
134 NativeParallelFor(threads, RunWithLoad());
135 }
136
TestMain()137 int 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