diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2012-01-29 20:07:31 +0400 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2012-01-29 20:07:31 +0400 |
commit | e07b66f5450830cf8ddeee5f79c7fdc06177e864 (patch) | |
tree | 39c476461c6fd3a18a0f4e062f9d99ec012a375e | |
parent | 8a9f0fc4e2684ec2427cac7a555a2692881d370c (diff) | |
download | bdwgc-e07b66f5450830cf8ddeee5f79c7fdc06177e864.tar.gz |
Use union of AO_t and 'tse' data pointer in specific.c to avoid type
casting (breaking strict-aliasing rules)
* include/private/specific.h (ptse_ao_u): New union type.
* include/private/specific.h (thread_specific_data): Change type of
"hash" field from "tse" pointer to ptse_ao_u.
* specific.c (invalid_tse): Put to 'const' data section.
* specific.c (GC_key_create_inner, GC_setspecific, GC_remove_specific,
GC_slow_getspecific, GC_check_tsd_marks): Use "p" element of union to
access "tse" pointer of hash table.
* specific.c (GC_setspecific): Use "ao" element of union to store
"hash" table entry atomically; remove type cast.
-rw-r--r-- | include/private/specific.h | 7 | ||||
-rw-r--r-- | specific.c | 14 |
2 files changed, 13 insertions, 8 deletions
diff --git a/include/private/specific.h b/include/private/specific.h index 3a73a0fb..3382558e 100644 --- a/include/private/specific.h +++ b/include/private/specific.h @@ -57,10 +57,15 @@ typedef struct thread_specific_entry { #define INVALID_QTID ((unsigned long)0) #define INVALID_THREADID ((pthread_t)0) +union ptse_ao_u { + tse *p; + volatile AO_t ao; +}; + typedef struct thread_specific_data { tse * volatile cache[TS_CACHE_SIZE]; /* A faster index to the hash table */ - tse * hash[TS_HASH_SIZE]; + union ptse_ao_u hash[TS_HASH_SIZE]; pthread_mutex_t lock; } tsd; @@ -21,7 +21,7 @@ #include "atomic_ops.h" -static tse invalid_tse = {INVALID_QTID, 0, 0, INVALID_THREADID}; +static const 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. */ @@ -40,7 +40,7 @@ GC_INNER int GC_key_create_inner(tsd ** key_ptr) } # ifdef GC_ASSERTIONS for (i = 0; i < TS_HASH_SIZE; ++i) { - GC_ASSERT(result -> hash[i] == 0); + GC_ASSERT(result -> hash[i].p == 0); } # endif *key_ptr = result; @@ -57,13 +57,13 @@ GC_INNER int GC_setspecific(tsd * key, void * value) if (0 == entry) return ENOMEM; pthread_mutex_lock(&(key -> lock)); /* Could easily check for an existing entry here. */ - entry -> next = key -> hash[hash_val]; + entry -> next = key->hash[hash_val].p; 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. */ - AO_store_release((volatile AO_t *)(key -> hash + hash_val), (AO_t)entry); + AO_store_release(&key->hash[hash_val].ao, (AO_t)entry); pthread_mutex_unlock(&(key -> lock)); return 0; } @@ -75,7 +75,7 @@ GC_INNER void GC_remove_specific(tsd * key) pthread_t self = pthread_self(); unsigned hash_val = HASH(self); tse *entry; - tse **link = key -> hash + hash_val; + tse **link = &key->hash[hash_val].p; pthread_mutex_lock(&(key -> lock)); entry = *link; @@ -114,7 +114,7 @@ GC_INNER void * GC_slow_getspecific(tsd * key, unsigned long qtid, { pthread_t self = pthread_self(); unsigned hash_val = HASH(self); - tse *entry = key -> hash[hash_val]; + tse *entry = key->hash[hash_val].p; GC_ASSERT(qtid != INVALID_QTID); while (entry != NULL && entry -> thread != self) { @@ -145,7 +145,7 @@ GC_INNER void * GC_slow_getspecific(tsd * key, unsigned long qtid, ABORT("Unmarked thread-specific-data table"); } for (i = 0; i < TS_HASH_SIZE; ++i) { - for (p = key -> hash[i]; p != 0; p = p -> next) { + for (p = key->hash[i].p; 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"); |