summaryrefslogtreecommitdiff
path: root/libjava/java/lang/natThreadLocal.cc
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/java/lang/natThreadLocal.cc
downloadcbb-gcc-4.6.4-15d2061ac0796199866debe9ac87130894b0cdd3.tar.bz2
cbb-gcc-4.6.4-15d2061ac0796199866debe9ac87130894b0cdd3.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'libjava/java/lang/natThreadLocal.cc')
-rw-r--r--libjava/java/lang/natThreadLocal.cc169
1 files changed, 169 insertions, 0 deletions
diff --git a/libjava/java/lang/natThreadLocal.cc b/libjava/java/lang/natThreadLocal.cc
new file mode 100644
index 000000000..cd61f4a62
--- /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 <config.h>
+
+#include <stdlib.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+#include <java-threads.h>
+
+#include <gnu/gcj/RawDataManaged.h>
+#include <java/lang/ThreadLocal.h>
+#include <java/lang/IllegalArgumentException.h>
+#include <java/lang/IllegalThreadStateException.h>
+#include <java/lang/InterruptedException.h>
+#include <java/util/Map.h>
+
+#include <jni.h>
+
+/* 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