summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kern/thread.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/kern/thread.c b/kern/thread.c
index b02b86ed..077d5405 100644
--- a/kern/thread.c
+++ b/kern/thread.c
@@ -1496,6 +1496,7 @@ thread_destroy(struct thread *thread)
struct thread_runq *runq;
unsigned long flags, state;
unsigned int i;
+ void *ptr;
do {
runq = thread_lock_runq(thread, &flags);
@@ -1503,12 +1504,23 @@ thread_destroy(struct thread *thread)
thread_unlock_runq(runq, flags);
} while (state != THREAD_DEAD);
- for (i = 0; i < thread_nr_keys; i++) {
+ i = 0;
+
+ while (i < thread_nr_keys) {
if ((thread->tsd[i] == NULL)
|| (thread_dtors[i] == NULL))
continue;
+ /*
+ * Follow the POSIX description of TSD: set the key to NULL before
+ * calling the destructor and repeat as long as it's not NULL.
+ */
+ ptr = thread->tsd[i];
+ thread->tsd[i] = NULL;
thread_dtors[i](thread->tsd[i]);
+
+ if (thread->tsd[i] == NULL)
+ i++;
}
task_remove_thread(thread->task, thread);