1 // natThread.cc - Native part of Thread class.
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2006 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/ThreadGroup.h>
22 #include <java/lang/IllegalArgumentException.h>
23 #include <java/lang/IllegalThreadStateException.h>
24 #include <java/lang/InterruptedException.h>
25 #include <java/lang/NullPointerException.h>
35 // This structure is used to represent all the data the native side
36 // needs. An object of this type is assigned to the `data' member of
40 // These are used to interrupt sleep and join calls. We can share a
41 // condition variable here since it only ever gets notified when the thread
43 _Jv_Mutex_t join_mutex
;
44 _Jv_ConditionVariable_t join_cond
;
46 // This is private data for the thread system layer.
49 // Each thread has its own JNI object.
53 static void finalize_native (jobject ptr
);
55 // This is called from the constructor to initialize the native side
58 java::lang::Thread::initialize_native (void)
60 natThread
*nt
= (natThread
*) _Jv_AllocBytes (sizeof (natThread
));
62 data
= (gnu::gcj::RawDataManaged
*) nt
;
64 // Register a finalizer to clean up the native thread resources.
65 _Jv_RegisterFinalizer (data
, finalize_native
);
67 _Jv_MutexInit (&nt
->join_mutex
);
68 _Jv_CondInit (&nt
->join_cond
);
69 nt
->thread
= _Jv_ThreadInitData (this);
70 // FIXME: if JNI_ENV is set we will want to free it. It is
76 finalize_native (jobject ptr
)
78 natThread
*nt
= (natThread
*) ptr
;
79 _Jv_ThreadDestroyData (nt
->thread
);
80 #ifdef _Jv_HaveCondDestroy
81 _Jv_CondDestroy (&nt
->join_cond
);
83 #ifdef _Jv_HaveMutexDestroy
84 _Jv_MutexDestroy (&nt
->join_mutex
);
86 _Jv_FreeJNIEnv(nt
->jni_env
);
90 java::lang::Thread::countStackFrames (void)
92 // NOTE: This is deprecated in JDK 1.2.
94 // Old applets still call this method. Rather than throwing
95 // UnsupportedOperationException we simply fail silently.
101 java::lang::Thread::currentThread (void)
103 return _Jv_ThreadCurrent ();
107 java::lang::Thread::holdsLock (jobject obj
)
110 throw new NullPointerException
;
111 return !_Jv_ObjectCheckMonitor (obj
);
115 java::lang::Thread::interrupt (void)
118 natThread
*nt
= (natThread
*) data
;
119 JvSynchronize
sync (this);
121 _Jv_ThreadInterrupt (nt
->thread
);
125 java::lang::Thread::join (jlong millis
, jint nanos
)
127 if (millis
< 0 || nanos
< 0 || nanos
> 999999)
128 throw new IllegalArgumentException
;
130 Thread
*current
= currentThread ();
132 // Here `NT' is the native structure for the thread we are trying to join.
133 natThread
*nt
= (natThread
*) data
;
135 // Now wait for: (1) an interrupt, (2) the thread to exit, or (3)
136 // the timeout to occur.
137 _Jv_MutexLock (&nt
->join_mutex
);
140 _Jv_MutexUnlock (&nt
->join_mutex
);
143 _Jv_CondWait (&nt
->join_cond
, &nt
->join_mutex
, millis
, nanos
);
144 _Jv_MutexUnlock (&nt
->join_mutex
);
146 if (current
->isInterrupted (true))
147 throw new InterruptedException
;
151 java::lang::Thread::resume (void)
155 // Old applets still call this method. Rather than throwing
156 // UnsupportedOperationException we simply fail silently.
160 java::lang::Thread::setPriority (jint newPriority
)
163 if (newPriority
< MIN_PRIORITY
|| newPriority
> MAX_PRIORITY
)
164 throw new IllegalArgumentException
;
166 jint gmax
= group
->getMaxPriority();
167 if (newPriority
> gmax
)
170 priority
= newPriority
;
171 natThread
*nt
= (natThread
*) data
;
172 _Jv_ThreadSetPriority (nt
->thread
, priority
);
176 java::lang::Thread::sleep (jlong millis
, jint nanos
)
178 if (millis
< 0 || nanos
< 0 || nanos
> 999999)
179 throw new IllegalArgumentException
;
181 if (millis
== 0 && nanos
== 0)
184 Thread
*current
= currentThread ();
186 // We use a condition variable to implement sleeping so that an
187 // interrupt can wake us up.
188 natThread
*nt
= (natThread
*) current
->data
;
189 _Jv_MutexLock (&nt
->join_mutex
);
190 _Jv_CondWait (&nt
->join_cond
, &nt
->join_mutex
, millis
, nanos
);
191 _Jv_MutexUnlock (&nt
->join_mutex
);
193 if (current
->isInterrupted (true))
194 throw new InterruptedException
;
198 java::lang::Thread::finish_ ()
200 natThread
*nt
= (natThread
*) data
;
202 group
->removeThread (this);
205 if (_Jv_JVMPI_Notify_THREAD_END
)
209 event
.event_type
= JVMPI_EVENT_THREAD_END
;
210 event
.env_id
= _Jv_GetCurrentJNIEnv ();
213 (*_Jv_JVMPI_Notify_THREAD_END
) (&event
);
218 // If a method cache was created, free it.
219 _Jv_FreeMethodCache();
221 // Clear out thread locals.
224 // Signal any threads that are waiting to join() us.
225 _Jv_MutexLock (&nt
->join_mutex
);
228 JvSynchronize
sync (this);
232 _Jv_CondNotifyAll (&nt
->join_cond
, &nt
->join_mutex
);
233 _Jv_MutexUnlock (&nt
->join_mutex
);
236 // Run once at thread startup, either when thread is attached or when
237 // _Jv_ThreadRun is called.
239 _Jv_NotifyThreadStart (java::lang::Thread
* thread
)
242 if (_Jv_JVMPI_Notify_THREAD_START
)
246 jstring thread_name
= thread
->getName ();
247 jstring group_name
= NULL
, parent_name
= NULL
;
248 java::lang::ThreadGroup
*group
= thread
->getThreadGroup ();
252 group_name
= group
->getName ();
253 group
= group
->getParent ();
256 parent_name
= group
->getName ();
259 int thread_len
= thread_name
? JvGetStringUTFLength (thread_name
) : 0;
260 int group_len
= group_name
? JvGetStringUTFLength (group_name
) : 0;
261 int parent_len
= parent_name
? JvGetStringUTFLength (parent_name
) : 0;
263 char thread_chars
[thread_len
+ 1];
264 char group_chars
[group_len
+ 1];
265 char parent_chars
[parent_len
+ 1];
268 JvGetStringUTFRegion (thread_name
, 0,
269 thread_name
->length(), thread_chars
);
271 JvGetStringUTFRegion (group_name
, 0,
272 group_name
->length(), group_chars
);
274 JvGetStringUTFRegion (parent_name
, 0,
275 parent_name
->length(), parent_chars
);
277 thread_chars
[thread_len
] = '\0';
278 group_chars
[group_len
] = '\0';
279 parent_chars
[parent_len
] = '\0';
281 event
.event_type
= JVMPI_EVENT_THREAD_START
;
283 event
.u
.thread_start
.thread_name
= thread_chars
;
284 event
.u
.thread_start
.group_name
= group_chars
;
285 event
.u
.thread_start
.parent_name
= parent_chars
;
286 event
.u
.thread_start
.thread_id
= (jobjectID
) thread
;
287 event
.u
.thread_start
.thread_env_id
= _Jv_GetCurrentJNIEnv ();
290 (*_Jv_JVMPI_Notify_THREAD_START
) (&event
);
297 _Jv_ThreadRun (java::lang::Thread
* thread
)
301 _Jv_NotifyThreadStart (thread
);
304 catch (java::lang::Throwable
*t
)
306 // Uncaught exceptions are forwarded to the ThreadGroup. If
307 // this results in an uncaught exception, that is ignored.
310 thread
->group
->uncaughtException (thread
, t
);
312 catch (java::lang::Throwable
*f
)
322 _Jv_ThreadGetData (java::lang::Thread
* thread
)
324 natThread
* nt
= (natThread
*) thread
->data
;
329 java::lang::Thread::start (void)
331 JvSynchronize
sync (this);
333 // Its illegal to re-start() a thread, even if its dead.
335 throw new IllegalThreadStateException
;
338 startable_flag
= false;
339 natThread
*nt
= (natThread
*) data
;
340 _Jv_ThreadStart (this, nt
->thread
, (_Jv_ThreadStartFunc
*) &_Jv_ThreadRun
);
344 java::lang::Thread::stop (java::lang::Throwable
*)
348 // Old applets still call this method. Rather than throwing
349 // UnsupportedOperationException we simply fail silently.
353 java::lang::Thread::suspend (void)
357 // Old applets still call this method. Rather than throwing
358 // UnsupportedOperationException we simply fail silently.
361 static int nextThreadNumber
= 0;
364 java::lang::Thread::gen_name (void)
367 jclass sync
= &java::lang::Thread::class$
;
369 JvSynchronize
dummy(sync
);
370 i
= ++nextThreadNumber
;
373 // Use an array large enough for "-2147483648"; i.e. 11 chars, + "Thread-".
375 jchar
*bufend
= (jchar
*) ((char *) buffer
+ sizeof(buffer
));
376 i
= _Jv_FormatInt (bufend
, i
);
377 jchar
*ptr
= bufend
- i
;
378 // Prepend "Thread-".
386 return JvNewString (ptr
, bufend
- ptr
);
390 java::lang::Thread::yield (void)
396 _Jv_GetCurrentJNIEnv ()
398 java::lang::Thread
*t
= _Jv_ThreadCurrent ();
401 return ((natThread
*) t
->data
)->jni_env
;
405 _Jv_SetCurrentJNIEnv (JNIEnv
*env
)
407 java::lang::Thread
*t
= _Jv_ThreadCurrent ();
408 JvAssert (t
!= NULL
);
409 ((natThread
*) t
->data
)->jni_env
= env
;
412 // Attach the current native thread to an existing (but unstarted) Thread
413 // object. Does not register thread with the garbage collector.
414 // Returns -1 on failure, 0 upon success.
416 _Jv_AttachCurrentThread(java::lang::Thread
* thread
)
418 JvSynchronize
sync (thread
);
419 if (thread
== NULL
|| thread
->startable_flag
== false)
421 thread
->startable_flag
= false;
422 thread
->alive_flag
= true;
423 natThread
*nt
= (natThread
*) thread
->data
;
424 _Jv_ThreadRegister (nt
->thread
);
429 _Jv_AttachCurrentThread(jstring name
, java::lang::ThreadGroup
* group
)
431 // Register thread with GC before attempting any allocations.
432 _Jv_GCAttachThread ();
433 java::lang::Thread
*thread
= _Jv_ThreadCurrent ();
437 name
= java::lang::Thread::gen_name ();
438 thread
= new java::lang::Thread (NULL
, group
, NULL
, name
);
439 _Jv_AttachCurrentThread (thread
);
440 _Jv_NotifyThreadStart (thread
);
445 _Jv_AttachCurrentThreadAsDaemon(jstring name
, java::lang::ThreadGroup
* group
)
447 java::lang::Thread
*thread
= _Jv_ThreadCurrent ();
451 name
= java::lang::Thread::gen_name ();
452 thread
= new java::lang::Thread (NULL
, group
, NULL
, name
);
453 thread
->setDaemon (true);
454 _Jv_AttachCurrentThread (thread
);
455 _Jv_NotifyThreadStart (thread
);
460 _Jv_DetachCurrentThread (void)
462 java::lang::Thread
*t
= _Jv_ThreadCurrent ();
466 _Jv_ThreadUnRegister ();
467 _Jv_GCDetachThread ();
468 // Release the monitors.