Skip to content

stdlib/public fixes for Windows support #11110

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions stdlib/public/SwiftShims/LibcShims.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,16 @@ typedef unsigned long __swift_pthread_key_t;
#endif

SWIFT_RUNTIME_STDLIB_INTERFACE
int _swift_stdlib_pthread_key_create(
int _swift_stdlib_tls_key_create(
__swift_pthread_key_t * _Nonnull key, void
(* _Nullable destructor)(void * _Nullable )
);

SWIFT_RUNTIME_STDLIB_INTERFACE
void * _Nullable _swift_stdlib_pthread_getspecific(__swift_pthread_key_t key);
void * _Nullable _swift_stdlib_tls_getspecific(__swift_pthread_key_t key);

SWIFT_RUNTIME_STDLIB_INTERFACE
int _swift_stdlib_pthread_setspecific(
int _swift_stdlib_tls_setspecific(
__swift_pthread_key_t key, const void * _Nullable value
);

Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/SwiftShims/RefCount.h
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ class SideTableRefCountBits : public RefCountBitsT<RefCountNotInline>
template <typename RefCountBits>
class RefCounts {
std::atomic<RefCountBits> refCounts;
#if !__LP64__
#if !__LP64__ && !defined(_WIN64)
// FIXME: hack - something somewhere is assuming a 3-word header on 32-bit
// See also other fixmes marked "small header for 32-bit"
uintptr_t unused SWIFT_ATTRIBUTE_UNAVAILABLE;
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/SwiftShims/Visibility.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@

#else
# if defined(__CYGWIN__)
# define SWIFT_RUNTIME_EXPORT
# define SWIFT_EXPORT_ATTRIBUTE
# else
# if defined(swiftCore_EXPORTS)
# define SWIFT_EXPORT_ATTRIBUTE __declspec(dllexport)
Expand Down
8 changes: 4 additions & 4 deletions stdlib/public/core/ThreadLocalStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ internal struct _ThreadLocalStorage {
static internal func getPointer()
-> UnsafeMutablePointer<_ThreadLocalStorage>
{
let tlsRawPtr = _swift_stdlib_pthread_getspecific(_tlsKey)
let tlsRawPtr = _swift_stdlib_tls_getspecific(_tlsKey)
if _fastPath(tlsRawPtr != nil) {
return tlsRawPtr._unsafelyUnwrappedUnchecked.assumingMemoryBound(
to: _ThreadLocalStorage.self)
Expand Down Expand Up @@ -119,7 +119,7 @@ internal func _destroyTLS(_ ptr: UnsafeMutableRawPointer?) {
internal let _tlsKey: __swift_pthread_key_t = {
let sentinelValue = __swift_pthread_key_t.max
var key: __swift_pthread_key_t = sentinelValue
let success = _swift_stdlib_pthread_key_create(&key, _destroyTLS)
let success = _swift_stdlib_tls_key_create(&key, _destroyTLS)
_sanityCheck(success == 0, "somehow failed to create TLS key")
_sanityCheck(key != sentinelValue, "Didn't make a new key")
return key
Expand All @@ -129,7 +129,7 @@ internal let _tlsKey: __swift_pthread_key_t = {
internal func _initializeThreadLocalStorage()
-> UnsafeMutablePointer<_ThreadLocalStorage>
{
_sanityCheck(_swift_stdlib_pthread_getspecific(_tlsKey) == nil,
_sanityCheck(_swift_stdlib_tls_getspecific(_tlsKey) == nil,
"already initialized")

// Create and initialize one.
Expand All @@ -146,7 +146,7 @@ internal func _initializeThreadLocalStorage()
tlsPtr.initialize(
to: _ThreadLocalStorage(_uBreakIterator: newUBreakIterator)
)
let success = _swift_stdlib_pthread_setspecific(_tlsKey, tlsPtr)
let success = _swift_stdlib_tls_setspecific(_tlsKey, tlsPtr)
_sanityCheck(success == 0, "setspecific failed")
return tlsPtr
}
Expand Down
34 changes: 23 additions & 11 deletions stdlib/public/runtime/Errors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
#include <asl.h>
#elif defined(__ANDROID__)
#include <android/log.h>
#elif defined(_WIN32)
#include <Dbghelp.h>
#endif

namespace FatalErrorFlags {
Expand Down Expand Up @@ -78,17 +80,27 @@ static bool getSymbolNameAddr(llvm::StringRef libraryName, SymbolInfo syminfo,
// demangle with swift. We are taking advantage of __cxa_demangle actually
// providing failure status instead of just returning the original string like
// swift demangle.
int status;
char *demangled = abi::__cxa_demangle(syminfo.symbolName, 0, 0, &status);
if (status == 0) {
assert(demangled != nullptr && "If __cxa_demangle succeeds, demangled "
"should never be nullptr");
symbolName += demangled;
free(demangled);
return true;
}
assert(demangled == nullptr && "If __cxa_demangle fails, demangled should "
"be a nullptr");

#if defined(_WIN32)
char demangled[1024];
DWORD length = UnDecorateSymbolName(syminfo.symbolName, demangled, 1024, 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using sizeof(demanglled) / sizeof(*demangled) or defining a local array_size as follows would be nicer:

template <typename T, size_t N>
size_t array_size(const T (&)[N]) { return N; }

if (length > 0) {
symbolName += demangled;
return true;
}
#else
int status;
char *demangled = abi::__cxa_demangle(syminfo.symbolName, 0, 0, &status);
if (status == 0) {
assert(demangled != nullptr && "If __cxa_demangle succeeds, demangled "
"should never be nullptr");
symbolName += demangled;
free(demangled);
return true;
}
assert(demangled == nullptr && "If __cxa_demangle fails, demangled should "
"be a nullptr");
#endif

// Otherwise, try to demangle with swift. If swift fails to demangle, it will
// just pass through the original output.
Expand Down
48 changes: 38 additions & 10 deletions stdlib/public/stubs/LibcShims.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@
#include <cmath>
#if defined(_WIN32)
#include <io.h>
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#define NOMINMAX
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <pthread.h>
#endif

#include <stdlib.h>
#include <stdio.h>
Expand Down Expand Up @@ -98,33 +102,57 @@ int swift::_swift_stdlib_close(int fd) {
#endif
}

#if !defined(_WIN32)
// Guard compilation on the typedef for __swift_pthread_key_t in LibcShims.h
// being identical to the platform's pthread_key_t
static_assert(std::is_same<__swift_pthread_key_t, pthread_key_t>::value,
"This platform's pthread_key_t differs. If you hit this assert, "
"fix __swift_pthread_key_t's typedef in LibcShims.h by adding an "
"#if guard and definition for your platform");
#endif

SWIFT_RUNTIME_STDLIB_INTERFACE
int swift::_swift_stdlib_pthread_key_create(
int swift::_swift_stdlib_tls_key_create(
__swift_pthread_key_t * _Nonnull key,
void (* _Nullable destructor)(void *)
) {
return pthread_key_create(key, destructor);
}

SWIFT_RUNTIME_STDLIB_INTERFACE
void * _Nullable swift::_swift_stdlib_pthread_getspecific(
#if defined(_WIN32)
// We're using the Fls- (Fiber) instead of Tls- (Thread) functions since
// on Windows, "If no fiber switching occurs, FLS acts exactly the same
// as thread local storage," and FlsAlloc takes a destructor while
// TlsAlloc doesn't.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms682661.aspx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also makes the code more portable, as some Windows targets (e.g. Windows Store, Windows Phone) only support the FLS variant.

__swift_pthread_key_t result = FlsAlloc(destructor);
if (result != FLS_OUT_OF_INDEXES) {
*key = result;
return 0;
}
return result;
#else
return pthread_key_create(key, destructor);
#endif
}

SWIFT_RUNTIME_STDLIB_INTERFACE
void * _Nullable swift::_swift_stdlib_tls_getspecific(
__swift_pthread_key_t key
) {
return pthread_getspecific(key);
#if defined(_WIN32)
return FlsGetValue(key);
#else
return pthread_getspecific(key);
#endif
}

SWIFT_RUNTIME_STDLIB_INTERFACE
int swift::_swift_stdlib_pthread_setspecific(
int swift::_swift_stdlib_tls_setspecific(
__swift_pthread_key_t key, const void * _Nullable value
) {
return pthread_setspecific(key, value);
#if defined(_WIN32)
return FlsSetValue(key, const_cast<void*>(value));
#else
return pthread_setspecific(key, value);
#endif
}

#if defined(__APPLE__)
Expand Down