diff options
Diffstat (limited to 'winsup/cygwin/thread.cc')
-rw-r--r-- | winsup/cygwin/thread.cc | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 9ee9650..86a00e7 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -32,6 +32,7 @@ details. */ #include "ntdll.h" #include "cygwait.h" #include "exception.h" +#include "register.h" /* For Linux compatibility, the length of a thread name is 16 characters. */ #define THRNAMELEN 16 @@ -629,7 +630,7 @@ pthread::cancel () threadlist_t *tl_entry = cygheap->find_tls (cygtls); if (!cygtls->inside_kernel (&context)) { - context.Rip = (ULONG_PTR) pthread::static_cancel_self; + context._CX_instPtr = (ULONG_PTR) pthread::static_cancel_self; SetThreadContext (win32_obj_id, &context); } cygheap->unlock_tls (tl_entry); @@ -1666,27 +1667,49 @@ pthread_rwlock::_fixup_after_fork () /* pthread_key */ /* static members */ /* This stores pthread_key information across fork() boundaries */ -List<pthread_key> pthread_key::keys; +pthread_key::keys_list pthread_key::keys[PTHREAD_KEYS_MAX]; /* non-static members */ -pthread_key::pthread_key (void (*aDestructor) (void *)):verifyable_object (PTHREAD_KEY_MAGIC), destructor (aDestructor) +pthread_key::pthread_key (void (*aDestructor) (void *)) : + verifyable_object (PTHREAD_KEY_MAGIC), destructor (aDestructor) { tls_index = TlsAlloc (); if (tls_index == TLS_OUT_OF_INDEXES) magic = 0; else - keys.insert (this); + for (size_t cnt = 0; cnt < PTHREAD_KEYS_MAX; cnt++) + { + LONG64 seq = keys[cnt].seq; + if (!keys_list::used (seq) + && InterlockedCompareExchange64 (&keys[cnt].seq, + seq + 1, seq) == seq) + { + keys[cnt].key = this; + keys[cnt].busy_cnt = 0; + key_idx = cnt; + InterlockedIncrement64 (&keys[key_idx].seq); + break; + } + } } pthread_key::~pthread_key () { - /* We may need to make the list code lock the list during operations - */ if (magic != 0) { - keys.remove (this); - TlsFree (tls_index); + LONG64 seq = keys[key_idx].seq; + if (keys_list::ready (seq) + && InterlockedCompareExchange64 (&keys[key_idx].seq, + seq + 1, seq) == seq) + { + while (InterlockedCompareExchange64 (&keys[key_idx].busy_cnt, + INT64_MIN, 0) > 0) + yield (); + keys[key_idx].key = NULL; + InterlockedIncrement64 (&keys[key_idx].seq); + TlsFree (tls_index); + } } } @@ -1946,7 +1969,12 @@ pthread_spinlock::lock () else if (spins < FAST_SPINS_LIMIT) { ++spins; +#if defined(__x86_64__) __asm__ volatile ("pause":::); +#elif defined(__aarch64__) + __asm__ volatile ("dmb ishst\n" + "yield":::); +#endif } else { @@ -2333,7 +2361,12 @@ pthread_convert_abstime (clockid_t clock_id, const struct timespec *abstime, { case CLOCK_REALTIME_COARSE: case CLOCK_REALTIME: + case CLOCK_TAI: timeout->QuadPart += FACTOR; + /* TAI time is realtime + leap secs. NT timers are on realtime. + Subtract leap secs to get the corresponding real due time. + Leap secs are always 0 unless CLOCK_TAI. */ + timeout->QuadPart -= get_clock (clock_id)->get_leap_secs () * NS100PERSEC; break; default: /* other clocks must be handled as relative timeout */ |