gcc/
[official-gcc.git] / libjava / java / lang / natThread.cc
blobd6abff13f54cf95d4d718e02a9597c08967cf7ca
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
9 details. */
11 #include <config.h>
13 #include <stdlib.h>
15 #include <gcj/cni.h>
16 #include <jvm.h>
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>
29 #include <jni.h>
31 #ifdef INTERPRETER
32 #include <jvmti.h>
33 #include "jvmti-int.h"
34 #endif
36 #ifdef ENABLE_JVMPI
37 #include <jvmpi.h>
38 #endif
42 static void finalize_native (jobject ptr);
44 // This is called from the constructor to initialize the native side
45 // of the Thread.
46 void
47 java::lang::Thread::initialize_native (void)
49 natThread *nt = (natThread *) _Jv_AllocBytes (sizeof (natThread));
51 state = JV_NEW;
52 nt->alive_flag = THREAD_DEAD;
54 data = (gnu::gcj::RawDataManaged *) nt;
56 // Register a finalizer to clean up the native thread resources.
57 _Jv_RegisterFinalizer (data, finalize_native);
59 _Jv_MutexInit (&nt->join_mutex);
60 _Jv_CondInit (&nt->join_cond);
62 nt->park_helper.init();
64 nt->thread = _Jv_ThreadInitData (this);
65 // FIXME: if JNI_ENV is set we will want to free it. It is
66 // malloc()d.
67 nt->jni_env = NULL;
70 static void
71 finalize_native (jobject ptr)
73 natThread *nt = (natThread *) ptr;
74 _Jv_ThreadDestroyData (nt->thread);
75 #ifdef _Jv_HaveCondDestroy
76 _Jv_CondDestroy (&nt->join_cond);
77 #endif
78 #ifdef _Jv_HaveMutexDestroy
79 _Jv_MutexDestroy (&nt->join_mutex);
80 #endif
81 _Jv_FreeJNIEnv((JNIEnv*)nt->jni_env);
83 nt->park_helper.destroy();
86 jint
87 java::lang::Thread::countStackFrames (void)
89 // NOTE: This is deprecated in JDK 1.2.
91 // Old applets still call this method. Rather than throwing
92 // UnsupportedOperationException we simply fail silently.
94 return 0;
97 java::lang::Thread *
98 java::lang::Thread::currentThread (void)
100 return _Jv_ThreadCurrent ();
103 jboolean
104 java::lang::Thread::holdsLock (jobject obj)
106 if (!obj)
107 throw new NullPointerException;
108 return !_Jv_ObjectCheckMonitor (obj);
111 jboolean
112 java::lang::Thread::isAlive (void)
114 natThread *nt = (natThread *) data;
115 return nt->alive_flag != (obj_addr_t)THREAD_DEAD;
118 void
119 java::lang::Thread::interrupt (void)
121 checkAccess ();
123 natThread *nt = (natThread *) data;
125 // If a thread is in state ALIVE, we atomically set it to state
126 // SIGNALED and send it a signal. Once we've sent it the signal, we
127 // set its state back to ALIVE.
128 if (compare_and_swap
129 (&nt->alive_flag, Thread::THREAD_ALIVE, Thread::THREAD_SIGNALED))
131 _Jv_ThreadInterrupt (nt->thread);
132 compare_and_swap
133 (&nt->alive_flag, THREAD_SIGNALED, Thread::THREAD_ALIVE);
135 // Even though we've interrupted this thread, it might still be
136 // parked.
137 nt->park_helper.unpark ();
141 void
142 java::lang::Thread::join (jlong millis, jint nanos)
144 if (millis < 0 || nanos < 0 || nanos > 999999)
145 throw new IllegalArgumentException;
147 Thread *current = currentThread ();
149 // Here `NT' is the native structure for the thread we are trying to join.
150 natThread *nt = (natThread *) data;
152 // Now wait for: (1) an interrupt, (2) the thread to exit, or (3)
153 // the timeout to occur.
154 _Jv_MutexLock (&nt->join_mutex);
155 if (! isAlive ())
157 _Jv_MutexUnlock (&nt->join_mutex);
158 return;
160 _Jv_CondWait (&nt->join_cond, &nt->join_mutex, millis, nanos);
161 _Jv_MutexUnlock (&nt->join_mutex);
163 if (current->isInterrupted (true))
164 throw new InterruptedException;
167 void
168 java::lang::Thread::resume (void)
170 checkAccess ();
172 // Old applets still call this method. Rather than throwing
173 // UnsupportedOperationException we simply fail silently.
176 void
177 java::lang::Thread::setPriority (jint newPriority)
179 checkAccess ();
180 if (newPriority < MIN_PRIORITY || newPriority > MAX_PRIORITY)
181 throw new IllegalArgumentException;
183 jint gmax = group->getMaxPriority();
184 if (newPriority > gmax)
185 newPriority = gmax;
187 priority = newPriority;
188 natThread *nt = (natThread *) data;
189 _Jv_ThreadSetPriority (nt->thread, priority);
192 void
193 java::lang::Thread::sleep (jlong millis, jint nanos)
195 if (millis < 0 || nanos < 0 || nanos > 999999)
196 throw new IllegalArgumentException;
198 if (millis == 0 && nanos == 0)
199 ++nanos;
201 Thread *current = currentThread ();
203 // We use a condition variable to implement sleeping so that an
204 // interrupt can wake us up.
205 natThread *nt = (natThread *) current->data;
206 _Jv_MutexLock (&nt->join_mutex);
207 _Jv_CondWait (&nt->join_cond, &nt->join_mutex, millis, nanos);
208 _Jv_MutexUnlock (&nt->join_mutex);
210 if (current->isInterrupted (true))
211 throw new InterruptedException;
214 void
215 java::lang::Thread::finish_ ()
217 __sync_synchronize();
218 natThread *nt = (natThread *) data;
220 nt->park_helper.deactivate ();
221 group->removeThread (this);
223 #ifdef INTERPRETER
224 if (JVMTI_REQUESTED_EVENT (ThreadEnd))
225 _Jv_JVMTI_PostEvent (JVMTI_EVENT_THREAD_END, this, nt->jni_env);
226 #endif
228 #ifdef ENABLE_JVMPI
229 if (_Jv_JVMPI_Notify_THREAD_END)
231 JVMPI_Event event;
233 event.event_type = JVMPI_EVENT_THREAD_END;
234 event.env_id = _Jv_GetCurrentJNIEnv ();
236 _Jv_DisableGC ();
237 (*_Jv_JVMPI_Notify_THREAD_END) (&event);
238 _Jv_EnableGC ();
240 #endif
242 // If a method cache was created, free it.
243 _Jv_FreeMethodCache();
245 // Clear out thread locals.
246 locals = NULL;
248 // Signal any threads that are waiting to join() us.
249 _Jv_MutexLock (&nt->join_mutex);
252 JvSynchronize sync (this);
253 nt->alive_flag = THREAD_DEAD;
254 state = JV_TERMINATED;
257 _Jv_CondNotifyAll (&nt->join_cond, &nt->join_mutex);
258 _Jv_MutexUnlock (&nt->join_mutex);
261 // Run once at thread startup, either when thread is attached or when
262 // _Jv_ThreadRun is called.
263 static void
264 _Jv_NotifyThreadStart (java::lang::Thread* thread)
266 #ifdef INTERPRETER
267 if (JVMTI_REQUESTED_EVENT (ThreadStart))
269 natThread *nt = reinterpret_cast<natThread *> (thread->data);
270 _Jv_JVMTI_PostEvent (JVMTI_EVENT_THREAD_START, thread, nt->jni_env);
272 #endif
274 #ifdef ENABLE_JVMPI
275 if (_Jv_JVMPI_Notify_THREAD_START)
277 JVMPI_Event event;
279 jstring thread_name = thread->getName ();
280 jstring group_name = NULL, parent_name = NULL;
281 java::lang::ThreadGroup *group = thread->getThreadGroup ();
283 if (group)
285 group_name = group->getName ();
286 group = group->getParent ();
288 if (group)
289 parent_name = group->getName ();
292 int thread_len = thread_name ? JvGetStringUTFLength (thread_name) : 0;
293 int group_len = group_name ? JvGetStringUTFLength (group_name) : 0;
294 int parent_len = parent_name ? JvGetStringUTFLength (parent_name) : 0;
296 char thread_chars[thread_len + 1];
297 char group_chars[group_len + 1];
298 char parent_chars[parent_len + 1];
300 if (thread_name)
301 JvGetStringUTFRegion (thread_name, 0,
302 thread_name->length(), thread_chars);
303 if (group_name)
304 JvGetStringUTFRegion (group_name, 0,
305 group_name->length(), group_chars);
306 if (parent_name)
307 JvGetStringUTFRegion (parent_name, 0,
308 parent_name->length(), parent_chars);
310 thread_chars[thread_len] = '\0';
311 group_chars[group_len] = '\0';
312 parent_chars[parent_len] = '\0';
314 event.event_type = JVMPI_EVENT_THREAD_START;
315 event.env_id = NULL;
316 event.u.thread_start.thread_name = thread_chars;
317 event.u.thread_start.group_name = group_chars;
318 event.u.thread_start.parent_name = parent_chars;
319 event.u.thread_start.thread_id = (jobjectID) thread;
320 event.u.thread_start.thread_env_id = _Jv_GetCurrentJNIEnv ();
322 _Jv_DisableGC ();
323 (*_Jv_JVMPI_Notify_THREAD_START) (&event);
324 _Jv_EnableGC ();
326 #endif
329 void
330 _Jv_ThreadRun (java::lang::Thread* thread)
334 _Jv_NotifyThreadStart (thread);
335 thread->run ();
337 catch (java::lang::Throwable *t)
339 // Uncaught exceptions are forwarded to the ThreadGroup. If
340 // this results in an uncaught exception, that is ignored.
343 thread->getUncaughtExceptionHandler()->uncaughtException (thread, t);
345 catch (java::lang::Throwable *f)
347 // Nothing.
351 thread->finish_ ();
354 _Jv_Thread_t*
355 _Jv_ThreadGetData (java::lang::Thread* thread)
357 natThread* nt = (natThread*) thread->data;
358 return nt->thread;
361 void
362 java::lang::Thread::start (void)
364 JvSynchronize sync (this);
366 // Its illegal to re-start() a thread, even if its dead.
367 if (!startable_flag)
368 throw new IllegalThreadStateException;
370 natThread *nt = (natThread *) data;
371 nt->alive_flag = THREAD_ALIVE;
372 startable_flag = false;
373 state = JV_RUNNABLE;
374 _Jv_ThreadStart (this, nt->thread, (_Jv_ThreadStartFunc *) &_Jv_ThreadRun);
377 void
378 java::lang::Thread::stop (java::lang::Throwable *)
380 checkAccess ();
382 // Old applets still call this method. Rather than throwing
383 // UnsupportedOperationException we simply fail silently.
386 void
387 java::lang::Thread::suspend (void)
389 checkAccess ();
391 // Old applets still call this method. Rather than throwing
392 // UnsupportedOperationException we simply fail silently.
395 static int nextThreadNumber = 0;
397 jstring
398 java::lang::Thread::gen_name (void)
400 jint i;
401 jclass sync = &java::lang::Thread::class$;
403 JvSynchronize dummy(sync);
404 i = ++nextThreadNumber;
407 // Use an array large enough for "-2147483648"; i.e. 11 chars, + "Thread-".
408 jchar buffer[7+11];
409 jchar *bufend = (jchar *) ((char *) buffer + sizeof(buffer));
410 i = _Jv_FormatInt (bufend, i);
411 jchar *ptr = bufend - i;
412 // Prepend "Thread-".
413 *--ptr = '-';
414 *--ptr = 'd';
415 *--ptr = 'a';
416 *--ptr = 'e';
417 *--ptr = 'r';
418 *--ptr = 'h';
419 *--ptr = 'T';
420 return JvNewString (ptr, bufend - ptr);
423 void
424 java::lang::Thread::yield (void)
426 _Jv_ThreadYield ();
429 ::java::lang::Thread$State *
430 java::lang::Thread::getState()
432 _Jv_InitClass(&::java::lang::Thread$State::class$);
434 switch (state)
436 case JV_BLOCKED:
437 return ::java::lang::Thread$State::BLOCKED;
438 case JV_NEW:
439 return ::java::lang::Thread$State::NEW;
441 case JV_RUNNABLE:
442 return ::java::lang::Thread$State::RUNNABLE;
443 case JV_TERMINATED:
444 return ::java::lang::Thread$State::TERMINATED;
445 case JV_TIMED_WAITING:
446 return ::java::lang::Thread$State::TIMED_WAITING;
447 case JV_WAITING:
448 return ::java::lang::Thread$State::WAITING;
451 // We don't really need a default, but this makes the compiler
452 // happy.
453 return ::java::lang::Thread$State::RUNNABLE;
456 JNIEnv *
457 _Jv_GetCurrentJNIEnv ()
459 java::lang::Thread *t = _Jv_ThreadCurrent ();
460 if (t == NULL)
461 return NULL;
462 return ((natThread *) t->data)->jni_env;
465 void
466 _Jv_SetCurrentJNIEnv (JNIEnv *env)
468 java::lang::Thread *t = _Jv_ThreadCurrent ();
469 JvAssert (t != NULL);
470 ((natThread *) t->data)->jni_env = env;
473 // Attach the current native thread to an existing (but unstarted) Thread
474 // object. Does not register thread with the garbage collector.
475 // Returns -1 on failure, 0 upon success.
476 jint
477 _Jv_AttachCurrentThread(java::lang::Thread* thread)
479 JvSynchronize sync (thread);
480 if (thread == NULL || thread->startable_flag == false)
481 return -1;
482 thread->startable_flag = false;
483 natThread *nt = (natThread *) thread->data;
484 nt->alive_flag = ::java::lang::Thread::THREAD_ALIVE;
485 thread->state = JV_RUNNABLE;
486 _Jv_ThreadRegister (nt->thread);
487 return 0;
490 java::lang::Thread*
491 _Jv_AttachCurrentThread(jstring name, java::lang::ThreadGroup* group)
493 // Register thread with GC before attempting any allocations.
494 _Jv_GCAttachThread ();
495 java::lang::Thread *thread = _Jv_ThreadCurrent ();
496 if (thread != NULL)
497 return thread;
498 if (name == NULL)
499 name = java::lang::Thread::gen_name ();
500 thread = new java::lang::Thread (NULL, group, NULL, name, false);
501 _Jv_AttachCurrentThread (thread);
502 _Jv_NotifyThreadStart (thread);
503 return thread;
506 java::lang::Thread*
507 _Jv_AttachCurrentThreadAsDaemon(jstring name, java::lang::ThreadGroup* group)
509 java::lang::Thread *thread = _Jv_ThreadCurrent ();
510 if (thread != NULL)
511 return thread;
512 if (name == NULL)
513 name = java::lang::Thread::gen_name ();
514 thread = new java::lang::Thread (NULL, group, NULL, name, false);
515 thread->setDaemon (true);
516 _Jv_AttachCurrentThread (thread);
517 _Jv_NotifyThreadStart (thread);
518 return thread;
521 jint
522 _Jv_DetachCurrentThread (void)
524 java::lang::Thread *t = _Jv_ThreadCurrent ();
525 if (t == NULL)
526 return -1;
528 _Jv_ThreadUnRegister ();
529 _Jv_GCDetachThread ();
530 // Release the monitors.
531 t->finish_ ();
533 return 0;