1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
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
|