Line data Source code
1 : /* src/threads/thread.hpp - machine independent thread functions
2 :
3 : Copyright (C) 1996-2013
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 :
6 : This file is part of CACAO.
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License as
10 : published by the Free Software Foundation; either version 2, or (at
11 : your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful, but
14 : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 : 02110-1301, USA.
22 :
23 : */
24 :
25 :
26 : #ifndef THREAD_HPP_
27 : #define THREAD_HPP_ 1
28 :
29 : #include "config.h"
30 :
31 : #include "native/llni.hpp"
32 : #include "vm/global.hpp"
33 : #include "vm/options.hpp" // for opt_DebugThreads
34 : #include "vm/os.hpp"
35 : #include "vm/types.hpp"
36 : #include "vm/utf8.hpp" // for Utf8String
37 :
38 : class Condition;
39 : class DumpMemory;
40 : struct localref_table;
41 : class Mutex;
42 : struct stackframeinfo_t;
43 : struct JavaVMAttachArgs;
44 :
45 : /* thread states **************************************************************/
46 :
47 : enum ThreadState {
48 : THREAD_STATE_NEW = 0,
49 : THREAD_STATE_RUNNABLE = 1,
50 : THREAD_STATE_BLOCKED = 2,
51 : THREAD_STATE_WAITING = 3,
52 : THREAD_STATE_TIMED_WAITING = 4,
53 : THREAD_STATE_TERMINATED = 5,
54 : THREAD_STATE_PARKED = 6,
55 : THREAD_STATE_TIMED_PARKED = 7
56 : };
57 :
58 : enum ThreadFlag {
59 : THREAD_FLAG_JAVA = 0x01, // a normal Java thread
60 : THREAD_FLAG_INTERNAL = 0x02, // CACAO internal thread
61 : THREAD_FLAG_DAEMON = 0x04, // daemon thread
62 : THREAD_FLAG_IN_NATIVE = 0x08 // currently executing native code
63 : };
64 :
65 : enum SuspendReason {
66 : SUSPEND_REASON_NONE = 0, // no reason to suspend
67 : SUSPEND_REASON_JAVA = 1, // suspended from java.lang.Thread
68 : SUSPEND_REASON_STOPWORLD = 2, // suspended from stop-the-world
69 : SUSPEND_REASON_DUMP = 3, // suspended from threadlist dumping
70 : SUSPEND_REASON_JVMTI = 4 // suspended from JVMTI agent
71 : };
72 :
73 : /* thread priorities **********************************************************/
74 :
75 : enum ThreadPriority {
76 : MIN_PRIORITY = 1,
77 : NORM_PRIORITY = 5,
78 : MAX_PRIORITY = 10
79 : };
80 :
81 : /* threadobject ***************************************************************/
82 :
83 : #if defined(ENABLE_THREADS)
84 : # include "threads/posix/threadobject.hpp"
85 : #else
86 : # include "threads/none/threadobject.hpp"
87 : #endif
88 :
89 : struct threadobject {
90 : //***** platform specific thread data
91 : cacao::detail::threadobject impl;
92 :
93 : java_object_t *object; /* link to java.lang.Thread object */
94 :
95 : ptrint thinlock; /* pre-computed thin lock value */
96 : u4 flags; /* flag field */
97 : ThreadState state; /* state field */
98 :
99 : //***** for ThreadList
100 : bool is_in_active_list; /* for debugging only */
101 : s4 index; /* thread index, starting with 1 */
102 :
103 : //***** for the sable tasuki lock extension */
104 : bool flc_bit;
105 : struct threadobject *flc_list; /* FLC list head for this thread */
106 : struct threadobject *flc_tail; /* tail pointer for FLC list */
107 : struct threadobject *flc_next; /* next pointer for FLC list */
108 : java_handle_t *flc_object;
109 : Mutex* flc_lock; /* controlling access to these fields */
110 : Condition* flc_cond;
111 :
112 : //***** these are used for the wait/notify implementation
113 : Mutex* waitmutex;
114 : Condition* waitcond;
115 :
116 : Mutex* suspendmutex; /* lock before suspending this thread */
117 : Condition* suspendcond; /* notify to resume this thread */
118 :
119 : bool interrupted;
120 : bool signaled;
121 : bool park_permit;
122 :
123 : bool suspended; /* is this thread suspended? */
124 : SuspendReason suspend_reason; /* reason for suspending */
125 :
126 : u1 *pc; /* current PC (used for profiling) */
127 :
128 : java_object_t *_exceptionptr; /* current exception */
129 : stackframeinfo_t *_stackframeinfo; /* current native stackframeinfo */
130 : localref_table *_localref_table; /* JNI local references */
131 :
132 : #if defined(ENABLE_INTRP)
133 : Cell *_global_sp; /* stack pointer for interpreter */
134 : #endif
135 :
136 : #if defined(ENABLE_GC_CACAO)
137 : bool gc_critical; /* indicates a critical section */
138 :
139 : sourcestate_t *ss;
140 : executionstate_t *es;
141 : #endif
142 :
143 : DumpMemory* _dumpmemory; ///< Dump memory structure.
144 :
145 : #if defined(ENABLE_DEBUG_FILTER)
146 : u2 filterverbosecallctr[2]; /* counters for verbose call filter */
147 : #endif
148 :
149 : #if !defined(NDEBUG)
150 : s4 tracejavacallindent;
151 : u4 tracejavacallcount;
152 : #endif
153 :
154 : #if defined(ENABLE_TLH)
155 : tlh_t tlh;
156 : #endif
157 :
158 : #if defined(ENABLE_ESCAPE_REASON)
159 : void *escape_reasons;
160 : #endif
161 : };
162 :
163 : /* debug **********************************************************************/
164 :
165 : #if !defined(NDEBUG)
166 : # define DEBUGTHREADS(message, thread) \
167 : do { \
168 : if (opt_DebugThreads) { \
169 : printf("[Thread %-16s: ", message); \
170 : thread_print_info(thread); \
171 : printf("]\n"); \
172 : } \
173 : } while (0)
174 : #else
175 : # define DEBUGTHREADS(message, thread)
176 : #endif
177 :
178 :
179 : /* global variables ***********************************************************/
180 :
181 : #if defined(__LINUX__)
182 : /* XXX Remove for exact-GC. */
183 : extern bool threads_pthreads_implementation_nptl;
184 : #endif
185 :
186 :
187 : /* state for trace java call **************************************************/
188 :
189 : #if !defined(NDEBUG)
190 : # define TRACEJAVACALLINDENT (THREADOBJECT->tracejavacallindent)
191 : # define TRACEJAVACALLCOUNT (THREADOBJECT->tracejavacallcount)
192 : #endif
193 :
194 :
195 : /* counter for verbose call filter ********************************************/
196 :
197 : #if defined(ENABLE_DEBUG_FILTER)
198 : # define FILTERVERBOSECALLCTR (THREADOBJECT->filterverbosecallctr)
199 : #endif
200 :
201 :
202 : /* native-world flags *********************************************************/
203 :
204 : #if defined(ENABLE_GC_CACAO)
205 : # define THREAD_NATIVEWORLD_ENTER THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE
206 : # define THREAD_NATIVEWORLD_EXIT THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE
207 : #else
208 : # define THREAD_NATIVEWORLD_ENTER /*nop*/
209 : # define THREAD_NATIVEWORLD_EXIT /*nop*/
210 : #endif
211 :
212 :
213 : /* inline functions ***********************************************************/
214 :
215 : inline static threadobject* thread_get_current(void);
216 :
217 : #if defined(ENABLE_THREADS)
218 : # include "threads/posix/thread-posix.hpp"
219 : #else
220 : # include "threads/none/thread-none.hpp"
221 : #endif
222 :
223 : /***
224 : * Return the java.lang.Thread object for the current thread.
225 : */
226 21990 : inline static java_handle_t *thread_get_current_object(void) {
227 21990 : return LLNI_WRAP(thread_get_current()->object);
228 : }
229 :
230 :
231 : /* cacaothread_get_state *******************************************************
232 :
233 : Returns the current state of the given thread.
234 :
235 : ARGUMENTS:
236 : t ... the thread to check
237 :
238 : RETURN:
239 : thread state
240 :
241 : *******************************************************************************/
242 :
243 0 : inline static int cacaothread_get_state(threadobject *t)
244 : {
245 0 : return t->state;
246 : }
247 :
248 :
249 : /* thread_is_attached **********************************************************
250 :
251 : Returns if the given thread is attached to the VM.
252 :
253 : ARGUMENTS:
254 : t ... the thread to check
255 :
256 : RETURN:
257 : true .... the thread is attached to the VM
258 : false ... the thread is not
259 :
260 : *******************************************************************************/
261 :
262 413 : inline static bool thread_is_attached(threadobject *t)
263 : {
264 : java_handle_t *o;
265 :
266 413 : o = LLNI_WRAP(t->object);
267 :
268 413 : return o != NULL;
269 : }
270 :
271 :
272 : /* thread_is_daemon ************************************************************
273 :
274 : Returns if the given thread is a daemon thread.
275 :
276 : ARGUMENTS:
277 : t ... the thread to check
278 :
279 : RETURN:
280 : true .... the thread is a daemon thread
281 : false ... the thread is not
282 :
283 : *******************************************************************************/
284 :
285 1307 : inline static bool thread_is_daemon(threadobject *t)
286 : {
287 1307 : return (t->flags & THREAD_FLAG_DAEMON) != 0;
288 : }
289 :
290 :
291 : /* thread_current_is_attached **************************************************
292 :
293 : Returns if the current thread is attached to the VM.
294 :
295 : RETURN:
296 : true .... the thread is attached to the VM
297 : false ... the thread is not
298 :
299 : *******************************************************************************/
300 :
301 131 : inline static bool thread_current_is_attached(void)
302 : {
303 : threadobject *t;
304 :
305 131 : t = thread_get_current();
306 :
307 131 : if (t == NULL)
308 0 : return false;
309 :
310 131 : return thread_is_attached(t);
311 : }
312 :
313 3378134 : inline static struct stackframeinfo_t* threads_get_current_stackframeinfo(void)
314 : {
315 3378134 : return THREADOBJECT->_stackframeinfo;
316 : }
317 :
318 6709995 : inline static void threads_set_current_stackframeinfo(struct stackframeinfo_t* sfi)
319 : {
320 6709995 : THREADOBJECT->_stackframeinfo = sfi;
321 6709995 : }
322 :
323 :
324 : /* function prototypes ********************************************************/
325 :
326 : void threads_preinit(void);
327 : void threads_init(void);
328 :
329 : void thread_free(threadobject *t);
330 :
331 : bool threads_thread_start_internal(Utf8String name, functionptr f);
332 : void threads_thread_start(java_handle_t *object);
333 :
334 : bool thread_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon);
335 : bool thread_attach_current_external_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon);
336 : bool thread_detach_current_thread(void);
337 :
338 : bool thread_detach_current_external_thread(void);
339 :
340 : void thread_fprint_name(threadobject *t, FILE *stream);
341 : void thread_print_info(threadobject *t);
342 :
343 : intptr_t threads_get_current_tid(void);
344 : intptr_t threads_get_tid(threadobject*);
345 :
346 : void thread_set_state_runnable(threadobject *t);
347 : void thread_set_state_waiting(threadobject *t);
348 : void thread_set_state_timed_waiting(threadobject *t);
349 : void thread_set_state_parked(threadobject *t);
350 : void thread_set_state_timed_parked(threadobject *t);
351 : void thread_set_state_terminated(threadobject *t);
352 :
353 : threadobject *thread_get_thread(java_handle_t *h);
354 :
355 : bool threads_thread_is_alive(threadobject *t);
356 : bool thread_is_interrupted(threadobject *t);
357 : void thread_set_interrupted(threadobject *t, bool interrupted);
358 : void threads_thread_interrupt(threadobject *thread);
359 :
360 :
361 : void threads_start_thread(threadobject *thread, functionptr function);
362 :
363 : void threads_set_thread_priority(threadobject *t, int priority);
364 :
365 : bool threads_suspend_thread(threadobject *thread, SuspendReason reason);
366 : bool threads_resume_thread(threadobject *thread, SuspendReason reason);
367 : void threads_suspend_ack();
368 :
369 : void threads_join_all_threads(void);
370 :
371 : void threads_sleep(int64_t millis, int32_t nanos);
372 :
373 : void threads_wait_with_timeout_relative(threadobject *t, s8 millis, s4 nanos);
374 :
375 : void threads_park(bool absolute, int64_t nanos);
376 : void threads_unpark(threadobject *thread);
377 :
378 : #if defined(ENABLE_TLH)
379 : void threads_tlh_add_frame();
380 : void threads_tlh_remove_frame();
381 : #endif
382 :
383 : /* implementation specific functions */
384 :
385 : void threads_impl_preinit(void);
386 : void threads_impl_init(void);
387 :
388 : #if defined(ENABLE_GC_CACAO)
389 : void threads_mutex_gc_lock(void);
390 : void threads_mutex_gc_unlock(void);
391 : #endif
392 :
393 : void threads_impl_thread_clear(threadobject *t);
394 : void threads_impl_thread_reuse(threadobject *t);
395 : void threads_impl_clear_heap_pointers(threadobject *t);
396 : void threads_impl_thread_start(threadobject *thread, functionptr f);
397 :
398 : void threads_yield(void);
399 :
400 : void thread_handle_set_priority(java_handle_t *th, int);
401 : bool thread_handle_is_interrupted(java_handle_t *th);
402 : void thread_handle_interrupt(java_handle_t *th);
403 : int thread_handle_get_state(java_handle_t *th);
404 :
405 : #endif // THREAD_HPP_
406 :
407 :
408 : /*
409 : * These are local overrides for various environment variables in Emacs.
410 : * Please do not remove this and leave it at the end of the file, where
411 : * Emacs will automagically detect them.
412 : * ---------------------------------------------------------------------
413 : * Local variables:
414 : * mode: c++
415 : * indent-tabs-mode: t
416 : * c-basic-offset: 4
417 : * tab-width: 4
418 : * End:
419 : * vim:noexpandtab:sw=4:ts=4:
420 : */
|