OSDN Git Service

2008-09-17 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / java / lang / natThreadLocal.cc
1 // natThreadLocal.cc - Native part of ThreadLocal class.
2
3 // Fast thread local storage for systems that support the __thread
4 // variable attribute.
5    
6 /* Copyright (C) 2006  Free Software Foundation
7
8    This file is part of libgcj.
9
10 This software is copyrighted work licensed under the terms of the
11 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
12 details.  */
13
14 #include <config.h>
15
16 #include <stdlib.h>
17
18 #include <gcj/cni.h>
19 #include <jvm.h>
20 #include <java-threads.h>
21
22 #include <gnu/gcj/RawDataManaged.h>
23 #include <java/lang/ThreadLocal.h>
24 #include <java/lang/IllegalArgumentException.h>
25 #include <java/lang/IllegalThreadStateException.h>
26 #include <java/lang/InterruptedException.h>
27 #include <java/util/Map.h>
28
29 #include <jni.h>
30
31 /* We would like to have fast thread local variables that behave in
32    the same way as C and C++ thread local variables.  This would mean
33    having an field attribute "thread" (like static, final, etc.).
34    However, this is not compatible with java semantics, which we wish
35    to support transparently.  The problems we must overcome are:
36
37    * In Java, ThreadLocal variables are not statically allocated: they
38      are objects, created at runtime.
39
40    * Class ThreadLocal is not final and neither are its methods, so it
41      is possible to create a subclass of ThreadLocal that overrides
42      any method.
43
44    * __thread variables in DSOs are not visible to the garbage
45      collector, so we must ensure that we keep a copy of every thread
46      local variable somewhere on the heap.
47
48    * Once a ThreadLocal instance has been created and assigned to a
49      static field, that field may be reassigned to a different
50      ThreadLocal instance or null.  
51
52    So, we can't simply replace get() and set() with accesses of a
53    __thread variable.
54
55    So, we create a pthread_key in each ThreadLocal object and use that
56    as a kind of "look-aside cache".  When a ThreadLocal is set, we
57    also set the corresponding thread-specific value.  When the
58    ThreadLocal is collected, we delete the key.
59
60    This scheme is biased towards efficiency when get() is called much
61    more frequently than set().  It is slightly internaler than the
62    all-Java solution using the underlying map in the set() case.
63    However, get() is very much more frequently invoked than set().
64
65 */
66
67
68 #ifdef _POSIX_PTHREAD_SEMANTICS
69
70 class tls_t
71 {
72 public:
73   pthread_key_t key;
74 };
75
76 void
77 java::lang::ThreadLocal::constructNative (void)
78 {
79   tls_t *tls = (tls_t *)_Jv_Malloc (sizeof (tls_t));
80   if (pthread_key_create (&tls->key, NULL) == 0)
81     TLSPointer = (::gnu::gcj::RawData *)tls;
82   else
83     _Jv_Free (tls);
84 }
85
86 void 
87 java::lang::ThreadLocal::set (::java::lang::Object *value)
88 {
89   if (TLSPointer != NULL)
90     {
91       tls_t* tls = (tls_t*)TLSPointer;
92       pthread_setspecific (tls->key, value);
93     } 
94
95   internalSet (value);
96 }
97
98 ::java::lang::Object *
99 java::lang::ThreadLocal::get (void)
100 {
101   if (TLSPointer == NULL)
102     return internalGet ();
103
104   tls_t* tls = (tls_t*)TLSPointer;
105   void *obj = pthread_getspecific(tls->key);
106
107   if (obj)
108     return (::java::lang::Object *)obj;
109
110   ::java::lang::Object *value = internalGet ();
111   pthread_setspecific (tls->key, value);
112
113   return value;
114 }
115
116 void 
117 java::lang::ThreadLocal::remove (void)
118 {
119   if (TLSPointer != NULL)
120     {
121       tls_t* tls = (tls_t*)TLSPointer;
122       pthread_setspecific (tls->key, NULL);
123     }
124
125   internalRemove ();
126 }
127
128 void 
129 java::lang::ThreadLocal::finalize (void)
130 {
131   if (TLSPointer != NULL)
132     {
133       tls_t* tls = (tls_t*)TLSPointer;
134       pthread_key_delete (tls->key);
135       _Jv_Free (tls);
136     }
137 }
138
139 #else
140
141 void
142 java::lang::ThreadLocal::constructNative (void)
143 {
144 }
145
146 void 
147 java::lang::ThreadLocal::set (::java::lang::Object *value)
148 {
149   internalSet (value);
150 }
151
152 ::java::lang::Object *
153 java::lang::ThreadLocal::get (void)
154 {
155   return internalGet ();
156 }
157
158 void 
159 java::lang::ThreadLocal::remove (void)
160 {
161   internalRemove ();
162 }
163
164 void 
165 java::lang::ThreadLocal::finalize (void)
166 {
167 }
168
169 #endif