aboutsummaryrefslogtreecommitdiff
path: root/nptl/pthread_create.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2003-04-02 03:51:24 +0000
committerUlrich Drepper <drepper@redhat.com>2003-04-02 03:51:24 +0000
commit6b4686a534c10cc9011c9d352d1b57d5a76d5579 (patch)
treef83ff4ca255084c741620875883da8ce4823d7a5 /nptl/pthread_create.c
parentfa36efe8931c7e0dc8c7bf6973d97de32bddd6d4 (diff)
downloadglibc-6b4686a534c10cc9011c9d352d1b57d5a76d5579.tar
glibc-6b4686a534c10cc9011c9d352d1b57d5a76d5579.tar.gz
glibc-6b4686a534c10cc9011c9d352d1b57d5a76d5579.tar.bz2
glibc-6b4686a534c10cc9011c9d352d1b57d5a76d5579.zip
Update.
2003-04-01 Ulrich Drepper <drepper@redhat.com> * pthread_create.c (deallocate_tsd): Clear/free memory after the last round, not the first. Use specific_used flag instead of local found_nonzero variable. Use THREAD_[SG]ETMEM where possible. (__free_tcb): Don't call deallocate_tsd here. (start_thread): Call deallocate_tsd here. * pthread_setspecific.c: Set specific_used flag really only when needed. * Makefile (tests): Add tst-tsd3.c * tst-tsd3.c: New file.
Diffstat (limited to 'nptl/pthread_create.c')
-rw-r--r--nptl/pthread_create.c117
1 files changed, 64 insertions, 53 deletions
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index 8598e4c763..748cb93686 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -112,67 +112,78 @@ deallocate_tsd (struct pthread *pd)
{
/* Maybe no data was ever allocated. This happens often so we have
a flag for this. */
- if (pd->specific_used)
+ if (THREAD_GETMEM (pd, specific_used))
{
size_t round;
- bool found_nonzero;
+ size_t cnt;
- for (round = 0, found_nonzero = true;
- found_nonzero && round < PTHREAD_DESTRUCTOR_ITERATIONS;
- ++round)
+ round = 0;
+ do
{
- size_t cnt;
size_t idx;
/* So far no new nonzero data entry. */
- found_nonzero = false;
+ THREAD_SETMEM (pd, specific_used, false);
for (cnt = idx = 0; cnt < PTHREAD_KEY_1STLEVEL_SIZE; ++cnt)
- if (pd->specific[cnt] != NULL)
- {
- size_t inner;
-
- for (inner = 0; inner < PTHREAD_KEY_2NDLEVEL_SIZE;
- ++inner, ++idx)
- {
- void *data = pd->specific[cnt][inner].data;
-
- if (data != NULL
- /* Make sure the data corresponds to a valid
- key. This test fails if the key was
- deallocated and also if it was
- re-allocated. It is the user's
- responsibility to free the memory in this
- case. */
- && (pd->specific[cnt][inner].seq
- == __pthread_keys[idx].seq)
- /* It is not necessary to register a destructor
- function. */
- && __pthread_keys[idx].destr != NULL)
- {
- pd->specific[cnt][inner].data = NULL;
- __pthread_keys[idx].destr (data);
- found_nonzero = true;
- }
- }
-
- if (cnt != 0)
- {
- /* The first block is allocated as part of the thread
- descriptor. */
- free (pd->specific[cnt]);
- pd->specific[cnt] = NULL;
- }
- else
- /* Clear the memory of the first block for reuse. */
- memset (&pd->specific_1stblock, '\0',
- sizeof (pd->specific_1stblock));
- }
- else
- idx += PTHREAD_KEY_1STLEVEL_SIZE;
+ {
+ struct pthread_key_data *level2;
+
+ level2 = THREAD_GETMEM_NC (pd, specific, cnt);
+
+ if (level2 != NULL)
+ {
+ size_t inner;
+
+ for (inner = 0; inner < PTHREAD_KEY_2NDLEVEL_SIZE;
+ ++inner, ++idx)
+ {
+ void *data = level2[inner].data;
+
+ if (data != NULL
+ /* Make sure the data corresponds to a valid
+ key. This test fails if the key was
+ deallocated and also if it was
+ re-allocated. It is the user's
+ responsibility to free the memory in this
+ case. */
+ && (level2[inner].seq
+ == __pthread_keys[idx].seq)
+ /* It is not necessary to register a destructor
+ function. */
+ && __pthread_keys[idx].destr != NULL)
+ {
+ level2[inner].data = NULL;
+ __pthread_keys[idx].destr (data);
+ }
+ }
+ }
+ else
+ idx += PTHREAD_KEY_1STLEVEL_SIZE;
+ }
}
+ while (THREAD_GETMEM (pd, specific_used)
+ && ++round < PTHREAD_DESTRUCTOR_ITERATIONS);
+
+ /* Clear the memory of the first block for reuse. */
+ memset (&pd->specific_1stblock, '\0', sizeof (pd->specific_1stblock));
- pd->specific_used = false;
+ /* Free the memory for the other blocks. */
+ for (cnt = 1; cnt < PTHREAD_KEY_1STLEVEL_SIZE; ++cnt)
+ {
+ struct pthread_key_data *level2;
+
+ level2 = THREAD_GETMEM_NC (pd, specific, cnt);
+ if (level2 != NULL)
+ {
+ /* The first block is allocated as part of the thread
+ descriptor. */
+ free (level2);
+ THREAD_SETMEM_NC (pd, specific, cnt, NULL);
+ }
+ }
+
+ THREAD_SETMEM (pd, specific_used, false);
}
}
@@ -193,9 +204,6 @@ __free_tcb (struct pthread *pd)
running thread is gone. */
abort ();
- /* Run the destructor for the thread-local data. */
- deallocate_tsd (pd);
-
/* Queue the stack memory block for reuse and exit the process. The
kernel will signal via writing to the address returned by
QUEUE-STACK when the stack is available. */
@@ -232,6 +240,9 @@ start_thread (void *arg)
#endif
}
+ /* Run the destructor for the thread-local data. */
+ deallocate_tsd (pd);
+
/* Clean up any state libc stored in thread-local variables. */
__libc_thread_freeres ();