thread.c

来自「基于LWVCL开发的库」· C语言 代码 · 共 793 行 · 第 1/2 页

C
793
字号
			     vmtid, name, prio, true);  unhand(vmtid)->thread = tid;  unhand(vmtid)->running = true;  do_execute_java_class_method (&retval, "java/lang/ClassLoader",				NULL,				"getSystemClassLoader",				"()Ljava/lang/ClassLoader;");  unhand(tid)->contextClassLoader = (struct Hjava_lang_ClassLoader *) retval.l;    specialArgument[0] = func;  specialArgument[1] = arg;  specialArgument[2] = KTHREAD(current)();    nativeTid =     KTHREAD(create)((unhand(tid)->priority),		   startSpecialThread,		   true,		   specialArgument,		   stacksize);    if (nativeTid == NULL) {    postOutOfMemory(einfo);    return NULL;  }  KTHREAD(get_data)(nativeTid)->exceptPtr = NULL;  KTHREAD(get_data)(nativeTid)->exceptObj = NULL;  do {    r = KSEM(get)(&THREAD_DATA()->sem, (jlong)0);  } while (!r);    linkNativeAndJavaThread (nativeTid, vmtid);  KSEM(put)(&KTHREAD(get_data)(nativeTid)->sem);    return (tid);}/* * All threads start here. */staticvoidfirstStartThread(void* arg){	Hjava_lang_VMThread* tid;	jthread_t cur;	JNIEnv *env;	jmethodID runmethod;	jthread_t calling_thread = (jthread_t) arg;	threadData *thread_data;	int r;	cur = KTHREAD(current)();	thread_data = KTHREAD(get_data)(cur);	KSEM(init)(&thread_data->sem);	/* We acknowledge the parent thread that this thread has been started. */	KSEM(put)(&KTHREAD(get_data)(calling_thread)->sem);	/* Now we must wait the parent to link the thread to the Java VM. */	do {	  r = KSEM(get)(&thread_data->sem, (jlong)0);	} while (!r); 	tid = (Hjava_lang_VMThread *)(thread_data->jlThread);	env = &thread_data->jniEnv;#if defined(ENABLE_JVMPI)	if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_THREAD_START) )	{		JVMPI_Event ev;		jvmpiFillThreadStart(&ev, tid);		jvmpiPostEvent(&ev);		jvmpiCleanupThreadStart(&ev);	}#endifDBG(VMTHREAD,		dprintf("%p (%p) firstStartThread\n", cur, tid);		    );	/*	 * We use JNI here to make sure the stack is unrolled when we get	 * into the uncaughtException handler.  Otherwise, we wouldn't be	 * able to handle StackOverflowError.	 */	/* Find the run()V method and call it */	runmethod = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, tid),					"run", "()V");	if (runmethod != 0)		(*env)->CallVoidMethod(env, tid, runmethod);	/*	 * We may ignore all exceptions here as it is already handled by VMThread.run().	 */	(*env)->ExceptionClear(env);	exitThread();}/* * Yield process to another thread of equal priority. */voidyieldThread(void){	KTHREAD(yield)();}/* * Change thread priority. * * We assume the call comes from VMThread and so that the field priority has * already been updated. In the other case, there will be a small inconsistency. */voidsetPriorityThread(Hjava_lang_VMThread* tid, jint prio){	/* no native thread yet */	if (unhand(tid)->vmdata == 0)	        return;	KTHREAD(setpriority)((jthread_t)unhand(tid)->vmdata, prio);}/* * Terminate a thread.  This function never returns. */voidexitThread(void){DBG(VMTHREAD,		dprintf("%p (%p) exitThread\n", KTHREAD(current)(), THREAD_DATA()->jlThread);    );#if defined(ENABLE_JVMPI)	if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_THREAD_END) )	{		JVMPI_Event ev;		ev.event_type = JVMPI_EVENT_THREAD_END;		jvmpiPostEvent(&ev);	}#endif	/*	 * This may never return. If it does return, control is returned to	 * the threading implementation where firstStartThread() is called.	 *	 * The threading implementation is responsible for calling	 * KaffeVM_unlinkNativeAndJavaThread() before killing or	 * reusing the thread.	 */	KTHREAD(exit)();}/* * Get the current JavaVM thread. */Hjava_lang_VMThread*getCurrentVMThread(void){	return (Hjava_lang_VMThread *) THREAD_DATA()->jlThread;}/* * Get the current Java thread. */Hjava_lang_Thread*getCurrentThread(void){	Hjava_lang_VMThread *vmtid;	vmtid = getCurrentVMThread();	assert(vmtid != NULL);		return unhand(vmtid)->thread;}/* * Finalize a thread. *  This is to free the native thread context. */voidfinalizeThread(Hjava_lang_VMThread* tid){	jthread_t jtid = (jthread_t)unhand(tid)->vmdata;	if (jtid != NULL) {		KTHREAD(destroy)(jtid);	}}/*  * extract name of a thread as a C string. * Returns static buffer. */char *nameThread(Hjava_lang_VMThread *tid){	static char buf[80];	if (tid != NULL && unhand(tid)->thread != NULL && unhand(unhand(tid)->thread)->name != NULL)	  stringJava2CBuf(unhand(unhand(tid)->thread)->name, buf, sizeof(buf));	else	  strcpy(buf, "<null name>");	return buf;}static void broadcastDeath(void *jlThread){        Hjava_lang_VMThread *vmtid = (Hjava_lang_VMThread *)jlThread;	Hjava_lang_Thread *tid = unhand(vmtid)->thread;        /* Notify on the object just in case anyone is waiting */        lockMutex(&tid->base);        broadcastCond(&tid->base);        unlockMutex(&tid->base);}static voidthrowDeath(void){	throwException(ThreadDeath);}staticvoidrunfinalizer(void){	DBG (VMTHREAD, dprintf ("shutting down %p\n", THREAD_DATA()->jlThread); );	if (THREAD_DATA()->jlThread == 0) {		/* if the thread executing the shutdown hooks doesn't have a		 * java.lang.Thread instance or it was gc'ed in the mean time,		 * create a new one.		 */		KaffeVM_attachFakedThreadInstance("main", false);	}	if (runFinalizerOnExit) {		invokeFinalizer();	}#if defined(ENABLE_JVMPI)	if( JVMPI_EVENT_ISENABLED(JVMPI_EVENT_JVM_SHUT_DOWN) )	{		JVMPI_Event ev;		ev.event_type = JVMPI_EVENT_JVM_SHUT_DOWN;		jvmpiPostEvent(&ev);	}#endif}/* * print info about a java thread. */static voiddumpJavaThread(jthread_t thread, UNUSED void *p){DBG(VMTHREAD,	Hjava_lang_VMThread *tid = (Hjava_lang_VMThread *)KTHREAD(get_data)(thread)->jlThread;	dprintf("`%s' ", nameThread(tid));	KTHREAD(dumpthreadinfo)(thread);	dprintf("\n"););}static voiddumpThreads(void){DBG(VMTHREAD,	dprintf("Dumping live threads:\n");	KTHREAD(walkLiveThreads_r)(dumpJavaThread, NULL););}/* * Return the name of a java thread, given its native thread pointer. */char*nameNativeThread(void* native_data){	return nameThread((Hjava_lang_VMThread*)		KTHREAD(get_data)((jthread_t)native_data)->jlThread);}/* * Invoked when threading system detects a deadlock. */static voidonDeadlock(void){	if (!deadlockDetection) {		return;	}#if defined(JTHREAD_RESTORE_FD)        jthreadRestoreFD(2);#endif	dumpLocks();	dumpThreads();DBG(VMTHREAD,	dprintf("Deadlock: all threads blocked on internal events\n"););	fflush(stderr);	KAFFEVM_ABORT();}voidinitNativeThreads(int nativestacksize){	threadData *thread_data;	rlim_t stackSize;	DBG(INIT, dprintf("initNativeThreads(0x%x)\n", nativestacksize); );	/* Even though the underlying operating or threading system could	 * probably extend the main thread's stack, we must impose this 	 * artificial boundary, because otherwise we wouldn't be able to 	 * catch stack overflow exceptions thrown by the main thread.	 */	threadStackSize = nativestacksize;	KTHREAD(init)(		DBGEXPR(JTHREADNOPREEMPT, false, true),		java_lang_Thread_MAX_PRIORITY+1,		java_lang_Thread_MIN_PRIORITY,		main_collector,		broadcastDeath,		throwDeath,		onDeadlock);	KTHREAD(atexit)(runfinalizer);	/*	 * Doing KTHREAD(createfirst) as early as possible has several advantages:	 *	 * 	- we can rely on a working KTHREAD(current)() and KTHREAD(get_data)()	 *	  everywhere else in the vm, no need to specialcase anything	 *	 *	- catching exceptions during the initialisation is easier now	 *	 * Since everything is stored in the threadData struct now, we can simply	 * attach a faked java.lang.Thread instance later on.	 */#if defined(KAFFEMD_STACKSIZE)	stackSize = mdGetStackSize();	if (stackSize == KAFFEMD_STACK_ERROR)	  {	    fprintf(stderr, "WARNING: Impossible to retrieve the real stack size\n");	    fprintf(stderr, "WARNING: You may experience deadlocks\n");	  }	else if (stackSize == KAFFEMD_STACK_INFINITE || stackSize >= threadStackSize)	  {#ifndef KAFFEMD_DISABLE_SETSTACKSIZE	    mdSetStackSize(threadStackSize);#endif	    /* Last chance. We check whether the size has really been updated. */	    stackSize = mdGetStackSize();	  }	else	  {	    fprintf(stderr, 	            "NOTE: It is impossible to set the main thread stack\n"		    "NOTE: size because the system stack size is too low\n");	  }#else	stackSize = MAINSTACKSIZE;#endif	DBG(INIT, dprintf("Detected stackSize %zu\n", (size_t)stackSize); );	KTHREAD(createfirst)((size_t)stackSize, (unsigned char)java_lang_Thread_NORM_PRIORITY, NULL);	/*	 * initialize some things that are absolutely necessary:	 *    - the semaphore	 *    - the jniEnv         */	thread_data = THREAD_DATA(); 	KSEM(init)(&thread_data->sem);	thread_data->jnireferences = NULL;	thread_data->jniEnv = &Kaffe_JNINativeInterface;	DBG(INIT, dprintf("initNativeThreads(0x%x) done\n", nativestacksize); );}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?