summaryrefslogtreecommitdiff
path: root/specific.c
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2011-07-26 20:09:54 +0400
committerIvan Maidanski <ivmai@mail.ru>2011-07-26 20:09:54 +0400
commite35a4171fe47dfbf847e08988ea6cec4dfc8d124 (patch)
tree25f3501669fbf24a4b370c4f8b0c0701b1da4062 /specific.c
parentffa0c9ea38b3dd87e91b5ed2118c74002fed6782 (diff)
downloadbdwgc-e35a4171fe47dfbf847e08988ea6cec4dfc8d124.tar.gz
gc7.0alpha1 tarball importgc7_0alpha1
Diffstat (limited to 'specific.c')
-rw-r--r--specific.c44
1 files changed, 39 insertions, 5 deletions
diff --git a/specific.c b/specific.c
index 7d5d8894..67addec8 100644
--- a/specific.c
+++ b/specific.c
@@ -11,16 +11,17 @@
* modified is included with the above copyright notice.
*/
-#include "private/gc_priv.h" /* For GC_compare_and_exchange, GC_memory_barrier */
+#include "private/gc_priv.h" /* For configuration, pthreads.h. */
+#include "atomic_ops.h"
#if defined(GC_LINUX_THREADS)
#include "private/specific.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;
@@ -57,7 +58,7 @@ int PREFIXED(setspecific) (tsd * key, void * 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. */
- *(volatile tse **)(key -> hash + hash_val) = entry;
+ AO_store_release((volatile AO_t *)(key -> hash + hash_val), (AO_t)entry);
pthread_mutex_unlock(&(key -> lock));
return 0;
}
@@ -125,4 +126,37 @@ void * PREFIXED(slow_getspecific) (tsd * key, unsigned long qtid,
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)
+{
+ int i;
+ tse *p;
+
+ if (!GC_is_marked(GC_base(key))) {
+ 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 (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");
+ }
+ }
+}
+
+#endif
+
#endif /* GC_LINUX_THREADS */