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 <__config>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <iosfwd>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
|
#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
|
#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_END_NAMESPACE_STD
|
||||||
|
|
||||||
_LIBCPP_POP_MACROS
|
_LIBCPP_POP_MACROS
|
||||||
|
@ -280,7 +280,7 @@ class _LIBCPP_TYPE_VIS recursive_timed_mutex
|
|||||||
mutex __m_;
|
mutex __m_;
|
||||||
condition_variable __cv_;
|
condition_variable __cv_;
|
||||||
size_t __count_;
|
size_t __count_;
|
||||||
__libcpp_thread_id __id_;
|
__thread_id __id_;
|
||||||
public:
|
public:
|
||||||
recursive_timed_mutex();
|
recursive_timed_mutex();
|
||||||
~recursive_timed_mutex();
|
~recursive_timed_mutex();
|
||||||
@ -307,9 +307,9 @@ bool
|
|||||||
recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
|
recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
|
||||||
{
|
{
|
||||||
using namespace chrono;
|
using namespace chrono;
|
||||||
__libcpp_thread_id __id = __libcpp_thread_get_current_id();
|
__thread_id __id = this_thread::get_id();
|
||||||
unique_lock<mutex> lk(__m_);
|
unique_lock<mutex> lk(__m_);
|
||||||
if (__libcpp_thread_id_equal(__id, __id_))
|
if (__id == __id_)
|
||||||
{
|
{
|
||||||
if (__count_ == numeric_limits<size_t>::max())
|
if (__count_ == numeric_limits<size_t>::max())
|
||||||
return false;
|
return false;
|
||||||
|
@ -201,64 +201,6 @@ __thread_specific_ptr<_Tp>::set_pointer(pointer __p)
|
|||||||
__libcpp_tls_set(__key_, __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<>
|
template<>
|
||||||
struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>
|
struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>
|
||||||
: public unary_function<__thread_id, size_t>
|
: public unary_function<__thread_id, size_t>
|
||||||
@ -270,17 +212,11 @@ struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace this_thread
|
template<class _CharT, class _Traits>
|
||||||
{
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
basic_ostream<_CharT, _Traits>&
|
||||||
inline _LIBCPP_INLINE_VISIBILITY
|
operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id)
|
||||||
__thread_id
|
{return __os << __id.__id_;}
|
||||||
get_id() _NOEXCEPT
|
|
||||||
{
|
|
||||||
return __libcpp_thread_get_current_id();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // this_thread
|
|
||||||
|
|
||||||
class _LIBCPP_TYPE_VIS thread
|
class _LIBCPP_TYPE_VIS thread
|
||||||
{
|
{
|
||||||
|
@ -130,7 +130,7 @@ timed_mutex::unlock() _NOEXCEPT
|
|||||||
|
|
||||||
recursive_timed_mutex::recursive_timed_mutex()
|
recursive_timed_mutex::recursive_timed_mutex()
|
||||||
: __count_(0),
|
: __count_(0),
|
||||||
__id_(0)
|
__id_{}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,9 +142,9 @@ recursive_timed_mutex::~recursive_timed_mutex()
|
|||||||
void
|
void
|
||||||
recursive_timed_mutex::lock()
|
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_);
|
unique_lock<mutex> lk(__m_);
|
||||||
if (__libcpp_thread_id_equal(id, __id_))
|
if (id ==__id_)
|
||||||
{
|
{
|
||||||
if (__count_ == numeric_limits<size_t>::max())
|
if (__count_ == numeric_limits<size_t>::max())
|
||||||
__throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached");
|
__throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached");
|
||||||
@ -160,9 +160,9 @@ recursive_timed_mutex::lock()
|
|||||||
bool
|
bool
|
||||||
recursive_timed_mutex::try_lock() _NOEXCEPT
|
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);
|
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())
|
if (__count_ == numeric_limits<size_t>::max())
|
||||||
return false;
|
return false;
|
||||||
@ -179,7 +179,7 @@ recursive_timed_mutex::unlock() _NOEXCEPT
|
|||||||
unique_lock<mutex> lk(__m_);
|
unique_lock<mutex> lk(__m_);
|
||||||
if (--__count_ == 0)
|
if (--__count_ == 0)
|
||||||
{
|
{
|
||||||
__id_ = 0;
|
__id_.__reset();
|
||||||
lk.unlock();
|
lk.unlock();
|
||||||
__cv_.notify_one();
|
__cv_.notify_one();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user