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> // for NULL
20#include "harness_assert.h"
21#define HARNESS_CUSTOM_MAIN 1
22#define HARNESS_NO_PARSE_COMMAND_LINE 1
23#include "harness.h"
24
25const char *globalCallMsg = "A TBB allocator function call is resolved into wrong implementation.";
26
27#if _WIN32||_WIN64
28// must be defined in DLL for linker to not drop the dependency on the DLL.
29extern "C" {
30 extern __declspec(dllexport) void *scalable_malloc(size_t);
31 extern __declspec(dllexport) void scalable_free (void *);
32 extern __declspec(dllexport) void safer_scalable_free (void *, void (*)(void*));
33 extern __declspec(dllexport) void *scalable_realloc(void *, size_t);
34 extern __declspec(dllexport) void *safer_scalable_realloc(void *, size_t, void *);
35 extern __declspec(dllexport) void *scalable_calloc(size_t, size_t);
36 extern __declspec(dllexport) int scalable_posix_memalign(void **, size_t, size_t);
37 extern __declspec(dllexport) void *scalable_aligned_malloc(size_t, size_t);
38 extern __declspec(dllexport) void *scalable_aligned_realloc(void *, size_t, size_t);
39 extern __declspec(dllexport) void *safer_scalable_aligned_realloc(void *, size_t, size_t, void *);
40 extern __declspec(dllexport) void scalable_aligned_free(void *);
41 extern __declspec(dllexport) size_t scalable_msize(void *);
42 extern __declspec(dllexport) size_t safer_scalable_msize (void *, size_t (*)(void*));
43}
44#endif
45
46// Those functions must not be called instead of presented in dynamic library.
47extern "C" void *scalable_malloc(size_t)
48{
49 ASSERT(0, globalCallMsg);
50 return NULL;
51}
52extern "C" void scalable_free (void *)
53{
54 ASSERT(0, globalCallMsg);
55}
56extern "C" void safer_scalable_free (void *, void (*)(void*))
57{
58 ASSERT(0, globalCallMsg);
59}
60extern "C" void *scalable_realloc(void *, size_t)
61{
62 ASSERT(0, globalCallMsg);
63 return NULL;
64}
65extern "C" void *safer_scalable_realloc(void *, size_t, void *)
66{
67 ASSERT(0, globalCallMsg);
68 return NULL;
69}
70extern "C" void *scalable_calloc(size_t, size_t)
71{
72 ASSERT(0, globalCallMsg);
73 return NULL;
74}
75extern "C" int scalable_posix_memalign(void **, size_t, size_t)
76{
77 ASSERT(0, globalCallMsg);
78 return 0;
79}
80extern "C" void *scalable_aligned_malloc(size_t, size_t)
81{
82 ASSERT(0, globalCallMsg);
83 return NULL;
84}
85extern "C" void *scalable_aligned_realloc(void *, size_t, size_t)
86{
87 ASSERT(0, globalCallMsg);
88 return NULL;
89}
90extern "C" void *safer_scalable_aligned_realloc(void *, size_t, size_t, void *)
91{
92 ASSERT(0, globalCallMsg);
93 return NULL;
94}
95extern "C" void scalable_aligned_free(void *)
96{
97 ASSERT(0, globalCallMsg);
98}
99extern "C" size_t scalable_msize(void *)
100{
101 ASSERT(0, globalCallMsg);
102 return 0;
103}
104extern "C" size_t safer_scalable_msize (void *, size_t (*)(void*))
105{
106 ASSERT(0, globalCallMsg);
107 return 0;
108}
109
110#else // _USRDLL
111
112// harness_defs.h must be included before tbb_stddef.h to overcome exception-dependent
113// system headers that come from tbb_stddef.h
114#include "harness_defs.h"
115#include "tbb/tbb_stddef.h"
116#if __TBB_WIN8UI_SUPPORT || __TBB_SOURCE_DIRECTLY_INCLUDED || __TBB_MIC_OFFLOAD
117// The test does not work if dynamic load is unavailable.
118// For MIC offload, it fails because liboffload brings libiomp which observes and uses the fake scalable_* calls.
119#define HARNESS_SKIP_TEST 1
120#endif
121#define HARNESS_NO_PARSE_COMMAND_LINE 1
122#define HARNESS_TBBMALLOC_THREAD_SHUTDOWN 1
123#include "harness.h"
124
125#if !HARNESS_SKIP_TEST
126
127#include "harness_dynamic_libs.h"
128#include "harness_memory.h"
129
130extern "C" {
131#if _WIN32||_WIN64
132extern __declspec(dllimport)
133#endif
134void *scalable_malloc(size_t);
135}
136
137struct Run {
138 void operator()( int /*id*/ ) const {
139 using namespace Harness;
140
141 void* (*malloc_ptr)(std::size_t);
142 void (*free_ptr)(void*);
143
144 void* (*aligned_malloc_ptr)(size_t size, size_t alignment);
145 void (*aligned_free_ptr)(void*);
146
147 const char* actual_name;
148 LIBRARY_HANDLE lib = OpenLibrary(actual_name = MALLOCLIB_NAME1);
149 if (!lib) lib = OpenLibrary(actual_name = MALLOCLIB_NAME2);
150 if (!lib) {
151 REPORT("Can't load " MALLOCLIB_NAME1 " or " MALLOCLIB_NAME2 "\n");
152 exit(1);
153 }
154 GetAddress(lib, "scalable_malloc", malloc_ptr);
155 GetAddress(lib, "scalable_free", free_ptr);
156 GetAddress(lib, "scalable_aligned_malloc", aligned_malloc_ptr);
157 GetAddress(lib, "scalable_aligned_free", aligned_free_ptr);
158
159 for (size_t sz = 1024; sz <= 10*1024 ; sz*=10) {
160 void *p1 = aligned_malloc_ptr(sz, 16);
161 memset(p1, 0, sz);
162 aligned_free_ptr(p1);
163 }
164
165 void *p = malloc_ptr(100);
166 memset(p, 1, 100);
167 free_ptr(p);
168
169 CloseLibrary(lib);
170#if _WIN32 || _WIN64
171 ASSERT(GetModuleHandle(actual_name),
172 "allocator library must not be unloaded");
173#else
174 ASSERT(dlsym(RTLD_DEFAULT, "scalable_malloc"),
175 "allocator library must not be unloaded");
176#endif
177 }
178};
179
180int TestMain () {
181 int i;
182 std::ptrdiff_t memory_leak;
183
184 // warm-up run
185 NativeParallelFor( 1, Run() );
186
187 {
188 /* 1st call to GetMemoryUsage() allocate some memory,
189 but it seems memory consumption stabilized after this.
190 */
191 GetMemoryUsage();
192 std::size_t memory_in_use = GetMemoryUsage();
193 ASSERT(memory_in_use == GetMemoryUsage(),
194 "Memory consumption should not increase after 1st GetMemoryUsage() call");
195 }
196 {
197 // expect that memory consumption stabilized after several runs
198 for (i=0; i<3; i++) {
199 std::size_t memory_in_use = GetMemoryUsage();
200 for (int j=0; j<10; j++)
201 NativeParallelFor( 1, Run() );
202 memory_leak = GetMemoryUsage() - memory_in_use;
203 if (memory_leak == 0) // possibly too strong?
204 break;
205 }
206 }
207 if(3==i) {
208 // not stabilized, could be leak
209 REPORT( "Error: memory leak of up to %ld bytes\n", static_cast<long>(memory_leak));
210 exit(1);
211 }
212
213 return Harness::Done;
214}
215
216#endif /* HARNESS_SKIP_TEST */
217
218#endif // _USRDLL
219