Skip to content

Commit 5154cf5

Browse files
Add test for custom assertion handler inside TBBbind (#1828)
Co-authored-by: Konstantin Boyarinov <[email protected]>
1 parent 2a483d2 commit 5154cf5

File tree

5 files changed

+191
-25
lines changed

5 files changed

+191
-25
lines changed

src/tbb/dynamic_link.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@
1919

2020
#include "oneapi/tbb/detail/_template_helpers.h"
2121
#include "oneapi/tbb/detail/_utils.h"
22+
#if DYNAMIC_LINK_FIND_LIB_WITH_TBB_RUNTIME_VERSION
23+
#include "oneapi/tbb/version.h" // to get TBB_runtime_version
24+
#endif
2225

2326
/*
24-
This file is used by both TBB and OpenMP RTL. Do not use __TBB_ASSERT() macro
27+
This file can be used by both TBB and OpenMP RTL. Do not use __TBB_ASSERT() macro
2528
and runtime_warning() function because they are not available in OpenMP. Use
2629
__TBB_ASSERT_EX and DYNAMIC_LINK_WARNING instead.
2730
*/
@@ -376,9 +379,20 @@ namespace r1 {
376379
ap_data._len = (std::size_t)(backslash - ap_data._path) + 1;
377380
*(backslash+1) = 0;
378381
#else
382+
// There is an use case, when we want to find TBB library, not just some shared object
383+
// providing "dynamic_link" symbol (it can be shared object that directly includes
384+
// dynamic_link.cpp). For this case we use a public TBB symbol. Searching for public symbol
385+
// in every case leads to finding main executable instead of TBB library on some version of
386+
// Linux.
387+
#if DYNAMIC_LINK_FIND_LIB_WITH_TBB_RUNTIME_VERSION
388+
static void *func_from_lib = (void*)&TBB_runtime_version;
389+
#else
390+
static void *func_from_lib = (void*)&dynamic_link;
391+
#endif
392+
379393
// Get the library path
380394
Dl_info dlinfo;
381-
int res = dladdr( (void*)&dynamic_link, &dlinfo ); // any function inside the library can be used for the address
395+
int res = dladdr( func_from_lib, &dlinfo );
382396
if ( !res ) {
383397
char const * err = dlerror();
384398
DYNAMIC_LINK_WARNING( dl_sys_fail, "dladdr", err );

src/tbb/governor.cpp

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "dynamic_link.h"
2525
#include "concurrent_monitor.h"
2626
#include "thread_dispatcher.h"
27+
#include "load_tbbbind.h"
2728

2829
#include "oneapi/tbb/task_group.h"
2930
#include "oneapi/tbb/global_control.h"
@@ -431,28 +432,7 @@ static const dynamic_link_descriptor TbbBindLinkTable[] = {
431432
};
432433

433434
static const unsigned LinkTableSize = sizeof(TbbBindLinkTable) / sizeof(dynamic_link_descriptor);
434-
435-
#if TBB_USE_DEBUG
436-
#define DEBUG_SUFFIX "_debug"
437-
#else
438-
#define DEBUG_SUFFIX
439-
#endif /* TBB_USE_DEBUG */
440-
441-
#if _WIN32 || _WIN64
442-
#define LIBRARY_EXTENSION ".dll"
443-
#define LIBRARY_PREFIX
444-
#elif __APPLE__
445-
#define LIBRARY_EXTENSION __TBB_STRING(.3.dylib)
446-
#define LIBRARY_PREFIX "lib"
447-
#elif __unix__
448-
#define LIBRARY_EXTENSION __TBB_STRING(.so.3)
449-
#define LIBRARY_PREFIX "lib"
450-
#endif /* __unix__ */
451-
452-
#define TBBBIND_NAME LIBRARY_PREFIX "tbbbind" DEBUG_SUFFIX LIBRARY_EXTENSION
453-
#define TBBBIND_2_0_NAME LIBRARY_PREFIX "tbbbind_2_0" DEBUG_SUFFIX LIBRARY_EXTENSION
454-
#define TBBBIND_2_5_NAME LIBRARY_PREFIX "tbbbind_2_5" DEBUG_SUFFIX LIBRARY_EXTENSION
455-
#endif /* _WIN32 || _WIN64 || __unix__ */
435+
#endif /* _WIN32 || _WIN64 || __unix__ || __APPLE__ */
456436

457437
// Representation of system hardware topology information on the TBB side.
458438
// System topology may be initialized by third-party component (e.g. hwloc)
@@ -478,7 +458,7 @@ const char* load_tbbbind_shared_object() {
478458
GetNativeSystemInfo(&si);
479459
if (si.dwNumberOfProcessors > 32) return nullptr;
480460
#endif /* _WIN32 && !_WIN64 */
481-
for (const auto& tbbbind_version : {TBBBIND_2_5_NAME, TBBBIND_2_0_NAME, TBBBIND_NAME}) {
461+
for (const auto& tbbbind_version : tbbbind_libraries_list) {
482462
if (dynamic_link(tbbbind_version, TbbBindLinkTable, LinkTableSize, nullptr, DYNAMIC_LINK_LOCAL_BINDING)) {
483463
return tbbbind_version;
484464
}

src/tbb/load_tbbbind.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
Copyright (c) 2025 Intel Corporation
3+
Copyright (c) 2025 UXL Foundation Contributors
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
#ifndef __TBB_load_tbbbind_H
19+
#define __TBB_load_tbbbind_H
20+
21+
#include "oneapi/tbb/version.h" // __TBB_STRING
22+
23+
#if _WIN32 || _WIN64 || __unix__ || __APPLE__
24+
25+
#if TBB_USE_DEBUG
26+
#define DEBUG_SUFFIX "_debug"
27+
#else
28+
#define DEBUG_SUFFIX
29+
#endif /* TBB_USE_DEBUG */
30+
31+
#if _WIN32 || _WIN64
32+
#define LIBRARY_EXTENSION ".dll"
33+
#define LIBRARY_PREFIX
34+
#elif __APPLE__
35+
#define LIBRARY_EXTENSION __TBB_STRING(.3.dylib)
36+
#define LIBRARY_PREFIX "lib"
37+
#elif __unix__
38+
#define LIBRARY_EXTENSION __TBB_STRING(.so.3)
39+
#define LIBRARY_PREFIX "lib"
40+
#endif /* __unix__ */
41+
42+
#define TBBBIND_NAME LIBRARY_PREFIX "tbbbind" DEBUG_SUFFIX LIBRARY_EXTENSION
43+
#define TBBBIND_2_0_NAME LIBRARY_PREFIX "tbbbind_2_0" DEBUG_SUFFIX LIBRARY_EXTENSION
44+
#define TBBBIND_2_5_NAME LIBRARY_PREFIX "tbbbind_2_5" DEBUG_SUFFIX LIBRARY_EXTENSION
45+
46+
// different versions of TBBbind are tried in that order
47+
static const char* tbbbind_libraries_list[] = {
48+
TBBBIND_2_5_NAME,
49+
TBBBIND_2_0_NAME,
50+
TBBBIND_NAME
51+
};
52+
53+
#endif /* _WIN32 || _WIN64 || __unix__ || __APPLE__ */
54+
55+
#endif /* __TBB_load_tbbbind_H */

test/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Copyright (c) 2020-2025 Intel Corporation
2+
# Copyright (c) 2025 UXL Foundation Contributors
23
#
34
# Licensed under the Apache License, Version 2.0 (the "License");
45
# you may not use this file except in compliance with the License.
@@ -542,6 +543,7 @@ if (TARGET TBB::tbb)
542543
# HWLOC related test
543544
if (NOT TBB_EMSCRIPTEN)
544545
tbb_add_tbbbind_test(SUBDIR tbb NAME test_arena_constraints)
546+
tbb_add_tbbbind_test(SUBDIR tbb NAME test_tbbbind)
545547
endif()
546548

547549
if ((NOT "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "mips") AND (NOT TBB_EMSCRIPTEN))

test/tbb/test_tbbbind.cpp

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
Copyright (c) 2025 Intel Corporation
3+
Copyright (c) 2025 UXL Foundation Contributors
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
//! \file test_tbbbind.cpp
19+
//! \brief Test for TBBbind library, covers [configuration.debug_features]
20+
21+
#define TEST_CUSTOM_ASSERTION_HANDLER_ENABLED 1
22+
#if _WIN32 || _WIN64
23+
#define _CRT_SECURE_NO_WARNINGS
24+
#endif
25+
26+
#include "oneapi/tbb/global_control.h"
27+
#include "oneapi/tbb/task_arena.h"
28+
#include "common/test.h"
29+
#include "common/utils_assert.h"
30+
31+
// no need to do it in the test
32+
#define __TBB_SKIP_DEPENDENCY_SIGNATURE_VERIFICATION 1
33+
34+
#define DYNAMIC_LINK_FIND_LIB_WITH_TBB_RUNTIME_VERSION 1
35+
#include "../../src/tbb/dynamic_link.cpp"
36+
#include "../../src/tbb/load_tbbbind.h"
37+
38+
#if __TBB_WEAK_SYMBOLS_PRESENT
39+
#pragma weak __TBB_internal_deallocate_binding_handler
40+
#endif /* __TBB_WEAK_SYMBOLS_PRESENT */
41+
42+
namespace tbb {
43+
namespace detail {
44+
namespace r1 {
45+
class binding_handler;
46+
47+
extern "C" {
48+
void __TBB_internal_deallocate_binding_handler( binding_handler* handler_ptr );
49+
}
50+
}}}
51+
52+
using BindingHandlerType = void (*)(tbb::detail::r1::binding_handler* handler_ptr);
53+
54+
BindingHandlerType GetDeallocateBindingHandler() {
55+
using namespace tbb::detail::r1;
56+
57+
BindingHandlerType deallocate_binding_handler_ptr;
58+
59+
const dynamic_link_descriptor LinkTable[] = {
60+
DLD(__TBB_internal_deallocate_binding_handler, deallocate_binding_handler_ptr)
61+
};
62+
63+
for (const auto& tbbbind_version : tbbbind_libraries_list) {
64+
if (dynamic_link(tbbbind_version, LinkTable,
65+
sizeof(LinkTable) / sizeof(dynamic_link_descriptor), nullptr,
66+
DYNAMIC_LINK_LOCAL_BINDING)) {
67+
return deallocate_binding_handler_ptr;
68+
}
69+
}
70+
return nullptr;
71+
}
72+
73+
// Testing can't be done without TBBbind.
74+
#if __TBB_SELF_CONTAINED_TBBBIND || __TBB_HWLOC_VALID_ENVIRONMENT
75+
static bool isTbbBindAvailable() { return true; }
76+
#else
77+
static bool isTbbBindAvailable() { return false; }
78+
#endif
79+
80+
// All assertions in TBBbind are available only in TBB_USE_ASSERT mode.
81+
#if TBB_USE_ASSERT
82+
static bool canTestAsserts() { return true; }
83+
#else
84+
static bool canTestAsserts() { return false; }
85+
#endif
86+
87+
// this code hangs in -DBUILD_SHARED_LIBS=OFF case (#1832)
88+
#if __TBB_DYNAMIC_LOAD_ENABLED
89+
// Must initialize system_topology and so register assertion handler in TBBbind.
90+
// The test harness expects TBBBIND status always to be reported as part of TBB_VERSION output, so
91+
// initialize system_topology even if TBBbind is not available.
92+
struct Init {
93+
Init() {
94+
auto constraints = tbb::task_arena::constraints{}.set_max_threads_per_core(1);
95+
tbb::task_arena arena( constraints );
96+
arena.initialize();
97+
}
98+
} init;
99+
#endif
100+
101+
// The test relies on an assumption that system_topology::load_tbbbind_shared_object() find
102+
// same instance of TBBbind as TBB uses internally.
103+
//! Testing that assertions called inside TBBbind are handled correctly
104+
//! \brief \ref interface \ref requirement
105+
TEST_CASE("Using custom assertion handler inside TBBbind"
106+
* doctest::skip(!isTbbBindAvailable() || !canTestAsserts())) {
107+
// fills pointers to TBBbind entry points
108+
BindingHandlerType deallocate_binding_handler = GetDeallocateBindingHandler();
109+
REQUIRE_MESSAGE(deallocate_binding_handler != nullptr,
110+
"Failed to fill deallocate_binding_handler_ptr");
111+
112+
// we are expecting that deallocate_binding_handler points to TBBbind entry point
113+
TEST_CUSTOM_ASSERTION_HANDLER(deallocate_binding_handler(nullptr),
114+
"Trying to deallocate nullptr pointer.");
115+
}

0 commit comments

Comments
 (0)