1999-04-07 16:42:40 +02:00
|
|
|
|
// natThread.cc - Native part of Thread class.
|
|
|
|
|
|
2007-01-17 02:36:33 +01:00
|
|
|
|
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2006, 2007 Free Software Foundation
|
1999-04-07 16:42:40 +02:00
|
|
|
|
|
|
|
|
|
This file is part of libgcj.
|
|
|
|
|
|
|
|
|
|
This software is copyrighted work licensed under the terms of the
|
|
|
|
|
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
|
|
|
|
details. */
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
1999-09-11 00:03:10 +02:00
|
|
|
|
#include <gcj/cni.h>
|
1999-04-07 16:42:40 +02:00
|
|
|
|
#include <jvm.h>
|
1999-09-11 00:03:10 +02:00
|
|
|
|
#include <java-threads.h>
|
|
|
|
|
|
2004-05-28 20:53:06 +02:00
|
|
|
|
#include <gnu/gcj/RawDataManaged.h>
|
1999-04-07 16:42:40 +02:00
|
|
|
|
#include <java/lang/Thread.h>
|
2007-01-09 20:58:05 +01:00
|
|
|
|
#include <java/lang/Thread$State.h>
|
|
|
|
|
#include <java/lang/Thread$UncaughtExceptionHandler.h>
|
1999-04-07 16:42:40 +02:00
|
|
|
|
#include <java/lang/ThreadGroup.h>
|
|
|
|
|
#include <java/lang/IllegalArgumentException.h>
|
|
|
|
|
#include <java/lang/IllegalThreadStateException.h>
|
|
|
|
|
#include <java/lang/InterruptedException.h>
|
|
|
|
|
#include <java/lang/NullPointerException.h>
|
2000-02-10 21:31:48 +01:00
|
|
|
|
|
|
|
|
|
#include <jni.h>
|
2007-01-17 23:05:10 +01:00
|
|
|
|
#include <jvmti.h>
|
|
|
|
|
#include "jvmti-int.h"
|
1999-04-07 16:42:40 +02:00
|
|
|
|
|
2000-04-02 17:34:17 +02:00
|
|
|
|
#ifdef ENABLE_JVMPI
|
|
|
|
|
#include <jvmpi.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
1999-04-07 16:42:40 +02:00
|
|
|
|
|
|
|
|
|
|
2000-12-30 13:18:39 +01:00
|
|
|
|
static void finalize_native (jobject ptr);
|
|
|
|
|
|
1999-04-07 16:42:40 +02:00
|
|
|
|
// This is called from the constructor to initialize the native side
|
|
|
|
|
// of the Thread.
|
|
|
|
|
void
|
|
|
|
|
java::lang::Thread::initialize_native (void)
|
|
|
|
|
{
|
|
|
|
|
natThread *nt = (natThread *) _Jv_AllocBytes (sizeof (natThread));
|
2000-12-30 13:18:39 +01:00
|
|
|
|
|
2007-01-09 20:58:05 +01:00
|
|
|
|
state = JV_NEW;
|
|
|
|
|
nt->alive_flag = THREAD_DEAD;
|
|
|
|
|
|
2004-05-28 20:53:06 +02:00
|
|
|
|
data = (gnu::gcj::RawDataManaged *) nt;
|
2000-12-30 13:18:39 +01:00
|
|
|
|
|
|
|
|
|
// Register a finalizer to clean up the native thread resources.
|
|
|
|
|
_Jv_RegisterFinalizer (data, finalize_native);
|
|
|
|
|
|
2000-03-28 04:22:24 +02:00
|
|
|
|
_Jv_MutexInit (&nt->join_mutex);
|
|
|
|
|
_Jv_CondInit (&nt->join_cond);
|
2007-01-09 20:58:05 +01:00
|
|
|
|
|
|
|
|
|
nt->park_helper.init();
|
|
|
|
|
|
2000-12-30 13:18:39 +01:00
|
|
|
|
nt->thread = _Jv_ThreadInitData (this);
|
2000-02-10 21:31:48 +01:00
|
|
|
|
// FIXME: if JNI_ENV is set we will want to free it. It is
|
|
|
|
|
// malloc()d.
|
|
|
|
|
nt->jni_env = NULL;
|
1999-04-07 16:42:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
2000-12-30 13:18:39 +01:00
|
|
|
|
static void
|
|
|
|
|
finalize_native (jobject ptr)
|
|
|
|
|
{
|
|
|
|
|
natThread *nt = (natThread *) ptr;
|
|
|
|
|
_Jv_ThreadDestroyData (nt->thread);
|
2004-09-11 21:10:44 +02:00
|
|
|
|
#ifdef _Jv_HaveCondDestroy
|
|
|
|
|
_Jv_CondDestroy (&nt->join_cond);
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef _Jv_HaveMutexDestroy
|
|
|
|
|
_Jv_MutexDestroy (&nt->join_mutex);
|
|
|
|
|
#endif
|
2007-01-09 20:58:05 +01:00
|
|
|
|
_Jv_FreeJNIEnv((JNIEnv*)nt->jni_env);
|
|
|
|
|
|
|
|
|
|
nt->park_helper.destroy();
|
2000-12-30 13:18:39 +01:00
|
|
|
|
}
|
|
|
|
|
|
1999-04-07 16:42:40 +02:00
|
|
|
|
jint
|
|
|
|
|
java::lang::Thread::countStackFrames (void)
|
|
|
|
|
{
|
|
|
|
|
// NOTE: This is deprecated in JDK 1.2.
|
2006-05-30 00:04:13 +02:00
|
|
|
|
|
|
|
|
|
// Old applets still call this method. Rather than throwing
|
|
|
|
|
// UnsupportedOperationException we simply fail silently.
|
|
|
|
|
|
1999-04-07 16:42:40 +02:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
java::lang::Thread *
|
|
|
|
|
java::lang::Thread::currentThread (void)
|
|
|
|
|
{
|
|
|
|
|
return _Jv_ThreadCurrent ();
|
|
|
|
|
}
|
|
|
|
|
|
2003-10-21 06:46:19 +02:00
|
|
|
|
jboolean
|
|
|
|
|
java::lang::Thread::holdsLock (jobject obj)
|
|
|
|
|
{
|
|
|
|
|
if (!obj)
|
|
|
|
|
throw new NullPointerException;
|
|
|
|
|
return !_Jv_ObjectCheckMonitor (obj);
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-09 20:58:05 +01:00
|
|
|
|
jboolean
|
|
|
|
|
java::lang::Thread::isAlive (void)
|
|
|
|
|
{
|
|
|
|
|
natThread *nt = (natThread *) data;
|
|
|
|
|
return nt->alive_flag != (obj_addr_t)THREAD_DEAD;
|
|
|
|
|
}
|
|
|
|
|
|
1999-04-07 16:42:40 +02:00
|
|
|
|
void
|
|
|
|
|
java::lang::Thread::interrupt (void)
|
|
|
|
|
{
|
2005-01-13 21:26:38 +01:00
|
|
|
|
checkAccess ();
|
2007-01-09 20:58:05 +01:00
|
|
|
|
|
1999-04-07 16:42:40 +02:00
|
|
|
|
natThread *nt = (natThread *) data;
|
2007-01-09 20:58:05 +01:00
|
|
|
|
|
|
|
|
|
// If a thread is in state ALIVE, we atomically set it to state
|
|
|
|
|
// SIGNALED and send it a signal. Once we've sent it the signal, we
|
|
|
|
|
// set its state back to ALIVE.
|
|
|
|
|
if (compare_and_swap
|
|
|
|
|
(&nt->alive_flag, Thread::THREAD_ALIVE, Thread::THREAD_SIGNALED))
|
|
|
|
|
{
|
|
|
|
|
_Jv_ThreadInterrupt (nt->thread);
|
|
|
|
|
compare_and_swap
|
|
|
|
|
(&nt->alive_flag, THREAD_SIGNALED, Thread::THREAD_ALIVE);
|
|
|
|
|
|
|
|
|
|
// Even though we've interrupted this thread, it might still be
|
|
|
|
|
// parked.
|
|
|
|
|
nt->park_helper.unpark ();
|
|
|
|
|
}
|
1999-04-07 16:42:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
java::lang::Thread::join (jlong millis, jint nanos)
|
|
|
|
|
{
|
|
|
|
|
if (millis < 0 || nanos < 0 || nanos > 999999)
|
exception.cc (java_eh_info): Make value type jthrowable.
* exception.cc (java_eh_info): Make value type jthrowable.
(_Jv_type_matcher): Remove now unneeded cast.
(_Jv_Throw): Make argument type jthrowable. Munge name
for SJLJ_EXCEPTIONS here ...
* gcj/cni.h: ... not here.
(JvThrow): Remove.
* gcj/javaprims.h (_Jv_Throw, _Jv_Sjlj_Throw): Update declarations.
* defineclass.cc, interpret.cc, jni.cc, posix-threads.cc,
prims.cc, resolve.cc, gnu/gcj/runtime/natFirstThread.cc,
gnu/gcj/xlib/natDrawable.cc, gnu/gcj/xlib/natFont.cc,
gnu/gcj/xlib/natWMSizeHints.cc, gnu/gcj/xlib/natWindowAttributes.cc,
gnu/gcj/xlib/natXImage.cc, java/io/natFile.cc,
java/io/natFileDescriptorEcos.cc, java/io/natFileDescriptorPosix.cc,
java/io/natFileDescriptorWin32.cc, java/io/natFileWin32.cc,
java/lang/natClass.cc, java/lang/natClassLoader.cc,
java/lang/natDouble.cc, java/lang/natObject.cc,
java/lang/natPosixProcess.cc, java/lang/natRuntime.cc,
java/lang/natString.cc, java/lang/natSystem.cc,
java/lang/natThread.cc, java/lang/reflect/natArray.cc,
java/lang/reflect/natConstructor.cc, java/lang/reflect/natField.cc,
java/lang/reflect/natMethod.cc, java/util/zip/natDeflater.cc,
java/util/zip/natInflater.cc:
Use throw, not JvThrow or _Jv_Throw.
From-SVN: r40838
2001-03-26 09:05:32 +02:00
|
|
|
|
throw new IllegalArgumentException;
|
1999-04-07 16:42:40 +02:00
|
|
|
|
|
|
|
|
|
Thread *current = currentThread ();
|
|
|
|
|
|
2000-03-28 04:22:24 +02:00
|
|
|
|
// Here `NT' is the native structure for the thread we are trying to join.
|
1999-04-07 16:42:40 +02:00
|
|
|
|
natThread *nt = (natThread *) data;
|
|
|
|
|
|
|
|
|
|
// Now wait for: (1) an interrupt, (2) the thread to exit, or (3)
|
2000-03-28 04:22:24 +02:00
|
|
|
|
// the timeout to occur.
|
|
|
|
|
_Jv_MutexLock (&nt->join_mutex);
|
|
|
|
|
if (! isAlive ())
|
1999-04-07 16:42:40 +02:00
|
|
|
|
{
|
2000-03-28 04:22:24 +02:00
|
|
|
|
_Jv_MutexUnlock (&nt->join_mutex);
|
|
|
|
|
return;
|
1999-04-07 16:42:40 +02:00
|
|
|
|
}
|
2000-03-28 04:22:24 +02:00
|
|
|
|
_Jv_CondWait (&nt->join_cond, &nt->join_mutex, millis, nanos);
|
|
|
|
|
_Jv_MutexUnlock (&nt->join_mutex);
|
1999-04-07 16:42:40 +02:00
|
|
|
|
|
2000-03-28 04:22:24 +02:00
|
|
|
|
if (current->isInterrupted (true))
|
exception.cc (java_eh_info): Make value type jthrowable.
* exception.cc (java_eh_info): Make value type jthrowable.
(_Jv_type_matcher): Remove now unneeded cast.
(_Jv_Throw): Make argument type jthrowable. Munge name
for SJLJ_EXCEPTIONS here ...
* gcj/cni.h: ... not here.
(JvThrow): Remove.
* gcj/javaprims.h (_Jv_Throw, _Jv_Sjlj_Throw): Update declarations.
* defineclass.cc, interpret.cc, jni.cc, posix-threads.cc,
prims.cc, resolve.cc, gnu/gcj/runtime/natFirstThread.cc,
gnu/gcj/xlib/natDrawable.cc, gnu/gcj/xlib/natFont.cc,
gnu/gcj/xlib/natWMSizeHints.cc, gnu/gcj/xlib/natWindowAttributes.cc,
gnu/gcj/xlib/natXImage.cc, java/io/natFile.cc,
java/io/natFileDescriptorEcos.cc, java/io/natFileDescriptorPosix.cc,
java/io/natFileDescriptorWin32.cc, java/io/natFileWin32.cc,
java/lang/natClass.cc, java/lang/natClassLoader.cc,
java/lang/natDouble.cc, java/lang/natObject.cc,
java/lang/natPosixProcess.cc, java/lang/natRuntime.cc,
java/lang/natString.cc, java/lang/natSystem.cc,
java/lang/natThread.cc, java/lang/reflect/natArray.cc,
java/lang/reflect/natConstructor.cc, java/lang/reflect/natField.cc,
java/lang/reflect/natMethod.cc, java/util/zip/natDeflater.cc,
java/util/zip/natInflater.cc:
Use throw, not JvThrow or _Jv_Throw.
From-SVN: r40838
2001-03-26 09:05:32 +02:00
|
|
|
|
throw new InterruptedException;
|
1999-04-07 16:42:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
java::lang::Thread::resume (void)
|
|
|
|
|
{
|
|
|
|
|
checkAccess ();
|
2006-05-30 00:04:13 +02:00
|
|
|
|
|
|
|
|
|
// Old applets still call this method. Rather than throwing
|
|
|
|
|
// UnsupportedOperationException we simply fail silently.
|
1999-04-07 16:42:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
java::lang::Thread::setPriority (jint newPriority)
|
|
|
|
|
{
|
|
|
|
|
checkAccess ();
|
|
|
|
|
if (newPriority < MIN_PRIORITY || newPriority > MAX_PRIORITY)
|
exception.cc (java_eh_info): Make value type jthrowable.
* exception.cc (java_eh_info): Make value type jthrowable.
(_Jv_type_matcher): Remove now unneeded cast.
(_Jv_Throw): Make argument type jthrowable. Munge name
for SJLJ_EXCEPTIONS here ...
* gcj/cni.h: ... not here.
(JvThrow): Remove.
* gcj/javaprims.h (_Jv_Throw, _Jv_Sjlj_Throw): Update declarations.
* defineclass.cc, interpret.cc, jni.cc, posix-threads.cc,
prims.cc, resolve.cc, gnu/gcj/runtime/natFirstThread.cc,
gnu/gcj/xlib/natDrawable.cc, gnu/gcj/xlib/natFont.cc,
gnu/gcj/xlib/natWMSizeHints.cc, gnu/gcj/xlib/natWindowAttributes.cc,
gnu/gcj/xlib/natXImage.cc, java/io/natFile.cc,
java/io/natFileDescriptorEcos.cc, java/io/natFileDescriptorPosix.cc,
java/io/natFileDescriptorWin32.cc, java/io/natFileWin32.cc,
java/lang/natClass.cc, java/lang/natClassLoader.cc,
java/lang/natDouble.cc, java/lang/natObject.cc,
java/lang/natPosixProcess.cc, java/lang/natRuntime.cc,
java/lang/natString.cc, java/lang/natSystem.cc,
java/lang/natThread.cc, java/lang/reflect/natArray.cc,
java/lang/reflect/natConstructor.cc, java/lang/reflect/natField.cc,
java/lang/reflect/natMethod.cc, java/util/zip/natDeflater.cc,
java/util/zip/natInflater.cc:
Use throw, not JvThrow or _Jv_Throw.
From-SVN: r40838
2001-03-26 09:05:32 +02:00
|
|
|
|
throw new IllegalArgumentException;
|
1999-04-07 16:42:40 +02:00
|
|
|
|
|
|
|
|
|
jint gmax = group->getMaxPriority();
|
|
|
|
|
if (newPriority > gmax)
|
|
|
|
|
newPriority = gmax;
|
|
|
|
|
|
|
|
|
|
priority = newPriority;
|
|
|
|
|
natThread *nt = (natThread *) data;
|
|
|
|
|
_Jv_ThreadSetPriority (nt->thread, priority);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
java::lang::Thread::sleep (jlong millis, jint nanos)
|
|
|
|
|
{
|
|
|
|
|
if (millis < 0 || nanos < 0 || nanos > 999999)
|
exception.cc (java_eh_info): Make value type jthrowable.
* exception.cc (java_eh_info): Make value type jthrowable.
(_Jv_type_matcher): Remove now unneeded cast.
(_Jv_Throw): Make argument type jthrowable. Munge name
for SJLJ_EXCEPTIONS here ...
* gcj/cni.h: ... not here.
(JvThrow): Remove.
* gcj/javaprims.h (_Jv_Throw, _Jv_Sjlj_Throw): Update declarations.
* defineclass.cc, interpret.cc, jni.cc, posix-threads.cc,
prims.cc, resolve.cc, gnu/gcj/runtime/natFirstThread.cc,
gnu/gcj/xlib/natDrawable.cc, gnu/gcj/xlib/natFont.cc,
gnu/gcj/xlib/natWMSizeHints.cc, gnu/gcj/xlib/natWindowAttributes.cc,
gnu/gcj/xlib/natXImage.cc, java/io/natFile.cc,
java/io/natFileDescriptorEcos.cc, java/io/natFileDescriptorPosix.cc,
java/io/natFileDescriptorWin32.cc, java/io/natFileWin32.cc,
java/lang/natClass.cc, java/lang/natClassLoader.cc,
java/lang/natDouble.cc, java/lang/natObject.cc,
java/lang/natPosixProcess.cc, java/lang/natRuntime.cc,
java/lang/natString.cc, java/lang/natSystem.cc,
java/lang/natThread.cc, java/lang/reflect/natArray.cc,
java/lang/reflect/natConstructor.cc, java/lang/reflect/natField.cc,
java/lang/reflect/natMethod.cc, java/util/zip/natDeflater.cc,
java/util/zip/natInflater.cc:
Use throw, not JvThrow or _Jv_Throw.
From-SVN: r40838
2001-03-26 09:05:32 +02:00
|
|
|
|
throw new IllegalArgumentException;
|
1999-04-07 16:42:40 +02:00
|
|
|
|
|
1999-08-18 05:48:37 +02:00
|
|
|
|
if (millis == 0 && nanos == 0)
|
|
|
|
|
++nanos;
|
|
|
|
|
|
1999-04-07 16:42:40 +02:00
|
|
|
|
Thread *current = currentThread ();
|
|
|
|
|
|
|
|
|
|
// We use a condition variable to implement sleeping so that an
|
2000-03-28 04:22:24 +02:00
|
|
|
|
// interrupt can wake us up.
|
1999-04-07 16:42:40 +02:00
|
|
|
|
natThread *nt = (natThread *) current->data;
|
2000-03-28 04:22:24 +02:00
|
|
|
|
_Jv_MutexLock (&nt->join_mutex);
|
|
|
|
|
_Jv_CondWait (&nt->join_cond, &nt->join_mutex, millis, nanos);
|
|
|
|
|
_Jv_MutexUnlock (&nt->join_mutex);
|
|
|
|
|
|
|
|
|
|
if (current->isInterrupted (true))
|
exception.cc (java_eh_info): Make value type jthrowable.
* exception.cc (java_eh_info): Make value type jthrowable.
(_Jv_type_matcher): Remove now unneeded cast.
(_Jv_Throw): Make argument type jthrowable. Munge name
for SJLJ_EXCEPTIONS here ...
* gcj/cni.h: ... not here.
(JvThrow): Remove.
* gcj/javaprims.h (_Jv_Throw, _Jv_Sjlj_Throw): Update declarations.
* defineclass.cc, interpret.cc, jni.cc, posix-threads.cc,
prims.cc, resolve.cc, gnu/gcj/runtime/natFirstThread.cc,
gnu/gcj/xlib/natDrawable.cc, gnu/gcj/xlib/natFont.cc,
gnu/gcj/xlib/natWMSizeHints.cc, gnu/gcj/xlib/natWindowAttributes.cc,
gnu/gcj/xlib/natXImage.cc, java/io/natFile.cc,
java/io/natFileDescriptorEcos.cc, java/io/natFileDescriptorPosix.cc,
java/io/natFileDescriptorWin32.cc, java/io/natFileWin32.cc,
java/lang/natClass.cc, java/lang/natClassLoader.cc,
java/lang/natDouble.cc, java/lang/natObject.cc,
java/lang/natPosixProcess.cc, java/lang/natRuntime.cc,
java/lang/natString.cc, java/lang/natSystem.cc,
java/lang/natThread.cc, java/lang/reflect/natArray.cc,
java/lang/reflect/natConstructor.cc, java/lang/reflect/natField.cc,
java/lang/reflect/natMethod.cc, java/util/zip/natDeflater.cc,
java/util/zip/natInflater.cc:
Use throw, not JvThrow or _Jv_Throw.
From-SVN: r40838
2001-03-26 09:05:32 +02:00
|
|
|
|
throw new InterruptedException;
|
1999-04-07 16:42:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2000-03-02 21:25:20 +01:00
|
|
|
|
java::lang::Thread::finish_ ()
|
1999-04-07 16:42:40 +02:00
|
|
|
|
{
|
2007-01-09 20:58:05 +01:00
|
|
|
|
__sync_synchronize();
|
1999-04-07 16:42:40 +02:00
|
|
|
|
natThread *nt = (natThread *) data;
|
2000-03-28 04:22:24 +02:00
|
|
|
|
|
2007-01-09 20:58:05 +01:00
|
|
|
|
nt->park_helper.deactivate ();
|
2000-06-21 05:55:35 +02:00
|
|
|
|
group->removeThread (this);
|
2000-04-02 17:34:17 +02:00
|
|
|
|
|
2007-01-17 23:05:10 +01:00
|
|
|
|
if (JVMTI_REQUESTED_EVENT (ThreadEnd))
|
|
|
|
|
_Jv_JVMTI_PostEvent (JVMTI_EVENT_THREAD_END, this, nt->jni_env);
|
|
|
|
|
|
2000-04-02 17:34:17 +02:00
|
|
|
|
#ifdef ENABLE_JVMPI
|
|
|
|
|
if (_Jv_JVMPI_Notify_THREAD_END)
|
|
|
|
|
{
|
|
|
|
|
JVMPI_Event event;
|
|
|
|
|
|
|
|
|
|
event.event_type = JVMPI_EVENT_THREAD_END;
|
|
|
|
|
event.env_id = _Jv_GetCurrentJNIEnv ();
|
|
|
|
|
|
|
|
|
|
_Jv_DisableGC ();
|
|
|
|
|
(*_Jv_JVMPI_Notify_THREAD_END) (&event);
|
|
|
|
|
_Jv_EnableGC ();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-09-27 22:03:09 +02:00
|
|
|
|
// If a method cache was created, free it.
|
|
|
|
|
_Jv_FreeMethodCache();
|
|
|
|
|
|
2006-05-13 04:16:22 +02:00
|
|
|
|
// Clear out thread locals.
|
|
|
|
|
locals = NULL;
|
|
|
|
|
|
2000-03-28 04:22:24 +02:00
|
|
|
|
// Signal any threads that are waiting to join() us.
|
|
|
|
|
_Jv_MutexLock (&nt->join_mutex);
|
2005-06-29 19:36:16 +02:00
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
JvSynchronize sync (this);
|
2007-01-09 20:58:05 +01:00
|
|
|
|
nt->alive_flag = THREAD_DEAD;
|
|
|
|
|
state = JV_TERMINATED;
|
2005-06-29 19:36:16 +02:00
|
|
|
|
}
|
|
|
|
|
|
2000-03-28 04:22:24 +02:00
|
|
|
|
_Jv_CondNotifyAll (&nt->join_cond, &nt->join_mutex);
|
|
|
|
|
_Jv_MutexUnlock (&nt->join_mutex);
|
1999-04-07 16:42:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
2001-08-26 13:30:09 +02:00
|
|
|
|
// Run once at thread startup, either when thread is attached or when
|
|
|
|
|
// _Jv_ThreadRun is called.
|
|
|
|
|
static void
|
|
|
|
|
_Jv_NotifyThreadStart (java::lang::Thread* thread)
|
1999-04-07 16:42:40 +02:00
|
|
|
|
{
|
2007-01-17 23:05:10 +01:00
|
|
|
|
if (JVMTI_REQUESTED_EVENT (ThreadStart))
|
|
|
|
|
{
|
|
|
|
|
natThread *nt = reinterpret_cast<natThread *> (thread->data);
|
|
|
|
|
_Jv_JVMTI_PostEvent (JVMTI_EVENT_THREAD_START, thread, nt->jni_env);
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-02 17:34:17 +02:00
|
|
|
|
#ifdef ENABLE_JVMPI
|
|
|
|
|
if (_Jv_JVMPI_Notify_THREAD_START)
|
|
|
|
|
{
|
|
|
|
|
JVMPI_Event event;
|
|
|
|
|
|
|
|
|
|
jstring thread_name = thread->getName ();
|
|
|
|
|
jstring group_name = NULL, parent_name = NULL;
|
|
|
|
|
java::lang::ThreadGroup *group = thread->getThreadGroup ();
|
|
|
|
|
|
|
|
|
|
if (group)
|
|
|
|
|
{
|
|
|
|
|
group_name = group->getName ();
|
|
|
|
|
group = group->getParent ();
|
|
|
|
|
|
|
|
|
|
if (group)
|
|
|
|
|
parent_name = group->getName ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int thread_len = thread_name ? JvGetStringUTFLength (thread_name) : 0;
|
|
|
|
|
int group_len = group_name ? JvGetStringUTFLength (group_name) : 0;
|
|
|
|
|
int parent_len = parent_name ? JvGetStringUTFLength (parent_name) : 0;
|
|
|
|
|
|
|
|
|
|
char thread_chars[thread_len + 1];
|
|
|
|
|
char group_chars[group_len + 1];
|
|
|
|
|
char parent_chars[parent_len + 1];
|
|
|
|
|
|
|
|
|
|
if (thread_name)
|
|
|
|
|
JvGetStringUTFRegion (thread_name, 0,
|
|
|
|
|
thread_name->length(), thread_chars);
|
|
|
|
|
if (group_name)
|
|
|
|
|
JvGetStringUTFRegion (group_name, 0,
|
|
|
|
|
group_name->length(), group_chars);
|
|
|
|
|
if (parent_name)
|
|
|
|
|
JvGetStringUTFRegion (parent_name, 0,
|
|
|
|
|
parent_name->length(), parent_chars);
|
|
|
|
|
|
|
|
|
|
thread_chars[thread_len] = '\0';
|
|
|
|
|
group_chars[group_len] = '\0';
|
|
|
|
|
parent_chars[parent_len] = '\0';
|
|
|
|
|
|
|
|
|
|
event.event_type = JVMPI_EVENT_THREAD_START;
|
|
|
|
|
event.env_id = NULL;
|
|
|
|
|
event.u.thread_start.thread_name = thread_chars;
|
|
|
|
|
event.u.thread_start.group_name = group_chars;
|
|
|
|
|
event.u.thread_start.parent_name = parent_chars;
|
|
|
|
|
event.u.thread_start.thread_id = (jobjectID) thread;
|
|
|
|
|
event.u.thread_start.thread_env_id = _Jv_GetCurrentJNIEnv ();
|
|
|
|
|
|
|
|
|
|
_Jv_DisableGC ();
|
|
|
|
|
(*_Jv_JVMPI_Notify_THREAD_START) (&event);
|
|
|
|
|
_Jv_EnableGC ();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2001-08-26 13:30:09 +02:00
|
|
|
|
}
|
2000-04-02 17:34:17 +02:00
|
|
|
|
|
2001-08-26 13:30:09 +02:00
|
|
|
|
void
|
|
|
|
|
_Jv_ThreadRun (java::lang::Thread* thread)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
_Jv_NotifyThreadStart (thread);
|
2000-03-02 21:25:20 +01:00
|
|
|
|
thread->run ();
|
|
|
|
|
}
|
|
|
|
|
catch (java::lang::Throwable *t)
|
|
|
|
|
{
|
|
|
|
|
// Uncaught exceptions are forwarded to the ThreadGroup. If
|
|
|
|
|
// this results in an uncaught exception, that is ignored.
|
|
|
|
|
try
|
|
|
|
|
{
|
2007-01-09 20:58:05 +01:00
|
|
|
|
thread->getUncaughtExceptionHandler()->uncaughtException (thread, t);
|
2000-03-02 21:25:20 +01:00
|
|
|
|
}
|
|
|
|
|
catch (java::lang::Throwable *f)
|
|
|
|
|
{
|
|
|
|
|
// Nothing.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
thread->finish_ ();
|
1999-04-07 16:42:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
2006-07-21 20:50:48 +02:00
|
|
|
|
_Jv_Thread_t*
|
|
|
|
|
_Jv_ThreadGetData (java::lang::Thread* thread)
|
|
|
|
|
{
|
|
|
|
|
natThread* nt = (natThread*) thread->data;
|
|
|
|
|
return nt->thread;
|
|
|
|
|
}
|
|
|
|
|
|
1999-04-07 16:42:40 +02:00
|
|
|
|
void
|
|
|
|
|
java::lang::Thread::start (void)
|
|
|
|
|
{
|
|
|
|
|
JvSynchronize sync (this);
|
|
|
|
|
|
2000-03-28 04:22:24 +02:00
|
|
|
|
// Its illegal to re-start() a thread, even if its dead.
|
|
|
|
|
if (!startable_flag)
|
exception.cc (java_eh_info): Make value type jthrowable.
* exception.cc (java_eh_info): Make value type jthrowable.
(_Jv_type_matcher): Remove now unneeded cast.
(_Jv_Throw): Make argument type jthrowable. Munge name
for SJLJ_EXCEPTIONS here ...
* gcj/cni.h: ... not here.
(JvThrow): Remove.
* gcj/javaprims.h (_Jv_Throw, _Jv_Sjlj_Throw): Update declarations.
* defineclass.cc, interpret.cc, jni.cc, posix-threads.cc,
prims.cc, resolve.cc, gnu/gcj/runtime/natFirstThread.cc,
gnu/gcj/xlib/natDrawable.cc, gnu/gcj/xlib/natFont.cc,
gnu/gcj/xlib/natWMSizeHints.cc, gnu/gcj/xlib/natWindowAttributes.cc,
gnu/gcj/xlib/natXImage.cc, java/io/natFile.cc,
java/io/natFileDescriptorEcos.cc, java/io/natFileDescriptorPosix.cc,
java/io/natFileDescriptorWin32.cc, java/io/natFileWin32.cc,
java/lang/natClass.cc, java/lang/natClassLoader.cc,
java/lang/natDouble.cc, java/lang/natObject.cc,
java/lang/natPosixProcess.cc, java/lang/natRuntime.cc,
java/lang/natString.cc, java/lang/natSystem.cc,
java/lang/natThread.cc, java/lang/reflect/natArray.cc,
java/lang/reflect/natConstructor.cc, java/lang/reflect/natField.cc,
java/lang/reflect/natMethod.cc, java/util/zip/natDeflater.cc,
java/util/zip/natInflater.cc:
Use throw, not JvThrow or _Jv_Throw.
From-SVN: r40838
2001-03-26 09:05:32 +02:00
|
|
|
|
throw new IllegalThreadStateException;
|
1999-04-07 16:42:40 +02:00
|
|
|
|
|
|
|
|
|
natThread *nt = (natThread *) data;
|
2007-01-09 20:58:05 +01:00
|
|
|
|
nt->alive_flag = THREAD_ALIVE;
|
|
|
|
|
startable_flag = false;
|
|
|
|
|
state = JV_RUNNABLE;
|
2001-08-26 13:30:09 +02:00
|
|
|
|
_Jv_ThreadStart (this, nt->thread, (_Jv_ThreadStartFunc *) &_Jv_ThreadRun);
|
1999-04-07 16:42:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
1999-11-05 18:10:17 +01:00
|
|
|
|
java::lang::Thread::stop (java::lang::Throwable *)
|
1999-04-07 16:42:40 +02:00
|
|
|
|
{
|
2005-01-13 21:26:38 +01:00
|
|
|
|
checkAccess ();
|
2006-05-30 00:04:13 +02:00
|
|
|
|
|
|
|
|
|
// Old applets still call this method. Rather than throwing
|
|
|
|
|
// UnsupportedOperationException we simply fail silently.
|
1999-04-07 16:42:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
java::lang::Thread::suspend (void)
|
|
|
|
|
{
|
|
|
|
|
checkAccess ();
|
2006-05-30 00:04:13 +02:00
|
|
|
|
|
|
|
|
|
// Old applets still call this method. Rather than throwing
|
|
|
|
|
// UnsupportedOperationException we simply fail silently.
|
1999-04-07 16:42:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
2001-05-22 08:47:48 +02:00
|
|
|
|
static int nextThreadNumber = 0;
|
|
|
|
|
|
|
|
|
|
jstring
|
|
|
|
|
java::lang::Thread::gen_name (void)
|
|
|
|
|
{
|
|
|
|
|
jint i;
|
|
|
|
|
jclass sync = &java::lang::Thread::class$;
|
|
|
|
|
{
|
|
|
|
|
JvSynchronize dummy(sync);
|
|
|
|
|
i = ++nextThreadNumber;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Use an array large enough for "-2147483648"; i.e. 11 chars, + "Thread-".
|
|
|
|
|
jchar buffer[7+11];
|
|
|
|
|
jchar *bufend = (jchar *) ((char *) buffer + sizeof(buffer));
|
|
|
|
|
i = _Jv_FormatInt (bufend, i);
|
|
|
|
|
jchar *ptr = bufend - i;
|
|
|
|
|
// Prepend "Thread-".
|
|
|
|
|
*--ptr = '-';
|
|
|
|
|
*--ptr = 'd';
|
|
|
|
|
*--ptr = 'a';
|
|
|
|
|
*--ptr = 'e';
|
|
|
|
|
*--ptr = 'r';
|
|
|
|
|
*--ptr = 'h';
|
|
|
|
|
*--ptr = 'T';
|
|
|
|
|
return JvNewString (ptr, bufend - ptr);
|
|
|
|
|
}
|
|
|
|
|
|
1999-04-07 16:42:40 +02:00
|
|
|
|
void
|
|
|
|
|
java::lang::Thread::yield (void)
|
|
|
|
|
{
|
|
|
|
|
_Jv_ThreadYield ();
|
|
|
|
|
}
|
2000-02-10 21:31:48 +01:00
|
|
|
|
|
2007-01-09 20:58:05 +01:00
|
|
|
|
::java::lang::Thread$State *
|
|
|
|
|
java::lang::Thread::getState()
|
|
|
|
|
{
|
|
|
|
|
_Jv_InitClass(&::java::lang::Thread$State::class$);
|
|
|
|
|
|
|
|
|
|
switch (state)
|
|
|
|
|
{
|
|
|
|
|
case JV_BLOCKED:
|
|
|
|
|
return ::java::lang::Thread$State::BLOCKED;
|
|
|
|
|
case JV_NEW:
|
|
|
|
|
return ::java::lang::Thread$State::NEW;
|
|
|
|
|
|
|
|
|
|
case JV_RUNNABLE:
|
|
|
|
|
return ::java::lang::Thread$State::RUNNABLE;
|
|
|
|
|
case JV_TERMINATED:
|
|
|
|
|
return ::java::lang::Thread$State::TERMINATED;
|
|
|
|
|
case JV_TIMED_WAITING:
|
|
|
|
|
return ::java::lang::Thread$State::TIMED_WAITING;
|
|
|
|
|
case JV_WAITING:
|
|
|
|
|
return ::java::lang::Thread$State::WAITING;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We don't really need a default, but this makes the compiler
|
|
|
|
|
// happy.
|
|
|
|
|
return ::java::lang::Thread$State::RUNNABLE;
|
|
|
|
|
}
|
|
|
|
|
|
2000-02-10 21:31:48 +01:00
|
|
|
|
JNIEnv *
|
|
|
|
|
_Jv_GetCurrentJNIEnv ()
|
|
|
|
|
{
|
|
|
|
|
java::lang::Thread *t = _Jv_ThreadCurrent ();
|
|
|
|
|
if (t == NULL)
|
|
|
|
|
return NULL;
|
2007-01-17 02:36:33 +01:00
|
|
|
|
return ((natThread *) t->data)->jni_env;
|
2000-02-10 21:31:48 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
_Jv_SetCurrentJNIEnv (JNIEnv *env)
|
|
|
|
|
{
|
|
|
|
|
java::lang::Thread *t = _Jv_ThreadCurrent ();
|
|
|
|
|
JvAssert (t != NULL);
|
|
|
|
|
((natThread *) t->data)->jni_env = env;
|
|
|
|
|
}
|
2001-05-22 08:47:48 +02:00
|
|
|
|
|
2001-08-26 13:30:09 +02:00
|
|
|
|
// Attach the current native thread to an existing (but unstarted) Thread
|
2006-08-22 00:07:30 +02:00
|
|
|
|
// object. Does not register thread with the garbage collector.
|
|
|
|
|
// Returns -1 on failure, 0 upon success.
|
2001-08-26 13:30:09 +02:00
|
|
|
|
jint
|
|
|
|
|
_Jv_AttachCurrentThread(java::lang::Thread* thread)
|
|
|
|
|
{
|
2005-06-29 19:36:16 +02:00
|
|
|
|
JvSynchronize sync (thread);
|
2001-08-26 13:30:09 +02:00
|
|
|
|
if (thread == NULL || thread->startable_flag == false)
|
|
|
|
|
return -1;
|
|
|
|
|
thread->startable_flag = false;
|
|
|
|
|
natThread *nt = (natThread *) thread->data;
|
2007-01-09 20:58:05 +01:00
|
|
|
|
nt->alive_flag = ::java::lang::Thread::THREAD_ALIVE;
|
|
|
|
|
thread->state = JV_RUNNABLE;
|
2001-08-26 13:30:09 +02:00
|
|
|
|
_Jv_ThreadRegister (nt->thread);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2001-05-22 08:47:48 +02:00
|
|
|
|
java::lang::Thread*
|
|
|
|
|
_Jv_AttachCurrentThread(jstring name, java::lang::ThreadGroup* group)
|
|
|
|
|
{
|
2006-08-22 00:07:30 +02:00
|
|
|
|
// Register thread with GC before attempting any allocations.
|
|
|
|
|
_Jv_GCAttachThread ();
|
2001-05-22 08:47:48 +02:00
|
|
|
|
java::lang::Thread *thread = _Jv_ThreadCurrent ();
|
|
|
|
|
if (thread != NULL)
|
|
|
|
|
return thread;
|
|
|
|
|
if (name == NULL)
|
|
|
|
|
name = java::lang::Thread::gen_name ();
|
Thread.java (Thread(ThreadGroup, Runnable, String)): Pass new parameter constructor.
* java/lang/Thread.java (Thread(ThreadGroup, Runnable, String)): Pass
new parameter constructor.
(Thread(ThreadGroup, Runnable, String, long)): Same.
(Thread(String, boolean)): New constructor.
(Thread(Thread, ThreadGroup, Runnable, String): Add parameter
noInheritableThreadLocal, don't call
InheritableThreadLocal.newChildThread if set.
* java/lang/PosixProcess.java(ProcessManager()): Set
noInheritableThreadLocal in super.
* java/lang/natThread.cc (_Jv_AttachCurrentThread): Pass new
parameter to Thread constructor.
(_Jv_AttachCurrentThreadAsDaemon): Same.
* java/lang/Thread.h: Regenerate.
* classpath/lib/java/lang/Thread.class: Same.
* classpath/lib/java/lang/PosixProcess$EOFInputStream.class: Same.
* classpath/lib/java/lang/PosixProcess.class: Same.
* classpath/lib/java/lang/Thread$State.class: Same.
* classpath/lib/java/lang/PosixProcess$ProcessManager.class: Same.
From-SVN: r122054
2007-02-16 22:23:10 +01:00
|
|
|
|
thread = new java::lang::Thread (NULL, group, NULL, name, false);
|
2001-08-26 13:30:09 +02:00
|
|
|
|
_Jv_AttachCurrentThread (thread);
|
|
|
|
|
_Jv_NotifyThreadStart (thread);
|
2001-05-22 08:47:48 +02:00
|
|
|
|
return thread;
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-10 22:36:04 +02:00
|
|
|
|
java::lang::Thread*
|
|
|
|
|
_Jv_AttachCurrentThreadAsDaemon(jstring name, java::lang::ThreadGroup* group)
|
|
|
|
|
{
|
|
|
|
|
java::lang::Thread *thread = _Jv_ThreadCurrent ();
|
|
|
|
|
if (thread != NULL)
|
|
|
|
|
return thread;
|
|
|
|
|
if (name == NULL)
|
|
|
|
|
name = java::lang::Thread::gen_name ();
|
Thread.java (Thread(ThreadGroup, Runnable, String)): Pass new parameter constructor.
* java/lang/Thread.java (Thread(ThreadGroup, Runnable, String)): Pass
new parameter constructor.
(Thread(ThreadGroup, Runnable, String, long)): Same.
(Thread(String, boolean)): New constructor.
(Thread(Thread, ThreadGroup, Runnable, String): Add parameter
noInheritableThreadLocal, don't call
InheritableThreadLocal.newChildThread if set.
* java/lang/PosixProcess.java(ProcessManager()): Set
noInheritableThreadLocal in super.
* java/lang/natThread.cc (_Jv_AttachCurrentThread): Pass new
parameter to Thread constructor.
(_Jv_AttachCurrentThreadAsDaemon): Same.
* java/lang/Thread.h: Regenerate.
* classpath/lib/java/lang/Thread.class: Same.
* classpath/lib/java/lang/PosixProcess$EOFInputStream.class: Same.
* classpath/lib/java/lang/PosixProcess.class: Same.
* classpath/lib/java/lang/Thread$State.class: Same.
* classpath/lib/java/lang/PosixProcess$ProcessManager.class: Same.
From-SVN: r122054
2007-02-16 22:23:10 +01:00
|
|
|
|
thread = new java::lang::Thread (NULL, group, NULL, name, false);
|
2002-04-10 22:36:04 +02:00
|
|
|
|
thread->setDaemon (true);
|
|
|
|
|
_Jv_AttachCurrentThread (thread);
|
|
|
|
|
_Jv_NotifyThreadStart (thread);
|
|
|
|
|
return thread;
|
|
|
|
|
}
|
|
|
|
|
|
2001-05-22 08:47:48 +02:00
|
|
|
|
jint
|
|
|
|
|
_Jv_DetachCurrentThread (void)
|
|
|
|
|
{
|
|
|
|
|
java::lang::Thread *t = _Jv_ThreadCurrent ();
|
|
|
|
|
if (t == NULL)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
_Jv_ThreadUnRegister ();
|
2006-08-22 00:07:30 +02:00
|
|
|
|
_Jv_GCDetachThread ();
|
2001-05-22 08:47:48 +02:00
|
|
|
|
// Release the monitors.
|
|
|
|
|
t->finish_ ();
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|