Pull in r368867 from upstream libc++ trunk (by Marshall Clow):
Rework recursive_timed_mutex so that it uses __thread_id instead of using the lower-level __libcpp_thread_id. This is prep for fixing PR42918. Reviewed as https://reviews.llvm.org/D65895 Pull in r368916 from upstream libc++ trunk (by Marshall Clow): Fix thread comparison by making sure we never pass our special 'not a thread' value to the underlying implementation. Fixes PR#42918. This should fix std:🧵🆔:operator==() attempting to call pthread_equal(3) with zero values. Reported by: andrew@tao11.riddles.org.uk PR: 239038, 239550 MFC after: 3 days
This commit is contained in:
parent
cf5228cea1
commit
23cc093cf6
@ -13,6 +13,7 @@
|
||||
|
||||
#include <__config>
|
||||
#include <chrono>
|
||||
#include <iosfwd>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
|
||||
@ -393,6 +394,86 @@ int __libcpp_tls_set(__libcpp_tls_key __key, void *__p)
|
||||
|
||||
#endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL
|
||||
|
||||
class _LIBCPP_TYPE_VIS thread;
|
||||
class _LIBCPP_TYPE_VIS __thread_id;
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
|
||||
|
||||
} // this_thread
|
||||
|
||||
template<> struct hash<__thread_id>;
|
||||
|
||||
class _LIBCPP_TEMPLATE_VIS __thread_id
|
||||
{
|
||||
// FIXME: pthread_t is a pointer on Darwin but a long on Linux.
|
||||
// NULL is the no-thread value on Darwin. Someone needs to check
|
||||
// on other platforms. We assume 0 works everywhere for now.
|
||||
__libcpp_thread_id __id_;
|
||||
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__thread_id() _NOEXCEPT : __id_(0) {}
|
||||
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{ // don't pass id==0 to underlying routines
|
||||
if (__x.__id_ == 0) return __y.__id_ == 0;
|
||||
if (__y.__id_ == 0) return false;
|
||||
return __libcpp_thread_id_equal(__x.__id_, __y.__id_);
|
||||
}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{return !(__x == __y);}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{ // id==0 is always less than any other thread_id
|
||||
if (__x.__id_ == 0) return __y.__id_ != 0;
|
||||
if (__y.__id_ == 0) return false;
|
||||
return __libcpp_thread_id_less(__x.__id_, __y.__id_);
|
||||
}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{return !(__y < __x);}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{return __y < __x ;}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{return !(__x < __y);}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __reset() { __id_ = 0; }
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
friend
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
basic_ostream<_CharT, _Traits>&
|
||||
operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id);
|
||||
|
||||
private:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__thread_id(__libcpp_thread_id __id) : __id_(__id) {}
|
||||
|
||||
friend __thread_id this_thread::get_id() _NOEXCEPT;
|
||||
friend class _LIBCPP_TYPE_VIS thread;
|
||||
friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
|
||||
};
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
__thread_id
|
||||
get_id() _NOEXCEPT
|
||||
{
|
||||
return __libcpp_thread_get_current_id();
|
||||
}
|
||||
|
||||
} // this_thread
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
@ -280,7 +280,7 @@ class _LIBCPP_TYPE_VIS recursive_timed_mutex
|
||||
mutex __m_;
|
||||
condition_variable __cv_;
|
||||
size_t __count_;
|
||||
__libcpp_thread_id __id_;
|
||||
__thread_id __id_;
|
||||
public:
|
||||
recursive_timed_mutex();
|
||||
~recursive_timed_mutex();
|
||||
@ -307,9 +307,9 @@ bool
|
||||
recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
|
||||
{
|
||||
using namespace chrono;
|
||||
__libcpp_thread_id __id = __libcpp_thread_get_current_id();
|
||||
__thread_id __id = this_thread::get_id();
|
||||
unique_lock<mutex> lk(__m_);
|
||||
if (__libcpp_thread_id_equal(__id, __id_))
|
||||
if (__id == __id_)
|
||||
{
|
||||
if (__count_ == numeric_limits<size_t>::max())
|
||||
return false;
|
||||
|
@ -201,64 +201,6 @@ __thread_specific_ptr<_Tp>::set_pointer(pointer __p)
|
||||
__libcpp_tls_set(__key_, __p);
|
||||
}
|
||||
|
||||
class _LIBCPP_TYPE_VIS thread;
|
||||
class _LIBCPP_TYPE_VIS __thread_id;
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT;
|
||||
|
||||
} // this_thread
|
||||
|
||||
template<> struct hash<__thread_id>;
|
||||
|
||||
class _LIBCPP_TEMPLATE_VIS __thread_id
|
||||
{
|
||||
// FIXME: pthread_t is a pointer on Darwin but a long on Linux.
|
||||
// NULL is the no-thread value on Darwin. Someone needs to check
|
||||
// on other platforms. We assume 0 works everywhere for now.
|
||||
__libcpp_thread_id __id_;
|
||||
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__thread_id() _NOEXCEPT : __id_(0) {}
|
||||
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{return __libcpp_thread_id_equal(__x.__id_, __y.__id_);}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{return !(__x == __y);}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{return __libcpp_thread_id_less(__x.__id_, __y.__id_);}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{return !(__y < __x);}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{return __y < __x ;}
|
||||
friend _LIBCPP_INLINE_VISIBILITY
|
||||
bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT
|
||||
{return !(__x < __y);}
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
friend
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
basic_ostream<_CharT, _Traits>&
|
||||
operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
|
||||
{return __os << __id.__id_;}
|
||||
|
||||
private:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__thread_id(__libcpp_thread_id __id) : __id_(__id) {}
|
||||
|
||||
friend __thread_id this_thread::get_id() _NOEXCEPT;
|
||||
friend class _LIBCPP_TYPE_VIS thread;
|
||||
friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>
|
||||
: public unary_function<__thread_id, size_t>
|
||||
@ -270,17 +212,11 @@ struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>
|
||||
}
|
||||
};
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
__thread_id
|
||||
get_id() _NOEXCEPT
|
||||
{
|
||||
return __libcpp_thread_get_current_id();
|
||||
}
|
||||
|
||||
} // this_thread
|
||||
template<class _CharT, class _Traits>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
basic_ostream<_CharT, _Traits>&
|
||||
operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
|
||||
{return __os << __id.__id_;}
|
||||
|
||||
class _LIBCPP_TYPE_VIS thread
|
||||
{
|
||||
|
@ -130,7 +130,7 @@ timed_mutex::unlock() _NOEXCEPT
|
||||
|
||||
recursive_timed_mutex::recursive_timed_mutex()
|
||||
: __count_(0),
|
||||
__id_(0)
|
||||
__id_{}
|
||||
{
|
||||
}
|
||||
|
||||
@ -142,9 +142,9 @@ recursive_timed_mutex::~recursive_timed_mutex()
|
||||
void
|
||||
recursive_timed_mutex::lock()
|
||||
{
|
||||
__libcpp_thread_id id = __libcpp_thread_get_current_id();
|
||||
__thread_id id = this_thread::get_id();
|
||||
unique_lock<mutex> lk(__m_);
|
||||
if (__libcpp_thread_id_equal(id, __id_))
|
||||
if (id ==__id_)
|
||||
{
|
||||
if (__count_ == numeric_limits<size_t>::max())
|
||||
__throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached");
|
||||
@ -160,9 +160,9 @@ recursive_timed_mutex::lock()
|
||||
bool
|
||||
recursive_timed_mutex::try_lock() _NOEXCEPT
|
||||
{
|
||||
__libcpp_thread_id id = __libcpp_thread_get_current_id();
|
||||
__thread_id id = this_thread::get_id();
|
||||
unique_lock<mutex> lk(__m_, try_to_lock);
|
||||
if (lk.owns_lock() && (__count_ == 0 || __libcpp_thread_id_equal(id, __id_)))
|
||||
if (lk.owns_lock() && (__count_ == 0 || id == __id_))
|
||||
{
|
||||
if (__count_ == numeric_limits<size_t>::max())
|
||||
return false;
|
||||
@ -179,7 +179,7 @@ recursive_timed_mutex::unlock() _NOEXCEPT
|
||||
unique_lock<mutex> lk(__m_);
|
||||
if (--__count_ == 0)
|
||||
{
|
||||
__id_ = 0;
|
||||
__id_.__reset();
|
||||
lk.unlock();
|
||||
__cv_.notify_one();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user