Skip to content

Commit 9d85bf3

Browse files
authored
Fix get stack base in linux (#1485)
In case of pthread_attr_getstack() returns np_stack_size = 1MB, - calculated stack_base = stack_limit + stack_size(default: 4MB) - real stack_base = stack_limit + np_stack_size(1MB) stack_base is wrong because calculated with 4MB stack size. Due to this wrong stack_base, task_dispatcher::can_steal() can be always false. It causes abnormal long loop in task_dispatcher::receive_or_steal_task(). Correct this problem using np_stack_size instead of stack_size. Signed-off-by: Bongkyu Kim <[email protected]>
1 parent af8d95c commit 9d85bf3

File tree

1 file changed

+8
-9
lines changed

1 file changed

+8
-9
lines changed

src/tbb/governor.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -151,17 +151,16 @@ bool governor::does_client_join_workers(const rml::tbb_client &client) {
151151
3) If the user app strives to conserve the memory by cutting stack size, it
152152
should do this for TBB workers too (as in the #1).
153153
*/
154-
static std::uintptr_t get_stack_base(std::size_t stack_size) {
154+
static void get_stack_attributes(std::uintptr_t& stack_base, std::size_t& stack_size, std::size_t fallback_stack_size) {
155155
// Stacks are growing top-down. Highest address is called "stack base",
156156
// and the lowest is "stack limit".
157+
stack_size = fallback_stack_size;
157158
#if __TBB_USE_WINAPI
158-
suppress_unused_warning(stack_size);
159159
NT_TIB* pteb = (NT_TIB*)NtCurrentTeb();
160160
__TBB_ASSERT(&pteb < pteb->StackBase && &pteb > pteb->StackLimit, "invalid stack info in TEB");
161-
return reinterpret_cast<std::uintptr_t>(pteb->StackBase);
161+
stack_base = reinterpret_cast<std::uintptr_t>(pteb->StackBase);
162162
#elif defined(EMSCRIPTEN)
163-
suppress_unused_warning(stack_size);
164-
return reinterpret_cast<std::uintptr_t>(emscripten_stack_get_base());
163+
stack_base = reinterpret_cast<std::uintptr_t>(emscripten_stack_get_base());
165164
#else
166165
// There is no portable way to get stack base address in Posix, so we use
167166
// non-portable method (on all modern Linux) or the simplified approach
@@ -176,19 +175,19 @@ static std::uintptr_t get_stack_base(std::size_t stack_size) {
176175
if (0 == pthread_getattr_np(pthread_self(), &np_attr_stack)) {
177176
if (0 == pthread_attr_getstack(&np_attr_stack, &stack_limit, &np_stack_size)) {
178177
__TBB_ASSERT( &stack_limit > stack_limit, "stack size must be positive" );
178+
if (np_stack_size > 0)
179+
stack_size = np_stack_size;
179180
}
180181
pthread_attr_destroy(&np_attr_stack);
181182
}
182183
#endif /* __linux__ */
183-
std::uintptr_t stack_base{};
184184
if (stack_limit) {
185185
stack_base = reinterpret_cast<std::uintptr_t>(stack_limit) + stack_size;
186186
} else {
187187
// Use an anchor as a base stack address.
188188
int anchor{};
189189
stack_base = reinterpret_cast<std::uintptr_t>(&anchor);
190190
}
191-
return stack_base;
192191
#endif /* __TBB_USE_WINAPI */
193192
}
194193

@@ -219,8 +218,8 @@ void governor::init_external_thread() {
219218
td.attach_arena(a, /*slot index*/ 0);
220219
__TBB_ASSERT(td.my_inbox.is_idle_state(false), nullptr);
221220

222-
stack_size = a.my_threading_control->worker_stack_size();
223-
std::uintptr_t stack_base = get_stack_base(stack_size);
221+
std::uintptr_t stack_base{};
222+
get_stack_attributes(stack_base, stack_size, a.my_threading_control->worker_stack_size());
224223
task_dispatcher& task_disp = td.my_arena_slot->default_task_dispatcher();
225224
td.enter_task_dispatcher(task_disp, calculate_stealing_threshold(stack_base, stack_size));
226225

0 commit comments

Comments
 (0)