+static void
+_pthread_tsd_cleanup_new(pthread_t self)
+{
+ int j;
+
+ // clean up all keys
+ for (j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; j++) {
+ pthread_key_t k;
+ for (k = __pthread_tsd_start; k <= self->max_tsd_key; k++) {
+ _pthread_tsd_cleanup_key(self, k);
+ }
+
+ for (k = __pthread_tsd_first; k <= __pthread_tsd_max; k++) {
+ _pthread_tsd_cleanup_key(self, k);
+ }
+ }
+
+ self->max_tsd_key = 0;
+}
+
+#if PTHREAD_KEY_LEGACY_SUPPORT
+#import <_simple.h>
+#import <dlfcn.h>
+static void
+_pthread_tsd_behaviour_check(pthread_t self)
+{
+ // Iterate from dynamic-key start to dynamic-key end, if the key has both
+ // a desctructor and a value then _pthread_tsd_cleanup_key would cause
+ // us to re-trigger the destructor.
+ pthread_key_t k;
+
+ for (k = __pthread_tsd_start; k < __pthread_tsd_end; k++) {
+ void (*destructor)(void *);
+ if (_pthread_key_get_destructor(k, &destructor)) {
+ void **ptr = &self->tsd[k];
+ void *value = *ptr;
+ if (value && destructor) {
+ _simple_asl_log(ASL_LEVEL_ERR, "pthread_tsd",
+ "warning: dynamic tsd keys dirty after static key cleanup loop.");
+#if 0
+ // enable this for debugging
+ Dl_info i;
+ if (dladdr(destructor, &i) == 0) {
+ _simple_asl_log(ASL_LEVEL_ERR, "pthread_tsd", i.dli_fname);
+ _simple_asl_log(ASL_LEVEL_ERR, "pthread_tsd", i.dli_saddr);
+ }
+#endif
+ }
+ }
+ }
+
+}
+
+static void
+_pthread_tsd_cleanup_legacy(pthread_t self)