From 97b8365cafc3a344a22d3980b8ed885f5c6d8357 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 9 Jan 2007 19:58:05 +0000 Subject: Merged gcj-eclipse branch to trunk. From-SVN: r120621 --- libjava/java/lang/natThreadLocal.cc | 169 ++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 libjava/java/lang/natThreadLocal.cc (limited to 'libjava/java/lang/natThreadLocal.cc') diff --git a/libjava/java/lang/natThreadLocal.cc b/libjava/java/lang/natThreadLocal.cc new file mode 100644 index 0000000..cd61f4a --- /dev/null +++ b/libjava/java/lang/natThreadLocal.cc @@ -0,0 +1,169 @@ +// natThreadLocal.cc - Native part of ThreadLocal class. + +// Fast thread local storage for systems that support the __thread +// variable attribute. + +/* Copyright (C) 2006 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* We would like to have fast thread local variables that behave in + the same way as C and C++ thread local variables. This would mean + having an field attribute "thread" (like static, final, etc.). + However, this is not compatible with java semantics, which we wish + to support transparently. The problems we must overcome are: + + * In Java, ThreadLocal variables are not statically allocated: they + are objects, created at runtime. + + * Class ThreadLocal is not final and neither are its methods, so it + is possible to create a subclass of ThreadLocal that overrides + any method. + + * __thread variables in DSOs are not visible to the garbage + collector, so we must ensure that we keep a copy of every thread + local variable somewhere on the heap. + + * Once a ThreadLocal instance has been created and assigned to a + static field, that field may be reassigned to a different + ThreadLocal instance or null. + + So, we can't simply replace get() and set() with accesses of a + __thread variable. + + So, we create a pthread_key in each ThreadLocal object and use that + as a kind of "look-aside cache". When a ThreadLocal is set, we + also set the corresponding thread-specific value. When the + ThreadLocal is collected, we delete the key. + + This scheme is biased towards efficiency when get() is called much + more frequently than set(). It is slightly internaler than the + all-Java solution using the underlying map in the set() case. + However, get() is very much more frequently invoked than set(). + +*/ + + +#ifdef _POSIX_PTHREAD_SEMANTICS + +class tls_t +{ +public: + pthread_key_t key; +}; + +void +java::lang::ThreadLocal::constructNative (void) +{ + tls_t *tls = (tls_t *)_Jv_Malloc (sizeof (tls_t)); + if (pthread_key_create (&tls->key, NULL) == 0) + TLSPointer = (::gnu::gcj::RawData *)tls; + else + _Jv_Free (tls); +} + +void +java::lang::ThreadLocal::set (::java::lang::Object *value) +{ + if (TLSPointer != NULL) + { + tls_t* tls = (tls_t*)TLSPointer; + pthread_setspecific (tls->key, value); + } + + internalSet (value); +} + +::java::lang::Object * +java::lang::ThreadLocal::get (void) +{ + if (TLSPointer == NULL) + return internalGet (); + + tls_t* tls = (tls_t*)TLSPointer; + void *obj = pthread_getspecific(tls->key); + + if (obj) + return (::java::lang::Object *)obj; + + ::java::lang::Object *value = internalGet (); + pthread_setspecific (tls->key, value); + + return value; +} + +void +java::lang::ThreadLocal::remove (void) +{ + if (TLSPointer != NULL) + { + tls_t* tls = (tls_t*)TLSPointer; + pthread_setspecific (tls->key, NULL); + } + + internalRemove (); +} + +void +java::lang::ThreadLocal::finalize (void) +{ + if (TLSPointer != NULL) + { + tls_t* tls = (tls_t*)TLSPointer; + pthread_key_delete (tls->key); + _Jv_Free (tls); + } +} + +#else + +void +java::lang::ThreadLocal::constructNative (void) +{ +} + +void +java::lang::ThreadLocal::set (::java::lang::Object *value) +{ + internalSet (value); +} + +::java::lang::Object * +java::lang::ThreadLocal::get (void) +{ + return internalGet (); +} + +void +java::lang::ThreadLocal::remove (void) +{ + internalRemove (); +} + +void +java::lang::ThreadLocal::finalize (void) +{ +} + +#endif -- cgit v1.1