📄 thread.c
字号:
/* * thread.c * Thread support. * * Copyright (c) 1996, 1997 * Transvirtual Technologies, Inc. All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. */#include "config.h"#include "debug.h"#include "config-std.h"#include "config-mem.h"#include "config-io.h"#include "config-signal.h"#include "kaffe/jtypes.h"#include "gtypes.h"#include "access.h"#include "object.h"#include "constants.h"#include "errors.h"#include "classMethod.h"#include "baseClasses.h"#include "stringSupport.h"#include "lookup.h"#include "thread.h"#include "jthread.h"#include "locks.h"#include "ksem.h"#include "exception.h"#include "support.h"#include "external.h"#include "gc.h"#include "jni.h"#include "md.h"#include "jvmpi_kaffe.h"/* If not otherwise specified, assume at least 1MB for main thread */#ifndef MAINSTACKSIZE#define MAINSTACKSIZE (1024*1024)#endif extern struct JNINativeInterface Kaffe_JNINativeInterface;static int threadStackSize; /* native stack size *//* referenced by native/Runtime.c */jbool runFinalizerOnExit; /* should we run finalizers? */jbool deadlockDetection = 1; /* abort if we detect deadlock */Hjava_lang_Class* ThreadClass;Hjava_lang_Class* ThreadGroupClass;Hjava_lang_ThreadGroup* standardGroup;static void firstStartThread(void*);static void runfinalizer(void);static iStaticLock thread_start_lock;/* * How do I get memory? */staticvoid *thread_malloc(size_t s){ return gc_malloc(s, GC_ALLOC_THREADCTX);}staticvoidthread_free(void *p){ gc_free(p);}staticvoid *thread_realloc(void *p, size_t s){ return gc_realloc(p, s, GC_ALLOC_THREADCTX);}static voidlinkNativeAndJavaThread(jthread_t thread, Hjava_lang_Thread *jlThread){ threadData *thread_data = jthread_get_data(thread); thread_data->jlThread = jlThread; unhand (jlThread)->PrivateInfo = (struct Hkaffe_util_Ptr *)thread; thread_data->jniEnv = &Kaffe_JNINativeInterface; thread_data->needOnStack = STACK_HIGH; }static voidunlinkNativeAndJavaThread(jthread_t thread){ threadData *thread_data = jthread_get_data(thread); /* unhand((Hjava_lang_Thread *)thread_data->jlThread)->PrivateInfo = 0; */ //thread_data->jlThread = 0; thread_data->jniEnv = 0; ksemDestroy (&thread_data->sem);}/* * Initialise threads. */voidinitThreads(void){ errorInfo info; DBG(INIT, dprintf("initThreads()\n"); ) /* Get a handle on the thread and thread group classes */ ThreadClass = lookupClass(THREADCLASS, NULL, &info); assert(ThreadClass != 0); ThreadGroupClass = lookupClass(THREADGROUPCLASS, NULL, &info); assert(ThreadGroupClass != 0); /* Create base group */ standardGroup = (Hjava_lang_ThreadGroup*)newObject(ThreadGroupClass); assert(standardGroup != 0); unhand(standardGroup)->parent = 0; unhand(standardGroup)->name = stringC2Java("main"); assert(unhand(standardGroup)->name != NULL); unhand(standardGroup)->maxPriority = java_lang_Thread_MAX_PRIORITY; unhand(standardGroup)->destroyed = 0; unhand(standardGroup)->daemon = 0; unhand(standardGroup)->nthreads = 0; unhand(standardGroup)->threads = (HArrayOfObject*)newArray(ThreadClass, 0); unhand(standardGroup)->ngroups = 0; unhand(standardGroup)->groups = (HArrayOfObject*)newArray(ThreadGroupClass, 0); /* Allocate a thread to be the main thread */ attachFakedThreadInstance("main"); DBG(INIT, dprintf("initThreads() done\n"); )}static jthread_tcreateThread(Hjava_lang_Thread* tid, void* func, size_t stacksize, struct _errorInfo *einfo){ jthread_t nativeThread; nativeThread = jthread_create(unhand(tid)->priority, func, unhand(tid)->daemon, tid, stacksize); if (nativeThread == NULL) { postOutOfMemory(einfo); return 0; } return nativeThread;}/* * Start a new thread running. */voidstartThread(Hjava_lang_Thread* tid){ jthread_t nativeTid; struct _errorInfo info; int iLockRoot;#if 0 if (aliveThread(tid) == true) { throwException(IllegalThreadStateException); }#endif /* Hold the start lock while the thread is created. * This lock prevents the new thread from running until we're * finished in create. * See also firstStartThread. */ lockStaticMutex(&thread_start_lock); nativeTid = createThread(tid, &firstStartThread, threadStackSize, &info); linkNativeAndJavaThread (nativeTid, tid); unlockStaticMutex(&thread_start_lock); if (nativeTid == NULL) { throwError(&info); }}/* * Interrupt a thread */voidinterruptThread(Hjava_lang_Thread* tid){ if ((jthread_t)unhand(tid)->PrivateInfo) { jthread_interrupt((jthread_t)unhand(tid)->PrivateInfo); }}/* * Stop a thread from running and terminate it. */voidstopThread(Hjava_lang_Thread* tid, Hjava_lang_Object* obj){ if (getCurrentThread() == tid) { throwException((Hjava_lang_Throwable*)obj); } else { /* * Note that we deviate from the spec here in that the target * thread won't throw the exception `obj', but it will * construct a new ThreadDeath exception when it dies. */ if ((jthread_t)unhand(tid)->PrivateInfo) jthread_stop((jthread_t)unhand(tid)->PrivateInfo); }}/* * Create the initial thread with a given name. * We should only ever call this once. */voidattachFakedThreadInstance(const char* nm){ Hjava_lang_Thread* tid; DBG(VMTHREAD, dprintf("attachFakedThreadInstance(%s)\n", nm); ) /* Allocate a thread to be the main thread */ tid = (Hjava_lang_Thread*)newObject(ThreadClass); assert(tid != 0); unhand(tid)->name = stringC2Java(nm); assert(unhand(tid)->name != NULL); unhand(tid)->priority = java_lang_Thread_NORM_PRIORITY; unhand(tid)->daemon = 0; unhand(tid)->interrupting = 0; unhand(tid)->target = 0; unhand(tid)->group = standardGroup; unhand(tid)->started = 1; /* set Java thread associated with main thread */ linkNativeAndJavaThread (jthread_current(), tid); /* * set context class loader of primordial thread to app classloader * must not be done earlier, since getCurrentThread() won't work * before the jthread_createfirst and the PrivateInfo assignment */ unhand(tid)->context = do_execute_java_class_method ("kaffe/lang/AppClassLoader", NULL, "getSingleton", "()Ljava/lang/ClassLoader;").l; /* Attach thread to threadGroup */ do_execute_java_method(unhand(tid)->group, "add", "(Ljava/lang/Thread;)V", 0, 0, tid); DBG(VMTHREAD, dprintf("attachFakedThreadInstance(%s)=%p done\n", nm, tid); )}/* * helper function to start gc thread */staticvoidstartSpecialThread(void *arg){ void (*func)(void *); void *argument; int iLockRoot; ksemInit(&THREAD_DATA()->sem); lockStaticMutex(&thread_start_lock); unlockStaticMutex(&thread_start_lock); func = (void *)THREAD_DATA()->exceptPtr; THREAD_DATA()->exceptPtr = NULL; argument = (void *)THREAD_DATA()->exceptObj; THREAD_DATA()->exceptObj = NULL; func(argument);}/* * Start a daemon thread, such as a gc or finalizer thread. * We give these threads a java incarnation for consistency. * It might not be strictly necessary for the gc thread. * * This guy can fail because of allocation failure, or because * createThread failed. * XXX */Hjava_lang_Thread*createDaemon(void* func, const char* nm, void *arg, int prio, size_t stacksize, struct _errorInfo *einfo){ Hjava_lang_Thread* tid; jthread_t nativeTid; int iLockRoot;DBG(VMTHREAD, dprintf("createDaemon %s\n", nm); ) /* Keep daemon threads as root objects */ tid = (Hjava_lang_Thread*)newObject(ThreadClass); assert(tid != 0); unhand(tid)->name = stringC2Java(nm); if (!unhand(tid)->name) { postOutOfMemory(einfo); return 0; } unhand(tid)->priority = prio; unhand(tid)->daemon = 1; unhand(tid)->interrupting = 0; unhand(tid)->target = 0; unhand(tid)->group = 0; lockStaticMutex(&thread_start_lock); nativeTid = createThread(tid, startSpecialThread, stacksize, einfo); linkNativeAndJavaThread (nativeTid, tid); jthread_get_data(nativeTid)->exceptPtr = func; jthread_get_data(nativeTid)->exceptObj = arg; unlockStaticMutex(&thread_start_lock); return (tid);}/* * All threads start here. */staticvoidfirstStartThread(void* arg){ Hjava_lang_Thread* tid; jthread_t cur; JNIEnv *env; jmethodID runmethod;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -