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>
37 static void finalize_native (jobject ptr
);
39 // This is called from the constructor to initialize the native side
42 java::lang::Thread::initialize_native (void)
44 natThread
*nt
= (natThread
*) _Jv_AllocBytes (sizeof (natThread
));
47 nt
->alive_flag
= THREAD_DEAD
;
49 data
= (gnu::gcj::RawDataManaged
*) nt
;
51 // Register a finalizer to clean up the native thread resources.
52 _Jv_RegisterFinalizer (data
, finalize_native
);
54 _Jv_MutexInit (&nt
->join_mutex
);
55 _Jv_CondInit (&nt
->join_cond
);
57 nt
->park_helper
.init();
59 nt
->thread
= _Jv_ThreadInitData (this);
60 // FIXME: if JNI_ENV is set we will want to free it. It is
66 finalize_native (jobject ptr
)
68 natThread
*nt
= (natThread
*) ptr
;
69 _Jv_ThreadDestroyData (nt
->thread
);
70 #ifdef _Jv_HaveCondDestroy
71 _Jv_CondDestroy (&nt
->join_cond
);
73 #ifdef _Jv_HaveMutexDestroy
74 _Jv_MutexDestroy (&nt
->join_mutex
);
76 _Jv_FreeJNIEnv((JNIEnv
*)nt
->jni_env
);
78 nt
->park_helper
.destroy();
82 java::lang::Thread::countStackFrames (void)
84 // NOTE: This is deprecated in JDK 1.2.
86 // Old applets still call this method. Rather than throwing
87 // UnsupportedOperationException we simply fail silently.
93 java::lang::Thread::currentThread (void)
95 return _Jv_ThreadCurrent ();
99 java::lang::Thread::holdsLock (jobject obj
)
102 throw new NullPointerException
;
103 return !_Jv_ObjectCheckMonitor (obj
);
107 java::lang::Thread::isAlive (void)
109 natThread
*nt
= (natThread
*) data
;
110 return nt
->alive_flag
!= (obj_addr_t
)THREAD_DEAD
;
114 java::lang::Thread::interrupt (void)
118 natThread
*nt
= (natThread
*) data
;
120 // If a thread is in state ALIVE, we atomically set it to state
121 // SIGNALED and send it a signal. Once we've sent it the signal, we
122 // set its state back to ALIVE.
124 (&nt
->alive_flag
, Thread::THREAD_ALIVE
, Thread::THREAD_SIGNALED
))
126 _Jv_ThreadInterrupt (nt
->thread
);
128 (&nt
->alive_flag
, THREAD_SIGNALED
, Thread::THREAD_ALIVE
);
130 // Even though we've interrupted this thread, it might still be
132 nt
->park_helper
.unpark ();
137 java::lang::Thread::join (jlong millis
, jint nanos
)
139 if (millis
< 0 || nanos
< 0 || nanos
> 999999)
140 throw new IllegalArgumentException
;
142 Thread
*current
= currentThread ();
144 // Here `NT' is the native structure for the thread we are trying to join.
145 natThread
*nt
= (natThread
*) data
;
147 // Now wait for: (1) an interrupt, (2) the thread to exit, or (3)
148 // the timeout to occur.
149 _Jv_MutexLock (&nt
->join_mutex
);
152 _Jv_MutexUnlock (&nt
->join_mutex
);
155 _Jv_CondWait (&nt
->join_cond
, &nt
->join_mutex
, millis
, nanos
);
156 _Jv_MutexUnlock (&nt
->join_mutex
);
158 if (current
->isInterrupted (true))
159 throw new InterruptedException
;
163 java::lang::Thread::resume (void)
167 // Old applets still call this method. Rather than throwing
168 // UnsupportedOperationException we simply fail silently.
172 java::lang::Thread::setPriority (jint newPriority
)
175 if (newPriority
< MIN_PRIORITY
|| newPriority
> MAX_PRIORITY
)
176 throw new IllegalArgumentException
;
178 jint gmax
= group
->getMaxPriority();
179 if (newPriority
> gmax
)
182 priority
= newPriority
;
183 natThread
*nt
= (natThread
*) data
;
184 _Jv_ThreadSetPriority (nt
->thread
, priority
);
188 java::lang::Thread::sleep (jlong millis
, jint nanos
)
190 if (millis
< 0 || nanos
< 0 || nanos
> 999999)
191 throw new IllegalArgumentException
;
193 if (millis
== 0 && nanos
== 0)
196 Thread
*current
= currentThread ();
198 // We use a condition variable to implement sleeping so that an
199 // interrupt can wake us up.
200 natThread
*nt
= (natThread
*) current
->data
;
201 _Jv_MutexLock (&nt
->join_mutex
);
202 _Jv_CondWait (&nt
->join_cond
, &nt
->join_mutex
, millis
, nanos
);
203 _Jv_MutexUnlock (&nt
->join_mutex
);
205 if (current
->isInterrupted (true))
206 throw new InterruptedException
;
210 java::lang::Thread::finish_ ()
212 __sync_synchronize();
213 natThread
*nt
= (natThread
*) data
;
215 nt
->park_helper
.deactivate ();
216 group
->removeThread (this);
219 if (_Jv_JVMPI_Notify_THREAD_END
)
223 event
.event_type
= JVMPI_EVENT_THREAD_END
;
224 event
.env_id
= _Jv_GetCurrentJNIEnv ();
227 (*_Jv_JVMPI_Notify_THREAD_END
) (&event
);
232 // If a method cache was created, free it.
233 _Jv_FreeMethodCache();
235 // Clear out thread locals.
238 // Signal any threads that are waiting to join() us.
239 _Jv_MutexLock (&nt
->join_mutex
);
242 JvSynchronize
sync (this);
243 nt
->alive_flag
= THREAD_DEAD
;
244 state
= JV_TERMINATED
;
247 _Jv_CondNotifyAll (&nt
->join_cond
, &nt
->join_mutex
);
248 _Jv_MutexUnlock (&nt
->join_mutex
);
251 // Run once at thread startup, either when thread is attached or when
252 // _Jv_ThreadRun is called.
254 _Jv_NotifyThreadStart (java::lang::Thread
* thread
)
257 if (_Jv_JVMPI_Notify_THREAD_START
)
261 jstring thread_name
= thread
->getName ();
262 jstring group_name
= NULL
, parent_name
= NULL
;
263 java::lang::ThreadGroup
*group
= thread
->getThreadGroup ();
267 group_name
= group
->getName ();
268 group
= group
->getParent ();
271 parent_name
= group
->getName ();
274 int thread_len
= thread_name
? JvGetStringUTFLength (thread_name
) : 0;
275 int group_len
= group_name
? JvGetStringUTFLength (group_name
) : 0;
276 int parent_len
= parent_name
? JvGetStringUTFLength (parent_name
) : 0;
278 char thread_chars
[thread_len
+ 1];
279 char group_chars
[group_len
+ 1];
280 char parent_chars
[parent_len
+ 1];
283 JvGetStringUTFRegion (thread_name
, 0,
284 thread_name
->length(), thread_chars
);
286 JvGetStringUTFRegion (group_name
, 0,
287 group_name
->length(), group_chars
);
289 JvGetStringUTFRegion (parent_name
, 0,
290 parent_name
->length(), parent_chars
);
292 thread_chars
[thread_len
] = '\0';
293 group_chars
[group_len
] = '\0';
294 parent_chars
[parent_len
] = '\0';
296 event
.event_type
= JVMPI_EVENT_THREAD_START
;
298 event
.u
.thread_start
.thread_name
= thread_chars
;
299 event
.u
.thread_start
.group_name
= group_chars
;
300 event
.u
.thread_start
.parent_name
= parent_chars
;
301 event
.u
.thread_start
.thread_id
= (jobjectID
) thread
;
302 event
.u
.thread_start
.thread_env_id
= _Jv_GetCurrentJNIEnv ();
305 (*_Jv_JVMPI_Notify_THREAD_START
) (&event
);
312 _Jv_ThreadRun (java::lang::Thread
* thread
)
316 _Jv_NotifyThreadStart (thread
);
319 catch (java::lang::Throwable
*t
)
321 // Uncaught exceptions are forwarded to the ThreadGroup. If
322 // this results in an uncaught exception, that is ignored.
325 thread
->getUncaughtExceptionHandler()->uncaughtException (thread
, t
);
327 catch (java::lang::Throwable
*f
)
337 _Jv_ThreadGetData (java::lang::Thread
* thread
)
339 natThread
* nt
= (natThread
*) thread
->data
;
344 java::lang::Thread::start (void)
346 JvSynchronize
sync (this);
348 // Its illegal to re-start() a thread, even if its dead.
350 throw new IllegalThreadStateException
;
352 natThread
*nt
= (natThread
*) data
;
353 nt
->alive_flag
= THREAD_ALIVE
;
354 startable_flag
= false;
356 _Jv_ThreadStart (this, nt
->thread
, (_Jv_ThreadStartFunc
*) &_Jv_ThreadRun
);
360 java::lang::Thread::stop (java::lang::Throwable
*)
364 // Old applets still call this method. Rather than throwing
365 // UnsupportedOperationException we simply fail silently.
369 java::lang::Thread::suspend (void)
373 // Old applets still call this method. Rather than throwing
374 // UnsupportedOperationException we simply fail silently.
377 static int nextThreadNumber
= 0;
380 java::lang::Thread::gen_name (void)
383 jclass sync
= &java::lang::Thread::class$
;
385 JvSynchronize
dummy(sync
);
386 i
= ++nextThreadNumber
;
389 // Use an array large enough for "-2147483648"; i.e. 11 chars, + "Thread-".
391 jchar
*bufend
= (jchar
*) ((char *) buffer
+ sizeof(buffer
));
392 i
= _Jv_FormatInt (bufend
, i
);
393 jchar
*ptr
= bufend
- i
;
394 // Prepend "Thread-".
402 return JvNewString (ptr
, bufend
- ptr
);
406 java::lang::Thread::yield (void)
411 ::java::lang::Thread$State
*
412 java::lang::Thread::getState()
414 _Jv_InitClass(&::java::lang::Thread$
State::class$
);
419 return ::java::lang::Thread$
State::BLOCKED
;
421 return ::java::lang::Thread$
State::NEW
;
424 return ::java::lang::Thread$
State::RUNNABLE
;
426 return ::java::lang::Thread$
State::TERMINATED
;
427 case JV_TIMED_WAITING
:
428 return ::java::lang::Thread$
State::TIMED_WAITING
;
430 return ::java::lang::Thread$
State::WAITING
;
433 // We don't really need a default, but this makes the compiler
435 return ::java::lang::Thread$
State::RUNNABLE
;
439 _Jv_GetCurrentJNIEnv ()
441 java::lang::Thread
*t
= _Jv_ThreadCurrent ();
444 return ((natThread
*) t
->data
)->jni_env
;
448 _Jv_SetCurrentJNIEnv (JNIEnv
*env
)
450 java::lang::Thread
*t
= _Jv_ThreadCurrent ();
451 JvAssert (t
!= NULL
);
452 ((natThread
*) t
->data
)->jni_env
= env
;
455 // Attach the current native thread to an existing (but unstarted) Thread
456 // object. Does not register thread with the garbage collector.
457 // Returns -1 on failure, 0 upon success.
459 _Jv_AttachCurrentThread(java::lang::Thread
* thread
)
461 JvSynchronize
sync (thread
);
462 if (thread
== NULL
|| thread
->startable_flag
== false)
464 thread
->startable_flag
= false;
465 natThread
*nt
= (natThread
*) thread
->data
;
466 nt
->alive_flag
= ::java::lang::Thread::THREAD_ALIVE
;
467 thread
->state
= JV_RUNNABLE
;
468 _Jv_ThreadRegister (nt
->thread
);
473 _Jv_AttachCurrentThread(jstring name
, java::lang::ThreadGroup
* group
)
475 // Register thread with GC before attempting any allocations.
476 _Jv_GCAttachThread ();
477 java::lang::Thread
*thread
= _Jv_ThreadCurrent ();
481 name
= java::lang::Thread::gen_name ();
482 thread
= new java::lang::Thread (NULL
, group
, NULL
, name
);
483 _Jv_AttachCurrentThread (thread
);
484 _Jv_NotifyThreadStart (thread
);
489 _Jv_AttachCurrentThreadAsDaemon(jstring name
, java::lang::ThreadGroup
* group
)
491 java::lang::Thread
*thread
= _Jv_ThreadCurrent ();
495 name
= java::lang::Thread::gen_name ();
496 thread
= new java::lang::Thread (NULL
, group
, NULL
, name
);
497 thread
->setDaemon (true);
498 _Jv_AttachCurrentThread (thread
);
499 _Jv_NotifyThreadStart (thread
);
504 _Jv_DetachCurrentThread (void)
506 java::lang::Thread
*t
= _Jv_ThreadCurrent ();
510 _Jv_ThreadUnRegister ();
511 _Jv_GCDetachThread ();
512 // Release the monitors.