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

📄 jthread.c

📁 java virtual machince kaffe
💻 C
📖 第 1 页 / 共 5 页
字号:
{	if( jt != currentJThread )	{		intsDisable();		if( jt->suspender == suspender )		{			assert(jt->suspendCount > 0);						jt->suspendCount -= 1;			if( jt->suspendCount == 0 )			{				if( jt->status == THREAD_RUNNING )				{					jt->status = THREAD_SUSPENDED;				}				resumeThread(jt);				jt->suspender = NULL;			}		}		intsRestore();	}}jthread_t jthread_from_data(threadData *td, void *suspender){	jthread_t retval = NULL;	intsDisable();	{		KaffeNodeQueue *curr;		jthread_t tid;				for( curr = liveThreads;		     (curr != NULL) && (retval == NULL);		     curr = curr->next)		{		        tid = JTHREADQ(curr);			if( &tid->localData == td )			{				if( tid != currentJThread )				{					jthread_suspend(tid, suspender);				}				retval = tid;			}		}	}	intsRestore();		return( retval );}/*============================================================================ * * 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);}#elsestatic void activate_time_slicing(void) { }#endif/** * Thread allocation function alias. */static void *thread_static_allocator(size_t bytes){	return KGC_malloc(threadCollector, bytes, KGC_ALLOC_STATIC_THREADDATA);}static void thread_static_free(void *p){	return KGC_free(threadCollector, p);}static void *thread_reallocator(void *p, size_t bytes){	return KGC_realloc(threadCollector, p, bytes, KGC_ALLOC_STATIC_THREADDATA);}/* * Initialize the threading system.  */voidjthread_init(int pre,	int maxpr, int minpr,	Collector *collector,	void (*_destructor1)(void*),	void (*_onstop)(void),	void (*_ondeadlock)(void)){        jthread *jtid; 	int i;	threadCollector = collector;	blockInts = 0;	/* 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.	 */	KaffeJThread_ignoreSignal(SIGHUP);	KaffeSetDefaultAllocator(thread_static_allocator, thread_static_free, thread_reallocator);	queuePool = KaffeCreatePool();#if defined(SIGVTALRM)	registerAsyncSignalHandler(SIGVTALRM, interrupt);#endif	registerAsyncSignalHandler(SIGALRM, interrupt);	registerAsyncSignalHandler(SIGIO, interrupt);        registerAsyncSignalHandler(SIGCHLD, interrupt);        registerAsyncSignalHandler(SIGUSR1, interrupt);        registerAsyncSignalHandler(SIGUSR2, 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;	onstop = _onstop;	ondeadlock = _ondeadlock;	destructor1 = _destructor1;	threadQhead = (KaffeNodeQueue **)thread_static_allocator((maxpr + 1) * sizeof (KaffeNodeQueue *));	threadQtail = (KaffeNodeQueue **)thread_static_allocator((maxpr + 1) * sizeof (KaffeNodeQueue *));	for (i=0;i<FD_SETSIZE;i++) {	  readQ[i] = writeQ[i] = NULL;	  blockingFD[i] = true;	}	alarmList = NULL;	waitForList = NULL;	for (i=0;i<=maxpr;i++)	  threadQhead[i] = threadQtail[i] = NULL;	/* 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;        	liveThreads = KaffePoolNewNode(queuePool);	liveThreads->element = jtid;        jtid->time = 0;        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();	jmutex_initialise(&GClock);}jthread_tjthread_createfirst(size_t mainThreadStackSize, unsigned int 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.	 */	detectStackBoundaries(jtid, mainThreadStackSize);	jtid->localData.jlThread = jlThread;	jthread_setpriority(jtid, prio);	firstThread = jtid;	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) {	  /* DBG(JTHREAD,	dprintf("disable stop for thread  %p\n", currentJThread);	) */		intsDisable();		currentJThread->flags |= THREAD_FLAGS_DONTSTOP;		currentJThread->stopCounter++;		assert(currentJThread->stopCounter > 0);		/* XXX Shouldn't recurse that much... ever... hopefully. */		assert(currentJThread->stopCounter < 50);  		intsRestore();	}}/* * reallow cancellation and stop if cancellation pending */void jthread_enable_stop(void){	if (currentJThread) {	  /* DBG(JTHREAD,	dprintf("enable stop for thread  %p\n", 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();	/* mark thread as interrupted */	jtid->flags |= THREAD_FLAGS_INTERRUPTED;	/* make sure we only resume suspended threads 	 * (and neither dead nor runnable threads) that	 * are not trying to acquire a mutex.	 */	if ((jtid->status == THREAD_SUSPENDED) && !jthread_on_mutex(jtid)) {		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->localData.jlThread);	jthread_exit(); }/* * create a new jthread */jthread *jthread_create(unsigned int pri, void (*func)(void *), int isDaemon,        void *jlThread, size_t threadStackSize){        KaffeNodeQueue *liveQ;	jthread *jtid; 	void	*oldstack, *newstack;#if defined(__ia64__)	void	*oldbsp, *newbsp;#endif	size_t   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();	/* Adjust stack size */	page_size = getpagesize();	if (threadStackSize == 0)		threadStackSize = THREADSTACKSIZE;	threadStackSize = (threadStackSize + page_size - 1) & (uintp)-page_size;	jmutex_lock(&threadLock);	jtid = newThreadCtx(threadStackSize);	if (!jtid) {		jmutex_unlock(&threadLock);		jthread_enable_stop();		return 0;	}        jtid->priority = pri;        jtid->localData.jlThread = jlThread;        jtid->status = THREAD_SUSPENDED;        jtid->flags = THREAD_FLAGS_GENERAL;	jtid->blockqueue = NULL;	liveQ = KaffePoolNewNode(queuePool);	liveQ->next = liveThreads;	liveQ->element = jtid;	liveThreads = liveQ;        talive++;               if ((jtid->daemon = isDaemon) != 0) {                tdaemon++;        }DBG(JTHREAD,	dprintf("creating thread %p, daemon=%d\n", jtid, isDaemon); );	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_CONTEXT_SAVE(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(jtid->env);#if defined(__ia64__)	oldbsp = GET_BSP(jtid->env);#endif#if defined(STACK_GROWS_UP)	newstack = jtid->stackBase+STACK_COPY;	memcpy(newstack-STACK_COPY, oldstack-STACK_COPY, STACK_COPY);#else /* !STACK_GROWS_UP */	newstack = jtid->stackEnd;#if defined(__ia64__)	/*	 * The stack segment is split in the middle. The upper half is used	 * as backing store for the register stack which grows upward.	 * The lower half is used for the traditional memory stack which	 * grows downward. Both stacks start in the middle and grow outward	 * from each other.	 */	newstack = (void *)((uintp)newstack - (threadStackSize >> 1));	newbsp = newstack;	/* Make register stack 64-byte aligned */	if ((unsigned long)newbsp & 0x3f)		newbsp = newbsp + (0x40 - ((unsigned long)newbsp & 0x3f));	newbsp += STACK_COPY;	memcpy(newbsp-STACK_COPY, oldbsp-STACK_COPY, STACK_COPY);#endif	newstack = (void *)((uintp)newstack - STACK_COPY);	memcpy(newstack, oldstack, STACK_COPY);#endif /* !STACK_GROWS_UP */#if defined(NEED_STACK_ALIGN)	newstack = (void *) STACK_ALIGN(newstack);#endif	SET_SP(jtid->env, newstack);#if defined(__ia64__)	SET_BSP(jtid->env, newbsp);#endif#if defined(SET_BP)	/*	 * Clear the base pointer in the new thread's stack.	 * Nice for debugging, but not strictly necessary.	 */	SET_BP(jtid->env, 0);#endif#if defined(FP_OFFSET)	/* needed for: IRIX */	SET_FP(jtid->env, newstack + ((void *)GET_FP(jtid->env) - oldstack));#endif        resumeThread(jtid);	jthread_enable_stop();        return jtid;}/*============================================================================ * * Functions that are part of the user interface * *//* * return the current thread */jthread_tjthread_current(void){       return currentJThread;}/* * determine whether a location is on the stack of the current thread */intjthread_on_current_stack(void *bp){        int rc = bp >= currentJThread->stackBase && bp < currentJThread->stackEnd;DBG(JTHREADDETAIL,       dprintf("on current stack: base=%p size=%ld bp=%p %s\n",               currentJThread->stackBase,               (long)((char *) currentJThread->stackEnd - (char *) currentJThread->stackBase),               bp,               (rc ? "yes" : "no"));    );        return rc;}/* * Check for room on stack. */intjthread_stackcheck(int left){       int rc;#if defined(STACK_GROWS_UP)        rc = jthread_on_current_stack((char*)&rc + left);#else        rc = jthread_on_current_stack((char*)&rc - left);#endif       return (rc);}/* * Get the current stack limit. */#define        REDZONE 1024voidjthread_relaxstack(int yes){       if( yes )       {#if defined(STACK_GROWS_UP)               uintp end = (uintp) currentJThread->stackEnd;               end += REDZONE;               currentJThread->stackEnd = (void *) end;#else               uintp base = (uintp) currentJThread->stackBase;               base -= REDZONE;               currentJThread->stackBase = (void *) base;#endif       }       else       {#if defined(STACK_GROWS_UP)               uintp end = (uintp) currentJThread->stackEnd;               end -= REDZONE;               currentJThread->stackEnd = (void *) end;#else               uintp base = (uintp) currentJThread->stackBase;

⌨️ 快捷键说明

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