diff options
Diffstat (limited to 'libcxx/src')
-rw-r--r-- | libcxx/src/algorithm.cpp | 48 | ||||
-rw-r--r-- | libcxx/src/atomic.cpp | 189 | ||||
-rw-r--r-- | libcxx/src/barrier.cpp | 103 | ||||
-rw-r--r-- | libcxx/src/charconv.cpp | 18 | ||||
-rw-r--r-- | libcxx/src/chrono.cpp | 120 | ||||
-rw-r--r-- | libcxx/src/filesystem/operations.cpp | 12 | ||||
-rw-r--r-- | libcxx/src/include/apple_availability.h | 16 | ||||
-rw-r--r-- | libcxx/src/locale.cpp | 4 | ||||
-rw-r--r-- | libcxx/src/random_shuffle.cpp | 61 | ||||
-rw-r--r-- | libcxx/src/string.cpp | 9 | ||||
-rw-r--r-- | libcxx/src/thread.cpp | 6 |
11 files changed, 417 insertions, 169 deletions
diff --git a/libcxx/src/algorithm.cpp b/libcxx/src/algorithm.cpp index 40669fb9e756..9f11dc38b15b 100644 --- a/libcxx/src/algorithm.cpp +++ b/libcxx/src/algorithm.cpp @@ -7,13 +7,6 @@ //===----------------------------------------------------------------------===// #include "algorithm" -#include "random" -#ifndef _LIBCPP_HAS_NO_THREADS -#include "mutex" -#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) -#pragma comment(lib, "pthread") -#endif -#endif _LIBCPP_BEGIN_NAMESPACE_STD @@ -51,45 +44,4 @@ template bool __insertion_sort_incomplete<__less<long double>&, long double*>(lo template unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&); -#ifndef _LIBCPP_HAS_NO_THREADS -_LIBCPP_SAFE_STATIC static __libcpp_mutex_t __rs_mut = _LIBCPP_MUTEX_INITIALIZER; -#endif -unsigned __rs_default::__c_ = 0; - -__rs_default::__rs_default() -{ -#ifndef _LIBCPP_HAS_NO_THREADS - __libcpp_mutex_lock(&__rs_mut); -#endif - __c_ = 1; -} - -__rs_default::__rs_default(const __rs_default&) -{ - ++__c_; -} - -__rs_default::~__rs_default() -{ -#ifndef _LIBCPP_HAS_NO_THREADS - if (--__c_ == 0) - __libcpp_mutex_unlock(&__rs_mut); -#else - --__c_; -#endif -} - -__rs_default::result_type -__rs_default::operator()() -{ - static mt19937 __rs_g; - return __rs_g(); -} - -__rs_default -__rs_get() -{ - return __rs_default(); -} - _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/atomic.cpp b/libcxx/src/atomic.cpp new file mode 100644 index 000000000000..65d4837bb4a7 --- /dev/null +++ b/libcxx/src/atomic.cpp @@ -0,0 +1,189 @@ +//===------------------------- atomic.cpp ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <__config> +#ifndef _LIBCPP_HAS_NO_THREADS + +#include <climits> +#include <atomic> +#include <functional> + +#include <iostream> + +#ifdef __linux__ + +#include <unistd.h> +#include <linux/futex.h> +#include <sys/syscall.h> + +#else // <- Add other operating systems here + +// Baseline needs no new headers + +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifdef __linux__ + +static void __libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, + __cxx_contention_t __val) +{ + static constexpr timespec __timeout = { 2, 0 }; + syscall(SYS_futex, __ptr, FUTEX_WAIT_PRIVATE, __val, &__timeout, 0, 0); +} + +static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile* __ptr, + bool __notify_one) +{ + syscall(SYS_futex, __ptr, FUTEX_WAKE_PRIVATE, __notify_one ? 1 : INT_MAX, 0, 0, 0); +} + +#elif defined(__APPLE__) && defined(_LIBCPP_USE_ULOCK) + +extern "C" int __ulock_wait(uint32_t operation, void *addr, uint64_t value, + uint32_t timeout); /* timeout is specified in microseconds */ +extern "C" int __ulock_wake(uint32_t operation, void *addr, uint64_t wake_value); + +#define UL_COMPARE_AND_WAIT 1 +#define ULF_WAKE_ALL 0x00000100 + +static void __libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, + __cxx_contention_t __val) +{ + __ulock_wait(UL_COMPARE_AND_WAIT, + const_cast<__cxx_atomic_contention_t*>(__ptr), __val, 0); +} + +static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile* __ptr, + bool __notify_one) +{ + __ulock_wake(UL_COMPARE_AND_WAIT | (__notify_one ? 0 : ULF_WAKE_ALL), + const_cast<__cxx_atomic_contention_t*>(__ptr), 0); +} + +#else // <- Add other operating systems here + +// Baseline is just a timed backoff + +static void __libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, + __cxx_contention_t __val) +{ + __libcpp_thread_poll_with_backoff([=]() -> bool { + return !__cxx_nonatomic_compare_equal(__cxx_atomic_load(__ptr, memory_order_relaxed), __val); + }, __libcpp_timed_backoff_policy()); +} + +static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile*, bool) { } + +#endif // __linux__ + +static constexpr size_t __libcpp_contention_table_size = (1 << 8); /* < there's no magic in this number */ + +struct alignas(64) /* aim to avoid false sharing */ __libcpp_contention_table_entry +{ + __cxx_atomic_contention_t __contention_state; + __cxx_atomic_contention_t __platform_state; + inline constexpr __libcpp_contention_table_entry() : + __contention_state(0), __platform_state(0) { } +}; + +static __libcpp_contention_table_entry __libcpp_contention_table[ __libcpp_contention_table_size ]; + +static hash<void const volatile*> __libcpp_contention_hasher; + +static __libcpp_contention_table_entry* __libcpp_contention_state(void const volatile * p) +{ + return &__libcpp_contention_table[__libcpp_contention_hasher(p) & (__libcpp_contention_table_size - 1)]; +} + +/* Given an atomic to track contention and an atomic to actually wait on, which may be + the same atomic, we try to detect contention to avoid spuriously calling the platform. */ + +static void __libcpp_contention_notify(__cxx_atomic_contention_t volatile* __contention_state, + __cxx_atomic_contention_t const volatile* __platform_state, + bool __notify_one) +{ + if(0 != __cxx_atomic_load(__contention_state, memory_order_seq_cst)) + // We only call 'wake' if we consumed a contention bit here. + __libcpp_platform_wake_by_address(__platform_state, __notify_one); +} +static __cxx_contention_t __libcpp_contention_monitor_for_wait(__cxx_atomic_contention_t volatile* __contention_state, + __cxx_atomic_contention_t const volatile* __platform_state) +{ + // We will monitor this value. + return __cxx_atomic_load(__platform_state, memory_order_acquire); +} +static void __libcpp_contention_wait(__cxx_atomic_contention_t volatile* __contention_state, + __cxx_atomic_contention_t const volatile* __platform_state, + __cxx_contention_t __old_value) +{ + __cxx_atomic_fetch_add(__contention_state, __cxx_contention_t(1), memory_order_seq_cst); + // We sleep as long as the monitored value hasn't changed. + __libcpp_platform_wait_on_address(__platform_state, __old_value); + __cxx_atomic_fetch_sub(__contention_state, __cxx_contention_t(1), memory_order_release); +} + +/* When the incoming atomic is the wrong size for the platform wait size, need to + launder the value sequence through an atomic from our table. */ + +static void __libcpp_atomic_notify(void const volatile* __location) +{ + auto const __entry = __libcpp_contention_state(__location); + // The value sequence laundering happens on the next line below. + __cxx_atomic_fetch_add(&__entry->__platform_state, __cxx_contention_t(1), memory_order_release); + __libcpp_contention_notify(&__entry->__contention_state, + &__entry->__platform_state, + false /* when laundering, we can't handle notify_one */); +} +_LIBCPP_EXPORTED_FROM_ABI +void __cxx_atomic_notify_one(void const volatile* __location) + { __libcpp_atomic_notify(__location); } +_LIBCPP_EXPORTED_FROM_ABI +void __cxx_atomic_notify_all(void const volatile* __location) + { __libcpp_atomic_notify(__location); } +_LIBCPP_EXPORTED_FROM_ABI +__cxx_contention_t __libcpp_atomic_monitor(void const volatile* __location) +{ + auto const __entry = __libcpp_contention_state(__location); + return __libcpp_contention_monitor_for_wait(&__entry->__contention_state, &__entry->__platform_state); +} +_LIBCPP_EXPORTED_FROM_ABI +void __libcpp_atomic_wait(void const volatile* __location, __cxx_contention_t __old_value) +{ + auto const __entry = __libcpp_contention_state(__location); + __libcpp_contention_wait(&__entry->__contention_state, &__entry->__platform_state, __old_value); +} + +/* When the incoming atomic happens to be the platform wait size, we still need to use the + table for the contention detection, but we can use the atomic directly for the wait. */ + +_LIBCPP_EXPORTED_FROM_ABI +void __cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile* __location) +{ + __libcpp_contention_notify(&__libcpp_contention_state(__location)->__contention_state, __location, true); +} +_LIBCPP_EXPORTED_FROM_ABI +void __cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile* __location) +{ + __libcpp_contention_notify(&__libcpp_contention_state(__location)->__contention_state, __location, false); +} +_LIBCPP_EXPORTED_FROM_ABI +__cxx_contention_t __libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile* __location) +{ + return __libcpp_contention_monitor_for_wait(&__libcpp_contention_state(__location)->__contention_state, __location); +} +_LIBCPP_EXPORTED_FROM_ABI +void __libcpp_atomic_wait(__cxx_atomic_contention_t const volatile* __location, __cxx_contention_t __old_value) +{ + __libcpp_contention_wait(&__libcpp_contention_state(__location)->__contention_state, __location, __old_value); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif //_LIBCPP_HAS_NO_THREADS diff --git a/libcxx/src/barrier.cpp b/libcxx/src/barrier.cpp new file mode 100644 index 000000000000..c5e33cbba3bd --- /dev/null +++ b/libcxx/src/barrier.cpp @@ -0,0 +1,103 @@ +//===------------------------- barrier.cpp ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <__config> + +#ifndef _LIBCPP_HAS_NO_THREADS + +#include <barrier> +#include <thread> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_TREE_BARRIER) && (_LIBCPP_STD_VER > 11) + +class __barrier_algorithm_base { +public: + struct alignas(64) /* naturally-align the heap state */ __state_t + { + struct { + __atomic_base<__barrier_phase_t> __phase = ATOMIC_VAR_INIT(0); + } __tickets[64]; + }; + + ptrdiff_t& __expected; + unique_ptr<char[]> __state_allocation; + __state_t* __state; + + _LIBCPP_HIDDEN + __barrier_algorithm_base(ptrdiff_t& __expected) + : __expected(__expected) + { + size_t const __count = (__expected + 1) >> 1; + size_t const __size = sizeof(__state_t) * __count; + size_t __allocation_size = __size + alignof(__state_t); + __state_allocation = unique_ptr<char[]>(new char[__allocation_size]); + void* __allocation = __state_allocation.get(); + void* const __state_ = align(alignof(__state_t), __size, __allocation, __allocation_size); + __state = new (__state_) __barrier_algorithm_base::__state_t[__count]; + } + _LIBCPP_HIDDEN + bool __arrive(__barrier_phase_t __old_phase) + { + __barrier_phase_t const __half_step = __old_phase + 1, + __full_step = __old_phase + 2; + size_t __current_expected = __expected, + __current = hash<thread::id>()(this_thread::get_id()) % ((__expected + 1) >> 1); + for(int __round = 0;; ++__round) { + if(__current_expected <= 1) + return true; + size_t const __end_node = ((__current_expected + 1) >> 1), + __last_node = __end_node - 1; + for(;;++__current) { + if(__current == __end_node) + __current = 0; + __barrier_phase_t expect = __old_phase; + if(__current == __last_node && (__current_expected & 1)) + { + if(__state[__current].__tickets[__round].__phase.compare_exchange_strong(expect, __full_step, memory_order_acq_rel)) + break; // I'm 1 in 1, go to next __round + } + else if(__state[__current].__tickets[__round].__phase.compare_exchange_strong(expect, __half_step, memory_order_acq_rel)) + { + return false; // I'm 1 in 2, done with arrival + } + else if(expect == __half_step) + { + if(__state[__current].__tickets[__round].__phase.compare_exchange_strong(expect, __full_step, memory_order_acq_rel)) + break; // I'm 2 in 2, go to next __round + } + } + __current_expected = __last_node + 1; + __current >>= 1; + } + } +}; + +_LIBCPP_EXPORTED_FROM_ABI +__barrier_algorithm_base * __construct_barrier_algorithm_base(ptrdiff_t& __expected) +{ + return new __barrier_algorithm_base(__expected); +} +_LIBCPP_EXPORTED_FROM_ABI +bool __arrive_barrier_algorithm_base(__barrier_algorithm_base* __barrier, + __barrier_phase_t __old_phase) +{ + return __barrier->__arrive(__old_phase); +} +_LIBCPP_EXPORTED_FROM_ABI +void __destroy_barrier_algorithm_base(__barrier_algorithm_base* __barrier) +{ + delete __barrier; +} + +#endif //!defined(_LIBCPP_HAS_NO_TREE_BARRIER) && (_LIBCPP_STD_VER >= 11) + +_LIBCPP_END_NAMESPACE_STD + +#endif //_LIBCPP_HAS_NO_THREADS diff --git a/libcxx/src/charconv.cpp b/libcxx/src/charconv.cpp index d3035883a78f..8cfe40d156b2 100644 --- a/libcxx/src/charconv.cpp +++ b/libcxx/src/charconv.cpp @@ -32,7 +32,7 @@ static constexpr char cDigitsLut[200] = { template <typename T> inline _LIBCPP_INLINE_VISIBILITY char* -append1(char* buffer, T i) +append1(char* buffer, T i) noexcept { *buffer = '0' + static_cast<char>(i); return buffer + 1; @@ -40,7 +40,7 @@ append1(char* buffer, T i) template <typename T> inline _LIBCPP_INLINE_VISIBILITY char* -append2(char* buffer, T i) +append2(char* buffer, T i) noexcept { memcpy(buffer, &cDigitsLut[(i)*2], 2); return buffer + 2; @@ -48,21 +48,21 @@ append2(char* buffer, T i) template <typename T> inline _LIBCPP_INLINE_VISIBILITY char* -append3(char* buffer, T i) +append3(char* buffer, T i) noexcept { return append2(append1(buffer, (i) / 100), (i) % 100); } template <typename T> inline _LIBCPP_INLINE_VISIBILITY char* -append4(char* buffer, T i) +append4(char* buffer, T i) noexcept { return append2(append2(buffer, (i) / 100), (i) % 100); } template <typename T> inline _LIBCPP_INLINE_VISIBILITY char* -append2_no_zeros(char* buffer, T v) +append2_no_zeros(char* buffer, T v) noexcept { if (v < 10) return append1(buffer, v); @@ -72,7 +72,7 @@ append2_no_zeros(char* buffer, T v) template <typename T> inline _LIBCPP_INLINE_VISIBILITY char* -append4_no_zeros(char* buffer, T v) +append4_no_zeros(char* buffer, T v) noexcept { if (v < 100) return append2_no_zeros(buffer, v); @@ -84,7 +84,7 @@ append4_no_zeros(char* buffer, T v) template <typename T> inline _LIBCPP_INLINE_VISIBILITY char* -append8_no_zeros(char* buffer, T v) +append8_no_zeros(char* buffer, T v) noexcept { if (v < 10000) { @@ -99,7 +99,7 @@ append8_no_zeros(char* buffer, T v) } char* -__u32toa(uint32_t value, char* buffer) +__u32toa(uint32_t value, char* buffer) _NOEXCEPT { if (value < 100000000) { @@ -120,7 +120,7 @@ __u32toa(uint32_t value, char* buffer) } char* -__u64toa(uint64_t value, char* buffer) +__u64toa(uint64_t value, char* buffer) _NOEXCEPT { if (value < 100000000) { diff --git a/libcxx/src/chrono.cpp b/libcxx/src/chrono.cpp index 9d448b6a985b..f0a5d50ddf77 100644 --- a/libcxx/src/chrono.cpp +++ b/libcxx/src/chrono.cpp @@ -9,36 +9,32 @@ #include "chrono" #include "cerrno" // errno #include "system_error" // __throw_system_error -#include <time.h> // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME +#include <time.h> // clock_gettime and CLOCK_{MONOTONIC,REALTIME,MONOTONIC_RAW} #include "include/apple_availability.h" -#if !defined(__APPLE__) +#if __has_include(<unistd.h>) +#include <unistd.h> +#endif + +#if !defined(__APPLE__) && _POSIX_TIMERS > 0 #define _LIBCPP_USE_CLOCK_GETTIME -#endif // __APPLE__ +#endif #if defined(_LIBCPP_WIN32API) -#define WIN32_LEAN_AND_MEAN -#define VC_EXTRA_LEAN -#include <windows.h> -#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 -#include <winapifamily.h> -#endif +# define WIN32_LEAN_AND_MEAN +# define VC_EXTRA_LEAN +# include <windows.h> +# if _WIN32_WINNT >= _WIN32_WINNT_WIN8 +# include <winapifamily.h> +# endif #else -#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME) -#include <sys/time.h> // for gettimeofday and timeval -#endif // !defined(CLOCK_REALTIME) +# if !defined(CLOCK_REALTIME) +# include <sys/time.h> // for gettimeofday and timeval +# endif // !defined(CLOCK_REALTIME) #endif // defined(_LIBCPP_WIN32API) -#if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) -#if __APPLE__ -#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t -#elif !defined(_LIBCPP_WIN32API) && !defined(CLOCK_MONOTONIC) -#error "Monotonic clock not implemented" -#endif -#endif - #if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB) -#pragma comment(lib, "rt") +# pragma comment(lib, "rt") #endif _LIBCPP_BEGIN_NAMESPACE_STD @@ -78,7 +74,7 @@ system_clock::now() _NOEXCEPT static_cast<__int64>(ft.dwLowDateTime)}; return time_point(duration_cast<duration>(d - nt_to_unix_epoch)); #else -#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) +#if defined(CLOCK_REALTIME) struct timespec tp; if (0 != clock_gettime(CLOCK_REALTIME, &tp)) __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); @@ -87,7 +83,7 @@ system_clock::now() _NOEXCEPT timeval tv; gettimeofday(&tv, 0); return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); -#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME +#endif // CLOCK_REALTIME #endif } @@ -114,71 +110,24 @@ const bool steady_clock::is_steady; #if defined(__APPLE__) -// Darwin libc versions >= 1133 provide ns precision via CLOCK_UPTIME_RAW -#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW) +#if !defined(CLOCK_MONOTONIC_RAW) +# error "Building libc++ on Apple platforms requires CLOCK_MONOTONIC_RAW" +#endif + +// On Apple platforms, only CLOCK_UPTIME_RAW, CLOCK_MONOTONIC_RAW or +// mach_absolute_time are able to time functions in the nanosecond range. +// Furthermore, only CLOCK_MONOTONIC_RAW is truly monotonic, because it +// also counts cycles when the system is asleep. Thus, it is the only +// acceptable implementation of steady_clock. steady_clock::time_point steady_clock::now() _NOEXCEPT { struct timespec tp; - if (0 != clock_gettime(CLOCK_UPTIME_RAW, &tp)) - __throw_system_error(errno, "clock_gettime(CLOCK_UPTIME_RAW) failed"); + if (0 != clock_gettime(CLOCK_MONOTONIC_RAW, &tp)) + __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC_RAW) failed"); return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); } -#else -// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of -// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom -// are run time constants supplied by the OS. This clock has no relationship -// to the Gregorian calendar. It's main use is as a high resolution timer. - -// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize -// for that case as an optimization. - -static -steady_clock::rep -steady_simplified() -{ - return static_cast<steady_clock::rep>(mach_absolute_time()); -} - -static -double -compute_steady_factor() -{ - mach_timebase_info_data_t MachInfo; - mach_timebase_info(&MachInfo); - return static_cast<double>(MachInfo.numer) / MachInfo.denom; -} - -static -steady_clock::rep -steady_full() -{ - static const double factor = compute_steady_factor(); - return static_cast<steady_clock::rep>(mach_absolute_time() * factor); -} - -typedef steady_clock::rep (*FP)(); - -static -FP -init_steady_clock() -{ - mach_timebase_info_data_t MachInfo; - mach_timebase_info(&MachInfo); - if (MachInfo.numer == MachInfo.denom) - return &steady_simplified; - return &steady_full; -} - -steady_clock::time_point -steady_clock::now() _NOEXCEPT -{ - static FP fp = init_steady_clock(); - return time_point(duration(fp())); -} -#endif // defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW) - #elif defined(_LIBCPP_WIN32API) // https://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx says: @@ -206,13 +155,6 @@ steady_clock::now() _NOEXCEPT #elif defined(CLOCK_MONOTONIC) -// On Apple platforms only CLOCK_UPTIME_RAW or mach_absolute_time are able to -// time functions in the nanosecond range. Thus, they are the only acceptable -// implementations of steady_clock. -#ifdef __APPLE__ -#error "Never use CLOCK_MONOTONIC for steady_clock::now on Apple platforms" -#endif - steady_clock::time_point steady_clock::now() _NOEXCEPT { @@ -223,7 +165,7 @@ steady_clock::now() _NOEXCEPT } #else -#error "Monotonic clock not implemented" +# error "Monotonic clock not implemented" #endif #endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK diff --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp index 876399fb4d4e..5c98671feeed 100644 --- a/libcxx/src/filesystem/operations.cpp +++ b/libcxx/src/filesystem/operations.cpp @@ -36,13 +36,9 @@ #define _LIBCPP_USE_COPYFILE #endif -#if !defined(__APPLE__) -#define _LIBCPP_USE_CLOCK_GETTIME -#endif - -#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME) +#if !defined(CLOCK_REALTIME) #include <sys/time.h> // for gettimeofday and timeval -#endif // !defined(CLOCK_REALTIME) +#endif // !defined(CLOCK_REALTIME) #if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB) #pragma comment(lib, "rt") @@ -490,7 +486,7 @@ const bool _FilesystemClock::is_steady; _FilesystemClock::time_point _FilesystemClock::now() noexcept { typedef chrono::duration<rep> __secs; -#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) +#if defined(CLOCK_REALTIME) typedef chrono::duration<rep, nano> __nsecs; struct timespec tp; if (0 != clock_gettime(CLOCK_REALTIME, &tp)) @@ -502,7 +498,7 @@ _FilesystemClock::time_point _FilesystemClock::now() noexcept { timeval tv; gettimeofday(&tv, 0); return time_point(__secs(tv.tv_sec) + __microsecs(tv.tv_usec)); -#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME +#endif // CLOCK_REALTIME } filesystem_error::~filesystem_error() {} diff --git a/libcxx/src/include/apple_availability.h b/libcxx/src/include/apple_availability.h index 0091138170fd..0f999d3feafb 100644 --- a/libcxx/src/include/apple_availability.h +++ b/libcxx/src/include/apple_availability.h @@ -29,20 +29,20 @@ #endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__ #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101200 -#define _LIBCPP_USE_CLOCK_GETTIME +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101500 +#define _LIBCPP_USE_ULOCK #endif #elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 100000 -#define _LIBCPP_USE_CLOCK_GETTIME +#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 130000 +#define _LIBCPP_USE_ULOCK #endif #elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 100000 -#define _LIBCPP_USE_CLOCK_GETTIME +#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 130000 +#define _LIBCPP_USE_ULOCK #endif #elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 30000 -#define _LIBCPP_USE_CLOCK_GETTIME +#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 60000 +#define _LIBCPP_USE_ULOCK #endif #endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__ diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp index 2757eaa5acda..b9180880e494 100644 --- a/libcxx/src/locale.cpp +++ b/libcxx/src/locale.cpp @@ -536,7 +536,7 @@ locale::operator=(const locale& other) _NOEXCEPT locale::locale(const char* name) : __locale_(name ? new __imp(name) - : (__throw_runtime_error("locale constructed with null"), (__imp*)0)) + : (__throw_runtime_error("locale constructed with null"), nullptr)) { __locale_->__add_shared(); } @@ -549,7 +549,7 @@ locale::locale(const string& name) locale::locale(const locale& other, const char* name, category c) : __locale_(name ? new __imp(*other.__locale_, name, c) - : (__throw_runtime_error("locale constructed with null"), (__imp*)0)) + : (__throw_runtime_error("locale constructed with null"), nullptr)) { __locale_->__add_shared(); } diff --git a/libcxx/src/random_shuffle.cpp b/libcxx/src/random_shuffle.cpp new file mode 100644 index 000000000000..be2c47fa0def --- /dev/null +++ b/libcxx/src/random_shuffle.cpp @@ -0,0 +1,61 @@ +//===----------------------- random_shuffle.cpp ---------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "algorithm" +#include "random" +#ifndef _LIBCPP_HAS_NO_THREADS +# include "mutex" +# if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) +# pragma comment(lib, "pthread") +# endif +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_HAS_NO_THREADS +_LIBCPP_SAFE_STATIC static __libcpp_mutex_t __rs_mut = _LIBCPP_MUTEX_INITIALIZER; +#endif +unsigned __rs_default::__c_ = 0; + +__rs_default::__rs_default() +{ +#ifndef _LIBCPP_HAS_NO_THREADS + __libcpp_mutex_lock(&__rs_mut); +#endif + __c_ = 1; +} + +__rs_default::__rs_default(const __rs_default&) +{ + ++__c_; +} + +__rs_default::~__rs_default() +{ +#ifndef _LIBCPP_HAS_NO_THREADS + if (--__c_ == 0) + __libcpp_mutex_unlock(&__rs_mut); +#else + --__c_; +#endif +} + +__rs_default::result_type +__rs_default::operator()() +{ + static mt19937 __rs_g; + return __rs_g(); +} + +__rs_default +__rs_get() +{ + return __rs_default(); +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/string.cpp b/libcxx/src/string.cpp index 4802d63c811b..5105594cf38b 100644 --- a/libcxx/src/string.cpp +++ b/libcxx/src/string.cpp @@ -20,8 +20,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<wchar_t>; +#ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION +_LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) +_LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) +#else +_LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) +_LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) +#endif template string diff --git a/libcxx/src/thread.cpp b/libcxx/src/thread.cpp index c0bc1cbbbbc3..5f44e9e40fc7 100644 --- a/libcxx/src/thread.cpp +++ b/libcxx/src/thread.cpp @@ -23,9 +23,9 @@ # endif #endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__CloudABI__) || defined(__Fuchsia__) || defined(__wasi__) -# include <unistd.h> -#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__CloudABI__) || defined(__Fuchsia__) || defined(__wasi__) +#if __has_include(<unistd.h>) +#include <unistd.h> +#endif #if defined(__NetBSD__) #pragma weak pthread_create // Do not create libpthread dependency |