* java/lang/natThread.cc (finalize_native): Remove cast.
[official-gcc.git] / libjava / java / lang / natThread.cc
blob9e2f7dd674d9241fbe7caf1df4cffd6644e7f286
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 ENABLE_JVMPI
32 #include <jvmpi.h>
33 #endif
37 static void finalize_native (jobject ptr);
39 // This is called from the constructor to initialize the native side
40 // of the Thread.
41 void
42 java::lang::Thread::initialize_native (void)
44 natThread *nt = (natThread *) _Jv_AllocBytes (sizeof (natThread));
46 state = JV_NEW;
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
61 // malloc()d.
62 nt->jni_env = NULL;
65 static void
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);
72 #endif
73 #ifdef _Jv_HaveMutexDestroy
74 _Jv_MutexDestroy (&nt->join_mutex);
75 #endif
76 _Jv_FreeJNIEnv((JNIEnv*)nt->jni_env);
78 nt->park_helper.destroy();
81 jint
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.
89 return 0;
92 java::lang::Thread *
93 java::lang::Thread::currentThread (void)
95 return _Jv_ThreadCurrent ();
98 jboolean
99 java::lang::Thread::holdsLock (jobject obj)
101 if (!obj)
102 throw new NullPointerException;
103 return !_Jv_ObjectCheckMonitor (obj);
106 jboolean
107 java::lang::Thread::isAlive (void)
109 natThread *nt = (natThread *) data;
110 return nt->alive_flag != (obj_addr_t)THREAD_DEAD;
113 void
114 java::lang::Thread::interrupt (void)
116 checkAccess ();
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.
123 if (compare_and_swap
124 (&nt->alive_flag, Thread::THREAD_ALIVE, Thread::THREAD_SIGNALED))
126 _Jv_ThreadInterrupt (nt->thread);
127 compare_and_swap
128 (&nt->alive_flag, THREAD_SIGNALED, Thread::THREAD_ALIVE);
130 // Even though we've interrupted this thread, it might still be
131 // parked.
132 nt->park_helper.unpark ();
136 void
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);
150 if (! isAlive ())
152 _Jv_MutexUnlock (&nt->join_mutex);
153 return;
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;
162 void
163 java::lang::Thread::resume (void)
165 checkAccess ();
167 // Old applets still call this method. Rather than throwing
168 // UnsupportedOperationException we simply fail silently.
171 void
172 java::lang::Thread::setPriority (jint newPriority)
174 checkAccess ();
175 if (newPriority < MIN_PRIORITY || newPriority > MAX_PRIORITY)
176 throw new IllegalArgumentException;
178 jint gmax = group->getMaxPriority();
179 if (newPriority > gmax)
180 newPriority = gmax;
182 priority = newPriority;
183 natThread *nt = (natThread *) data;
184 _Jv_ThreadSetPriority (nt->thread, priority);
187 void
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)
194 ++nanos;
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;
209 void
210 java::lang::Thread::finish_ ()
212 __sync_synchronize();
213 natThread *nt = (natThread *) data;
215 nt->park_helper.deactivate ();
216 group->removeThread (this);
218 #ifdef ENABLE_JVMPI
219 if (_Jv_JVMPI_Notify_THREAD_END)
221 JVMPI_Event event;
223 event.event_type = JVMPI_EVENT_THREAD_END;
224 event.env_id = _Jv_GetCurrentJNIEnv ();
226 _Jv_DisableGC ();
227 (*_Jv_JVMPI_Notify_THREAD_END) (&event);
228 _Jv_EnableGC ();
230 #endif
232 // If a method cache was created, free it.
233 _Jv_FreeMethodCache();
235 // Clear out thread locals.
236 locals = NULL;
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.
253 static void
254 _Jv_NotifyThreadStart (java::lang::Thread* thread)
256 #ifdef ENABLE_JVMPI
257 if (_Jv_JVMPI_Notify_THREAD_START)
259 JVMPI_Event event;
261 jstring thread_name = thread->getName ();
262 jstring group_name = NULL, parent_name = NULL;
263 java::lang::ThreadGroup *group = thread->getThreadGroup ();
265 if (group)
267 group_name = group->getName ();
268 group = group->getParent ();
270 if (group)
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];
282 if (thread_name)
283 JvGetStringUTFRegion (thread_name, 0,
284 thread_name->length(), thread_chars);
285 if (group_name)
286 JvGetStringUTFRegion (group_name, 0,
287 group_name->length(), group_chars);
288 if (parent_name)
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;
297 event.env_id = NULL;
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 ();
304 _Jv_DisableGC ();
305 (*_Jv_JVMPI_Notify_THREAD_START) (&event);
306 _Jv_EnableGC ();
308 #endif
311 void
312 _Jv_ThreadRun (java::lang::Thread* thread)
316 _Jv_NotifyThreadStart (thread);
317 thread->run ();
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)
329 // Nothing.
333 thread->finish_ ();
336 _Jv_Thread_t*
337 _Jv_ThreadGetData (java::lang::Thread* thread)
339 natThread* nt = (natThread*) thread->data;
340 return nt->thread;
343 void
344 java::lang::Thread::start (void)
346 JvSynchronize sync (this);
348 // Its illegal to re-start() a thread, even if its dead.
349 if (!startable_flag)
350 throw new IllegalThreadStateException;
352 natThread *nt = (natThread *) data;
353 nt->alive_flag = THREAD_ALIVE;
354 startable_flag = false;
355 state = JV_RUNNABLE;
356 _Jv_ThreadStart (this, nt->thread, (_Jv_ThreadStartFunc *) &_Jv_ThreadRun);
359 void
360 java::lang::Thread::stop (java::lang::Throwable *)
362 checkAccess ();
364 // Old applets still call this method. Rather than throwing
365 // UnsupportedOperationException we simply fail silently.
368 void
369 java::lang::Thread::suspend (void)
371 checkAccess ();
373 // Old applets still call this method. Rather than throwing
374 // UnsupportedOperationException we simply fail silently.
377 static int nextThreadNumber = 0;
379 jstring
380 java::lang::Thread::gen_name (void)
382 jint i;
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-".
390 jchar buffer[7+11];
391 jchar *bufend = (jchar *) ((char *) buffer + sizeof(buffer));
392 i = _Jv_FormatInt (bufend, i);
393 jchar *ptr = bufend - i;
394 // Prepend "Thread-".
395 *--ptr = '-';
396 *--ptr = 'd';
397 *--ptr = 'a';
398 *--ptr = 'e';
399 *--ptr = 'r';
400 *--ptr = 'h';
401 *--ptr = 'T';
402 return JvNewString (ptr, bufend - ptr);
405 void
406 java::lang::Thread::yield (void)
408 _Jv_ThreadYield ();
411 ::java::lang::Thread$State *
412 java::lang::Thread::getState()
414 _Jv_InitClass(&::java::lang::Thread$State::class$);
416 switch (state)
418 case JV_BLOCKED:
419 return ::java::lang::Thread$State::BLOCKED;
420 case JV_NEW:
421 return ::java::lang::Thread$State::NEW;
423 case JV_RUNNABLE:
424 return ::java::lang::Thread$State::RUNNABLE;
425 case JV_TERMINATED:
426 return ::java::lang::Thread$State::TERMINATED;
427 case JV_TIMED_WAITING:
428 return ::java::lang::Thread$State::TIMED_WAITING;
429 case JV_WAITING:
430 return ::java::lang::Thread$State::WAITING;
433 // We don't really need a default, but this makes the compiler
434 // happy.
435 return ::java::lang::Thread$State::RUNNABLE;
438 JNIEnv *
439 _Jv_GetCurrentJNIEnv ()
441 java::lang::Thread *t = _Jv_ThreadCurrent ();
442 if (t == NULL)
443 return NULL;
444 return ((natThread *) t->data)->jni_env;
447 void
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.
458 jint
459 _Jv_AttachCurrentThread(java::lang::Thread* thread)
461 JvSynchronize sync (thread);
462 if (thread == NULL || thread->startable_flag == false)
463 return -1;
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);
469 return 0;
472 java::lang::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 ();
478 if (thread != NULL)
479 return thread;
480 if (name == NULL)
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);
485 return thread;
488 java::lang::Thread*
489 _Jv_AttachCurrentThreadAsDaemon(jstring name, java::lang::ThreadGroup* group)
491 java::lang::Thread *thread = _Jv_ThreadCurrent ();
492 if (thread != NULL)
493 return thread;
494 if (name == NULL)
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);
500 return thread;
503 jint
504 _Jv_DetachCurrentThread (void)
506 java::lang::Thread *t = _Jv_ThreadCurrent ();
507 if (t == NULL)
508 return -1;
510 _Jv_ThreadUnRegister ();
511 _Jv_GCDetachThread ();
512 // Release the monitors.
513 t->finish_ ();
515 return 0;