+static void dirty(void *dummy)
+{
+}
+
+struct cleanup_args {
+ pthread_t caller;
+ int ret;
+};
+
+static void clean_dirty_tsd_callback(void *p)
+{
+ struct cleanup_args *args = p;
+ pthread_t self = __pthread_self();
+ pthread_key_t i;
+ for (i=0; i<PTHREAD_KEYS_MAX; i++) {
+ if (keys[i] == dirty && self->tsd[i])
+ self->tsd[i] = 0;
+ }
+ /* Arbitrary choice to avoid data race. */
+ if (args->caller == self) args->ret = 0;
+}
+
+static int clean_dirty_tsd(void)
+{
+ struct cleanup_args args = {
+ .caller = __pthread_self(),
+ .ret = EAGAIN
+ };
+ __pthread_key_delete_synccall(clean_dirty_tsd_callback, &args);
+ return args.ret;
+}
+