1 // natThread.cc - Native part of Thread class.
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2006, 2007 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
17 #include <java-threads.h>
19 #include <gnu/gcj/RawDataManaged.h>
20 #include <java/lang/Thread.h>
21 #include <java/lang/Thread$State.h>
22 #include <java/lang/Thread$UncaughtExceptionHandler.h>
23 #include <java/lang/ThreadGroup.h>
24 #include <java/lang/IllegalArgumentException.h>
25 #include <java/lang/IllegalThreadStateException.h>
26 #include <java/lang/InterruptedException.h>
27 #include <java/lang/NullPointerException.h>
31 #include "jvmti-int.h"
39 static void finalize_native (jobject ptr
);
41 // This is called from the constructor to initialize the native side
44 java::lang::Thread::initialize_native (void)
46 natThread
*nt
= (natThread
*) _Jv_AllocBytes (sizeof (natThread
));
49 nt
->alive_flag
= THREAD_DEAD
;
51 data
= (gnu::gcj::RawDataManaged
*) nt
;
53 // Register a finalizer to clean up the native thread resources.
54 _Jv_RegisterFinalizer (data
, finalize_native
);
56 _Jv_MutexInit (&nt
->join_mutex
);
57 _Jv_CondInit (&nt
->join_cond
);
59 nt
->park_helper
.init();
61 nt
->thread
= _Jv_ThreadInitData (this);
62 // FIXME: if JNI_ENV is set we will want to free it. It is
68 finalize_native (jobject ptr
)
70 natThread
*nt
= (natThread
*) ptr
;
71 _Jv_ThreadDestroyData (nt
->thread
);
72 #ifdef _Jv_HaveCondDestroy
73 _Jv_CondDestroy (&nt
->join_cond
);
75 #ifdef _Jv_HaveMutexDestroy
76 _Jv_MutexDestroy (&nt
->join_mutex
);
78 _Jv_FreeJNIEnv((JNIEnv
*)nt
->jni_env
);
80 nt
->park_helper
.destroy();
84 java::lang::Thread::countStackFrames (void)
86 // NOTE: This is deprecated in JDK 1.2.
88 // Old applets still call this method. Rather than throwing
89 // UnsupportedOperationException we simply fail silently.
95 java::lang::Thread::currentThread (void)
97 return _Jv_ThreadCurrent ();
101 java::lang::Thread::holdsLock (jobject obj
)
104 throw new NullPointerException
;
105 return !_Jv_ObjectCheckMonitor (obj
);
109 java::lang::Thread::isAlive (void)
111 natThread
*nt
= (natThread
*) data
;
112 return nt
->alive_flag
!= (obj_addr_t
)THREAD_DEAD
;
116 java::lang::Thread::interrupt (void)
120 natThread
*nt
= (natThread
*) data
;
122 // If a thread is in state ALIVE, we atomically set it to state
123 // SIGNALED and send it a signal. Once we've sent it the signal, we
124 // set its state back to ALIVE.
126 (&nt
->alive_flag
, Thread::THREAD_ALIVE
, Thread::THREAD_SIGNALED
))
128 _Jv_ThreadInterrupt (nt
->thread
);
130 (&nt
->alive_flag
, THREAD_SIGNALED
, Thread::THREAD_ALIVE
);
132 // Even though we've interrupted this thread, it might still be
134 nt
->park_helper
.unpark ();
139 java::lang::Thread::join (jlong millis
, jint nanos
)
141 if (millis
< 0 || nanos
< 0 || nanos
> 999999)
142 throw new IllegalArgumentException
;
144 Thread
*current
= currentThread ();
146 // Here `NT' is the native structure for the thread we are trying to join.
147 natThread
*nt
= (natThread
*) data
;
149 // Now wait for: (1) an interrupt, (2) the thread to exit, or (3)
150 // the timeout to occur.
151 _Jv_MutexLock (&nt
->join_mutex
);
154 _Jv_MutexUnlock (&nt
->join_mutex
);
157 _Jv_CondWait (&nt
->join_cond
, &nt
->join_mutex
, millis
, nanos
);
158 _Jv_MutexUnlock (&nt
->join_mutex
);
160 if (current
->isInterrupted (true))
161 throw new InterruptedException
;
165 java::lang::Thread::resume (void)
169 // Old applets still call this method. Rather than throwing
170 // UnsupportedOperationException we simply fail silently.
174 java::lang::Thread::setPriority (jint newPriority
)
177 if (newPriority
< MIN_PRIORITY
|| newPriority
> MAX_PRIORITY
)
178 throw new IllegalArgumentException
;
180 jint gmax
= group
->getMaxPriority();
181 if (newPriority
> gmax
)
184 priority
= newPriority
;
185 natThread
*nt
= (natThread
*) data
;
186 _Jv_ThreadSetPriority (nt
->thread
, priority
);
190 java::lang::Thread::sleep (jlong millis
, jint nanos
)
192 if (millis
< 0 || nanos
< 0 || nanos
> 999999)
193 throw new IllegalArgumentException
;
195 if (millis
== 0 && nanos
== 0)
198 Thread
*current
= currentThread ();
200 // We use a condition variable to implement sleeping so that an
201 // interrupt can wake us up.
202 natThread
*nt
= (natThread
*) current
->data
;
203 _Jv_MutexLock (&nt
->join_mutex
);
204 _Jv_CondWait (&nt
->join_cond
, &nt
->join_mutex
, millis
, nanos
);
205 _Jv_MutexUnlock (&nt
->join_mutex
);
207 if (current
->isInterrupted (true))
208 throw new InterruptedException
;
212 java::lang::Thread::finish_ ()
214 __sync_synchronize();
215 natThread
*nt
= (natThread
*) data
;
217 nt
->park_helper
.deactivate ();
218 group
->removeThread (this);
220 if (JVMTI_REQUESTED_EVENT (ThreadEnd
))
221 _Jv_JVMTI_PostEvent (JVMTI_EVENT_THREAD_END
, this, nt
->jni_env
);
224 if (_Jv_JVMPI_Notify_THREAD_END
)
228 event
.event_type
= JVMPI_EVENT_THREAD_END
;
229 event
.env_id
= _Jv_GetCurrentJNIEnv ();
232 (*_Jv_JVMPI_Notify_THREAD_END
) (&event
);
237 // If a method cache was created, free it.
238 _Jv_FreeMethodCache();
240 // Clear out thread locals.
243 // Signal any threads that are waiting to join() us.
244 _Jv_MutexLock (&nt
->join_mutex
);
247 JvSynchronize
sync (this);
248 nt
->alive_flag
= THREAD_DEAD
;
249 state
= JV_TERMINATED
;
252 _Jv_CondNotifyAll (&nt
->join_cond
, &nt
->join_mutex
);
253 _Jv_MutexUnlock (&nt
->join_mutex
);
256 // Run once at thread startup, either when thread is attached or when
257 // _Jv_ThreadRun is called.
259 _Jv_NotifyThreadStart (java::lang::Thread
* thread
)
261 if (JVMTI_REQUESTED_EVENT (ThreadStart
))
263 natThread
*nt
= reinterpret_cast<natThread
*> (thread
->data
);
264 _Jv_JVMTI_PostEvent (JVMTI_EVENT_THREAD_START
, thread
, nt
->jni_env
);
268 if (_Jv_JVMPI_Notify_THREAD_START
)
272 jstring thread_name
= thread
->getName ();
273 jstring group_name
= NULL
, parent_name
= NULL
;
274 java::lang::ThreadGroup
*group
= thread
->getThreadGroup ();
278 group_name
= group
->getName ();
279 group
= group
->getParent ();
282 parent_name
= group
->getName ();
285 int thread_len
= thread_name
? JvGetStringUTFLength (thread_name
) : 0;
286 int group_len
= group_name
? JvGetStringUTFLength (group_name
) : 0;
287 int parent_len
= parent_name
? JvGetStringUTFLength (parent_name
) : 0;
289 char thread_chars
[thread_len
+ 1];
290 char group_chars
[group_len
+ 1];
291 char parent_chars
[parent_len
+ 1];
294 JvGetStringUTFRegion (thread_name
, 0,
295 thread_name
->length(), thread_chars
);
297 JvGetStringUTFRegion (group_name
, 0,
298 group_name
->length(), group_chars
);
300 JvGetStringUTFRegion (parent_name
, 0,
301 parent_name
->length(), parent_chars
);
303 thread_chars
[thread_len
] = '\0';
304 group_chars
[group_len
] = '\0';
305 parent_chars
[parent_len
] = '\0';
307 event
.event_type
= JVMPI_EVENT_THREAD_START
;
309 event
.u
.thread_start
.thread_name
= thread_chars
;
310 event
.u
.thread_start
.group_name
= group_chars
;
311 event
.u
.thread_start
.parent_name
= parent_chars
;
312 event
.u
.thread_start
.thread_id
= (jobjectID
) thread
;
313 event
.u
.thread_start
.thread_env_id
= _Jv_GetCurrentJNIEnv ();
316 (*_Jv_JVMPI_Notify_THREAD_START
) (&event
);
323 _Jv_ThreadRun (java::lang::Thread
* thread
)
327 _Jv_NotifyThreadStart (thread
);
330 catch (java::lang::Throwable
*t
)
332 // Uncaught exceptions are forwarded to the ThreadGroup. If
333 // this results in an uncaught exception, that is ignored.
336 thread
->getUncaughtExceptionHandler()->uncaughtException (thread
, t
);
338 catch (java::lang::Throwable
*f
)
348 _Jv_ThreadGetData (java::lang::Thread
* thread
)
350 natThread
* nt
= (natThread
*) thread
->data
;
355 java::lang::Thread::start (void)
357 JvSynchronize
sync (this);
359 // Its illegal to re-start() a thread, even if its dead.
361 throw new IllegalThreadStateException
;
363 natThread
*nt
= (natThread
*) data
;
364 nt
->alive_flag
= THREAD_ALIVE
;
365 startable_flag
= false;
367 _Jv_ThreadStart (this, nt
->thread
, (_Jv_ThreadStartFunc
*) &_Jv_ThreadRun
);
371 java::lang::Thread::stop (java::lang::Throwable
*)
375 // Old applets still call this method. Rather than throwing
376 // UnsupportedOperationException we simply fail silently.
380 java::lang::Thread::suspend (void)
384 // Old applets still call this method. Rather than throwing
385 // UnsupportedOperationException we simply fail silently.
388 static int nextThreadNumber
= 0;
391 java::lang::Thread::gen_name (void)
394 jclass sync
= &java::lang::Thread::class$
;
396 JvSynchronize
dummy(sync
);
397 i
= ++nextThreadNumber
;
400 // Use an array large enough for "-2147483648"; i.e. 11 chars, + "Thread-".
402 jchar
*bufend
= (jchar
*) ((char *) buffer
+ sizeof(buffer
));
403 i
= _Jv_FormatInt (bufend
, i
);
404 jchar
*ptr
= bufend
- i
;
405 // Prepend "Thread-".
413 return JvNewString (ptr
, bufend
- ptr
);
417 java::lang::Thread::yield (void)
422 ::java::lang::Thread$State
*
423 java::lang::Thread::getState()
425 _Jv_InitClass(&::java::lang::Thread$
State::class$
);
430 return ::java::lang::Thread$
State::BLOCKED
;
432 return ::java::lang::Thread$
State::NEW
;
435 return ::java::lang::Thread$
State::RUNNABLE
;
437 return ::java::lang::Thread$
State::TERMINATED
;
438 case JV_TIMED_WAITING
:
439 return ::java::lang::Thread$
State::TIMED_WAITING
;
441 return ::java::lang::Thread$
State::WAITING
;
444 // We don't really need a default, but this makes the compiler
446 return ::java::lang::Thread$
State::RUNNABLE
;
450 _Jv_GetCurrentJNIEnv ()
452 java::lang::Thread
*t
= _Jv_ThreadCurrent ();
455 return ((natThread
*) t
->data
)->jni_env
;
459 _Jv_SetCurrentJNIEnv (JNIEnv
*env
)
461 java::lang::Thread
*t
= _Jv_ThreadCurrent ();
462 JvAssert (t
!= NULL
);
463 ((natThread
*) t
->data
)->jni_env
= env
;
466 // Attach the current native thread to an existing (but unstarted) Thread
467 // object. Does not register thread with the garbage collector.
468 // Returns -1 on failure, 0 upon success.
470 _Jv_AttachCurrentThread(java::lang::Thread
* thread
)
472 JvSynchronize
sync (thread
);
473 if (thread
== NULL
|| thread
->startable_flag
== false)
475 thread
->startable_flag
= false;
476 natThread
*nt
= (natThread
*) thread
->data
;
477 nt
->alive_flag
= ::java::lang::Thread::THREAD_ALIVE
;
478 thread
->state
= JV_RUNNABLE
;
479 _Jv_ThreadRegister (nt
->thread
);
484 _Jv_AttachCurrentThread(jstring name
, java::lang::ThreadGroup
* group
)
486 // Register thread with GC before attempting any allocations.
487 _Jv_GCAttachThread ();
488 java::lang::Thread
*thread
= _Jv_ThreadCurrent ();
492 name
= java::lang::Thread::gen_name ();
493 thread
= new java::lang::Thread (NULL
, group
, NULL
, name
, false);
494 _Jv_AttachCurrentThread (thread
);
495 _Jv_NotifyThreadStart (thread
);
500 _Jv_AttachCurrentThreadAsDaemon(jstring name
, java::lang::ThreadGroup
* group
)
502 java::lang::Thread
*thread
= _Jv_ThreadCurrent ();
506 name
= java::lang::Thread::gen_name ();
507 thread
= new java::lang::Thread (NULL
, group
, NULL
, name
, false);
508 thread
->setDaemon (true);
509 _Jv_AttachCurrentThread (thread
);
510 _Jv_NotifyThreadStart (thread
);
515 _Jv_DetachCurrentThread (void)
517 java::lang::Thread
*t
= _Jv_ThreadCurrent ();
521 _Jv_ThreadUnRegister ();
522 _Jv_GCDetachThread ();
523 // Release the monitors.