Commit c93d7fae by Per Bothner Committed by Per Bothner

Implement invocation interface; don't create new thread for main.

From-SVN: r42428
parent b4fbaca7
2001-05-21 Per Bothner <per@bothner.com> 2001-05-21 Per Bothner <per@bothner.com>
Implement invocation interface; don't create new thread for main.
* java/lang/Thread.java (gen_name): Make native.
(<init>(Thread,THreadGroup,Runnable,String)): New private
constructor, used by other constructors, and _Jv_AttachCurrentThread.
* java/lang/natThread.cc (gen_name): New implementation.
(_Jv_AttachCurrentThread, _Jv_DetachCurrentThread): New.
* prims.cc (main_init): Removed, replaced by _Jv_CreateJavaVM.
(_Jv_CreateJavaVM): New runtime initialization procedure.
(runFirst): New proecdure - mostly code from old FirstThread::run.
(JvRunMain, _Jv_RunMain): Re-write to use new invocation code.
* gcj/cni.h (JvCreateJavaVM, JvAttachCurrentThread,
JvDetachCurrentThread): New inline wrappers.
* gcj/javaprims.h (_Jv_CreateJavaVM, _Jv_AttachCurrentThread,
_Jv_DetachCurrentThread): New declarations.
* gnu/gcj/runtime/FirstThread.java: Gutted. Now contains only ...
(getMain): new static method.
* gnu/gcj/runtime/natFirstThread.cc: Removed; run method replaced
by runFirst in prims.cc.
(java/lang/Thread.h): Update for new invocation interface.
* include/posix-threads.h (_Jv_ThreadRegister,
_Jv_ThreadUnRegister): New declarations.
* posix-threads.cc (_Jv_ThreadRegister, _Jv_ThreadUnRegister): New.
(really_start): Use new _Jv_ThreadRegister.
* include/no-threads.h (_Jv_ThreadInitData): No longer inline.
(_Jv_ThreadRegister, _Jv_ThreadUnRegister): New empty inlines.
* no-threads.cc (_Jv_ThreadInitData): Set _Jv_OnlyThread here.
Complain of called when _Jv_OnlyThread already set.
(_Jv_ThreadStart): Always JvFail.
* include/win32-threads.h (_Jv_Thread_t): New thread_obj field.
(_Jv_ThreadRegister, _Jv_ThreadUnRegister): New declarations.
* win32-threads.cc (struct starter): Remove objet field -
we use _Jv_Thread_t's new thread_obj field instead.
(_Jv_ThreadInitData): Set _Jv_Thread_t's thread_obj field.
(_Jv_ThreadRegister, _Jv_ThreadUnRegister): New.
(really_start): Use new _Jv_ThreadRegister.
* jni.cc (_Jv_JNI_AttachCurrentThread): Use _Jv_AttachCurrentThread.
(_Jv_JNI_DetachCurrentThread): Use _Jv_DetachCurrentThread.
* gnu/gcj/jni/NativeThread.java, gnu/gcj/jni/natNativeThread.cc:
Removed - no longer needed with new invocation interface.
* Makefile.am: Update for removed/added files.
2001-05-21 Per Bothner <per@bothner.com>
* Makefile.am (libgcj_la_DEPENDENCIES): Add $(nat_files). * Makefile.am (libgcj_la_DEPENDENCIES): Add $(nat_files).
(libgcj_la_LIBADD): Likewise. (libgcj_la_LIBADD): Likewise.
(libgcjx_la_DEPENDENCIES, libgcjx_la_LIBADD): Add $(x_nat_files). (libgcjx_la_DEPENDENCIES, libgcjx_la_LIBADD): Add $(x_nat_files).
......
...@@ -303,12 +303,12 @@ gnu/gcj/runtime/FirstThread.h: gnu/gcj/runtime/FirstThread.class libgcj.jar ...@@ -303,12 +303,12 @@ gnu/gcj/runtime/FirstThread.h: gnu/gcj/runtime/FirstThread.class libgcj.jar
java/lang/Thread.h: java/lang/Thread.class libgcj.jar java/lang/Thread.h: java/lang/Thread.class libgcj.jar
$(GCJH) -classpath $(top_builddir) \ $(GCJH) -classpath $(top_builddir) \
-prepend 'class _Jv_JNIEnv;' \ -prepend 'class _Jv_JNIEnv;' \
-prepend 'extern "Java" { namespace gnu { namespace gcj { namespace jni { class NativeThread; } } } };' \
-prepend '#define _JV_NOT_OWNER 1' \ -prepend '#define _JV_NOT_OWNER 1' \
-prepend '#define _JV_INTERRUPTED 2' \ -prepend '#define _JV_INTERRUPTED 2' \
-friend '_Jv_JNIEnv * _Jv_GetCurrentJNIEnv ();' \ -friend '_Jv_JNIEnv * _Jv_GetCurrentJNIEnv ();' \
-friend 'void _Jv_SetCurrentJNIEnv (_Jv_JNIEnv *env);' \ -friend 'void _Jv_SetCurrentJNIEnv (_Jv_JNIEnv *env);' \
-friend 'class gnu::gcj::jni::NativeThread;' \ -friend 'java::lang::Thread* _Jv_AttachCurrentThread(jstring name, java::lang::ThreadGroup* group);' \
-friend 'jint _Jv_DetachCurrentThread ();' \
$(basename $<) $(basename $<)
java/lang/String.h: java/lang/String.class libgcj.jar java/lang/String.h: java/lang/String.class libgcj.jar
...@@ -1008,7 +1008,6 @@ gnu/gcj/RawData.java \ ...@@ -1008,7 +1008,6 @@ gnu/gcj/RawData.java \
gnu/gcj/io/DefaultMimeTypes.java \ gnu/gcj/io/DefaultMimeTypes.java \
gnu/gcj/io/MimeTypes.java \ gnu/gcj/io/MimeTypes.java \
gnu/gcj/io/SimpleSHSStream.java \ gnu/gcj/io/SimpleSHSStream.java \
gnu/gcj/jni/NativeThread.java \
gnu/gcj/math/MPN.java \ gnu/gcj/math/MPN.java \
gnu/gcj/protocol/file/Connection.java \ gnu/gcj/protocol/file/Connection.java \
gnu/gcj/protocol/file/Handler.java \ gnu/gcj/protocol/file/Handler.java \
...@@ -1308,8 +1307,6 @@ gnu/gcj/convert/natOutput_EUCJIS.cc \ ...@@ -1308,8 +1307,6 @@ gnu/gcj/convert/natOutput_EUCJIS.cc \
gnu/gcj/convert/natOutput_SJIS.cc \ gnu/gcj/convert/natOutput_SJIS.cc \
gnu/gcj/io/natSimpleSHSStream.cc \ gnu/gcj/io/natSimpleSHSStream.cc \
gnu/gcj/io/shs.cc \ gnu/gcj/io/shs.cc \
gnu/gcj/jni/natNativeThread.cc \
gnu/gcj/runtime/natFirstThread.cc \
java/io/natFile.cc \ java/io/natFile.cc \
java/io/natFileDescriptor.cc \ java/io/natFileDescriptor.cc \
java/io/natObjectInputStream.cc \ java/io/natObjectInputStream.cc \
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -73,6 +73,7 @@ CXXCPP = @CXXCPP@ ...@@ -73,6 +73,7 @@ CXXCPP = @CXXCPP@
DIRLTDL = @DIRLTDL@ DIRLTDL = @DIRLTDL@
DIVIDESPEC = @DIVIDESPEC@ DIVIDESPEC = @DIVIDESPEC@
DLLTOOL = @DLLTOOL@ DLLTOOL = @DLLTOOL@
EXCEPTIONSPEC = @EXCEPTIONSPEC@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
GCC_UNWIND_INCLUDE = @GCC_UNWIND_INCLUDE@ GCC_UNWIND_INCLUDE = @GCC_UNWIND_INCLUDE@
GCDEPS = @GCDEPS@ GCDEPS = @GCDEPS@
...@@ -202,7 +203,7 @@ distdir: $(DISTFILES) ...@@ -202,7 +203,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \ @for file in $(DISTFILES); do \
d=$(srcdir); \ d=$(srcdir); \
if test -d $$d/$$file; then \ if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \ cp -pr $$/$$file $(distdir)/$$file; \
else \ else \
test -f $(distdir)/$$file \ test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
......
...@@ -118,4 +118,22 @@ JvFree (void *ptr) ...@@ -118,4 +118,22 @@ JvFree (void *ptr)
{ {
return _Jv_Free (ptr); return _Jv_Free (ptr);
} }
extern inline jint
JvCreateJavaVM (void* vm_args)
{
return _Jv_CreateJavaVM (vm_args);
}
extern inline java::lang::Thread*
JvAttachCurrentThread (jstring name, java::lang::ThreadGroup* group)
{
return _Jv_AttachCurrentThread (name, group);
}
extern inline jint
JvDetachCurrentThread (void)
{
return _Jv_DetachCurrentThread ();
}
#endif /* __GCJ_CNI_H__ */ #endif /* __GCJ_CNI_H__ */
...@@ -380,6 +380,11 @@ extern "C" jstring _Jv_NewStringLatin1(const char*, jsize) ...@@ -380,6 +380,11 @@ extern "C" jstring _Jv_NewStringLatin1(const char*, jsize)
extern "C" jsize _Jv_GetStringUTFLength (jstring); extern "C" jsize _Jv_GetStringUTFLength (jstring);
extern "C" jsize _Jv_GetStringUTFRegion (jstring, jsize, jsize, char *); extern "C" jsize _Jv_GetStringUTFRegion (jstring, jsize, jsize, char *);
extern jint _Jv_CreateJavaVM (void* /*vm_args*/);
extern "C" java::lang::Thread*
_Jv_AttachCurrentThread(jstring name, java::lang::ThreadGroup* group);
extern "C" jint _Jv_DetachCurrentThread (void);
extern "C" void _Jv_Throw (jthrowable) __attribute__ ((__noreturn__)); extern "C" void _Jv_Throw (jthrowable) __attribute__ ((__noreturn__));
extern "C" void* _Jv_Malloc (jsize) __attribute__((__malloc__)); extern "C" void* _Jv_Malloc (jsize) __attribute__((__malloc__));
extern "C" void* _Jv_Realloc (void *, jsize); extern "C" void* _Jv_Realloc (void *, jsize);
......
// NativeThread.java - Wrapper for attached user threads.
/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
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. */
package gnu.gcj.jni;
/**
* @author Tom Tromey <tromey@cygnus.com>
* @date February 9, 2000
*/
public class NativeThread extends Thread
{
public NativeThread (ThreadGroup g, String name)
{
super (g, null, name);
init ();
}
// Call this to mark the thread as finished.
public native void finish ();
public native void init ();
}
// natNativeThread.cc - Native side of attached threads.
/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
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. */
// Written by Tom Tromey <tromey@cygnus.com>
#include <config.h>
#include <gcj/cni.h>
#include <jvm.h>
#include <gnu/gcj/jni/NativeThread.h>
#include <java/lang/Thread.h>
void
gnu::gcj::jni::NativeThread::finish ()
{
finish_ ();
}
void
gnu::gcj::jni::NativeThread::init ()
{
alive_flag = true; // alive_flag is private in java.lang.Thread
}
...@@ -19,59 +19,29 @@ import java.util.jar.*; ...@@ -19,59 +19,29 @@ import java.util.jar.*;
// This is entirely internal to our implementation. // This is entirely internal to our implementation.
final class FirstThread extends Thread final class FirstThread
{ {
public native void run (); public static String getMain (String name)
public FirstThread (Class k, Object o)
{
super (null, null, "main");
klass = k;
klass_name = null;
args = o;
}
public FirstThread (String class_name, Object o)
{
super (null, null, "main");
klass = null;
klass_name = class_name;
args = o;
}
private static void die (String s)
{
System.err.println(s);
System.exit(1);
}
public static void main (String[] args)
{ {
String mainName = null;
try { try {
JarFile j = new JarFile (args[0]); JarFile j = new JarFile (name);
Attributes a = j.getManifest().getMainAttributes(); Attributes a = j.getManifest().getMainAttributes();
jarMainClassName = a.getValue(Attributes.Name.MAIN_CLASS); mainName = a.getValue(Attributes.Name.MAIN_CLASS);
if (jarMainClassName != null)
{
jarMainClassName = jarMainClassName.replace('/','.');
return;
}
} catch (Exception e) { } catch (Exception e) {
// empty // empty
} }
System.err.println ("Failed to load Main-Class manifest attribute from\n" if (mainName == null)
+ args[0]); System.err.println ("Failed to load Main-Class manifest attribute from\n"
+ name);
return mainName;
} }
// If interpreter is invoked with -jar, the main class name is recorded
// here.
public static String jarMainClassName;
// Private data. // Private data.
private Class klass; private Class klass;
private String klass_name; private String klass_name;
......
// natFirstThread.cc - Implementation of FirstThread native methods.
/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
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>
#include <gcj/cni.h>
#include <jvm.h>
#include <jni.h>
#include <gnu/gcj/runtime/FirstThread.h>
#include <java/lang/Class.h>
#include <java/lang/String.h>
#include <java/lang/System.h>
#include <java/lang/reflect/Modifier.h>
#include <java/io/PrintStream.h>
#ifdef ENABLE_JVMPI
#include <jvmpi.h>
#include <java/lang/ThreadGroup.h>
#include <java/lang/UnsatisfiedLinkError.h>
#endif
#define DIE(Message) die (JvNewStringLatin1 (Message))
typedef void main_func (jobject);
#ifdef WITH_JVMPI
extern void (*_Jv_JVMPI_Notify_THREAD_START) (JVMPI_Event *event);
#endif
/* This will be non-NULL if the user has preloaded a JNI library, or
linked one into the executable. */
extern "C"
{
#pragma weak JNI_OnLoad
extern jint JNI_OnLoad (JavaVM *, void *) __attribute__((weak));
}
void
gnu::gcj::runtime::FirstThread::run (void)
{
Utf8Const* main_signature = _Jv_makeUtf8Const ("([Ljava.lang.String;)V", 22);
Utf8Const* main_name = _Jv_makeUtf8Const ("main", 4);
/* Some systems let you preload shared libraries before running a
program. Under Linux, this is done by setting the LD_PRELOAD
environment variable. We take advatage of this here to allow for
dynamically loading a JNI library into a fully linked executable. */
if (JNI_OnLoad != NULL)
{
JavaVM *vm = _Jv_GetJavaVM ();
if (vm == NULL)
{
// FIXME: what?
return;
}
jint vers = JNI_OnLoad (vm, NULL);
if (vers != JNI_VERSION_1_1 && vers != JNI_VERSION_1_2)
{
// FIXME: unload the library.
throw new java::lang::UnsatisfiedLinkError (JvNewStringLatin1 ("unrecognized version from preloaded JNI_OnLoad"));
}
}
if (klass == NULL)
klass = java::lang::Class::forName (klass_name);
if (klass != NULL)
_Jv_InitClass (klass);
_Jv_Method *meth = _Jv_GetMethodLocal (klass, main_name, main_signature);
// Some checks from Java Spec section 12.1.4.
if (meth == NULL)
DIE ("no suitable method `main' in class");
if (! java::lang::reflect::Modifier::isStatic(meth->accflags))
DIE ("`main' must be static");
if (! java::lang::reflect::Modifier::isPublic(meth->accflags))
DIE ("`main' must be public");
#ifdef WITH_JVMPI
if (_Jv_JVMPI_Notify_THREAD_START)
{
JVMPI_Event event;
jstring thread_name = getName ();
jstring group_name = NULL, parent_name = NULL;
java::lang::ThreadGroup *group = 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) this;
event.u.thread_start.thread_env_id = _Jv_GetCurrentJNIEnv ();
_Jv_DisableGC ();
(*_Jv_JVMPI_Notify_THREAD_START) (&event);
_Jv_EnableGC ();
}
#endif
main_func *real_main = (main_func *) meth->ncode;
(*real_main) (args);
}
...@@ -73,6 +73,7 @@ CXXCPP = @CXXCPP@ ...@@ -73,6 +73,7 @@ CXXCPP = @CXXCPP@
DIRLTDL = @DIRLTDL@ DIRLTDL = @DIRLTDL@
DIVIDESPEC = @DIVIDESPEC@ DIVIDESPEC = @DIVIDESPEC@
DLLTOOL = @DLLTOOL@ DLLTOOL = @DLLTOOL@
EXCEPTIONSPEC = @EXCEPTIONSPEC@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
GCC_UNWIND_INCLUDE = @GCC_UNWIND_INCLUDE@ GCC_UNWIND_INCLUDE = @GCC_UNWIND_INCLUDE@
GCDEPS = @GCDEPS@ GCDEPS = @GCDEPS@
......
...@@ -102,11 +102,8 @@ _Jv_InitThreads (void) ...@@ -102,11 +102,8 @@ _Jv_InitThreads (void)
{ {
} }
inline _Jv_Thread_t * _Jv_Thread_t *
_Jv_ThreadInitData (java::lang::Thread *) _Jv_ThreadInitData (java::lang::Thread *);
{
return NULL;
}
inline void inline void
_Jv_ThreadDestroyData (_Jv_Thread_t *data) _Jv_ThreadDestroyData (_Jv_Thread_t *data)
...@@ -130,6 +127,16 @@ _Jv_ThreadSetPriority (_Jv_Thread_t *, jint) ...@@ -130,6 +127,16 @@ _Jv_ThreadSetPriority (_Jv_Thread_t *, jint)
{ {
} }
inline void
_Jv_ThreadRegister (_Jv_Thread_t *data)
{
}
inline void
_Jv_ThreadUnRegister (void)
{
}
void _Jv_ThreadStart (java::lang::Thread *, _Jv_Thread_t *, void _Jv_ThreadStart (java::lang::Thread *, _Jv_Thread_t *,
_Jv_ThreadStartFunc *meth); _Jv_ThreadStartFunc *meth);
......
...@@ -194,6 +194,9 @@ _Jv_ThreadYield (void) ...@@ -194,6 +194,9 @@ _Jv_ThreadYield (void)
#endif /* HAVE_SCHED_YIELD */ #endif /* HAVE_SCHED_YIELD */
} }
void _Jv_ThreadRegister (_Jv_Thread_t *data);
void _Jv_ThreadUnRegister ();
void _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio); void _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio);
void _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data, void _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data,
......
...@@ -25,6 +25,7 @@ typedef struct ...@@ -25,6 +25,7 @@ typedef struct
{ {
int flags; // Flags are defined in implementation. int flags; // Flags are defined in implementation.
HANDLE handle; // Actual handle to the thread HANDLE handle; // Actual handle to the thread
java::lang::Thread *thread_obj;
} _Jv_Thread_t; } _Jv_Thread_t;
typedef void _Jv_ThreadStartFunc (java::lang::Thread *); typedef void _Jv_ThreadStartFunc (java::lang::Thread *);
...@@ -120,6 +121,9 @@ _Jv_ThreadYield (void) ...@@ -120,6 +121,9 @@ _Jv_ThreadYield (void)
Sleep (0); Sleep (0);
} }
void _Jv_ThreadRegister (_Jv_Thread_t *data);
void _Jv_ThreadUnRegister ();
void _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio); void _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio);
void _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data, void _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data,
_Jv_ThreadStartFunc *meth); _Jv_ThreadStartFunc *meth);
......
// Thread.java - Thread class. // Thread.java - Thread class.
/* Copyright (C) 1998, 1999, 2000 Free Software Foundation /* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -209,18 +209,20 @@ public class Thread implements Runnable ...@@ -209,18 +209,20 @@ public class Thread implements Runnable
private final native void initialize_native (); private final native void initialize_native ();
private final synchronized static String gen_name () private final native static String gen_name ();
public Thread (ThreadGroup g, Runnable r, String n)
{ {
String n; this (currentThread (), g, r, n);
n = "Thread-" + nextThreadNumber;
++nextThreadNumber; // The Class Libraries book says ``threadName cannot be null''. I
return n; // take this to mean NullPointerException.
if (n == null)
throw new NullPointerException ();
} }
public Thread (ThreadGroup g, Runnable r, String n) private Thread (Thread current, ThreadGroup g, Runnable r, String n)
{ {
Thread current = currentThread ();
if (g == null) if (g == null)
{ {
// If CURRENT is null, then we are bootstrapping the first thread. // If CURRENT is null, then we are bootstrapping the first thread.
...@@ -233,17 +235,6 @@ public class Thread implements Runnable ...@@ -233,17 +235,6 @@ public class Thread implements Runnable
else else
group = g; group = g;
group.checkAccess();
// The Class Libraries book says ``threadName cannot be null''. I
// take this to mean NullPointerException.
if (n == null)
throw new NullPointerException ();
name = n;
group.addThread(this);
runnable = r;
data = null; data = null;
interrupt_flag = false; interrupt_flag = false;
alive_flag = false; alive_flag = false;
...@@ -251,6 +242,8 @@ public class Thread implements Runnable ...@@ -251,6 +242,8 @@ public class Thread implements Runnable
if (current != null) if (current != null)
{ {
group.checkAccess();
daemon_flag = current.isDaemon(); daemon_flag = current.isDaemon();
int gmax = group.getMaxPriority(); int gmax = group.getMaxPriority();
int pri = current.getPriority(); int pri = current.getPriority();
...@@ -263,6 +256,10 @@ public class Thread implements Runnable ...@@ -263,6 +256,10 @@ public class Thread implements Runnable
priority = NORM_PRIORITY; priority = NORM_PRIORITY;
} }
name = n;
group.addThread(this);
runnable = r;
initialize_native (); initialize_native ();
} }
...@@ -315,9 +312,6 @@ public class Thread implements Runnable ...@@ -315,9 +312,6 @@ public class Thread implements Runnable
private boolean startable_flag; private boolean startable_flag;
private ClassLoader context_class_loader; private ClassLoader context_class_loader;
// Our native data. // Our native data - points to an instance of struct natThread.
private Object data; private Object data;
// Next thread number to assign.
private static int nextThreadNumber = 0;
} }
// natThread.cc - Native part of Thread class. // natThread.cc - Native part of Thread class.
/* Copyright (C) 1998, 1999, 2000 Free Software Foundation /* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -59,7 +59,7 @@ java::lang::Thread::initialize_native (void) ...@@ -59,7 +59,7 @@ java::lang::Thread::initialize_native (void)
{ {
natThread *nt = (natThread *) _Jv_AllocBytes (sizeof (natThread)); natThread *nt = (natThread *) _Jv_AllocBytes (sizeof (natThread));
// The native thread data is kept in a Object field, not a rawdata, so that // The native thread data is kept in a Object field, not a RawData, so that
// the GC allocator can be used and a finalizer run after the thread becomes // the GC allocator can be used and a finalizer run after the thread becomes
// unreachable. Note that this relies on the GC's ability to finalize // unreachable. Note that this relies on the GC's ability to finalize
// non-Java objects. FIXME? // non-Java objects. FIXME?
...@@ -322,6 +322,34 @@ java::lang::Thread::suspend (void) ...@@ -322,6 +322,34 @@ java::lang::Thread::suspend (void)
(JvNewStringLatin1 ("java::lang::Thread::suspend unimplemented")); (JvNewStringLatin1 ("java::lang::Thread::suspend unimplemented"));
} }
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);
}
void void
java::lang::Thread::yield (void) java::lang::Thread::yield (void)
{ {
...@@ -344,3 +372,33 @@ _Jv_SetCurrentJNIEnv (JNIEnv *env) ...@@ -344,3 +372,33 @@ _Jv_SetCurrentJNIEnv (JNIEnv *env)
JvAssert (t != NULL); JvAssert (t != NULL);
((natThread *) t->data)->jni_env = env; ((natThread *) t->data)->jni_env = env;
} }
java::lang::Thread*
_Jv_AttachCurrentThread(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 = new java::lang::Thread (NULL, group, NULL, name);
thread->startable_flag = false;
thread->alive_flag = true;
natThread *nt = (natThread *) thread->data;
_Jv_ThreadRegister (nt->thread);
return thread;
}
jint
_Jv_DetachCurrentThread (void)
{
java::lang::Thread *t = _Jv_ThreadCurrent ();
if (t == NULL)
return -1;
_Jv_ThreadUnRegister ();
// Release the monitors.
t->finish_ ();
return 0;
}
...@@ -40,12 +40,13 @@ details. */ ...@@ -40,12 +40,13 @@ details. */
#include <java/util/Hashtable.h> #include <java/util/Hashtable.h>
#include <java/lang/Integer.h> #include <java/lang/Integer.h>
#include <java/lang/ThreadGroup.h> #include <java/lang/ThreadGroup.h>
#include <gnu/gcj/jni/NativeThread.h> #include <java/lang/Thread.h>
#include <gcj/method.h> #include <gcj/method.h>
#include <gcj/field.h> #include <gcj/field.h>
#include <java-interp.h> #include <java-interp.h>
#include <java-threads.h>
// FIXME: remove these defines. // FIXME: remove these defines.
#define ClassClass java::lang::Class::class$ #define ClassClass java::lang::Class::class$
...@@ -53,7 +54,6 @@ details. */ ...@@ -53,7 +54,6 @@ details. */
#define ThrowableClass java::lang::Throwable::class$ #define ThrowableClass java::lang::Throwable::class$
#define MethodClass java::lang::reflect::Method::class$ #define MethodClass java::lang::reflect::Method::class$
#define ThreadGroupClass java::lang::ThreadGroup::class$ #define ThreadGroupClass java::lang::ThreadGroup::class$
#define NativeThreadClass gnu::gcj::jni::NativeThread::class$
// This enum is used to select different template instantiations in // This enum is used to select different template instantiations in
// the invocation code. // the invocation code.
...@@ -1862,7 +1862,7 @@ _Jv_JNI_AttachCurrentThread (JavaVM *, jstring name, void **penv, void *args) ...@@ -1862,7 +1862,7 @@ _Jv_JNI_AttachCurrentThread (JavaVM *, jstring name, void **penv, void *args)
{ {
try try
{ {
(void) new gnu::gcj::jni::NativeThread (group, name); _Jv_AttachCurrentThread (name, group);
} }
catch (jthrowable t) catch (jthrowable t)
{ {
...@@ -1916,28 +1916,11 @@ _Jv_JNI_DestroyJavaVM (JavaVM *vm) ...@@ -1916,28 +1916,11 @@ _Jv_JNI_DestroyJavaVM (JavaVM *vm)
return JNI_ERR; return JNI_ERR;
} }
static jint jint
_Jv_JNI_DetachCurrentThread (JavaVM *) _Jv_JNI_DetachCurrentThread (JavaVM *)
{ {
java::lang::Thread *t = _Jv_ThreadCurrent (); jint code = _Jv_DetachCurrentThread ();
if (t == NULL) return code ? JNI_EDETACHED : 0;
return JNI_EDETACHED;
// FIXME: we only allow threads attached via AttachCurrentThread to
// be detached. I have no idea how we could implement detaching
// other threads, given the requirement that we must release all the
// monitors. That just seems evil.
JvAssert ((&NativeThreadClass)->isInstance (t));
// FIXME: release the monitors. We'll take this to mean all
// monitors acquired via the JNI interface. This means we have to
// keep track of them.
gnu::gcj::jni::NativeThread *nt
= reinterpret_cast<gnu::gcj::jni::NativeThread *> (t);
nt->finish ();
return 0;
} }
static jint static jint
......
...@@ -16,14 +16,20 @@ details. */ ...@@ -16,14 +16,20 @@ details. */
java::lang::Thread *_Jv_OnlyThread = NULL; java::lang::Thread *_Jv_OnlyThread = NULL;
void _Jv_Thread_t *
_Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *, _Jv_ThreadInitData (java::lang::Thread * thread)
_Jv_ThreadStartFunc *meth)
{ {
// Don't use JvAssert, since we want this to fail even when compiled // Don't use JvAssert, since we want this to fail even when compiled
// without assertions. // without assertions.
if (_Jv_OnlyThread) if (_Jv_OnlyThread)
JvFail ("only thread already running"); JvFail ("only thread already running");
_Jv_OnlyThread = thread; _Jv_OnlyThread = thread;
(*meth) (thread); return NULL;
}
void
_Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *,
_Jv_ThreadStartFunc *meth)
{
JvFail ("Thread.start called but threads not available");
} }
...@@ -326,6 +326,25 @@ _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio) ...@@ -326,6 +326,25 @@ _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio)
} }
} }
void
_Jv_ThreadRegister (_Jv_Thread_t *data)
{
pthread_setspecific (_Jv_ThreadKey, data->thread_obj);
pthread_setspecific (_Jv_ThreadDataKey, data);
// glibc 2.1.3 doesn't set the value of `thread' until after start_routine
// is called. Since it may need to be accessed from the new thread, work
// around the potential race here by explicitly setting it again.
data->thread = pthread_self ();
}
void
_Jv_ThreadUnRegister ()
{
pthread_setspecific (_Jv_ThreadKey, NULL);
pthread_setspecific (_Jv_ThreadDataKey, NULL);
}
// This function is called when a thread is started. We don't arrange // This function is called when a thread is started. We don't arrange
// to call the `run' method directly, because this function must // to call the `run' method directly, because this function must
// return a value. // return a value.
...@@ -334,13 +353,7 @@ really_start (void *x) ...@@ -334,13 +353,7 @@ really_start (void *x)
{ {
struct starter *info = (struct starter *) x; struct starter *info = (struct starter *) x;
pthread_setspecific (_Jv_ThreadKey, info->data->thread_obj); _Jv_ThreadRegister (info->data);
pthread_setspecific (_Jv_ThreadDataKey, info->data);
// glibc 2.1.3 doesn't set the value of `thread' until after start_routine
// is called. Since it may need to be accessed from the new thread, work
// around the potential race here by explicitly setting it again.
info->data->thread = pthread_self ();
info->method (info->data->thread_obj); info->method (info->data->thread_obj);
......
...@@ -36,6 +36,7 @@ details. */ ...@@ -36,6 +36,7 @@ details. */
#ifdef ENABLE_JVMPI #ifdef ENABLE_JVMPI
#include <jvmpi.h> #include <jvmpi.h>
#include <java/lang/ThreadGroup.h>
#endif #endif
#ifndef DISABLE_GETENV_PROPERTIES #ifndef DISABLE_GETENV_PROPERTIES
...@@ -62,6 +63,7 @@ details. */ ...@@ -62,6 +63,7 @@ details. */
#include <java/lang/System.h> #include <java/lang/System.h>
#include <java/lang/reflect/Modifier.h> #include <java/lang/reflect/Modifier.h>
#include <java/io/PrintStream.h> #include <java/io/PrintStream.h>
#include <java/lang/UnsatisfiedLinkError.h>
#ifdef USE_LTDL #ifdef USE_LTDL
#include <ltdl.h> #include <ltdl.h>
...@@ -74,8 +76,10 @@ static java::lang::OutOfMemoryError *no_memory; ...@@ -74,8 +76,10 @@ static java::lang::OutOfMemoryError *no_memory;
// Largest representable size_t. // Largest representable size_t.
#define SIZE_T_MAX ((size_t) (~ (size_t) 0)) #define SIZE_T_MAX ((size_t) (~ (size_t) 0))
static const char *no_properties[] = { NULL };
// Properties set at compile time. // Properties set at compile time.
const char **_Jv_Compiler_Properties; const char **_Jv_Compiler_Properties = no_properties;
// The JAR file to add to the beginning of java.class.path. // The JAR file to add to the beginning of java.class.path.
const char *_Jv_Jar_Class_Path; const char *_Jv_Jar_Class_Path;
...@@ -92,6 +96,8 @@ static char * _Jv_execName; ...@@ -92,6 +96,8 @@ static char * _Jv_execName;
const char **_Jv_argv; const char **_Jv_argv;
int _Jv_argc; int _Jv_argc;
typedef void main_func (jobject);
#ifdef ENABLE_JVMPI #ifdef ENABLE_JVMPI
// Pointer to JVMPI notification functions. // Pointer to JVMPI notification functions.
void (*_Jv_JVMPI_Notify_OBJECT_ALLOC) (JVMPI_Event *event); void (*_Jv_JVMPI_Notify_OBJECT_ALLOC) (JVMPI_Event *event);
...@@ -640,51 +646,15 @@ win32_exception_handler (LPEXCEPTION_POINTERS e) ...@@ -640,51 +646,15 @@ win32_exception_handler (LPEXCEPTION_POINTERS e)
#endif #endif
static void /* This will be non-NULL if the user has preloaded a JNI library, or
main_init () linked one into the executable. */
extern "C"
{ {
// Turn stack trace generation off while creating exception objects. #pragma weak JNI_OnLoad
_Jv_InitClass (&java::lang::Throwable::class$); extern jint JNI_OnLoad (JavaVM *, void *) __attribute__((weak));
java::lang::Throwable::trace_enabled = 0;
INIT_SEGV;
#ifdef HANDLE_FPE
INIT_FPE;
#else
arithexception = new java::lang::ArithmeticException
(JvNewStringLatin1 ("/ by zero"));
#endif
no_memory = new java::lang::OutOfMemoryError;
java::lang::Throwable::trace_enabled = 1;
#ifdef USE_LTDL
LTDL_SET_PRELOADED_SYMBOLS ();
#endif
#ifdef USE_WINSOCK
// Initialise winsock for networking
WSADATA data;
if (WSAStartup (MAKEWORD (1, 1), &data))
MessageBox (NULL, "Error initialising winsock library.", "Error", MB_OK | MB_ICONEXCLAMATION);
#endif /* USE_WINSOCK */
#ifdef USE_WIN32_SIGNALLING
// Install exception handler
SetUnhandledExceptionFilter (win32_exception_handler);
#else
// We only want this on POSIX systems.
struct sigaction act;
act.sa_handler = SIG_IGN;
sigemptyset (&act.sa_mask);
act.sa_flags = 0;
sigaction (SIGPIPE, &act, NULL);
#endif /* USE_WIN32_SIGNALLING */
_Jv_JNI_Init ();
} }
#ifndef DISABLE_GETENV_PROPERTIES #ifndef DISABLE_GETENV_PROPERTIES
static char * static char *
...@@ -828,15 +798,162 @@ process_gcj_properties () ...@@ -828,15 +798,162 @@ process_gcj_properties ()
} }
#endif // DISABLE_GETENV_PROPERTIES #endif // DISABLE_GETENV_PROPERTIES
void jint
JvRunMain (jclass klass, int argc, const char **argv) _Jv_CreateJavaVM (void* /*vm_args*/)
{ {
PROCESS_GCJ_PROPERTIES; PROCESS_GCJ_PROPERTIES;
// Turn stack trace generation off while creating exception objects.
_Jv_InitClass (&java::lang::Throwable::class$);
java::lang::Throwable::trace_enabled = 0;
INIT_SEGV;
#ifdef HANDLE_FPE
INIT_FPE;
#else
arithexception = new java::lang::ArithmeticException
(JvNewStringLatin1 ("/ by zero"));
#endif
no_memory = new java::lang::OutOfMemoryError;
java::lang::Throwable::trace_enabled = 1;
#ifdef USE_LTDL
LTDL_SET_PRELOADED_SYMBOLS ();
#endif
#ifdef USE_WINSOCK
// Initialise winsock for networking
WSADATA data;
if (WSAStartup (MAKEWORD (1, 1), &data))
MessageBox (NULL, "Error initialising winsock library.", "Error", MB_OK | MB_ICONEXCLAMATION);
#endif /* USE_WINSOCK */
#ifdef USE_WIN32_SIGNALLING
// Install exception handler
SetUnhandledExceptionFilter (win32_exception_handler);
#else
// We only want this on POSIX systems.
struct sigaction act;
act.sa_handler = SIG_IGN;
sigemptyset (&act.sa_mask);
act.sa_flags = 0;
sigaction (SIGPIPE, &act, NULL);
#endif /* USE_WIN32_SIGNALLING */
_Jv_JNI_Init ();
/* Some systems let you preload shared libraries before running a
program. Under Linux, this is done by setting the LD_PRELOAD
environment variable. We take advatage of this here to allow for
dynamically loading a JNI library into a fully linked executable. */
if (JNI_OnLoad != NULL)
{
JavaVM *vm = _Jv_GetJavaVM ();
if (vm == NULL)
{
// FIXME: what?
return -1;
}
jint vers = JNI_OnLoad (vm, NULL);
if (vers != JNI_VERSION_1_1 && vers != JNI_VERSION_1_2)
{
// FIXME: unload the library.
_Jv_Throw (new java::lang::UnsatisfiedLinkError (JvNewStringLatin1 ("unrecognized version from preloaded JNI_OnLoad")));
}
}
return 0;
}
static void
runFirst (::java::lang::Class *klass, ::java::lang::Object *args)
{
Utf8Const* main_signature = _Jv_makeUtf8Const ("([Ljava.lang.String;)V", 22);
Utf8Const* main_name = _Jv_makeUtf8Const ("main", 4);
_Jv_Method *meth = _Jv_GetMethodLocal (klass, main_name, main_signature);
// Some checks from Java Spec section 12.1.4.
const char *msg = NULL;
if (meth == NULL)
msg = "no suitable method `main' in class";
else if (! java::lang::reflect::Modifier::isStatic(meth->accflags))
msg = "`main' must be static";
else if (! java::lang::reflect::Modifier::isPublic(meth->accflags))
msg = "`main' must be public";
if (msg != NULL)
{
fprintf (stderr, "%s\n", msg);
::exit(1);
}
#ifdef WITH_JVMPI
if (_Jv_JVMPI_Notify_THREAD_START)
{
JVMPI_Event event;
jstring thread_name = getName ();
jstring group_name = NULL, parent_name = NULL;
java::lang::ThreadGroup *group = 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) this;
event.u.thread_start.thread_env_id = _Jv_GetCurrentJNIEnv ();
_Jv_DisableGC ();
(*_Jv_JVMPI_Notify_THREAD_START) (&event);
_Jv_EnableGC ();
}
#endif
main_func *real_main = (main_func *) meth->ncode;
(*real_main) (args);
}
void
JvRunMain (jclass klass, int argc, const char **argv)
{
_Jv_argv = argv; _Jv_argv = argv;
_Jv_argc = argc; _Jv_argc = argc;
main_init (); _Jv_CreateJavaVM (NULL);
#ifdef HAVE_PROC_SELF_EXE #ifdef HAVE_PROC_SELF_EXE
char exec_name[20]; char exec_name[20];
sprintf (exec_name, "/proc/%d/exe", getpid ()); sprintf (exec_name, "/proc/%d/exe", getpid ());
...@@ -845,10 +962,9 @@ JvRunMain (jclass klass, int argc, const char **argv) ...@@ -845,10 +962,9 @@ JvRunMain (jclass klass, int argc, const char **argv)
_Jv_ThisExecutable (argv[0]); _Jv_ThisExecutable (argv[0]);
#endif #endif
main_thread = _Jv_AttachCurrentThread (JvNewStringLatin1 ("main"), NULL);
arg_vec = JvConvertArgv (argc - 1, argv + 1); arg_vec = JvConvertArgv (argc - 1, argv + 1);
main_thread = new gnu::gcj::runtime::FirstThread (klass, arg_vec); runFirst (klass, arg_vec);
main_thread->start();
_Jv_ThreadWait (); _Jv_ThreadWait ();
int status = (int) java::lang::ThreadGroup::had_uncaught_exception; int status = (int) java::lang::ThreadGroup::had_uncaught_exception;
...@@ -860,9 +976,8 @@ void ...@@ -860,9 +976,8 @@ void
_Jv_RunMain (const char *name, int argc, const char **argv, bool is_jar) _Jv_RunMain (const char *name, int argc, const char **argv, bool is_jar)
{ {
jstring class_name; jstring class_name;
PROCESS_GCJ_PROPERTIES;
main_init (); _Jv_CreateJavaVM (NULL);
#ifdef HAVE_PROC_SELF_EXE #ifdef HAVE_PROC_SELF_EXE
char exec_name[20]; char exec_name[20];
...@@ -870,23 +985,17 @@ _Jv_RunMain (const char *name, int argc, const char **argv, bool is_jar) ...@@ -870,23 +985,17 @@ _Jv_RunMain (const char *name, int argc, const char **argv, bool is_jar)
_Jv_ThisExecutable (exec_name); _Jv_ThisExecutable (exec_name);
#endif #endif
main_thread = _Jv_AttachCurrentThread (JvNewStringLatin1 ("main"), NULL);
if (is_jar) if (is_jar)
{ {
// name specifies a jar file. We must now extract the // name specifies a jar file. We must now extract the
// Main-Class attribute from the jar's manifest file. This is // Main-Class attribute from the jar's manifest file.
// done by gnu.gcj.runtime.FirstThread.main. // This is done by gnu.gcj.runtime.FirstThread.getMain.
_Jv_Jar_Class_Path = strdup (name); _Jv_Jar_Class_Path = strdup (name);
arg_vec = JvConvertArgv (1, &_Jv_Jar_Class_Path); jstring jar_name = JvNewStringLatin1 (name);
// FirstThread.getMain extracts the main class name.
main_thread = class_name = gnu::gcj::runtime::FirstThread::getMain (jar_name);
new gnu::gcj::runtime::FirstThread (&gnu::gcj::runtime::FirstThread::class$,
arg_vec);
main_thread->start();
_Jv_ThreadWait ();
// FirstThread.main extracts the main class name and stores it
// here.
class_name = gnu::gcj::runtime::FirstThread::jarMainClassName;
// We need a new ClassLoader because the classpath must be the // We need a new ClassLoader because the classpath must be the
// jar file only. The easiest way to do this is to lose our // jar file only. The easiest way to do this is to lose our
...@@ -900,8 +1009,7 @@ _Jv_RunMain (const char *name, int argc, const char **argv, bool is_jar) ...@@ -900,8 +1009,7 @@ _Jv_RunMain (const char *name, int argc, const char **argv, bool is_jar)
if (class_name) if (class_name)
{ {
main_thread = new gnu::gcj::runtime::FirstThread (class_name, arg_vec); runFirst(java::lang::Class::forName (class_name), arg_vec);
main_thread->start();
_Jv_ThreadWait (); _Jv_ThreadWait ();
} }
......
...@@ -73,6 +73,7 @@ CXXCPP = @CXXCPP@ ...@@ -73,6 +73,7 @@ CXXCPP = @CXXCPP@
DIRLTDL = @DIRLTDL@ DIRLTDL = @DIRLTDL@
DIVIDESPEC = @DIVIDESPEC@ DIVIDESPEC = @DIVIDESPEC@
DLLTOOL = @DLLTOOL@ DLLTOOL = @DLLTOOL@
EXCEPTIONSPEC = @EXCEPTIONSPEC@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
GCC_UNWIND_INCLUDE = @GCC_UNWIND_INCLUDE@ GCC_UNWIND_INCLUDE = @GCC_UNWIND_INCLUDE@
GCDEPS = @GCDEPS@ GCDEPS = @GCDEPS@
...@@ -122,14 +123,10 @@ libgcj_basedir = @libgcj_basedir@ ...@@ -122,14 +123,10 @@ libgcj_basedir = @libgcj_basedir@
AUTOMAKE_OPTIONS = foreign dejagnu AUTOMAKE_OPTIONS = foreign dejagnu
# Setup the testing framework, if you have one # Setup the testing framework, if you have one
EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \ EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then echo $(top_builddir)/../expect/expect ; else echo expect ; fi`
echo $(top_builddir)/../expect/expect ; \
else echo expect ; fi`
RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \ RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then echo $(top_srcdir)/../dejagnu/runtest ; else echo runtest; fi`
echo $(top_srcdir)/../dejagnu/runtest ; \
else echo runtest; fi`
RUNTESTFLAGS = @AM_RUNTESTFLAGS@ RUNTESTFLAGS = @AM_RUNTESTFLAGS@
......
...@@ -35,7 +35,6 @@ extern "C" ...@@ -35,7 +35,6 @@ extern "C"
struct starter struct starter
{ {
_Jv_ThreadStartFunc *method; _Jv_ThreadStartFunc *method;
java::lang::Thread *object;
_Jv_Thread_t *data; _Jv_Thread_t *data;
}; };
...@@ -124,10 +123,11 @@ _Jv_InitThreads (void) ...@@ -124,10 +123,11 @@ _Jv_InitThreads (void)
} }
_Jv_Thread_t * _Jv_Thread_t *
_Jv_ThreadInitData (java::lang::Thread *) _Jv_ThreadInitData (java::lang::Thread* obj)
{ {
_Jv_Thread_t *data = new _Jv_Thread_t; _Jv_Thread_t *data = new _Jv_Thread_t;
data->flags = 0; data->flags = 0;
data->thread_obj = obj;
return data; return data;
} }
...@@ -176,6 +176,20 @@ _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio) ...@@ -176,6 +176,20 @@ _Jv_ThreadSetPriority (_Jv_Thread_t *data, jint prio)
} }
} }
void
_Jv_ThreadRegister (_Jv_Thread_t *data)
{
TlsSetValue (_Jv_ThreadKey, data->thread_obj);
TlsSetValue (_Jv_ThreadDataKey, data);
}
void
_Jv_ThreadUnRegister ()
{
TlsSetValue (_Jv_ThreadKey, NULL);
TlsSetValue (_Jv_ThreadDataKey, NULL);
}
// This function is called when a thread is started. We don't arrange // This function is called when a thread is started. We don't arrange
// to call the `run' method directly, because this function must // to call the `run' method directly, because this function must
// return a value. // return a value.
...@@ -184,9 +198,9 @@ really_start (void* x) ...@@ -184,9 +198,9 @@ really_start (void* x)
{ {
struct starter *info = (struct starter *) x; struct starter *info = (struct starter *) x;
TlsSetValue (_Jv_ThreadKey, info->object); _Jv_ThreadRegister (info->data);
TlsSetValue (_Jv_ThreadDataKey, info->data);
info->method (info->object); info->method (info->data->thread_obj);
if (! (info->data->flags & FLAG_DAEMON)) if (! (info->data->flags & FLAG_DAEMON))
{ {
...@@ -214,7 +228,6 @@ _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data, _Jv_ThreadStart ...@@ -214,7 +228,6 @@ _Jv_ThreadStart (java::lang::Thread *thread, _Jv_Thread_t *data, _Jv_ThreadStart
// FIXME: handle marking the info object for GC. // FIXME: handle marking the info object for GC.
info = (struct starter *) _Jv_AllocBytes (sizeof (struct starter)); info = (struct starter *) _Jv_AllocBytes (sizeof (struct starter));
info->method = meth; info->method = meth;
info->object = thread;
info->data = data; info->data = data;
if (! thread->isDaemon ()) if (! thread->isDaemon ())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment