Skip to content

Commit b5c8b79

Browse files
committed
[Threading] Move stack bounds fetching into the threading library.
Fetching the current stack bounds is done using threading functions, so should be in the threading library. rdar://90776105
1 parent eb4c81d commit b5c8b79

File tree

12 files changed

+134
-82
lines changed

12 files changed

+134
-82
lines changed

include/swift/Threading/Impl.h

+12
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,18 @@
2020

2121
#include "TLSKeys.h"
2222

23+
namespace swift {
24+
namespace threading_impl {
25+
26+
struct stack_bounds {
27+
void *low;
28+
void *high;
29+
};
30+
31+
} // namespace swift
32+
} // namespace threading_impl
33+
34+
2335
// Try to autodetect if we aren't told what to do
2436
#if !SWIFT_THREADING_NONE && !SWIFT_THREADING_DARWIN && \
2537
!SWIFT_THREADING_LINUX && !SWIFT_THREADING_PTHREADS && \

include/swift/Threading/Impl/C11.h

+4
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ bool thread_is_main();
5555
inline bool threads_same(thread_id a, thread_id b) {
5656
return ::thrd_equal(a, b);
5757
}
58+
inline stack_bounds thread_get_current_stack_bounds() {
59+
stack_bounds zero = { nullptr, nullptr };
60+
return zero;
61+
}
5862

5963
// .. Mutex support ..........................................................
6064

include/swift/Threading/Impl/Darwin.h

+13
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,19 @@ inline bool threads_same(thread_id a, thread_id b) {
3838
return ::pthread_equal(a, b);
3939
}
4040

41+
inline stack_bounds thread_get_current_stack_bounds() {
42+
stack_bounds result;
43+
pthread_t thread = pthread_self();
44+
45+
// On Apple platforms, pthread_get_stackaddr_np() gets the address of the
46+
// *end* of the stack (i.e. the highest address in stack space), *NOT* the
47+
// address of the *base* of the stack (the lowest address).
48+
result.high = pthread_get_stackaddr_np(thread);
49+
result.low = (char *)result.high - pthread_get_stacksize_np(thread);
50+
51+
return result;
52+
}
53+
4154
// .. Mutex support ..........................................................
4255

4356
using mutex_handle = ::os_unfair_lock;

include/swift/Threading/Impl/Linux.h

+2
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ inline bool threads_same(thread_id a, thread_id b) {
6161
return ::pthread_equal(a, b);
6262
}
6363

64+
stack_bounds thread_get_current_stack_bounds();
65+
6466
// .. Mutex support ..........................................................
6567

6668
using mutex_handle = ::pthread_mutex_t;

include/swift/Threading/Impl/Nothreads.h

+4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ using thread_id = unsigned;
2727
inline thread_id thread_get_current() { return 0; }
2828
inline bool thread_is_main() { return true; }
2929
inline bool threads_same(thread_id a, thread_id b) { return a == b; }
30+
inline stack_bounds thread_get_current_stack_bounds() {
31+
stack_bounds zero = { nullptr, nullptr };
32+
return zero;
33+
}
3034

3135
// .. Mutex support ..........................................................
3236

include/swift/Threading/Impl/Pthreads.h

+2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ inline bool threads_same(thread_id a, thread_id b) {
6060
return ::pthread_equal(a, b);
6161
}
6262

63+
stack_bounds thread_get_current_stack_bounds();
64+
6365
// .. Mutex support ..........................................................
6466

6567
using mutex_handle = ::pthread_mutex_t;

include/swift/Threading/Impl/Win32.h

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ using thread_id = ::DWORD;
3131
inline thread_id thread_get_current() { return ::GetCurrentThreadId(); }
3232
bool thread_is_main();
3333
inline bool threads_same(thread_id a, thread_id b) { return a == b; }
34+
stack_bounds thread_get_current_stack_bounds();
3435

3536
// .. Mutex support ..........................................................
3637

include/swift/Threading/Thread.h

+6
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ namespace swift {
2727
class Thread {
2828
public:
2929
using Id = threading_impl::thread_id;
30+
using StackBounds = threading_impl::stack_bounds;
3031

3132
private:
3233
Id id_;
@@ -65,6 +66,11 @@ class Thread {
6566
bool operator!=(const Thread &other) const {
6667
return !threading_impl::threads_same(id_, other.id_);
6768
}
69+
70+
// Retrieve the bounds of the current thread's stack
71+
static StackBounds stackBounds() {
72+
return threading_impl::thread_get_current_stack_bounds();
73+
}
6874
};
6975

7076
} // namespace swift

lib/Threading/Linux.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,23 @@ void swift::threading_impl::once_slow(once_t &predicate, void (*fn)(void *),
5757
linux::ulock_unlock(&predicate.lock);
5858
}
5959

60+
swift::threading_impl::stack_bounds
61+
swift::threading_impl::thread_get_current_stack_bounds() {
62+
stack_bounds result = { nullptr, nullptr };
63+
pthread_attr_t attr;
64+
size_t size = 0;
65+
void *begin = nullptr;
66+
67+
if (!pthread_getattr_np(pthread_self(), &attr)) {
68+
if (!pthread_attr_getstack(&attr, &begin, &size)) {
69+
result.low = begin;
70+
result.high = (char *)begin + size;
71+
}
72+
73+
pthread_attr_destroy(&attr);
74+
}
75+
76+
return result;
77+
}
78+
6079
#endif // SWIFT_THREADING_LINUX

lib/Threading/Pthreads.cpp

+43
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
#if SWIFT_THREADING_PTHREADS
1818

19+
#if defined(__FreeBSD__) || defined(__OpenBSD__)
20+
#include <pthread_np.h>
21+
#endif
22+
1923
#include "swift/Threading/Impl/Pthreads.h"
2024
#include "swift/Threading/Errors.h"
2125

@@ -72,4 +76,43 @@ void swift::threading_impl::once_slow(once_t &predicate, void (*fn)(void *),
7276
pthread_mutex_unlock(&onceMutex);
7377
}
7478

79+
#if defined(__OpenBSD__)
80+
swift::threading_impl::stack_bounds
81+
swift::threading_impl::thread_get_current_stack_bounds() {
82+
stack_bounds result = { nullptr, nullptr };
83+
stack_t sinfo;
84+
85+
if (!pthread_stackseg_np(pthread_self(), &sinfo)) {
86+
result.low = (char *)sinfo.ss_sp - sinfo.ss_size;
87+
result.high = sinfo.ss_sp;
88+
}
89+
90+
return result;
91+
}
92+
#else
93+
swift::threading_impl::stack_bounds
94+
swift::threading_impl::thread_get_current_stack_bounds() {
95+
stack_bounds result = { nullptr, nullptr };
96+
pthread_attr_t attr;
97+
size_t size = 0;
98+
void *begin = nullptr;
99+
100+
#if defined(__FreeBSD__)
101+
if (pthread_attr_init(&attr))
102+
return result;
103+
#endif
104+
105+
if (!pthread_getattr_np(pthread_self(), &attr)) {
106+
if (!pthread_attr_getstack(&attr, &begin, &size)) {
107+
result.low = begin;
108+
result.high = (char *)begin + size;
109+
}
110+
111+
pthread_attr_destroy(&attr);
112+
}
113+
114+
return result;
115+
}
116+
#endif
117+
75118
#endif // SWIFT_THREADING_PTHREADS

lib/Threading/Win32.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,26 @@ void swift::threading_impl::once_slow(once_t &predicate, void (*fn)(void *),
9797
#endif
9898
}
9999

100+
swift::threading_impl::stack_bounds
101+
swift::threading_impl::thread_get_current_stack_bounds() {
102+
#if _WIN32_WINNT >= 0x0602
103+
ULONG_PTR lowLimit = 0;
104+
ULONG_PTR highLimit = 0;
105+
106+
GetCurrentThreadStackLimits(&lowLimit, &highLimit);
107+
108+
stack_bounds result = { (void *)lowLimit, (void *)highLimit };
109+
#else
110+
MEMORY_BASIC_INFORMATION mbi;
111+
VirtualQuery(&mbi, &mbi, sizeof(mbi));
112+
113+
stack_bounds result = {
114+
mbi.AllocationBase,
115+
(char *)mbi.BaseAddress + mbi.RegionSize
116+
};
117+
#endif
118+
119+
return result;
120+
}
121+
100122
#endif // SWIFT_THREADING_WIN32

stdlib/public/stubs/Stubs.cpp

+6-82
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,12 @@
6464
#include <android/api-level.h>
6565
#endif
6666

67-
#if defined(__FreeBSD__) || defined(__OpenBSD__)
68-
#include <pthread_np.h>
69-
#endif
70-
7167
#include "swift/Runtime/Debug.h"
7268
#include "swift/Runtime/SwiftDtoa.h"
7369
#include "swift/Basic/Lazy.h"
7470

71+
#include "swift/Threading/Thread.h"
72+
7573
#include "SwiftShims/LibcShims.h"
7674
#include "SwiftShims/RuntimeShims.h"
7775
#include "SwiftShims/RuntimeStubs.h"
@@ -537,84 +535,10 @@ __swift_bool swift_stdlib_isStackAllocationSafe(__swift_size_t byteCount,
537535

538536
__swift_bool _swift_stdlib_getCurrentStackBounds(__swift_uintptr_t *outBegin,
539537
__swift_uintptr_t *outEnd) {
540-
#if SWIFT_THREADING_NONE
541-
// This platform does not support threads, so the API we'd call to get stack
542-
// bounds (i.e. libpthread) is not going to be usable.
543-
return false;
544-
545-
#elif SWIFT_THREADING_DARWIN
546-
pthread_t thread = pthread_self();
547-
548-
// On Apple platforms, pthread_get_stackaddr_np() gets the address of the
549-
// *end* of the stack (i.e. the highest address in stack space), *NOT* the
550-
// address of the *base* of the stack (the lowest address).
551-
void *end = pthread_get_stackaddr_np(thread);
552-
if (!end) {
553-
return false;
554-
}
555-
*outEnd = (uintptr_t)end;
556-
*outBegin = *outEnd - pthread_get_stacksize_np(thread);
557-
return true;
558-
559-
#elif SWIFT_THREADING_C11
560-
// We don't know any way to do this for C11 threads
561-
return false;
562-
563-
#elif SWIFT_THREADING_WIN32
564-
565-
#if _WIN32_WINNT >= 0x0602
566-
ULONG_PTR lowLimit = 0;
567-
ULONG_PTR highLimit = 0;
568-
GetCurrentThreadStackLimits(&lowLimit, &highLimit);
569-
*outBegin = lowLimit;
570-
*outEnd = highLimit;
571-
return true;
572-
#else
573-
// Need _WIN32_WINNT to be 0x0602 or higher to use
574-
// GetCurrentThreadStackLimits(). We could use VirtualQuery() instead,
575-
// and give it the address of a page we know is on the stack?
576-
return false;
577-
#endif
578-
579-
#elif SWIFT_THREADING_PTHREADS || SWIFT_THREADING_LINUX
580-
581-
#if defined(__OpenBSD__)
582-
stack_t sinfo;
583-
if (pthread_stackseg_np(pthread_self(), &sinfo) != 0) {
538+
swift::Thread::StackBounds bounds = swift::Thread::stackBounds();
539+
if (!bounds.low)
584540
return false;
585-
}
586-
587-
*outBegin = (uintptr_t)sinfo.ss_sp - sinfo.ss_size;
588-
*outEnd = (uintptr_t)sinfo.ss_sp;
541+
*outBegin = (uintptr_t)bounds.low;
542+
*outEnd = (uintptr_t)bounds.high;
589543
return true;
590-
#elif defined(__FreeBSD__) || defined(__ANDROID__) || defined(__linux__)
591-
pthread_attr_t attr;
592-
593-
#if defined(__FreeBSD__)
594-
if (0 != pthread_attr_init(&attr) || 0 != pthread_attr_get_np(pthread_self(), &attr)) {
595-
return false;
596-
}
597-
#else
598-
if (0 != pthread_getattr_np(pthread_self(), &attr)) {
599-
return false;
600-
}
601-
#endif
602-
603-
void *begin = nullptr;
604-
size_t size = 0;
605-
bool success = (0 == pthread_attr_getstack(&attr, &begin, &size));
606-
607-
*outBegin = (uintptr_t)begin;
608-
*outEnd = *outBegin + size;
609-
610-
pthread_attr_destroy(&attr);
611-
return success;
612-
#else
613-
#warning Please teach _swift_stdlib_getCurrentStackBounds() about your platform
614-
return false;
615-
#endif
616-
617-
#else
618-
# error Unknown threading package selected; please teach _swift_stdlib_getCurrentStackBounds() what to do.
619-
#endif
620544
}

0 commit comments

Comments
 (0)