aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin/local_includes/thread.h
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/local_includes/thread.h')
-rw-r--r--winsup/cygwin/local_includes/thread.h31
1 files changed, 24 insertions, 7 deletions
diff --git a/winsup/cygwin/local_includes/thread.h b/winsup/cygwin/local_includes/thread.h
index b349628..3955609 100644
--- a/winsup/cygwin/local_includes/thread.h
+++ b/winsup/cygwin/local_includes/thread.h
@@ -221,13 +221,12 @@ public:
~pthread_key ();
static void fixup_before_fork ()
{
- keys.for_each (&pthread_key::_fixup_before_fork);
+ for_each (_fixup_before_fork);
}
static void fixup_after_fork ()
{
- keys.fixup_after_fork ();
- keys.for_each (&pthread_key::_fixup_after_fork);
+ for_each (_fixup_after_fork);
}
static void run_all_destructors ()
@@ -246,21 +245,39 @@ public:
for (int i = 0; i < PTHREAD_DESTRUCTOR_ITERATIONS; ++i)
{
iterate_dtors_once_more = false;
- keys.for_each (&pthread_key::run_destructor);
+ for_each (run_destructor);
if (!iterate_dtors_once_more)
break;
}
}
- /* List support calls */
- class pthread_key *next;
private:
- static List<pthread_key> keys;
+ int key_idx;
+ static class keys_list {
+ LONG64 seq;
+ LONG64 busy_cnt;
+ pthread_key *key;
+ static bool used (LONG64 seq1) { return (seq1 & 3) != 0; }
+ static bool ready (LONG64 seq1) { return (seq1 & 3) == 2; }
+ public:
+ keys_list () : seq (0), busy_cnt (INT64_MIN), key (NULL) {}
+ friend class pthread_key;
+ } keys[PTHREAD_KEYS_MAX];
void _fixup_before_fork ();
void _fixup_after_fork ();
void (*destructor) (void *);
void run_destructor ();
void *fork_buf;
+ static void for_each (void (pthread_key::*callback) ()) {
+ for (size_t cnt = 0; cnt < PTHREAD_KEYS_MAX; cnt++)
+ {
+ if (!keys_list::ready (keys[cnt].seq))
+ continue;
+ if (InterlockedIncrement64 (&keys[cnt].busy_cnt) > 0)
+ (keys[cnt].key->*callback) ();
+ InterlockedDecrement64 (&keys[cnt].busy_cnt);
+ }
+ }
};
class pthread_attr: public verifyable_object