summaryrefslogtreecommitdiff
path: root/runtime/contrib/heap_trace
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/contrib/heap_trace')
-rw-r--r--runtime/contrib/heap_trace/CMakeLists.txt18
-rw-r--r--runtime/contrib/heap_trace/src/cl_create_buffer_stub.cc44
-rw-r--r--runtime/contrib/heap_trace/src/cl_release_mem_object.cc43
-rw-r--r--runtime/contrib/heap_trace/src/free_stub.cc35
-rw-r--r--runtime/contrib/heap_trace/src/function_resolver.h29
-rw-r--r--runtime/contrib/heap_trace/src/malloc_stub.cc39
-rw-r--r--runtime/contrib/heap_trace/src/realloc_stub.cc40
-rw-r--r--runtime/contrib/heap_trace/src/symbol_searcher.cc82
-rw-r--r--runtime/contrib/heap_trace/src/symbol_searcher.h22
-rw-r--r--runtime/contrib/heap_trace/src/trace.cc103
-rw-r--r--runtime/contrib/heap_trace/src/trace.h75
-rw-r--r--runtime/contrib/heap_trace/src/valloc_stub.cc39
-rw-r--r--runtime/contrib/heap_trace/tests/CMakeLists.txt43
-rw-r--r--runtime/contrib/heap_trace/tests/src/cl_create_buffer_interception_test.cc89
-rw-r--r--runtime/contrib/heap_trace/tests/src/cl_release_mem_object_interception_test.cc91
-rw-r--r--runtime/contrib/heap_trace/tests/src/common_test_environment.cc51
-rw-r--r--runtime/contrib/heap_trace/tests/src/common_test_environment.h38
-rw-r--r--runtime/contrib/heap_trace/tests/src/file_content_manipulations.cc25
-rw-r--r--runtime/contrib/heap_trace/tests/src/file_content_manipulations.h24
-rw-r--r--runtime/contrib/heap_trace/tests/src/free_interception_test.cc60
-rw-r--r--runtime/contrib/heap_trace/tests/src/main.cc23
-rw-r--r--runtime/contrib/heap_trace/tests/src/malloc_interception_test.cc87
-rw-r--r--runtime/contrib/heap_trace/tests/src/realloc_interception_test.cc110
-rw-r--r--runtime/contrib/heap_trace/tests/src/symbol_searcher_test.cc79
-rw-r--r--runtime/contrib/heap_trace/tests/src/test_sample1.h25
-rw-r--r--runtime/contrib/heap_trace/tests/src/test_sample1/test_sample1.cc27
-rw-r--r--runtime/contrib/heap_trace/tests/src/test_sample2.h26
-rw-r--r--runtime/contrib/heap_trace/tests/src/test_sample2/test_sample2.cc24
-rw-r--r--runtime/contrib/heap_trace/tests/src/test_sample3.h25
-rw-r--r--runtime/contrib/heap_trace/tests/src/test_sample3/test_sample3.cc20
-rw-r--r--runtime/contrib/heap_trace/tests/src/test_sample4.h25
-rw-r--r--runtime/contrib/heap_trace/tests/src/test_sample4/test_sample4.cc21
-rw-r--r--runtime/contrib/heap_trace/tests/src/trace_test.cc175
-rw-r--r--runtime/contrib/heap_trace/tests/src/valloc_interception_test.cc73
34 files changed, 1730 insertions, 0 deletions
diff --git a/runtime/contrib/heap_trace/CMakeLists.txt b/runtime/contrib/heap_trace/CMakeLists.txt
new file mode 100644
index 000000000..1f18152d8
--- /dev/null
+++ b/runtime/contrib/heap_trace/CMakeLists.txt
@@ -0,0 +1,18 @@
+if(NOT BUILD_HEAP_TRACE)
+ return()
+endif(NOT BUILD_HEAP_TRACE)
+
+add_library(heap_trace SHARED src/cl_create_buffer_stub.cc
+ src/cl_release_mem_object.cc
+ src/free_stub.cc
+ src/malloc_stub.cc
+ src/realloc_stub.cc
+ src/valloc_stub.cc
+ src/symbol_searcher.cc
+ src/trace.cc
+)
+target_link_libraries(heap_trace PRIVATE ${CMAKE_DL_LIBS})
+
+add_subdirectory(tests)
+
+install(TARGETS heap_trace DESTINATION lib)
diff --git a/runtime/contrib/heap_trace/src/cl_create_buffer_stub.cc b/runtime/contrib/heap_trace/src/cl_create_buffer_stub.cc
new file mode 100644
index 000000000..d9d2700ee
--- /dev/null
+++ b/runtime/contrib/heap_trace/src/cl_create_buffer_stub.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "trace.h"
+#include "function_resolver.h"
+
+#include <CL/cl.h>
+
+#include <memory>
+
+extern std::unique_ptr<Trace> GlobalTrace;
+
+extern "C" {
+
+cl_mem clCreateBuffer(cl_context context, cl_mem_flags flags, size_t size, void *host_ptr,
+ cl_int *errcode_ret)
+{
+ static auto isOriginalFunctionCallSuccessful = [](cl_mem result) -> bool { return result; };
+
+ static auto originalFunction =
+ findFunctionByName<cl_mem, cl_context, cl_mem_flags, size_t, void *, cl_int *>(
+ "clCreateBuffer");
+ cl_mem result = originalFunction(context, flags, size, host_ptr, errcode_ret);
+ if (isOriginalFunctionCallSuccessful(result) && !Trace::Guard{}.isActive())
+ {
+ GlobalTrace->logAllocationEvent(result, size);
+ }
+
+ return result;
+}
+}
diff --git a/runtime/contrib/heap_trace/src/cl_release_mem_object.cc b/runtime/contrib/heap_trace/src/cl_release_mem_object.cc
new file mode 100644
index 000000000..f2f249e0b
--- /dev/null
+++ b/runtime/contrib/heap_trace/src/cl_release_mem_object.cc
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "trace.h"
+#include "function_resolver.h"
+
+#include <CL/cl.h>
+
+#include <memory>
+
+extern std::unique_ptr<Trace> GlobalTrace;
+
+extern "C" {
+
+cl_int clReleaseMemObject(cl_mem mem)
+{
+ static auto isOriginalFunctionCallSuccessful = [](cl_int result) -> bool {
+ return result == CL_SUCCESS;
+ };
+
+ auto originalFunction = findFunctionByName<cl_int, cl_mem>("clReleaseMemObject");
+ cl_int result = originalFunction(mem);
+ if (isOriginalFunctionCallSuccessful(result) && !Trace::Guard{}.isActive())
+ {
+ GlobalTrace->logDeallocationEvent(mem);
+ }
+
+ return result;
+}
+}
diff --git a/runtime/contrib/heap_trace/src/free_stub.cc b/runtime/contrib/heap_trace/src/free_stub.cc
new file mode 100644
index 000000000..31af63c8a
--- /dev/null
+++ b/runtime/contrib/heap_trace/src/free_stub.cc
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "trace.h"
+#include "function_resolver.h"
+
+#include <memory>
+
+extern std::unique_ptr<Trace> GlobalTrace;
+
+extern "C" {
+
+void free(void *p) noexcept
+{
+ static auto originalFunction = findFunctionByName<void, void *>("free");
+ originalFunction(p);
+ if (!Trace::Guard{}.isActive())
+ {
+ GlobalTrace->logDeallocationEvent(p);
+ }
+}
+}
diff --git a/runtime/contrib/heap_trace/src/function_resolver.h b/runtime/contrib/heap_trace/src/function_resolver.h
new file mode 100644
index 000000000..9b6879539
--- /dev/null
+++ b/runtime/contrib/heap_trace/src/function_resolver.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FUNCTION_RESOLVER_H
+#define FUNCTION_RESOLVER_H
+
+#include "symbol_searcher.h"
+
+template <typename ReturnType, typename... ArgTypes>
+ReturnType (*findFunctionByName(const char *function_name))(ArgTypes...)
+{
+ auto found_symbol = findSymbol(function_name);
+ return reinterpret_cast<ReturnType (*)(ArgTypes...)>(found_symbol);
+}
+
+#endif // ! FUNCTION_RESOLVER_H
diff --git a/runtime/contrib/heap_trace/src/malloc_stub.cc b/runtime/contrib/heap_trace/src/malloc_stub.cc
new file mode 100644
index 000000000..50124d164
--- /dev/null
+++ b/runtime/contrib/heap_trace/src/malloc_stub.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "trace.h"
+#include "function_resolver.h"
+
+#include <memory>
+
+extern std::unique_ptr<Trace> GlobalTrace;
+
+extern "C" {
+
+void *malloc(size_t sz) noexcept
+{
+ static auto isOriginalFunctionCallSuccessful = [](void *result) -> bool { return result; };
+
+ static auto originalFunction = findFunctionByName<void *, size_t>("malloc");
+ void *result = originalFunction(sz);
+ if (isOriginalFunctionCallSuccessful(result) && !Trace::Guard{}.isActive())
+ {
+ GlobalTrace->logAllocationEvent(result, sz);
+ }
+
+ return result;
+}
+}
diff --git a/runtime/contrib/heap_trace/src/realloc_stub.cc b/runtime/contrib/heap_trace/src/realloc_stub.cc
new file mode 100644
index 000000000..ce4569b0e
--- /dev/null
+++ b/runtime/contrib/heap_trace/src/realloc_stub.cc
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "trace.h"
+#include "function_resolver.h"
+
+#include <memory>
+
+extern std::unique_ptr<Trace> GlobalTrace;
+
+extern "C" {
+
+void *realloc(void *ptr, size_t sz) noexcept
+{
+ static auto isOriginalFunctionCallSuccessful = [](void *result) -> bool { return result; };
+
+ static auto originalFunction = findFunctionByName<void *, void *, size_t>("realloc");
+ void *result = originalFunction(ptr, sz);
+ if (isOriginalFunctionCallSuccessful(result) && !Trace::Guard{}.isActive())
+ {
+ GlobalTrace->logDeallocationEvent(ptr);
+ GlobalTrace->logAllocationEvent(result, sz);
+ }
+
+ return result;
+}
+}
diff --git a/runtime/contrib/heap_trace/src/symbol_searcher.cc b/runtime/contrib/heap_trace/src/symbol_searcher.cc
new file mode 100644
index 000000000..cf83f2f7b
--- /dev/null
+++ b/runtime/contrib/heap_trace/src/symbol_searcher.cc
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "symbol_searcher.h"
+
+#include <dlfcn.h>
+#include <link.h>
+
+struct SymbolDescription
+{
+ const char *name;
+ void *address = nullptr; // address in memory where this symbol can be found
+
+ SymbolDescription(const char *name) : name(name) {}
+};
+
+using InfoAboutLoadedLib = struct dl_phdr_info *;
+
+static void tryToFindSymbolInLinkedLibraries(SymbolDescription &symbol);
+static void tryToFindSymbolInAllLoadedLibraries(SymbolDescription &symbol);
+static int checkIfLibraryContainsSymbol(InfoAboutLoadedLib library_description, size_t /* size */,
+ void *data);
+static bool isSymbolAddressNotInTheSameTranslationUnit(SymbolDescription *symbol);
+void *findSymbol(const char *name)
+{
+ SymbolDescription symbol(name);
+ tryToFindSymbolInLinkedLibraries(symbol);
+ if (!symbol.address)
+ {
+ tryToFindSymbolInAllLoadedLibraries(symbol);
+ }
+
+ return symbol.address;
+}
+
+static void tryToFindSymbolInLinkedLibraries(SymbolDescription &symbol)
+{
+ symbol.address = dlsym(RTLD_NEXT, symbol.name);
+}
+
+static void tryToFindSymbolInAllLoadedLibraries(SymbolDescription &symbol)
+{
+ dl_iterate_phdr(checkIfLibraryContainsSymbol, &symbol);
+}
+
+static int checkIfLibraryContainsSymbol(InfoAboutLoadedLib library_description, size_t /* size */,
+ void *data)
+{
+ SymbolDescription *symbol = (SymbolDescription *)data;
+
+ void *handle = dlopen(library_description->dlpi_name, RTLD_NOW);
+ symbol->address = dlsym(handle, symbol->name);
+ dlclose(handle);
+ if (symbol->address && isSymbolAddressNotInTheSameTranslationUnit(symbol))
+ {
+ return 1;
+ }
+ return 0;
+}
+
+static bool isSymbolAddressNotInTheSameTranslationUnit(SymbolDescription *symbol)
+{
+ void *handle = dlopen("", RTLD_NOW);
+ void *addressInTheSameTranslationUnit = dlsym(handle, symbol->name);
+ dlclose(handle);
+
+ return addressInTheSameTranslationUnit == nullptr ||
+ addressInTheSameTranslationUnit != symbol->address;
+}
diff --git a/runtime/contrib/heap_trace/src/symbol_searcher.h b/runtime/contrib/heap_trace/src/symbol_searcher.h
new file mode 100644
index 000000000..f70a4e46f
--- /dev/null
+++ b/runtime/contrib/heap_trace/src/symbol_searcher.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYMBOL_SEARCHER_H
+#define SYMBOL_SEARCHER_H
+
+void *findSymbol(const char *name);
+
+#endif // ! SYMBOL_SEARCHER_H
diff --git a/runtime/contrib/heap_trace/src/trace.cc b/runtime/contrib/heap_trace/src/trace.cc
new file mode 100644
index 000000000..82f2915cb
--- /dev/null
+++ b/runtime/contrib/heap_trace/src/trace.cc
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "trace.h"
+
+#include <memory>
+
+std::unique_ptr<Trace> GlobalTrace(new Trace);
+
+bool Trace::Guard::_is_trace_not_available = true;
+thread_local bool Trace::Guard::_is_recursion_detected = false;
+
+Trace::Trace()
+{
+ if (!_out.is_open())
+ {
+ _out.open(getLogFileNameFromEnvVariable("HEAP_TRACE_LOG"));
+ }
+
+ Guard{}.markTraceAsReady();
+}
+
+const char *Trace::getLogFileNameFromEnvVariable(const char *env_variable_name)
+{
+ return getenv(env_variable_name);
+}
+
+void Trace::logAllocationEvent(void *memory_ptr, size_t size_of_allocated_space_in_bytes)
+{
+ Guard{}.signalizeAboutPossibleRecursion();
+ std::lock_guard<std::mutex> guard(_lock);
+ _total_allocated_bytes_on_cpu += size_of_allocated_space_in_bytes;
+ if (_peak_heap_usage_on_cpu < _total_allocated_bytes_on_cpu - _total_deallocated_bytes_on_cpu)
+ {
+ _peak_heap_usage_on_cpu = _total_allocated_bytes_on_cpu - _total_deallocated_bytes_on_cpu;
+ }
+ _memory_in_use_on_cpu[memory_ptr] = size_of_allocated_space_in_bytes;
+ Guard{}.signalizeThatDangerOfRecursionHAsPassed();
+}
+
+void Trace::logDeallocationEvent(void *memory_ptr)
+{
+ Guard{}.signalizeAboutPossibleRecursion();
+ std::lock_guard<std::mutex> guard(_lock);
+ auto found_memory_space_description = _memory_in_use_on_cpu.find(memory_ptr);
+ if (found_memory_space_description != _memory_in_use_on_cpu.end())
+ {
+ _total_deallocated_bytes_on_cpu += found_memory_space_description->second;
+ _memory_in_use_on_cpu.erase(found_memory_space_description);
+ }
+ Guard{}.signalizeThatDangerOfRecursionHAsPassed();
+}
+
+void Trace::logAllocationEvent(cl_mem memory_ptr, size_t size_of_allocated_space_in_bytes)
+{
+ Guard{}.signalizeAboutPossibleRecursion();
+ std::lock_guard<std::mutex> guard(_lock);
+ _total_allocated_bytes_on_gpu += size_of_allocated_space_in_bytes;
+ if (_peak_heap_usage_on_gpu < _total_allocated_bytes_on_gpu - _total_deallocated_bytes_on_gpu)
+ {
+ _peak_heap_usage_on_gpu = _total_allocated_bytes_on_gpu - _total_deallocated_bytes_on_gpu;
+ }
+ _memory_in_use_on_gpu[memory_ptr] = size_of_allocated_space_in_bytes;
+ Guard{}.signalizeThatDangerOfRecursionHAsPassed();
+}
+
+void Trace::logDeallocationEvent(cl_mem memory_ptr)
+{
+ Guard{}.signalizeAboutPossibleRecursion();
+ std::lock_guard<std::mutex> guard(_lock);
+ auto found_memory_space_description = _memory_in_use_on_gpu.find(memory_ptr);
+ if (found_memory_space_description != _memory_in_use_on_gpu.end())
+ {
+ _total_deallocated_bytes_on_gpu += found_memory_space_description->second;
+ _memory_in_use_on_gpu.erase(found_memory_space_description);
+ }
+ Guard{}.signalizeThatDangerOfRecursionHAsPassed();
+}
+
+Trace::~Trace()
+{
+ Guard{}.markTraceAsNotReady();
+
+ _out << "On CPU - Peak heap usage: " << _peak_heap_usage_on_cpu
+ << " B, Total allocated: " << _total_allocated_bytes_on_cpu
+ << " B, Total deallocated: " << _total_deallocated_bytes_on_cpu << " B\n";
+ _out << "On GPU - Peak mem usage: " << _peak_heap_usage_on_gpu
+ << " B, Total allocated: " << _total_allocated_bytes_on_gpu
+ << " B, Total deallocated: " << _total_deallocated_bytes_on_gpu << " B\n";
+}
diff --git a/runtime/contrib/heap_trace/src/trace.h b/runtime/contrib/heap_trace/src/trace.h
new file mode 100644
index 000000000..f03a65a58
--- /dev/null
+++ b/runtime/contrib/heap_trace/src/trace.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TRACE_H_
+#define TRACE_H_
+
+#include <CL/cl.h>
+
+#include <unordered_map>
+#include <fstream>
+#include <mutex>
+
+class Trace
+{
+public:
+ class Guard
+ {
+ friend class Trace;
+
+ public:
+ bool isActive() { return _is_trace_not_available || _is_recursion_detected; }
+
+ private:
+ void markTraceAsReady() { _is_trace_not_available = false; }
+ void markTraceAsNotReady() { _is_trace_not_available = true; }
+ void signalizeAboutPossibleRecursion() { _is_recursion_detected = true; }
+ void signalizeThatDangerOfRecursionHAsPassed() { _is_recursion_detected = false; }
+
+ private:
+ static bool _is_trace_not_available;
+ static thread_local bool _is_recursion_detected;
+ };
+
+public:
+ Trace();
+ Trace(const Trace &) = delete;
+ const Trace &operator=(const Trace &) = delete;
+
+ void logAllocationEvent(void *memory_ptr, size_t size_of_allocated_space_in_bytes);
+ void logAllocationEvent(cl_mem memory_ptr, size_t size_of_allocated_space_in_bytes);
+ void logDeallocationEvent(void *memory_ptr);
+ void logDeallocationEvent(cl_mem memory_ptr);
+
+ ~Trace();
+
+private:
+ const char *getLogFileNameFromEnvVariable(const char *env_variable_name);
+
+private:
+ std::mutex _lock;
+ std::ofstream _out;
+ size_t _total_allocated_bytes_on_cpu = 0;
+ size_t _total_deallocated_bytes_on_cpu = 0;
+ size_t _peak_heap_usage_on_cpu = 0;
+ size_t _total_allocated_bytes_on_gpu = 0;
+ size_t _total_deallocated_bytes_on_gpu = 0;
+ size_t _peak_heap_usage_on_gpu = 0;
+ std::unordered_map<void *, size_t> _memory_in_use_on_cpu;
+ std::unordered_map<cl_mem, size_t> _memory_in_use_on_gpu;
+};
+
+#endif // !TRACE_H
diff --git a/runtime/contrib/heap_trace/src/valloc_stub.cc b/runtime/contrib/heap_trace/src/valloc_stub.cc
new file mode 100644
index 000000000..24e91bd11
--- /dev/null
+++ b/runtime/contrib/heap_trace/src/valloc_stub.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "trace.h"
+#include "function_resolver.h"
+
+#include <memory>
+
+extern std::unique_ptr<Trace> GlobalTrace;
+
+extern "C" {
+
+void *valloc(size_t sz) noexcept
+{
+ static auto isOriginalFunctionCallSuccessful = [](void *result) -> bool { return result; };
+
+ static auto originalFunction = findFunctionByName<void *, size_t>("valloc");
+ void *result = originalFunction(sz);
+ if (isOriginalFunctionCallSuccessful(result) && !Trace::Guard{}.isActive())
+ {
+ GlobalTrace->logAllocationEvent(result, sz);
+ }
+
+ return result;
+}
+}
diff --git a/runtime/contrib/heap_trace/tests/CMakeLists.txt b/runtime/contrib/heap_trace/tests/CMakeLists.txt
new file mode 100644
index 000000000..8fbe5dec1
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/CMakeLists.txt
@@ -0,0 +1,43 @@
+set(HEAP_TRACE_TESTS heap_trace_test)
+
+find_package(OpenCL REQUIRED)
+
+add_library(test_sample1 SHARED src/test_sample1/test_sample1.cc)
+
+add_library(test_sample2 SHARED src/test_sample2/test_sample2.cc)
+target_link_libraries(test_sample2 test_sample3)
+
+add_library(test_sample3 SHARED src/test_sample3/test_sample3.cc)
+
+add_library(test_sample4 SHARED src/test_sample4/test_sample4.cc)
+
+add_executable(${HEAP_TRACE_TESTS} src/cl_release_mem_object_interception_test.cc
+ src/symbol_searcher_test.cc
+ src/cl_create_buffer_interception_test.cc
+ src/free_interception_test.cc
+ src/main.cc
+ src/common_test_environment.cc
+ src/trace_test.cc
+ src/malloc_interception_test.cc
+ src/realloc_interception_test.cc
+ src/valloc_interception_test.cc
+ src/file_content_manipulations.cc
+ )
+target_include_directories(${HEAP_TRACE_TESTS} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src)
+target_link_libraries(${HEAP_TRACE_TESTS} test_sample1)
+target_link_libraries(${HEAP_TRACE_TESTS} heap_trace)
+target_link_libraries(${HEAP_TRACE_TESTS} test_sample4)
+target_link_libraries(${HEAP_TRACE_TESTS} gtest)
+target_link_libraries(${HEAP_TRACE_TESTS} gtest_main)
+target_link_libraries(${HEAP_TRACE_TESTS} ${LIB_PTHREAD})
+target_link_libraries(${HEAP_TRACE_TESTS} ${CMAKE_DL_LIBS})
+target_link_libraries(${HEAP_TRACE_TESTS} ${OpenCL_LIBRARY})
+target_link_libraries(${HEAP_TRACE_TESTS} stdc++fs)
+
+add_test(${HEAP_TRACE_TESTS} ${HEAP_TRACE_TESTS})
+
+install(TARGETS test_sample1 DESTINATION unittest)
+install(TARGETS test_sample2 DESTINATION unittest)
+install(TARGETS test_sample3 DESTINATION unittest)
+install(TARGETS test_sample4 DESTINATION unittest)
+install(TARGETS ${HEAP_TRACE_TESTS} DESTINATION unittest)
diff --git a/runtime/contrib/heap_trace/tests/src/cl_create_buffer_interception_test.cc b/runtime/contrib/heap_trace/tests/src/cl_create_buffer_interception_test.cc
new file mode 100644
index 000000000..33d01868e
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/cl_create_buffer_interception_test.cc
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common_test_environment.h"
+#include "file_content_manipulations.h"
+
+#include "trace.h"
+
+#include <CL/cl.h>
+
+extern std::unique_ptr<Trace> GlobalTrace;
+
+namespace backstage
+{
+
+struct ClCreateBufferStub : public TestEnv
+{
+ cl_context context;
+
+ ClCreateBufferStub() : TestEnv("./cl_create_buffer_interception_test.log") {}
+
+ void SetUp() final
+ {
+ cl_device_id device_id;
+ int err = clGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, 1, &device_id, NULL);
+ context = clCreateContext(0, 1, &device_id, NULL, NULL, &err);
+
+ TestEnv::SetUp();
+ }
+
+ void TearDown() final
+ {
+ TestEnv::TearDown();
+
+ clReleaseContext(context);
+ }
+};
+
+TEST_F(ClCreateBufferStub, must_allocate_space_as_standard_ocl_function)
+{
+ cl_mem mem = clCreateBuffer(context, CL_MEM_READ_WRITE, 1024 * 1024, NULL, NULL);
+
+ ASSERT_TRUE(mem);
+
+ clReleaseMemObject(mem);
+}
+
+TEST_F(ClCreateBufferStub, must_log_allocation_events_if_trace_is_ready_for_it)
+{
+ GlobalTrace.reset();
+ clReleaseMemObject(clCreateBuffer(context, CL_MEM_READ_WRITE, 1024, NULL, NULL));
+
+ GlobalTrace.reset(new Trace);
+ clReleaseMemObject(clCreateBuffer(context, CL_MEM_READ_WRITE, 128, NULL, NULL));
+ clReleaseMemObject(clCreateBuffer(context, CL_MEM_READ_WRITE, 64, NULL, NULL));
+ GlobalTrace.reset();
+
+ ASSERT_STREQ(getContentOfFile("./cl_create_buffer_interception_test.log").c_str(),
+ "On CPU - Peak heap usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\nOn "
+ "GPU - Peak mem usage: 128 B, Total allocated: 192 B, Total deallocated: 192 B\n");
+}
+
+TEST_F(ClCreateBufferStub,
+ must_not_do_the_record_about_allocation_event_if_original_function_failed)
+{
+ cl_context badContext = nullptr;
+ cl_mem p = clCreateBuffer(badContext, CL_MEM_READ_WRITE, 1024, nullptr, nullptr);
+ GlobalTrace.reset();
+
+ ASSERT_FALSE(p);
+ ASSERT_STREQ(getContentOfFile("./cl_create_buffer_interception_test.log").c_str(),
+ "On CPU - Peak heap usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\nOn "
+ "GPU - Peak mem usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\n");
+}
+
+} // namespace backstage
diff --git a/runtime/contrib/heap_trace/tests/src/cl_release_mem_object_interception_test.cc b/runtime/contrib/heap_trace/tests/src/cl_release_mem_object_interception_test.cc
new file mode 100644
index 000000000..ddd1a0d5c
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/cl_release_mem_object_interception_test.cc
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common_test_environment.h"
+#include "file_content_manipulations.h"
+
+#include "trace.h"
+
+#include <CL/cl.h>
+
+extern std::unique_ptr<Trace> GlobalTrace;
+
+namespace backstage
+{
+
+struct ClReleaseMemObjectStub : public TestEnv
+{
+ cl_context context;
+
+ ClReleaseMemObjectStub() : TestEnv("./cl_release_mem_object_interception_test.log") {}
+
+ void SetUp() final
+ {
+ cl_device_id device_id;
+ int err = clGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, 1, &device_id, NULL);
+ context = clCreateContext(0, 1, &device_id, NULL, NULL, &err);
+
+ TestEnv::SetUp();
+ }
+
+ void TearDown() final
+ {
+ TestEnv::TearDown();
+
+ clReleaseContext(context);
+ }
+};
+
+TEST_F(ClReleaseMemObjectStub, should_work_as_standard_version)
+{
+ cl_mem mem = clCreateBuffer(context, CL_MEM_READ_WRITE, 1024, NULL, NULL);
+ clReleaseMemObject(mem);
+ ASSERT_TRUE(mem);
+}
+
+TEST_F(ClReleaseMemObjectStub, must_log_deallocation_events_if_trace_is_ready_for_it)
+{
+ GlobalTrace.reset();
+ cl_mem mem1 = clCreateBuffer(context, CL_MEM_READ_WRITE, 1024, NULL, NULL);
+ ASSERT_TRUE(mem1);
+ clReleaseMemObject(mem1);
+
+ GlobalTrace.reset(new Trace);
+ cl_mem mem2 = clCreateBuffer(context, CL_MEM_READ_WRITE, 128, NULL, NULL);
+ cl_mem mem3 = clCreateBuffer(context, CL_MEM_READ_WRITE, 64, NULL, NULL);
+ ASSERT_TRUE(mem2 && mem3);
+ clReleaseMemObject(mem2);
+ clReleaseMemObject(mem3);
+ GlobalTrace.reset();
+
+ ASSERT_STREQ(getContentOfFile("./cl_release_mem_object_interception_test.log").c_str(),
+ "On CPU - Peak heap usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\nOn "
+ "GPU - Peak mem usage: 192 B, Total allocated: 192 B, Total deallocated: 192 B\n");
+}
+
+TEST_F(ClReleaseMemObjectStub, must_not_log_deallocation_event_if_original_function_failed)
+{
+ cl_mem mem;
+ ASSERT_NE(clReleaseMemObject(mem), CL_SUCCESS);
+
+ GlobalTrace.reset();
+
+ ASSERT_STREQ(getContentOfFile("./cl_release_mem_object_interception_test.log").c_str(),
+ "On CPU - Peak heap usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\nOn "
+ "GPU - Peak mem usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\n");
+}
+
+} // namespace backstage
diff --git a/runtime/contrib/heap_trace/tests/src/common_test_environment.cc b/runtime/contrib/heap_trace/tests/src/common_test_environment.cc
new file mode 100644
index 000000000..e5c4dc121
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/common_test_environment.cc
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common_test_environment.h"
+
+#include "trace.h"
+
+#include <experimental/filesystem>
+
+namespace fs = std::experimental::filesystem;
+
+extern std::unique_ptr<Trace> GlobalTrace;
+
+void TestEnv::SetUp() { configureTraceToMakeLogInFile(); }
+
+void TestEnv::TearDown() { removeOldTraceLogIfNeed(); }
+
+void TestEnv::configureTraceToMakeLogInFile()
+{
+ removeOldTraceLogIfNeed();
+ setNewNameOfTraceLog();
+}
+
+void TestEnv::removeOldTraceLogIfNeed()
+{
+ GlobalTrace.reset();
+ const char *trace_log_name = getenv("HEAP_TRACE_LOG");
+ if (trace_log_name)
+ {
+ fs::remove(trace_log_name);
+ }
+}
+
+void TestEnv::setNewNameOfTraceLog()
+{
+ setenv("HEAP_TRACE_LOG", test_log_file.c_str(), 1);
+ GlobalTrace.reset(new ::Trace);
+}
diff --git a/runtime/contrib/heap_trace/tests/src/common_test_environment.h b/runtime/contrib/heap_trace/tests/src/common_test_environment.h
new file mode 100644
index 000000000..8c4c9e396
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/common_test_environment.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COMMON_TEST_ENVIRONMENT_H
+#define COMMON_TEST_ENVIRONMENT_H
+
+#include "gtest/gtest.h"
+
+struct TestEnv : public ::testing::Test
+{
+ TestEnv(const char *log_file) : test_log_file(log_file) {}
+
+ void SetUp() override;
+ void TearDown() override;
+
+private:
+ void configureTraceToMakeLogInFile();
+ void removeOldTraceLogIfNeed();
+ void setNewNameOfTraceLog();
+
+private:
+ std::string test_log_file;
+};
+
+#endif // ! COMMON_TEST_ENVIRONMENT_H
diff --git a/runtime/contrib/heap_trace/tests/src/file_content_manipulations.cc b/runtime/contrib/heap_trace/tests/src/file_content_manipulations.cc
new file mode 100644
index 000000000..0c968ab4b
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/file_content_manipulations.cc
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "file_content_manipulations.h"
+
+#include <fstream>
+
+std::string getContentOfFile(const char *file_name)
+{
+ std::ifstream in(file_name);
+ return std::string((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
+}
diff --git a/runtime/contrib/heap_trace/tests/src/file_content_manipulations.h b/runtime/contrib/heap_trace/tests/src/file_content_manipulations.h
new file mode 100644
index 000000000..ba938931c
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/file_content_manipulations.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TEST_SUPPORT_H
+#define TEST_SUPPORT_H
+
+#include <string>
+
+std::string getContentOfFile(const char *file_name);
+
+#endif //! TEST_SUPPORT_H
diff --git a/runtime/contrib/heap_trace/tests/src/free_interception_test.cc b/runtime/contrib/heap_trace/tests/src/free_interception_test.cc
new file mode 100644
index 000000000..e690718d0
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/free_interception_test.cc
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common_test_environment.h"
+#include "file_content_manipulations.h"
+
+#include "trace.h"
+
+extern std::unique_ptr<Trace> GlobalTrace;
+
+namespace backstage
+{
+
+struct FreeStub : public TestEnv
+{
+ FreeStub() : TestEnv("./free_interception_test.log") {}
+};
+
+TEST_F(FreeStub, should_work_as_standard_version)
+{
+ void *p = malloc(1024);
+ free(p);
+ ASSERT_TRUE(p);
+ // TODO Bad test. Need use death test from Google test framework
+}
+
+TEST_F(FreeStub, must_log_deallocation_events_if_trace_is_ready_for_it)
+{
+ GlobalTrace.reset();
+ void *p1 = malloc(1024);
+ ASSERT_TRUE(p1);
+ free(p1);
+
+ GlobalTrace.reset(new Trace);
+ void *p2 = malloc(128);
+ void *p3 = malloc(64);
+ ASSERT_TRUE(p2 && p3);
+ free(p2);
+ free(p3);
+ GlobalTrace.reset();
+
+ ASSERT_STREQ(getContentOfFile("./free_interception_test.log").c_str(),
+ "On CPU - Peak heap usage: 192 B, Total allocated: 192 B, Total deallocated: 192 "
+ "B\nOn GPU - Peak mem usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\n");
+}
+
+} // namespace backstage
diff --git a/runtime/contrib/heap_trace/tests/src/main.cc b/runtime/contrib/heap_trace/tests/src/main.cc
new file mode 100644
index 000000000..b53b2030b
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/main.cc
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "gtest/gtest.h"
+
+int main(int argc, char *argv[])
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/runtime/contrib/heap_trace/tests/src/malloc_interception_test.cc b/runtime/contrib/heap_trace/tests/src/malloc_interception_test.cc
new file mode 100644
index 000000000..7a2f5a915
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/malloc_interception_test.cc
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common_test_environment.h"
+#include "file_content_manipulations.h"
+
+#include "trace.h"
+
+#include <experimental/filesystem>
+#include <limits>
+
+extern std::unique_ptr<Trace> GlobalTrace;
+
+namespace backstage
+{
+
+struct MallocStub : public TestEnv
+{
+ MallocStub() : TestEnv("./malloc_interception_test.log") {}
+};
+
+TEST_F(MallocStub, must_allocate_space_as_standard_malloc)
+{
+ void *p = malloc(128);
+
+ ASSERT_TRUE(p);
+ free(p);
+}
+
+TEST_F(MallocStub, must_log_allocation_events_if_trace_is_ready_for_it)
+{
+ GlobalTrace.reset();
+ void *p1 = malloc(1024);
+
+ GlobalTrace.reset(new Trace);
+ void *p2 = malloc(128);
+ void *p3 = malloc(64);
+ GlobalTrace.reset();
+
+ ASSERT_TRUE(p1 && p2 && p3);
+ ASSERT_STREQ(getContentOfFile("./malloc_interception_test.log").c_str(),
+ "On CPU - Peak heap usage: 192 B, Total allocated: 192 B, Total deallocated: 0 "
+ "B\nOn GPU - Peak mem usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\n");
+ free(p1);
+ free(p2);
+ free(p3);
+}
+
+TEST_F(MallocStub, must_not_do_the_record_about_allocation_event_if_original_function_failed)
+{
+ void *p = malloc(std::numeric_limits<size_t>::max());
+ GlobalTrace.reset();
+
+ ASSERT_FALSE(p);
+ ASSERT_STREQ(getContentOfFile("./malloc_interception_test.log").c_str(),
+ "On CPU - Peak heap usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\nOn "
+ "GPU - Peak mem usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\n");
+}
+
+TEST_F(
+ MallocStub,
+ should_not_influence_on_trace_results_even_if_orignal_function_return_any_not_null_ptr_when_incoming_size_is_zero)
+{
+ void *p = malloc(0);
+ free(p);
+ GlobalTrace.reset();
+
+ ASSERT_TRUE(p);
+ ASSERT_STREQ(getContentOfFile("./malloc_interception_test.log").c_str(),
+ "On CPU - Peak heap usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\nOn "
+ "GPU - Peak mem usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\n");
+}
+
+} // namespace backstage
diff --git a/runtime/contrib/heap_trace/tests/src/realloc_interception_test.cc b/runtime/contrib/heap_trace/tests/src/realloc_interception_test.cc
new file mode 100644
index 000000000..160a19beb
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/realloc_interception_test.cc
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common_test_environment.h"
+#include "file_content_manipulations.h"
+
+#include "trace.h"
+
+#include <experimental/filesystem>
+#include <limits>
+#include <cstring>
+
+extern std::unique_ptr<Trace> GlobalTrace;
+
+namespace backstage
+{
+
+struct ReallocStub : public TestEnv
+{
+ ReallocStub() : TestEnv("./realloc_interception_test.log") {}
+};
+
+TEST_F(ReallocStub, must_allocate_space_as_standard_realloc)
+{
+ void *p = malloc(128);
+ p = realloc(p, 1024);
+
+ ASSERT_TRUE(p);
+ free(p);
+}
+
+TEST_F(ReallocStub, must_log_allocation_deallocation_events_if_trace_is_ready_for_it)
+{
+ std::array<char, 1024> reference_data;
+ reference_data.fill('a');
+ void *p1 = malloc(1024);
+ memcpy(p1, reference_data.data(), reference_data.size());
+ void *p2 = realloc(p1, 64);
+ void *p3 = realloc(p2, 128);
+ GlobalTrace.reset();
+
+ ASSERT_TRUE(p3);
+ ASSERT_TRUE(memcmp(p3, reference_data.data(), 64) == 0);
+ ASSERT_STREQ(getContentOfFile("./realloc_interception_test.log").c_str(),
+ "On CPU - Peak heap usage: 1024 B, Total allocated: 1216 B, Total deallocated: 1088 "
+ "B\nOn GPU - Peak mem usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\n");
+ free(p3);
+}
+
+TEST_F(ReallocStub,
+ must_not_do_the_record_about_allocation_deallocation_events_if_original_function_failed)
+{
+ GlobalTrace.reset();
+ void *p = malloc(128);
+ GlobalTrace.reset(new Trace);
+
+ void *ptr_after_realloc = realloc(p, std::numeric_limits<size_t>::max());
+ ptr_after_realloc = realloc(p, 0);
+ GlobalTrace.reset();
+
+ ASSERT_FALSE(ptr_after_realloc);
+ ASSERT_STREQ(getContentOfFile("./realloc_interception_test.log").c_str(),
+ "On CPU - Peak heap usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\nOn "
+ "GPU - Peak mem usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\n");
+
+ free(p);
+}
+
+TEST_F(ReallocStub, should_work_as_malloc_when_incoming_ptr_is_equal_to_nullptr)
+{
+ void *p = realloc(nullptr, 1024);
+ GlobalTrace.reset();
+
+ ASSERT_TRUE(p);
+ ASSERT_STREQ(
+ getContentOfFile("./realloc_interception_test.log").c_str(),
+ "On CPU - Peak heap usage: 1024 B, Total allocated: 1024 B, Total deallocated: 0 B\nOn "
+ "GPU - Peak mem usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\n");
+
+ free(p);
+}
+
+TEST_F(
+ ReallocStub,
+ should_not_influence_on_trace_results_even_if_orignal_function_return_any_not_null_ptr_when_incoming_size_is_zero_and_ptr_is_null)
+{
+ void *p = realloc(nullptr, 0);
+ free(p);
+ GlobalTrace.reset();
+
+ ASSERT_TRUE(p);
+ ASSERT_STREQ(getContentOfFile("./realloc_interception_test.log").c_str(),
+ "On CPU - Peak heap usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\nOn "
+ "GPU - Peak mem usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\n");
+}
+
+} // namespace backstage
diff --git a/runtime/contrib/heap_trace/tests/src/symbol_searcher_test.cc b/runtime/contrib/heap_trace/tests/src/symbol_searcher_test.cc
new file mode 100644
index 000000000..d615cc928
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/symbol_searcher_test.cc
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "gtest/gtest.h"
+#include "test_sample1.h"
+#include "test_sample2.h"
+#include "test_sample4.h"
+
+#include "symbol_searcher.h"
+
+#include <dlfcn.h>
+#include <linux/limits.h>
+#include <unistd.h>
+
+#include <cstdlib>
+
+#include <experimental/filesystem>
+
+namespace fs = std::experimental::filesystem;
+
+fs::path exePath()
+{
+ char result[PATH_MAX] = {0};
+ ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
+ return fs::path(result).parent_path();
+}
+
+namespace backstage
+{
+
+struct SymbolSearcher : public ::testing::Test
+{
+};
+
+TEST_F(SymbolSearcher, should_find_symbol_in_linked_library)
+{
+ ASSERT_TRUE((void *)funcDefinedOnlyInTestSample4 == findSymbol("funcDefinedOnlyInTestSample4"));
+}
+
+TEST_F(SymbolSearcher, should_find_symbol_in_library_which_have_been_loaded_in_runtime)
+{
+ fs::path pathToTestLib = exePath() / "libtest_sample2.so";
+ void *handle = dlopen(pathToTestLib.c_str(), RTLD_NOW);
+
+ ASSERT_TRUE(handle);
+ ASSERT_TRUE(dlsym(handle, "funcDefinedOnlyInTestSample2") ==
+ findSymbol("funcDefinedOnlyInTestSample2"));
+ dlclose(handle);
+}
+
+TEST_F(SymbolSearcher,
+ should_ignore_symbols_found_in_current_translation_unit_if_there_is_another_alternative)
+{
+ fs::path pathToTestSample2 = exePath() / "libtest_sample2.so";
+ void *test_sample2_handle = dlopen(pathToTestSample2.c_str(), RTLD_NOW);
+ void *func_addr_in_test_sample2 =
+ dlsym(test_sample2_handle, "funcWhichCallFuncDefinedInTestSample3");
+
+ ASSERT_TRUE(test_sample2_handle);
+ ASSERT_TRUE((void *)funcDefinedInTestSample3_ButWrappedInTestSample1 !=
+ reinterpret_cast<void *(*)()>(func_addr_in_test_sample2)());
+
+ dlclose(test_sample2_handle);
+}
+
+} // namespace backstage
diff --git a/runtime/contrib/heap_trace/tests/src/test_sample1.h b/runtime/contrib/heap_trace/tests/src/test_sample1.h
new file mode 100644
index 000000000..3abea56a3
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/test_sample1.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TEST_SAMPLE1_H
+#define TEST_SAMPLE1_H
+
+extern "C" {
+
+void *funcDefinedInTestSample3_ButWrappedInTestSample1();
+}
+
+#endif // ! TEST_SAMPLE1_H
diff --git a/runtime/contrib/heap_trace/tests/src/test_sample1/test_sample1.cc b/runtime/contrib/heap_trace/tests/src/test_sample1/test_sample1.cc
new file mode 100644
index 000000000..1d2843707
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/test_sample1/test_sample1.cc
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../test_sample1.h"
+
+#include "../../../src/symbol_searcher.h"
+
+extern "C" {
+
+void *funcDefinedInTestSample3_ButWrappedInTestSample1()
+{
+ return findSymbol("funcDefinedInTestSample3_ButWrappedInTestSample1");
+}
+}
diff --git a/runtime/contrib/heap_trace/tests/src/test_sample2.h b/runtime/contrib/heap_trace/tests/src/test_sample2.h
new file mode 100644
index 000000000..785fc252d
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/test_sample2.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TEST_SAMPLE2_H
+#define TEST_SAMPLE2_H
+
+extern "C" {
+
+void funcDefinedOnlyInTestSample2();
+void funcWhichCallFuncDefinedInTestSample3();
+}
+
+#endif // ! TEST_SAMPLE2_H
diff --git a/runtime/contrib/heap_trace/tests/src/test_sample2/test_sample2.cc b/runtime/contrib/heap_trace/tests/src/test_sample2/test_sample2.cc
new file mode 100644
index 000000000..792dba665
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/test_sample2/test_sample2.cc
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../test_sample2.h"
+#include "../test_sample3.h"
+
+extern "C" {
+
+void funcDefinedOnlyInTestSample2() {}
+void funcWhichCallFuncDefinedInTestSample3() { funcDefinedInTestSample3_ButWrappedInTestSample1(); }
+}
diff --git a/runtime/contrib/heap_trace/tests/src/test_sample3.h b/runtime/contrib/heap_trace/tests/src/test_sample3.h
new file mode 100644
index 000000000..8f85b8bd6
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/test_sample3.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TEST_SAMPLE3_H
+#define TEST_SAMPLE3_H
+
+extern "C" {
+
+void funcDefinedInTestSample3_ButWrappedInTestSample1();
+}
+
+#endif // ! TEST_SAMPLE3_H
diff --git a/runtime/contrib/heap_trace/tests/src/test_sample3/test_sample3.cc b/runtime/contrib/heap_trace/tests/src/test_sample3/test_sample3.cc
new file mode 100644
index 000000000..ded78db85
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/test_sample3/test_sample3.cc
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+extern "C" {
+
+void funcDefinedInTestSample3_ButWrappedInTestSample1() {}
+}
diff --git a/runtime/contrib/heap_trace/tests/src/test_sample4.h b/runtime/contrib/heap_trace/tests/src/test_sample4.h
new file mode 100644
index 000000000..47c9e8c92
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/test_sample4.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TEST_SAMPLE4_H
+#define TEST_SAMPLE4_H
+
+extern "C" {
+
+void funcDefinedOnlyInTestSample4();
+}
+
+#endif // ! TEST_SAMPLE4_H
diff --git a/runtime/contrib/heap_trace/tests/src/test_sample4/test_sample4.cc b/runtime/contrib/heap_trace/tests/src/test_sample4/test_sample4.cc
new file mode 100644
index 000000000..55c96cb0e
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/test_sample4/test_sample4.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../test_sample4.h"
+
+extern "C" {
+void funcDefinedOnlyInTestSample4() {}
+}
diff --git a/runtime/contrib/heap_trace/tests/src/trace_test.cc b/runtime/contrib/heap_trace/tests/src/trace_test.cc
new file mode 100644
index 000000000..1cf4c530b
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/trace_test.cc
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common_test_environment.h"
+#include "file_content_manipulations.h"
+
+#include "trace.h"
+
+#include <CL/cl.h>
+
+#include <experimental/filesystem>
+#include <thread>
+#include <atomic>
+
+using namespace std;
+namespace fs = experimental::filesystem;
+
+extern unique_ptr<::Trace> GlobalTrace;
+
+namespace backstage
+{
+
+struct Trace : TestEnv
+{
+ Trace() : TestEnv("./trace_test.log") {}
+
+ void generateGarbageInTestLogFile();
+ template <typename MemType>
+ static void emulateAllocationEvent(size_t eventsPoolId, size_t numberOfEmulation,
+ size_t numberOfBytesPerOneEmulation, atomic_bool &isPauseNeed);
+};
+
+TEST_F(Trace,
+ must_create_log_file_with_name_defined_in_env_var_HEAP_TRACE_LOG_during_initialization)
+{
+ ASSERT_TRUE(fs::exists("./trace_test.log"));
+}
+
+TEST_F(Trace, must_truncate_log_file_if_it_exists_during_initialization)
+{
+ GlobalTrace.reset();
+ generateGarbageInTestLogFile();
+ GlobalTrace.reset(new ::Trace);
+ GlobalTrace.reset();
+
+ ASSERT_STREQ(getContentOfFile("./trace_test.log").c_str(),
+ "On CPU - Peak heap usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\nOn "
+ "GPU - Peak mem usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\n");
+}
+
+void Trace::generateGarbageInTestLogFile()
+{
+ ofstream log("./trace_test.log");
+ log << string(256, 'a');
+}
+
+TEST_F(Trace, should_not_generate_any_records_in_log_during_creation)
+{
+ GlobalTrace.reset();
+
+ ASSERT_STREQ(getContentOfFile("./trace_test.log").c_str(),
+ "On CPU - Peak heap usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\nOn "
+ "GPU - Peak mem usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\n");
+}
+
+TEST_F(Trace, can_signalize_to_users_if_it_is_ready_for_using)
+{
+ ASSERT_FALSE(::Trace::Guard().isActive());
+}
+
+TEST_F(Trace, must_signalize_that_it_is_not_ready_for_using_until_it_is_not_created)
+{
+ GlobalTrace.reset();
+ ASSERT_TRUE(::Trace::Guard().isActive());
+}
+
+TEST_F(Trace, should_work_correctly_in_multithreaded_environment)
+{
+ constexpr size_t numberOfThreads = 10, numberOfEmulations = 100,
+ numberOfBytesPerOneEmulation = 1024;
+ atomic_bool isPauseNeed{true};
+ array<thread, numberOfThreads> threads;
+ for (size_t i = 0; i < numberOfThreads / 2; ++i)
+ {
+ threads[i] = thread(emulateAllocationEvent<void *>, i, numberOfEmulations,
+ numberOfBytesPerOneEmulation, ref(isPauseNeed));
+ }
+ for (size_t i = numberOfThreads / 2; i < numberOfThreads; ++i)
+ {
+ threads[i] = thread(emulateAllocationEvent<cl_mem>, i, numberOfEmulations,
+ numberOfBytesPerOneEmulation, ref(isPauseNeed));
+ }
+
+ GlobalTrace.reset(new ::Trace);
+ isPauseNeed = false;
+
+ for (size_t i = 0; i < numberOfThreads; ++i)
+ {
+ threads[i].join();
+ }
+ GlobalTrace.reset();
+
+ string thisShouldBeInLogFile =
+ "Total allocated: " +
+ to_string(numberOfThreads / 2 * numberOfEmulations * numberOfBytesPerOneEmulation) +
+ " B, Total deallocated: " +
+ to_string(numberOfThreads / 2 * numberOfEmulations * numberOfBytesPerOneEmulation) + " B\n";
+ string andThisToo =
+ "Total allocated: " +
+ to_string(numberOfThreads / 2 * numberOfEmulations * numberOfBytesPerOneEmulation) +
+ " B, Total deallocated: " +
+ to_string(numberOfThreads / 2 * numberOfEmulations * numberOfBytesPerOneEmulation) + " B\n";
+ ASSERT_TRUE(getContentOfFile("./trace_test.log").find(thisShouldBeInLogFile) != string::npos);
+ ASSERT_TRUE(getContentOfFile("./trace_test.log").find(andThisToo) != string::npos);
+}
+
+template <typename MemType>
+void Trace::emulateAllocationEvent(size_t eventsPoolId, size_t numberOfEmulation,
+ size_t numberOfBytesPerOneEmulation, atomic_bool &isPauseNeed)
+{
+ while (isPauseNeed)
+ {
+ continue;
+ }
+
+ for (size_t i = 1; i <= numberOfEmulation; ++i)
+ {
+ GlobalTrace->logAllocationEvent((MemType)(i + numberOfEmulation * eventsPoolId),
+ numberOfBytesPerOneEmulation);
+ }
+
+ for (size_t i = 1; i <= numberOfEmulation; ++i)
+ {
+ GlobalTrace->logDeallocationEvent((MemType)(i + numberOfEmulation * eventsPoolId));
+ }
+}
+
+TEST_F(Trace, must_log_allocation_and_deallocation_events)
+{
+ void *memOnCPU1 = (void *)1, *memOnCPU2 = (void *)3;
+ cl_mem memOnGPU1 = (cl_mem)2, memOnGPU2 = (cl_mem)4;
+ GlobalTrace->logAllocationEvent(memOnCPU1, 347);
+ GlobalTrace->logDeallocationEvent(memOnCPU1);
+ GlobalTrace->logAllocationEvent(memOnGPU2, 592);
+ GlobalTrace->logDeallocationEvent(memOnGPU2);
+ GlobalTrace->logAllocationEvent(memOnGPU1, 349);
+ GlobalTrace->logDeallocationEvent(memOnGPU1);
+ GlobalTrace->logAllocationEvent(memOnCPU2, 568);
+ GlobalTrace->logDeallocationEvent(memOnCPU2);
+ GlobalTrace.reset();
+
+ string shouldBeInLogFile = "On CPU - Peak heap usage: " + to_string(568) +
+ " B, Total allocated: " + to_string(347 + 568) +
+ " B, Total deallocated: " + to_string(347 + 568) +
+ " B\n"
+ "On GPU - Peak mem usage: " +
+ to_string(592) + " B, Total allocated: " + to_string(592 + 349) +
+ " B, Total deallocated: " + to_string(592 + 349) + " B\n";
+ ASSERT_STREQ(getContentOfFile("./trace_test.log").c_str(), shouldBeInLogFile.c_str());
+}
+
+} // namespace backstage
diff --git a/runtime/contrib/heap_trace/tests/src/valloc_interception_test.cc b/runtime/contrib/heap_trace/tests/src/valloc_interception_test.cc
new file mode 100644
index 000000000..6b3d6df82
--- /dev/null
+++ b/runtime/contrib/heap_trace/tests/src/valloc_interception_test.cc
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common_test_environment.h"
+#include "file_content_manipulations.h"
+
+#include "trace.h"
+
+#include <experimental/filesystem>
+#include <limits>
+
+extern std::unique_ptr<Trace> GlobalTrace;
+
+namespace backstage
+{
+
+struct VallocStub : public TestEnv
+{
+ VallocStub() : TestEnv("./valloc_interception_test.log") {}
+};
+
+TEST_F(VallocStub, must_allocate_space_as_standard_valloc)
+{
+ void *p = valloc(128);
+
+ ASSERT_TRUE(p);
+ free(p);
+}
+
+TEST_F(VallocStub, must_log_allocation_events_if_trace_is_ready_for_it)
+{
+ GlobalTrace.reset();
+ void *p1 = valloc(1024);
+
+ GlobalTrace.reset(new Trace);
+ void *p2 = valloc(128);
+ void *p3 = valloc(64);
+ GlobalTrace.reset();
+
+ ASSERT_TRUE(p1 && p2 && p3);
+ ASSERT_STREQ(getContentOfFile("./valloc_interception_test.log").c_str(),
+ "On CPU - Peak heap usage: 192 B, Total allocated: 192 B, Total deallocated: 0 "
+ "B\nOn GPU - Peak mem usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\n");
+ free(p1);
+ free(p2);
+ free(p3);
+}
+
+TEST_F(VallocStub, must_not_do_the_record_about_allocation_event_if_original_function_failed)
+{
+ void *p = valloc(std::numeric_limits<size_t>::max());
+ GlobalTrace.reset();
+
+ ASSERT_FALSE(p);
+ ASSERT_STREQ(getContentOfFile("./valloc_interception_test.log").c_str(),
+ "On CPU - Peak heap usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\nOn "
+ "GPU - Peak mem usage: 0 B, Total allocated: 0 B, Total deallocated: 0 B\n");
+}
+
+} // namespace backstage