⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jthread.c

📁 kaffe是一个java虚拟机的源代码。里面包含了一些java例程和标准的java包。
💻 C
📖 第 1 页 / 共 4 页
字号:
	case SIGUSR1:		ondeadlock();		break;#if defined(SIGVTALRM)	case SIGVTALRM:		handleVtAlarm(sig, sc);		break;#endif	case SIGCHLD:		childDeath();		break;	case SIGIO:		handleIO(false);		break;	default:		dprintf("unknown signal %d\n", sig);		exit(-1);	}}/*============================================================================ * * Functions related to run queue manipulation *//* * Resume a thread running. * This routine has to be called only from locations which ensure * run / block queue consistency. There is no check for illegal resume * conditions (like explicitly resuming an IO blocked thread).  */static voidresumeThread(jthread* jtid){	jthread** ntid;DBG(JTHREAD,	dprintf("resumeThread %p\n", jtid);	)	intsDisable();	if (jtid->status != THREAD_RUNNING) {		CLEAR_BLOCKED_ON_EXTERNAL(jtid);		/* Remove from alarmQ if necessary */		if ((jtid->flags & THREAD_FLAGS_ALARM) != 0) {			removeFromAlarmQ(jtid);		}		/* Remove from lockQ if necessary */		if (jtid->blockqueue != 0) {			for (ntid = jtid->blockqueue; 				*ntid != 0; 				ntid = &(*ntid)->nextQ) 			{				if (*ntid == jtid) {					*ntid = jtid->nextQ;					break;				}			}			jtid->blockqueue = 0;		}		jtid->status = THREAD_RUNNING;		/* Place thread on the end of its queue */		if (threadQhead[jtid->priority] == 0) {			threadQhead[jtid->priority] = jtid;			threadQtail[jtid->priority] = jtid;			if (jtid->priority > currentJThread->priority) {				needReschedule = true;			}		}		else {			threadQtail[jtid->priority]->nextQ = jtid;			threadQtail[jtid->priority] = jtid;		}		jtid->nextQ = 0;	} else {DBG(JTHREAD,		dprintf("Re-resuming %p\n", jtid); )	}	intsRestore();}/* * Suspend a thread on a queue. * Return true if thread was interrupted. */static intsuspendOnQThread(jthread* jtid, jthread** queue, jlong timeout){	int rc = false;	jthread** ntid;	jthread* last;DBG(JTHREAD,	dprintf("suspendOnQThread %p %p (%qd) bI %d\n", 	jtid, queue, timeout, blockInts); )	assert(intsDisabled());	if (jtid->status != THREAD_SUSPENDED) {		jtid->status = THREAD_SUSPENDED;		last = 0;		for (ntid = &threadQhead[jtid->priority]; 			*ntid != 0; 			ntid = &(*ntid)->nextQ) 		{			if (*ntid == jtid) {				/* Remove thread from runq */				*ntid = jtid->nextQ;				if (*ntid == 0) {					threadQtail[jtid->priority] = last;				}				/* Insert onto head of lock wait Q */				if (queue != 0) {					jtid->nextQ = *queue;					*queue = jtid;					jtid->blockqueue = queue;				}				/* If I have a timeout, insert into alarmq */				if (timeout > NOTIMEOUT) {					addToAlarmQ(jtid, timeout);				}				/* If I was running, reschedule */				if (jtid == currentJThread) {					reschedule();					if (jtid->flags & THREAD_FLAGS_INTERRUPTED) {						jtid->flags &= ~THREAD_FLAGS_INTERRUPTED;						rc = true;					}				}				break;			}			last = *ntid;		}	} else {	DBG(JTHREAD,			dprintf("Re-suspending %p on %p\n", jtid, *queue); )	}	return (rc);}/* * Kill thread. */static void killThread(jthread *tid){	jthread	**ntid;	jthread* last;	intsDisable();	/* allow thread to perform any action before being killed -	 * such as notifying on the object 	 */	if (destructor1)		(*destructor1)(tid->jlThread);DBG(JTHREAD,		dprintf("killThread %p kills %p\n", currentJThread, tid); )	if (tid->status != THREAD_DEAD) {		/* Get thread off runq (if it needs it) */		if (tid->status == THREAD_RUNNING) {			int pri = tid->priority;			last = 0;			for (ntid = &threadQhead[pri]; 				*ntid != 0; 				ntid = &(*ntid)->nextQ) 			{				if (*ntid == tid) {					*ntid = tid->nextQ;					if (*ntid == 0)						threadQtail[pri] = last;						break;				}				last = *ntid;			}		}		/* Run something else */		if (currentJThread == tid) {			needReschedule = true;			blockInts = 1;		}		/* Now that we are off the runQ, it is safe to leave		 * the list of live threads and be GCed.		 */		/* Remove thread from live list so it can be garbaged */		for (ntid = &liveThreads; *ntid != 0; ntid =			     &(*ntid)->nextlive) { 			if (tid == (*ntid)) {				(*ntid) = tid->nextlive;				break;			}		}		/* Dead Jim - let the GC pick up the remains */		tid->status = THREAD_DEAD;	}	intsRestore();}/*============================================================================ * * Functions dealing with thread contexts and the garbage collection interface * *//* * Allocate a new thread context and stack. */static jthread*newThreadCtx(int stackSize){	jthread *ct;	ct = allocator(sizeof(jthread) + stackSize);	if (ct == 0) {		return 0;	}	ct->stackBase = (ct + 1);	ct->stackEnd = ct->stackBase + stackSize;	ct->restorePoint = ct->stackEnd;	ct->status = THREAD_SUSPENDED;DBG(JTHREAD,	dprintf("allocating new thread, stack base %p-%p\n", 	    ct->stackBase, ct->stackEnd); )	return (ct);}/* * free a thread context and its stack */void    jthread_destroy(jthread *jtid){	jthread *x;	if (DBGEXPR(JTHREAD, true, false)) {		for (x = liveThreads; x; x = x->nextlive)			assert(x != jtid);	}	deallocator(jtid);}/* * iterate over all live threads */voidjthread_walkLiveThreads(void (*func)(void *jlThread)){        jthread* tid;        for (tid = liveThreads; tid != NULL; tid = tid->nextlive) {                func(tid->jlThread);        }}/* * determine the interesting stack range for a conservative gc */intjthread_extract_stack(jthread *jtid, void **from, unsigned *len){	assert(jtid != NULL);#if defined(STACK_GROWS_UP)	*from = jtid->stackBase;	*len = jtid->restorePoint - jtid->stackBase;#else   	*from = jtid->restorePoint;	*len = jtid->stackEnd - jtid->restorePoint;#endif	return (1);}/*  * XXX this is supposed to count the number of stack frames  */intjthread_frames(jthread *thrd){        return (0);}/*============================================================================ * * Functions for initialization and thread creation * */#if defined(HAVE_SETITIMER) && defined(ITIMER_VIRTUAL)/* * set virtual timer for 10ms round-robin time-slicing */static voidactivate_time_slicing(void){	struct itimerval tm;	tm.it_interval.tv_sec = tm.it_value.tv_sec = 0;	tm.it_interval.tv_usec = tm.it_value.tv_usec = 10000;/* 10 ms */	setitimer(ITIMER_VIRTUAL, &tm, 0);}/* * deactivate virtual timer */static voiddeactivate_time_slicing(void){	struct itimerval tm;	tm.it_interval.tv_sec = tm.it_value.tv_sec = 0;	tm.it_interval.tv_usec = tm.it_value.tv_usec = 0;	setitimer(ITIMER_VIRTUAL, &tm, 0);}#elsestatic void activate_time_slicing(void) { }static void deactivate_time_slicing(void) { }#endif/* * Initialize the threading system.  */voidjthread_init(int pre,	int maxpr, int minpr,	void *(*_allocator)(size_t), 	void (*_deallocator)(void*),	void (*_destructor1)(void*),	void (*_onstop)(void),	void (*_ondeadlock)(void)){        jthread *jtid; 	int i;	/* XXX this is f***ed.  On BSD, we get a SIGHUP if we try to put	 * a process that has a pseudo-tty in async mode in the background	 * So we'll just ignore it and keep running.  Note that this will	 * detach us from the session too.	 */	ignoreSignal(SIGHUP);#if defined(SIGVTALRM)	registerAsyncSignalHandler(SIGVTALRM, interrupt);#endif	registerAsyncSignalHandler(SIGALRM, interrupt);	registerAsyncSignalHandler(SIGIO, interrupt);        registerAsyncSignalHandler(SIGCHLD, interrupt);        registerAsyncSignalHandler(SIGUSR1, interrupt);	/* 	 * If debugging is not enabled, set stdin, stdout, and stderr in 	 * async mode.	 *	 * If debugging is enabled and ASYNCSTDIO is not given, do not	 * put them in async mode.	 *	 * If debugging is enabled and ASYNCSTDIO is given, put them in	 * async mode (as if debug weren't enabled.)	 *	 * This is useful because large amounts of fprintfs might be	 * not be seen if the underlying terminal is put in asynchronous	 * mode.  So by default, when debugging, we want stdio be synchronous.	 * To override this, give the ASYNCSTDIO flag.	 */#ifndef _HURD_ASYNC_QUICKFIX_	if (DBGEXPR(ANY, DBGEXPR(ASYNCSTDIO, true, false), true)) {		for (i = 0; i < 3; i++) {			if (i != jthreadedFileDescriptor(i)) {				return;			}		}	}#endif	/*	 * On some systems, it is essential that we put the fds back	 * in their non-blocking state	 */	atexit(restore_fds);	registerTerminalSignal(SIGINT, restore_fds_and_exit);	registerTerminalSignal(SIGTERM, restore_fds_and_exit);	preemptive = pre;	max_priority = maxpr;	min_priority = minpr;	allocator = _allocator;	deallocator = _deallocator;	onstop = _onstop;	ondeadlock = _ondeadlock;	destructor1 = _destructor1;	threadQhead = allocator((maxpr + 1) * sizeof (jthread *));	threadQtail = allocator((maxpr + 1) * sizeof (jthread *));	/* create the helper pipe for lost wakeup problem */	if (pipe(sigPipe) != 0) {		return;	}	if (maxFd == -1) {		maxFd = sigPipe[0] > sigPipe[1] ? sigPipe[0] : sigPipe[1];	}	jtid = newThreadCtx(0);	if (!jtid) {		return;	}	/* Fake up some stack bounds until we get the real ones later - we're	 * the only thread running so this isn't a problem.	 */	jtid->stackBase = 0;	jtid->stackEnd = (char*)0 - 1;#if defined(STACK_GROWS_UP)        jtid->restorePoint = jtid->stackEnd;#else        jtid->restorePoint = jtid->stackBase;#endif        jtid->priority = maxpr;        jtid->status = THREAD_SUSPENDED;        jtid->flags = THREAD_FLAGS_NOSTACKALLOC;        jtid->func = (void (*)(void*))jthread_init;        jtid->nextlive = liveThreads;        jtid->time = 0;        liveThreads = jtid;        talive++;        currentJThread = jtid;        resumeThread(jtid);#if defined(KAFFE_XPROFILER)	/*	 * The profiler is started at program startup, we take over from here	 * on out so we disable whatever one was installed	 */	disableProfileTimer();#endif	/* Because of the handleVtAlarm hack (poll every 20 SIGVTALRMs) 	 * we turn on the delivery of SIGVTALRM even if no actual time	 * slicing is possible because only one Java thread is running.	 * XXX We should be smarter about that.	 */	activate_time_slicing();}jthread_tjthread_createfirst(size_t mainThreadStackSize, unsigned char prio, void* jlThread){        jthread *jtid; 	jtid = currentJThread;	/*	 * Note: the stackBase and stackEnd values are used for two purposes:	 * - to report to the gc what area to scan (extract_stack)	 * - to help in determining whether the next frame in the link chain	 *   of frames is valid.  This is done by checking its range.	 */#if defined(STACK_GROWS_UP)	jtid->stackBase = (void*)((uintp)&jtid & -0x1000);	jtid->stackEnd = jtid->stackBase + mainThreadStackSize;        jtid->restorePoint = jtid->stackEnd;#else	jtid->stackEnd = (void*)(((uintp)&jtid + 0x1000 - 1) & -0x1000);        jtid->stackBase = jtid->stackEnd - mainThreadStackSize;        jtid->restorePoint = jtid->stackBase;#endif	jtid->jlThread = jlThread;	jthread_setpriority(jtid, prio);	return (jtid);}/* * set a function to be run when all non-daemon threads have exited */void jthread_atexit(void (*f)(void)){	runOnExit = f;}/* * disallow cancellation */void jthread_disable_stop(void){	if (currentJThread) {		intsDisable();		currentJThread->flags |= THREAD_FLAGS_DONTSTOP;		currentJThread->stopCounter++;		assert(currentJThread->stopCounter > 0);		/* XXX Shouldn't recurse that much... ever... hopefully. */		assert(currentJThread->stopCounter < 10);  		intsRestore();	}}/* * reallow cancellation and stop if cancellation pending */void jthread_enable_stop(void){	if (currentJThread) {		intsDisable();		if (--currentJThread->stopCounter == 0) {			currentJThread->flags &= ~THREAD_FLAGS_DONTSTOP;			if ((currentJThread->flags & THREAD_FLAGS_KILLED) != 0			   && ((currentJThread->flags & THREAD_FLAGS_EXITING) 			   	== 0))			{				die();			}		}		assert(currentJThread->stopCounter >= 0);		intsRestore();	}}/* * interrupt a thread */voidjthread_interrupt(jthread *jtid){	intsDisable();	/* make sure we only resume suspended threads 	 * (and neither dead nor runnable threads)	 */	if (jtid != currentJThread && jtid->status == THREAD_SUSPENDED) {		jtid->flags |= THREAD_FLAGS_INTERRUPTED;		resumeThread(jtid);	}	intsRestore();}static void die(void){	currentJThread->flags &= ~THREAD_FLAGS_KILLED;	currentJThread->flags |= THREAD_FLAGS_DYING;	assert(blockInts == 1);	blockInts = 0;	/* this is used to throw a ThreadDeath exception */	onstop();	assert(!"Rescheduling dead thread");}static voidstart_this_sucker_on_a_new_frame(void){	/* all threads start with interrupts turned off */	blockInts = 1;	/* I might be dying already */	if ((currentJThread->flags & THREAD_FLAGS_KILLED) != 0) {		die();	}	intsRestore();	assert(currentJThread->stopCounter == 0);	currentJThread->func(currentJThread->jlThread);	jthread_exit(); }/* * create a new jthread */jthread *jthread_create(unsigned char pri, void (*func)(void *), int daemon,        void *jlThread, size_t threadStackSize){	jthread *jtid; 	void	*oldstack, *newstack;#if defined(__ia64__)	void	*oldbsp, *newbsp;#endif	size_t   page_size;		/* Adjust stack size */	page_size = getpagesize();	if (threadStackSize == 0)		threadStackSize = THREADSTACKSIZE;	threadStackSize = (threadStackSize + page_size - 1) & -page_size;	/*	 * Disable stop to protect the threadLock lock, and prevent	 * the system from losing a new thread context (before the new	 * thread is queued up).	 */	jthread_disable_stop();	jmutex_lock(&threadLock);	jtid = newThreadCtx(threadStackSize);	if (!jtid) {		jmutex_unlock(&threadLock);		jthread_enable_stop();		return 0;	}        jtid->priority = pri;        jtid->jlThread = jlThread;        jtid->status = THREAD_SUSPENDED;        jtid->flags = THREAD_FLAGS_GENERAL;        jtid->nextlive = liveThreads;        liveThreads = jtid;        talive++;               if ((jtid->daemon = daemon) != 0) {                tdaemon++;        }DBG(JTHREAD,	dprintf("creating thread %p, daemon=%d\n", jtid, daemon); )	jmutex_unlock(&threadLock);        assert(func != 0);         jtid->func = func;	/* 	 * set the first jmp point 	 *	 * Note that when we return from setjmp in the context of	 * a new thread, we must no longer access any local variables	 * in this function.  The reason is that we didn't munge	 * the base pointer that is used to access these variables.	 *	 * To be safe, we immediately call a new function.	 */        if (JTHREAD_SETJMP(JTHREAD_ACCESS_JMPBUF(jtid, env))) {		/* new thread */		start_this_sucker_on_a_new_frame();		assert(!"Never!");		/* NOT REACHED */	} #if defined(SAVE_FP)	SAVE_FP(jtid->fpstate);#endif	/* set up context for new thread */	oldstack = GET_SP(JTHREAD_ACCESS_JMPBUF(jtid, env));#if defined(__ia64__)	oldbsp = GET_BSP(JTHREAD_ACCESS_JMPBUF(jtid, env));#endif#if defined(STACK_GROWS_UP)

⌨️ 快捷键说明

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