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/UnsupportedOperationException.h>
24 #include <java/lang/IllegalThreadStateException.h>
25 #include <java/lang/InterruptedException.h>
26 #include <java/lang/NullPointerException.h>
36 // This structure is used to represent all the data the native side
37 // needs. An object of this type is assigned to the `data' member of
41 // These are used to interrupt sleep and join calls. We can share a
42 // condition variable here since it only ever gets notified when the thread
44 _Jv_Mutex_t join_mutex
;
45 _Jv_ConditionVariable_t join_cond
;
47 // This is private data for the thread system layer.
50 // Each thread has its own JNI object.
54 static void finalize_native (jobject ptr
);
56 // This is called from the constructor to initialize the native side
59 java::lang::Thread::initialize_native (void)
61 natThread
*nt
= (natThread
*) _Jv_AllocBytes (sizeof (natThread
));
63 data
= (gnu::gcj::RawDataManaged
*) nt
;
65 // Register a finalizer to clean up the native thread resources.
66 _Jv_RegisterFinalizer (data
, finalize_native
);
68 _Jv_MutexInit (&nt
->join_mutex
);
69 _Jv_CondInit (&nt
->join_cond
);
70 nt
->thread
= _Jv_ThreadInitData (this);
71 // FIXME: if JNI_ENV is set we will want to free it. It is
77 finalize_native (jobject ptr
)
79 natThread
*nt
= (natThread
*) ptr
;
80 _Jv_ThreadDestroyData (nt
->thread
);
81 #ifdef _Jv_HaveCondDestroy
82 _Jv_CondDestroy (&nt
->join_cond
);
84 #ifdef _Jv_HaveMutexDestroy
85 _Jv_MutexDestroy (&nt
->join_mutex
);
87 _Jv_FreeJNIEnv(nt
->jni_env
);
91 java::lang::Thread::countStackFrames (void)
93 // NOTE: This is deprecated in JDK 1.2.
94 throw new UnsupportedOperationException
95 (JvNewStringLatin1 ("Thread.countStackFrames unimplemented"));
100 java::lang::Thread::currentThread (void)
102 return _Jv_ThreadCurrent ();
106 java::lang::Thread::holdsLock (jobject obj
)
109 throw new NullPointerException
;
110 return !_Jv_ObjectCheckMonitor (obj
);
114 java::lang::Thread::interrupt (void)
117 natThread
*nt
= (natThread
*) data
;
118 JvSynchronize
sync (this);
120 _Jv_ThreadInterrupt (nt
->thread
);
124 java::lang::Thread::join (jlong millis
, jint nanos
)
126 if (millis
< 0 || nanos
< 0 || nanos
> 999999)
127 throw new IllegalArgumentException
;
129 Thread
*current
= currentThread ();
131 // Here `NT' is the native structure for the thread we are trying to join.
132 natThread
*nt
= (natThread
*) data
;
134 // Now wait for: (1) an interrupt, (2) the thread to exit, or (3)
135 // the timeout to occur.
136 _Jv_MutexLock (&nt
->join_mutex
);
139 _Jv_MutexUnlock (&nt
->join_mutex
);
142 _Jv_CondWait (&nt
->join_cond
, &nt
->join_mutex
, millis
, nanos
);
143 _Jv_MutexUnlock (&nt
->join_mutex
);
145 if (current
->isInterrupted (true))
146 throw new InterruptedException
;
150 java::lang::Thread::resume (void)
153 throw new UnsupportedOperationException
154 (JvNewStringLatin1 ("Thread.resume unimplemented"));
158 java::lang::Thread::setPriority (jint newPriority
)
161 if (newPriority
< MIN_PRIORITY
|| newPriority
> MAX_PRIORITY
)
162 throw new IllegalArgumentException
;
164 jint gmax
= group
->getMaxPriority();
165 if (newPriority
> gmax
)
168 priority
= newPriority
;
169 natThread
*nt
= (natThread
*) data
;
170 _Jv_ThreadSetPriority (nt
->thread
, priority
);
174 java::lang::Thread::sleep (jlong millis
, jint nanos
)
176 if (millis
< 0 || nanos
< 0 || nanos
> 999999)
177 throw new IllegalArgumentException
;
179 if (millis
== 0 && nanos
== 0)
182 Thread
*current
= currentThread ();
184 // We use a condition variable to implement sleeping so that an
185 // interrupt can wake us up.
186 natThread
*nt
= (natThread
*) current
->data
;
187 _Jv_MutexLock (&nt
->join_mutex
);
188 _Jv_CondWait (&nt
->join_cond
, &nt
->join_mutex
, millis
, nanos
);
189 _Jv_MutexUnlock (&nt
->join_mutex
);
191 if (current
->isInterrupted (true))
192 throw new InterruptedException
;
196 java::lang::Thread::finish_ ()
198 natThread
*nt
= (natThread
*) data
;
200 group
->removeThread (this);
203 if (_Jv_JVMPI_Notify_THREAD_END
)
207 event
.event_type
= JVMPI_EVENT_THREAD_END
;
208 event
.env_id
= _Jv_GetCurrentJNIEnv ();
211 (*_Jv_JVMPI_Notify_THREAD_END
) (&event
);
216 // If a method cache was created, free it.
217 _Jv_FreeMethodCache();
219 // Signal any threads that are waiting to join() us.
220 _Jv_MutexLock (&nt
->join_mutex
);
223 JvSynchronize
sync (this);
227 _Jv_CondNotifyAll (&nt
->join_cond
, &nt
->join_mutex
);
228 _Jv_MutexUnlock (&nt
->join_mutex
);
231 // Run once at thread startup, either when thread is attached or when
232 // _Jv_ThreadRun is called.
234 _Jv_NotifyThreadStart (java::lang::Thread
* thread
)
237 if (_Jv_JVMPI_Notify_THREAD_START
)
241 jstring thread_name
= thread
->getName ();
242 jstring group_name
= NULL
, parent_name
= NULL
;
243 java::lang::ThreadGroup
*group
= thread
->getThreadGroup ();
247 group_name
= group
->getName ();
248 group
= group
->getParent ();
251 parent_name
= group
->getName ();
254 int thread_len
= thread_name
? JvGetStringUTFLength (thread_name
) : 0;
255 int group_len
= group_name
? JvGetStringUTFLength (group_name
) : 0;
256 int parent_len
= parent_name
? JvGetStringUTFLength (parent_name
) : 0;
258 char thread_chars
[thread_len
+ 1];
259 char group_chars
[group_len
+ 1];
260 char parent_chars
[parent_len
+ 1];
263 JvGetStringUTFRegion (thread_name
, 0,
264 thread_name
->length(), thread_chars
);
266 JvGetStringUTFRegion (group_name
, 0,
267 group_name
->length(), group_chars
);
269 JvGetStringUTFRegion (parent_name
, 0,
270 parent_name
->length(), parent_chars
);
272 thread_chars
[thread_len
] = '\0';
273 group_chars
[group_len
] = '\0';
274 parent_chars
[parent_len
] = '\0';
276 event
.event_type
= JVMPI_EVENT_THREAD_START
;
278 event
.u
.thread_start
.thread_name
= thread_chars
;
279 event
.u
.thread_start
.group_name
= group_chars
;
280 event
.u
.thread_start
.parent_name
= parent_chars
;
281 event
.u
.thread_start
.thread_id
= (jobjectID
) thread
;
282 event
.u
.thread_start
.thread_env_id
= _Jv_GetCurrentJNIEnv ();
285 (*_Jv_JVMPI_Notify_THREAD_START
) (&event
);
292 _Jv_ThreadRun (java::lang::Thread
* thread
)
296 _Jv_NotifyThreadStart (thread
);
299 catch (java::lang::Throwable
*t
)
301 // Uncaught exceptions are forwarded to the ThreadGroup. If
302 // this results in an uncaught exception, that is ignored.
305 thread
->group
->uncaughtException (thread
, t
);
307 catch (java::lang::Throwable
*f
)
317 java::lang::Thread::start (void)
319 JvSynchronize
sync (this);
321 // Its illegal to re-start() a thread, even if its dead.
323 throw new IllegalThreadStateException
;
326 startable_flag
= false;
327 natThread
*nt
= (natThread
*) data
;
328 _Jv_ThreadStart (this, nt
->thread
, (_Jv_ThreadStartFunc
*) &_Jv_ThreadRun
);
332 java::lang::Thread::stop (java::lang::Throwable
*)
335 throw new UnsupportedOperationException
336 (JvNewStringLatin1 ("Thread.stop unimplemented"));
340 java::lang::Thread::suspend (void)
343 throw new UnsupportedOperationException
344 (JvNewStringLatin1 ("Thread.suspend unimplemented"));
347 static int nextThreadNumber
= 0;
350 java::lang::Thread::gen_name (void)
353 jclass sync
= &java::lang::Thread::class$
;
355 JvSynchronize
dummy(sync
);
356 i
= ++nextThreadNumber
;
359 // Use an array large enough for "-2147483648"; i.e. 11 chars, + "Thread-".
361 jchar
*bufend
= (jchar
*) ((char *) buffer
+ sizeof(buffer
));
362 i
= _Jv_FormatInt (bufend
, i
);
363 jchar
*ptr
= bufend
- i
;
364 // Prepend "Thread-".
372 return JvNewString (ptr
, bufend
- ptr
);
376 java::lang::Thread::yield (void)
382 _Jv_GetCurrentJNIEnv ()
384 java::lang::Thread
*t
= _Jv_ThreadCurrent ();
387 return ((natThread
*) t
->data
)->jni_env
;
391 _Jv_SetCurrentJNIEnv (JNIEnv
*env
)
393 java::lang::Thread
*t
= _Jv_ThreadCurrent ();
394 JvAssert (t
!= NULL
);
395 ((natThread
*) t
->data
)->jni_env
= env
;
398 // Attach the current native thread to an existing (but unstarted) Thread
399 // object. Returns -1 on failure, 0 upon success.
401 _Jv_AttachCurrentThread(java::lang::Thread
* thread
)
403 JvSynchronize
sync (thread
);
404 if (thread
== NULL
|| thread
->startable_flag
== false)
406 thread
->startable_flag
= false;
407 thread
->alive_flag
= true;
408 natThread
*nt
= (natThread
*) thread
->data
;
409 _Jv_ThreadRegister (nt
->thread
);
414 _Jv_AttachCurrentThread(jstring name
, java::lang::ThreadGroup
* group
)
416 java::lang::Thread
*thread
= _Jv_ThreadCurrent ();
420 name
= java::lang::Thread::gen_name ();
421 thread
= new java::lang::Thread (NULL
, group
, NULL
, name
);
422 _Jv_AttachCurrentThread (thread
);
423 _Jv_NotifyThreadStart (thread
);
428 _Jv_AttachCurrentThreadAsDaemon(jstring name
, java::lang::ThreadGroup
* group
)
430 java::lang::Thread
*thread
= _Jv_ThreadCurrent ();
434 name
= java::lang::Thread::gen_name ();
435 thread
= new java::lang::Thread (NULL
, group
, NULL
, name
);
436 thread
->setDaemon (true);
437 _Jv_AttachCurrentThread (thread
);
438 _Jv_NotifyThreadStart (thread
);
443 _Jv_DetachCurrentThread (void)
445 java::lang::Thread
*t
= _Jv_ThreadCurrent ();
449 _Jv_ThreadUnRegister ();
450 // Release the monitors.