Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c276b03

Browse filesBrowse files
authored
provide some backwards compatibility with existing binaries (#233)
* first steps at backwards compat * more exports for linux * include stub library on Windows * tweaks * dll export * clean up when we're done * overwrite
1 parent 965e198 commit c276b03
Copy full SHA for c276b03

File tree

17 files changed

+378
-25
lines changed
Filter options

17 files changed

+378
-25
lines changed

‎R/tbb.R

Copy file name to clipboardExpand all lines: R/tbb.R
+8
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,17 @@ tbbLibraryPath <- function(name = NULL) {
3737
# find the request library (if any)
3838
libNames <- tbbLibNames[[sysname]]
3939
for (libName in libNames) {
40+
4041
tbbName <- file.path(tbbRoot, libName)
4142
if (file.exists(tbbName))
4243
return(tbbName)
44+
45+
arch <- if (nzchar(.Platform$r_arch)) .Platform$r_arch
46+
suffix <- paste(c("lib", arch, libName), collapse = "/")
47+
tbbName <- system.file(suffix, package = "RcppParallel")
48+
if (file.exists(tbbName))
49+
return(tbbName)
50+
4351
}
4452

4553
}

‎R/zzz.R

Copy file name to clipboardExpand all lines: R/zzz.R
+8-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ loadTbbLibrary <- function(name) {
2727

2828
.onLoad <- function(libname, pkgname) {
2929

30+
# on Windows, load RcppParallel first
31+
if (.Platform$OS.type == "windows") {
32+
.dllInfo <<- library.dynam("RcppParallel", pkgname, libname)
33+
}
34+
3035
# load tbb, tbbmalloc
3136
.tbbDllInfo <<- loadTbbLibrary("tbb")
3237
.tbbMallocDllInfo <<- loadTbbLibrary("tbbmalloc")
@@ -37,7 +42,9 @@ loadTbbLibrary <- function(name) {
3742
.tbbMallocProxyDllInfo <<- loadTbbLibrary("tbbmalloc_proxy")
3843

3944
# load RcppParallel library if available
40-
.dllInfo <<- library.dynam("RcppParallel", pkgname, libname)
45+
if (.Platform$OS.type != "windows") {
46+
.dllInfo <<- library.dynam("RcppParallel", pkgname, libname)
47+
}
4148

4249
}
4350

‎RcppParallel.Rproj

Copy file name to clipboardExpand all lines: RcppParallel.Rproj
+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ RnwWeave: Sweave
1414
LaTeX: pdfLaTeX
1515

1616
BuildType: Package
17+
PackageCleanBeforeInstall: No
1718
PackageInstallArgs: --with-keep.source --clean
1819
PackageCheckArgs: --as-cran
1920
PackageRoxygenize: rd,collate,namespace

‎src/install.libs.R

Copy file name to clipboardExpand all lines: src/install.libs.R
+18-8
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
tbbLibs <- tbbLibs[!nzchar(Sys.readlink(tbbLibs))]
5858

5959
# copy / link the libraries
60-
useSymlinks <- Sys.getenv("TBB_USE_SYMLINKS", unset = "TRUE")
60+
useSymlinks <- Sys.getenv("TBB_USE_SYMLINKS", unset = .Platform$OS.type != "windows")
6161
if (useSymlinks) {
6262
file.symlink(tbbLibs, tbbDest)
6363
} else {
@@ -68,6 +68,19 @@
6868

6969
}
7070

71+
# on Windows, we create a stub library that links to us so that
72+
# older binaries (like rstan) can still load
73+
if (.Platform$OS.type == "windows") {
74+
tbbDll <- file.path(tbbDest, "tbb.dll")
75+
if (!file.exists(tbbDll)) {
76+
writeLines("** creating tbb stub library")
77+
status <- system("R CMD SHLIB tbb-compat/tbb-compat.cpp")
78+
if (status != 0)
79+
stop("error building tbb stub library")
80+
file.rename("tbb-compat/tbb-compat.dll", file.path(tbbDest, "tbb.dll"))
81+
}
82+
}
83+
7184
}
7285

7386
useTbbPreamble <- function(tbbInc) {
@@ -99,7 +112,7 @@ useBundledTbb <- function() {
99112
"-DTBB_EXAMPLES=0",
100113
"-DTBB_STRICT=0",
101114
".."
102-
)
115+
)
103116

104117
writeLines("*** configuring tbb")
105118
owd <- setwd("tbb/build-tbb")
@@ -133,17 +146,14 @@ useBundledTbb <- function() {
133146
)
134147

135148
tbbFiles <- list.files(
136-
"tbb/build-tbb",
149+
file.path(getwd(), "tbb/build-tbb"),
137150
pattern = shlibPattern,
138151
recursive = TRUE,
139152
full.names = TRUE
140153
)
141154

142-
tbbDir <- dirname(tbbFiles[[1L]])
143-
144-
dir.create("tbb/build", showWarnings = FALSE)
145-
unlink("tbb/build/lib_release", recursive = TRUE)
146-
file.rename(tbbDir, "tbb/build/lib_release")
155+
dir.create("tbb/build/lib_release", recursive = TRUE, showWarnings = FALSE)
156+
file.copy(tbbFiles, "tbb/build/lib_release", overwrite = TRUE)
147157
unlink("tbb/build-tbb", recursive = TRUE)
148158
writeLines("*** finished building tbb")
149159

‎src/tbb-compat/tbb-compat.cpp

Copy file name to clipboard
+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
2+
#include <atomic>
3+
4+
#include "../tbb/include/oneapi/tbb/detail/_namespace_injection.h"
5+
#include "../tbb/include/oneapi/tbb/task_arena.h"
6+
7+
#include "../tbb/src/tbb/observer_proxy.h"
8+
#include "../tbb/src/tbb/main.h"
9+
#include "../tbb/src/tbb/thread_data.h"
10+
11+
#ifdef _WIN32
12+
# define DLL_EXPORT __declspec(dllexport)
13+
#else
14+
# define DLL_EXPORT
15+
#endif
16+
17+
namespace tbb {
18+
19+
namespace interface6 {
20+
class task_scheduler_observer;
21+
}
22+
23+
namespace internal {
24+
25+
class task_scheduler_observer_v3 {
26+
friend class tbb::detail::r1::observer_proxy;
27+
friend class tbb::detail::r1::observer_list;
28+
friend class interface6::task_scheduler_observer;
29+
30+
//! Pointer to the proxy holding this observer.
31+
/** Observers are proxied by the scheduler to maintain persistent lists of them. **/
32+
tbb::detail::r1::observer_proxy* my_proxy;
33+
34+
//! Counter preventing the observer from being destroyed while in use by the scheduler.
35+
/** Valid only when observation is on. **/
36+
std::atomic<intptr_t> my_busy_count;
37+
38+
public:
39+
//! Enable or disable observation
40+
/** For local observers the method can be used only when the current thread
41+
has the task scheduler initialized or is attached to an arena.
42+
Repeated calls with the same state are no-ops. **/
43+
void __TBB_EXPORTED_METHOD observe( bool state=true );
44+
45+
//! Returns true if observation is enabled, false otherwise.
46+
bool is_observing() const {return my_proxy!=NULL;}
47+
48+
//! Construct observer with observation disabled.
49+
task_scheduler_observer_v3() : my_proxy(NULL) { my_busy_count.store(0); }
50+
51+
//! Entry notification
52+
/** Invoked from inside observe(true) call and whenever a worker enters the arena
53+
this observer is associated with. If a thread is already in the arena when
54+
the observer is activated, the entry notification is called before it
55+
executes the first stolen task.
56+
Obsolete semantics. For global observers it is called by a thread before
57+
the first steal since observation became enabled. **/
58+
virtual void on_scheduler_entry( bool /*is_worker*/ ) {}
59+
60+
//! Exit notification
61+
/** Invoked from inside observe(false) call and whenever a worker leaves the
62+
arena this observer is associated with.
63+
Obsolete semantics. For global observers it is called by a thread before
64+
the first steal since observation became enabled. **/
65+
virtual void on_scheduler_exit( bool /*is_worker*/ ) {}
66+
67+
//! Destructor automatically switches observation off if it is enabled.
68+
virtual ~task_scheduler_observer_v3() { if(my_proxy) observe(false);}
69+
};
70+
71+
} // namespace internal
72+
73+
namespace interface6 {
74+
75+
class task_scheduler_observer : public internal::task_scheduler_observer_v3 {
76+
friend class internal::task_scheduler_observer_v3;
77+
friend class tbb::detail::r1::observer_proxy;
78+
friend class tbb::detail::r1::observer_list;
79+
80+
/** Negative numbers with the largest absolute value to minimize probability
81+
of coincidence in case of a bug in busy count usage. **/
82+
// TODO: take more high bits for version number
83+
static const intptr_t v6_trait = (intptr_t)((~(uintptr_t)0 >> 1) + 1);
84+
85+
//! contains task_arena pointer or tag indicating local or global semantics of the observer
86+
intptr_t my_context_tag;
87+
enum { global_tag = 0, implicit_tag = 1 };
88+
89+
public:
90+
//! Construct local or global observer in inactive state (observation disabled).
91+
/** For a local observer entry/exit notifications are invoked whenever a worker
92+
thread joins/leaves the arena of the observer's owner thread. If a thread is
93+
already in the arena when the observer is activated, the entry notification is
94+
called before it executes the first stolen task. **/
95+
/** TODO: Obsolete.
96+
Global observer semantics is obsolete as it violates master thread isolation
97+
guarantees and is not composable. Thus the current default behavior of the
98+
constructor is obsolete too and will be changed in one of the future versions
99+
of the library. **/
100+
explicit task_scheduler_observer( bool local = false ) {
101+
my_context_tag = local? implicit_tag : global_tag;
102+
}
103+
104+
//! Construct local observer for a given arena in inactive state (observation disabled).
105+
/** entry/exit notifications are invoked whenever a thread joins/leaves arena.
106+
If a thread is already in the arena when the observer is activated, the entry notification
107+
is called before it executes the first stolen task. **/
108+
explicit task_scheduler_observer( task_arena & a) {
109+
my_context_tag = (intptr_t)&a;
110+
}
111+
112+
/** Destructor protects instance of the observer from concurrent notification.
113+
It is recommended to disable observation before destructor of a derived class starts,
114+
otherwise it can lead to concurrent notification callback on partly destroyed object **/
115+
virtual ~task_scheduler_observer() { if(my_proxy) observe(false); }
116+
117+
//! Enable or disable observation
118+
/** Warning: concurrent invocations of this method are not safe.
119+
Repeated calls with the same state are no-ops. **/
120+
void observe( bool state=true ) {
121+
if( state && !my_proxy ) {
122+
__TBB_ASSERT( !my_busy_count, "Inconsistent state of task_scheduler_observer instance");
123+
my_busy_count.store(v6_trait);
124+
}
125+
internal::task_scheduler_observer_v3::observe(state);
126+
}
127+
};
128+
129+
} // namespace interface6
130+
131+
} // namespace tbb
132+
133+
namespace tbb {
134+
namespace internal {
135+
136+
DLL_EXPORT
137+
void __TBB_EXPORTED_FUNC task_scheduler_observer_v3::observe( bool enable ) {
138+
auto* tso = (tbb::detail::d1::task_scheduler_observer*) (this);
139+
tbb::detail::r1::observe(*tso, enable);
140+
}
141+
142+
} // namespace internal
143+
} // namespace tbb

‎src/tbb/include/oneapi/tbb/detail/_task.h

Copy file name to clipboardExpand all lines: src/tbb/include/oneapi/tbb/detail/_task.h
+3-1
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,14 @@ class wait_context {
124124
}
125125
}
126126

127+
public:
127128
bool continue_execution() const {
128129
std::uint64_t r = m_ref_count.load(std::memory_order_acquire);
129130
__TBB_ASSERT_EX((r & overflow_mask) == 0, "Overflow is detected");
130131
return r > 0;
131132
}
132-
133+
134+
private:
133135
friend class r1::thread_data;
134136
friend class r1::task_dispatcher;
135137
friend class r1::external_waiter;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.