diff options
author | ivmai <ivmai> | 2011-05-13 14:40:31 +0000 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2011-07-26 21:06:59 +0400 |
commit | 8d76348edc08b652a4357021756862ba27881371 (patch) | |
tree | 808e0a460f08810bfcafccb6c374d25385ab3f6f | |
parent | 25a9011f9979b6104a79b140cf3e56e16bc071d6 (diff) | |
download | bdwgc-8d76348edc08b652a4357021756862ba27881371.tar.gz |
2011-05-13 Ivan Maidanski <ivmai@mail.ru>
* dyn_load.c (GC_FirstDLOpenedLinkMap): Remove unused "r" local
variable.
* pthread_support.c (GC_unregister_my_thread_inner): Revert back
GC_remove_specific invocation; add a comment.
* include/private/thread_local_alloc.h (GC_remove_specific):
Revert back.
* specific.c: Expand all tabs to spaces.
* specific.c (slow_getspecific): Cast qtid to AO_t.
* include/private/specific.h (quick_thread_id): Reformat comment.
* include/private/specific.h (key_create, setspecific,
remove_specific): Remove "extern" keyword.
* include/private/specific.h (getspecific): Change type of "qtid"
local variable to unsigned long.
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | dyn_load.c | 1 | ||||
-rw-r--r-- | include/private/specific.h | 14 | ||||
-rw-r--r-- | include/private/thread_local_alloc.h | 3 | ||||
-rw-r--r-- | pthread_support.c | 4 | ||||
-rw-r--r-- | specific.c | 145 |
6 files changed, 100 insertions, 83 deletions
@@ -1,3 +1,19 @@ +2011-05-13 Ivan Maidanski <ivmai@mail.ru> + + * dyn_load.c (GC_FirstDLOpenedLinkMap): Remove unused "r" local + variable. + * pthread_support.c (GC_unregister_my_thread_inner): Revert back + GC_remove_specific invocation; add a comment. + * include/private/thread_local_alloc.h (GC_remove_specific): + Revert back. + * specific.c: Expand all tabs to spaces. + * specific.c (slow_getspecific): Cast qtid to AO_t. + * include/private/specific.h (quick_thread_id): Reformat comment. + * include/private/specific.h (key_create, setspecific, + remove_specific): Remove "extern" keyword. + * include/private/specific.h (getspecific): Change type of "qtid" + local variable to unsigned long. + 2011-05-11 Ivan Maidanski <ivmai@mail.ru> * pthread_support.c (GC_check_tls): Fix "#endif" comment. @@ -135,7 +135,6 @@ GC_FirstDLOpenedLinkMap(void) { extern ElfW(Dyn) _DYNAMIC; ElfW(Dyn) *dp; - struct r_debug *r; static struct link_map * cachedResult = 0; static ElfW(Dyn) *dynStructureAddr = 0; /* BTL: added to avoid Solaris 5.3 ld.so _DYNAMIC bug */ diff --git a/include/private/specific.h b/include/private/specific.h index 372238dc..8b5cf847 100644 --- a/include/private/specific.h +++ b/include/private/specific.h @@ -51,8 +51,8 @@ typedef struct thread_specific_entry { /* Return the "quick thread id". Default version. Assumes page size, */ /* or at least thread stack separation, is at least 4K. */ -/* Must be defined so that it never returns 0. (Page 0 can't really */ -/* be part of any stack, since that would make 0 a valid stack pointer.)*/ +/* Must be defined so that it never returns 0. (Page 0 can't really be */ +/* part of any stack, since that would make 0 a valid stack pointer.) */ #define quick_thread_id() (((unsigned long)GC_approx_sp()) >> 12) #define INVALID_QTID ((unsigned long)0) @@ -67,11 +67,9 @@ typedef struct thread_specific_data { typedef tsd * PREFIXED(key_t); -extern int PREFIXED(key_create) (tsd ** key_ptr, void (* destructor)(void *)); - -extern int PREFIXED(setspecific) (tsd * key, void * value); - -extern void PREFIXED(remove_specific) (tsd * key); +int PREFIXED(key_create) (tsd ** key_ptr, void (* destructor)(void *)); +int PREFIXED(setspecific) (tsd * key, void * value); +void PREFIXED(remove_specific) (tsd * key); /* An internal version of getspecific that assumes a cache miss. */ void * PREFIXED(slow_getspecific) (tsd * key, unsigned long qtid, @@ -80,7 +78,7 @@ void * PREFIXED(slow_getspecific) (tsd * key, unsigned long qtid, /* GC_INLINE is defined in gc_priv.h. */ GC_INLINE void * PREFIXED(getspecific) (tsd * key) { - long qtid = quick_thread_id(); + unsigned long qtid = quick_thread_id(); unsigned hash_val = CACHE_HASH(qtid); tse * volatile * entry_ptr = key -> cache + hash_val; tse * entry = *entry_ptr; /* Must be loaded only once. */ diff --git a/include/private/thread_local_alloc.h b/include/private/thread_local_alloc.h index 258b592e..55d8fd6e 100644 --- a/include/private/thread_local_alloc.h +++ b/include/private/thread_local_alloc.h @@ -94,11 +94,13 @@ typedef struct thread_local_freelists { # define GC_getspecific pthread_getspecific # define GC_setspecific pthread_setspecific # define GC_key_create pthread_key_create +# define GC_remove_specific(key) /* No need for cleanup on exit. */ typedef pthread_key_t GC_key_t; #elif defined(USE_COMPILER_TLS) || defined(USE_WIN32_COMPILER_TLS) # define GC_getspecific(x) (x) # define GC_setspecific(key, v) ((key) = (v), 0) # define GC_key_create(key, d) 0 +# define GC_remove_specific(key) /* No need for cleanup on exit. */ typedef void * GC_key_t; #elif defined(USE_WIN32_SPECIFIC) # ifndef WIN32_LEAN_AND_MEAN @@ -115,6 +117,7 @@ typedef struct thread_local_freelists { # endif # define GC_key_create(key, d) \ ((d) != 0 || (*(key) = TlsAlloc()) == TLS_OUT_OF_INDEXES ? -1 : 0) +# define GC_remove_specific(key) /* No need for cleanup on exit. */ /* Need TlsFree on process exit/detach? */ typedef DWORD GC_key_t; #elif defined(USE_CUSTOM_SPECIFIC) diff --git a/pthread_support.c b/pthread_support.c index 3a3f6672..175663c0 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -1182,6 +1182,10 @@ STATIC void GC_unregister_my_thread_inner(GC_thread me) } else { me -> flags |= FINISHED; } +# if defined(THREAD_LOCAL_ALLOC) + /* It is required to call remove_specific defined in specific.c. */ + GC_remove_specific(GC_thread_key); +# endif } GC_API int GC_CALL GC_unregister_my_thread(void) @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2000 by Hewlett-Packard Company. All rights reserved. * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED @@ -11,35 +11,35 @@ * modified is included with the above copyright notice. */ -#include "private/gc_priv.h" /* For configuration, pthreads.h. */ +#include "private/gc_priv.h" /* For configuration, pthreads.h. */ #include "private/thread_local_alloc.h" - /* To determine type of tsd impl. */ - /* Includes private/specific.h */ - /* if needed. */ + /* To determine type of tsd impl. */ + /* Includes private/specific.h */ + /* if needed. */ #if defined(USE_CUSTOM_SPECIFIC) #include "atomic_ops.h" static tse invalid_tse = {INVALID_QTID, 0, 0, INVALID_THREADID}; - /* A thread-specific data entry which will never */ - /* appear valid to a reader. Used to fill in empty */ - /* cache entries to avoid a check for 0. */ + /* A thread-specific data entry which will never */ + /* appear valid to a reader. Used to fill in empty */ + /* cache entries to avoid a check for 0. */ int PREFIXED(key_create) (tsd ** key_ptr, void (* destructor)(void *)) { int i; - tsd * result = (tsd *)MALLOC_CLEAR(sizeof (tsd)); + tsd * result = (tsd *)MALLOC_CLEAR(sizeof(tsd)); /* A quick alignment check, since we need atomic stores */ - GC_ASSERT((unsigned long)(&invalid_tse.next) % sizeof(tse *) == 0); + GC_ASSERT((unsigned long)(&invalid_tse.next) % sizeof(tse *) == 0); if (0 == result) return ENOMEM; pthread_mutex_init(&(result -> lock), NULL); for (i = 0; i < TS_CACHE_SIZE; ++i) { - result -> cache[i] = &invalid_tse; + result -> cache[i] = &invalid_tse; } # ifdef GC_ASSERTIONS for (i = 0; i < TS_HASH_SIZE; ++i) { - GC_ASSERT(result -> hash[i] == 0); + GC_ASSERT(result -> hash[i] == 0); } # endif *key_ptr = result; @@ -50,24 +50,24 @@ int PREFIXED(setspecific) (tsd * key, void * value) { pthread_t self = pthread_self(); int hash_val = HASH(self); volatile tse * entry = (volatile tse *)MALLOC_CLEAR(sizeof (tse)); - + GC_ASSERT(self != INVALID_THREADID); if (0 == entry) return ENOMEM; pthread_mutex_lock(&(key -> lock)); - /* Could easily check for an existing entry here. */ + /* Could easily check for an existing entry here. */ entry -> next = key -> hash[hash_val]; entry -> thread = self; entry -> value = value; GC_ASSERT(entry -> qtid == INVALID_QTID); - /* There can only be one writer at a time, but this needs to be */ - /* atomic with respect to concurrent readers. */ + /* There can only be one writer at a time, but this needs to be */ + /* atomic with respect to concurrent readers. */ AO_store_release((volatile AO_t *)(key -> hash + hash_val), (AO_t)entry); pthread_mutex_unlock(&(key -> lock)); return 0; } -/* Remove thread-specific data for this thread. Should be called on */ -/* thread exit. */ +/* Remove thread-specific data for this thread. Should be called on */ +/* thread exit. */ void PREFIXED(remove_specific) (tsd * key) { pthread_t self = pthread_self(); unsigned hash_val = HASH(self); @@ -77,89 +77,86 @@ void PREFIXED(remove_specific) (tsd * key) { pthread_mutex_lock(&(key -> lock)); entry = *link; while (entry != NULL && entry -> thread != self) { - link = &(entry -> next); - entry = *link; + link = &(entry -> next); + entry = *link; } - /* Invalidate qtid field, since qtids may be reused, and a later */ - /* cache lookup could otherwise find this entry. */ - entry -> qtid = INVALID_QTID; + /* Invalidate qtid field, since qtids may be reused, and a later */ + /* cache lookup could otherwise find this entry. */ + entry -> qtid = INVALID_QTID; if (entry != NULL) { - *link = entry -> next; - /* Atomic! concurrent accesses still work. */ - /* They must, since readers don't lock. */ - /* We shouldn't need a volatile access here, */ - /* since both this and the preceding write */ - /* should become visible no later than */ - /* the pthread_mutex_unlock() call. */ + *link = entry -> next; + /* Atomic! concurrent accesses still work. */ + /* They must, since readers don't lock. */ + /* We shouldn't need a volatile access here, */ + /* since both this and the preceding write */ + /* should become visible no later than */ + /* the pthread_mutex_unlock() call. */ } - /* If we wanted to deallocate the entry, we'd first have to clear */ - /* any cache entries pointing to it. That probably requires */ - /* additional synchronization, since we can't prevent a concurrent */ + /* If we wanted to deallocate the entry, we'd first have to clear */ + /* any cache entries pointing to it. That probably requires */ + /* additional synchronization, since we can't prevent a concurrent */ /* cache lookup, which should still be examining deallocated memory.*/ - /* This can only happen if the concurrent access is from another */ - /* thread, and hence has missed the cache, but still... */ + /* This can only happen if the concurrent access is from another */ + /* thread, and hence has missed the cache, but still... */ - /* With GC, we're done, since the pointers from the cache will */ - /* be overwritten, all local pointers to the entries will be */ - /* dropped, and the entry will then be reclaimed. */ + /* With GC, we're done, since the pointers from the cache will */ + /* be overwritten, all local pointers to the entries will be */ + /* dropped, and the entry will then be reclaimed. */ pthread_mutex_unlock(&(key -> lock)); } -/* Note that even the slow path doesn't lock. */ -void * PREFIXED(slow_getspecific) (tsd * key, unsigned long qtid, - tse * volatile * cache_ptr) { +/* Note that even the slow path doesn't lock. */ +void * PREFIXED(slow_getspecific) (tsd * key, unsigned long qtid, + tse * volatile * cache_ptr) { pthread_t self = pthread_self(); unsigned hash_val = HASH(self); tse *entry = key -> hash[hash_val]; GC_ASSERT(qtid != INVALID_QTID); while (entry != NULL && entry -> thread != self) { - entry = entry -> next; - } + entry = entry -> next; + } if (entry == NULL) return NULL; - /* Set cache_entry. */ - entry -> qtid = qtid; - /* It's safe to do this asynchronously. Either value */ - /* is safe, though may produce spurious misses. */ - /* We're replacing one qtid with another one for the */ - /* same thread. */ - *cache_ptr = entry; - /* Again this is safe since pointer assignments are */ - /* presumed atomic, and either pointer is valid. */ + /* Set cache_entry. */ + entry -> qtid = (AO_t)qtid; + /* It's safe to do this asynchronously. Either value */ + /* is safe, though may produce spurious misses. */ + /* We're replacing one qtid with another one for the */ + /* same thread. */ + *cache_ptr = entry; + /* Again this is safe since pointer assignments are */ + /* presumed atomic, and either pointer is valid. */ return entry -> value; } #ifdef GC_ASSERTIONS - -/* Check that that all elements of the data structure associated */ -/* with key are marked. */ -void PREFIXED(check_tsd_marks) (tsd *key) -{ + /* Check that that all elements of the data structure associated */ + /* with key are marked. */ + void PREFIXED(check_tsd_marks) (tsd *key) + { int i; tse *p; if (!GC_is_marked(GC_base(key))) { - ABORT("Unmarked thread-specific-data table"); + ABORT("Unmarked thread-specific-data table"); } for (i = 0; i < TS_HASH_SIZE; ++i) { - for (p = key -> hash[i]; p != 0; p = p -> next) { - if (!GC_is_marked(GC_base(p))) { - GC_err_printf( - "Thread-specific-data entry at %p not marked\n",p); - ABORT("Unmarked tse"); - } - } + for (p = key -> hash[i]; p != 0; p = p -> next) { + if (!GC_is_marked(GC_base(p))) { + GC_err_printf("Thread-specific-data entry at %p not marked\n", p); + ABORT("Unmarked tse"); + } + } } for (i = 0; i < TS_CACHE_SIZE; ++i) { - p = key -> cache[i]; - if (p != &invalid_tse && !GC_is_marked(GC_base(p))) { - GC_err_printf( - "Cached thread-specific-data entry at %p not marked\n",p); - ABORT("Unmarked cached tse"); - } + p = key -> cache[i]; + if (p != &invalid_tse && !GC_is_marked(GC_base(p))) { + GC_err_printf("Cached thread-specific-data entry at %p not marked\n", + p); + ABORT("Unmarked cached tse"); + } } -} - -#endif + } +#endif /* GC_ASSERTIONS */ #endif /* USE_CUSTOM_SPECIFIC */ |