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

📄 jthread.c

📁 kaffe是一个java虚拟机的源代码。里面包含了一些java例程和标准的java包。
💻 C
📖 第 1 页 / 共 4 页
字号:
	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 -= (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 -= STACK_COPY;	memcpy(newstack, oldstack, STACK_COPY);#endif /* !STACK_GROWS_UP */#if defined(NEED_STACK_ALIGN)	newstack = (void *) STACK_ALIGN(newstack);#endif	SET_SP(JTHREAD_ACCESS_JMPBUF(jtid, env), newstack);#if defined(__ia64__)	SET_BSP(JTHREAD_ACCESS_JMPBUF(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(JTHREAD_ACCESS_JMPBUF(jtid, env), 0);#endif#if defined(FP_OFFSET)	/* needed for: IRIX */	SET_FP(JTHREAD_ACCESS_JMPBUF(jtid, env), newstack + ((void *)GET_FP(JTHREAD_ACCESS_JMPBUF(jtid, env)) - oldstack));#endif        resumeThread(jtid);	jthread_enable_stop();        return jtid;}/*============================================================================ * * Functions that are part of the user interface * *//* * yield to a thread of equal priority */voidjthread_yield(void){        intsDisable();        internalYield();        intsRestore();}/*       * sleep for time milliseconds */     voidjthread_sleep(jlong time){        if (time == 0) {                return;         }        intsDisable();	BLOCKED_ON_EXTERNAL(currentJThread);        suspendOnQThread(currentJThread, 0, time);        intsRestore();}/*  * Check whether a thread is alive. * * Note that threads executing their onstop function are not alive. */intjthread_alive(jthread *jtid){        int status = true;        intsDisable();        if (jtid == 0#if 0	    /* this code makes kaffe behave like sun, but it means	     * that Thread.join() after Thread.stop() is useless.	     */	    || (jtid->flags & (THREAD_FLAGS_KILLED | THREAD_FLAGS_DYING)) != 0 #else	    /* There seems to be a window in which death can be	     * broadcast before it is waited for.  Basically,	     * jthread_alive will be false immediately after	     * Thread.stop(), unless stopping the thread was	     * disabled.  Thread.alive() will become false as soon as	     * the thread is on its way out.	     */	    || (jtid->flags & (THREAD_FLAGS_DYING | THREAD_FLAGS_EXITING))#endif	    || jtid->status == THREAD_DEAD)                status = false;        intsRestore();        return status;}/* * Change thread priority. */voidjthread_setpriority(jthread* jtid, int prio){	jthread** ntid;	jthread* last;	if (jtid->status == THREAD_SUSPENDED) {		jtid->priority = (unsigned char)prio;		return;	}	intsDisable();	/* Remove from current thread list */	last = 0;	for (ntid = &threadQhead[jtid->priority]; 		*ntid != 0; 		ntid = &(*ntid)->nextQ) 	{		if (*ntid == jtid) {			*ntid = jtid->nextQ;			if (*ntid == 0) {				threadQtail[jtid->priority] = last;			}			break;		}		last = *ntid;	}	/* Insert onto a new one */	jtid->priority = (unsigned char)prio;	if (threadQhead[prio] == 0) {		threadQhead[prio] = jtid;		threadQtail[prio] = jtid;	}	else {		threadQtail[prio]->nextQ = jtid;		threadQtail[prio] = jtid;	}	jtid->nextQ = 0;	/* If I was rescheduled, or something of greater priority was,	 * insist on a reschedule.	 */	if (jtid == currentJThread || prio > currentJThread->priority) {		needReschedule = true;	}	intsRestore();}/* * Stop a thread in its tracks. */voidjthread_stop(jthread *jtid){	intsDisable();	/* No reason to hit a dead man over the head */	if (jtid->status != THREAD_DEAD) {		jtid->flags |= THREAD_FLAGS_KILLED;	}	/* if it's us, die */	if (jtid == jthread_current() && 		(jtid->flags & THREAD_FLAGS_DONTSTOP) != 0 && blockInts == 1)		die();        resumeThread(jtid);	intsRestore();}/* * Have a thread exit.  This function does not return. */voidjthread_exit(void){	jthread* tid;DBG(JTHREAD,	dprintf("jthread_exit %p\n", currentJThread);		)	jthread_disable_stop();	jmutex_lock(&threadLock);	talive--;	if (currentJThread->daemon) {		tdaemon--;	}	assert(!(currentJThread->flags & THREAD_FLAGS_EXITING));	currentJThread->flags |= THREAD_FLAGS_EXITING;	jmutex_unlock(&threadLock);	jthread_enable_stop();	/* we disable interrupts while we go out to prevent a reschedule	 * in killThread()	 */	intsDisable();	/* If we only have daemons left, then we should exit. */	if (talive == tdaemon) {DBG(JTHREAD,	dprintf("all done, closing shop\n");	)		if (runOnExit != 0) {		    runOnExit();		}		for (tid = liveThreads; tid != 0; tid = tid->nextlive) {			/* The current thread is still on the live			 * list, and we don't want to recursively			 * suicide.			 */			if (!(tid->flags & THREAD_FLAGS_EXITING))				killThread(tid);		}		EXIT(0);	}	for (;;) {		killThread(currentJThread);		jthread_sleep(1000);	}}/* * have main thread wait for all threads to finish */void jthread_exit_when_done(void){        while (talive > 1)		jthread_yield();	jthread_exit();}/* * Reschedule the thread. * Called whenever a change in the running thread is required. */voidreschedule(void){	int i;	jthread* lastThread;	int b;	/* A reschedule in a non-blocked context is half way to hell */	assert(intsDisabled());	b = blockInts;	for (;;) {	        for (i = max_priority; i >= min_priority; i--) {			if (threadQhead[i] == 0) 			    continue;			if (threadQhead[i] != currentJThread) {				lastThread = currentJThread;				currentJThread = threadQhead[i];DBG(JTHREADDETAIL,dprintf("switch from %p to %p\n", lastThread, currentJThread); )				/* save and restore floating point state */#if defined(SAVE_FP)				SAVE_FP(lastThread->fpstate);#endif#if defined(CONTEXT_SWITCH)				CONTEXT_SWITCH(lastThread, currentJThread);#else				if (JTHREAD_SETJMP(JTHREAD_ACCESS_JMPBUF(lastThread, env)) == 0) {				    lastThread->restorePoint = GET_SP(JTHREAD_ACCESS_JMPBUF(lastThread, env));				    JTHREAD_LONGJMP(JTHREAD_ACCESS_JMPBUF(currentJThread, env), 1);				}#endif#if defined(LOAD_FP)				LOAD_FP(currentJThread->fpstate);#endif				/* Restore ints */				blockInts = b;				assert(currentJThread == lastThread);				/* Now handle external requests for cancelation				 * We do not act upon them if:				 * + The thread has the DONTSTOP flags set.				 * + The threads is already exiting				 */				if ((currentJThread->flags & 					THREAD_FLAGS_KILLED) != 0 && 				    (currentJThread->flags & 					THREAD_FLAGS_DONTSTOP) == 0 &&				    (currentJThread->flags & 					THREAD_FLAGS_EXITING) == 0 &&				    blockInts == 1) 				{					die();				}			}			/* Now kill the schedule */			needReschedule = false;			return;		}		/* since we set `wouldlosewakeup' first, we might write into		 * the pipe but not go to handleIO at all.  That's okay ---		 * all it means is that we'll return from the next select()		 * for no reason.  handleIO will eventually drain the pipe.		 */		wouldlosewakeup = 1;		if (sigPending) {			wouldlosewakeup = 0;			processSignals();			continue;		}#if defined(DETECTDEADLOCK)		if (tblocked_on_external == 0) {			ondeadlock();		}#endif		/* if we thought we should reschedule, but there's no thread		 * currently runnable, reset needReschedule and wait for another		 * event that will set it again.		 */		needReschedule = false;		handleIO(true);	}}/*============================================================================ *  * I/O interrupt related functions * *//* * resume all threads blocked on a given queue */static voidresumeQueue(jthread *queue){	jthread *tid, *ntid;	for (tid = queue; tid != 0; tid = ntid) {		ntid = tid->nextQ;		tid->blockqueue = 0;		resumeThread(tid);	}}/* * Process incoming SIGIO * return 1 if select was interrupted */staticvoidhandleIO(int sleep){	int r;	/* NB: both pollarray and rd, wr are thread-local */#if USE_POLL	/* for poll(2) */	int nfd;#if DONT_USE_ALLOCA	struct pollfd pollarray[FD_SETSIZE];	/* huge (use alloca?) */#else	struct pollfd *pollarray = alloca(sizeof(struct pollfd) * (maxFd+1));#endif#else	/* for select(2) */	fd_set rd;	fd_set wr;	struct timeval zero = { 0, 0 };#endif	int i, b = 0;	assert(intsDisabled());DBG(JTHREADDETAIL,	dprintf("handleIO(sleep=%d)\n", sleep);		)#if USE_POLL	/* Build pollarray from fd_sets.	 * This is probably not the most efficient way to handle this.	 */	for (nfd = 0, i = 0; i <= maxFd; i++) {		short ev = 0;		if (readQ[i] != 0) { 	/* FD_ISSET(i, &readsPending) */			ev |= POLLIN;			assert(FD_ISSET(i, &readsPending));		}		if (writeQ[i] != 0) {   /* FD_ISSET(i, &writesPending) */			ev |= POLLOUT;			assert(FD_ISSET(i, &writesPending));		}		if (ev != 0) {			pollarray[nfd].fd = i;			pollarray[nfd].events = ev;			nfd++;		}	}#else	FD_COPY(&readsPending, &rd);	FD_COPY(&writesPending, &wr);#endif	/*	 * figure out which fds are ready	 */retry:	if (sleep) {		b = blockInts;		/* NB: BEGIN unprotected region */		blockInts = 0;		/* add sigpipe[0] if needed */#if USE_POLL		pollarray[nfd].fd = sigPipe[0];		pollarray[nfd].events = POLLIN;		nfd++;#else		FD_SET(sigPipe[0], &rd);#endif	}#if USE_POLL	r = poll(pollarray, nfd, sleep ? -1 : 0);#else	r = select(maxFd+1, &rd, &wr, 0, sleep ? 0 : &zero);#endif	/* Reset wouldlosewakeup here */	wouldlosewakeup = 0; 	if (sleep) {		int can_read_from_pipe = 0;		blockInts = b;		/* NB: END unprotected region */#if USE_POLL		can_read_from_pipe = (pollarray[--nfd].revents & POLLIN);#else		can_read_from_pipe = FD_ISSET(sigPipe[0], &rd);#endif		/* drain helper pipe if a byte was written */		if (r > 0 && can_read_from_pipe) {			char c;			/* NB: since "rd" is a thread-local variable, it can 			 * still say that we should read from the pipe when 			 * in fact another thread has already read from it.			 * That's why we count how many bytes go in and out.			 */			if (bytesInPipe > 0) {				read(sigPipe[0], &c, 1);				bytesInPipe--;			}		}		if (sigPending) {			processSignals();		}	}	if ((r < 0 && errno == EINTR) && !sleep) 		goto retry;	if (r <= 0)		return;DBG(JTHREADDETAIL,	dprintf("Select returns %d\n", r);			)#if USE_POLL	for (i = 0; r > 0 && i < nfd; i++) {		int fd;		register short rev = pollarray[i].revents;		if (rev == 0) {			continue;		}		fd = pollarray[i].fd;		needReschedule = true;		r--;		/* If there's an error, we don't know whether to wake		 * up readers or writers.  So wake up both if so.		 * Note that things such as failed connect attempts		 * are reported as errors, not a read or write readiness.		 */		/* wake up readers when not just POLLOUT */		if (rev != POLLOUT && readQ[fd] != 0) {			resumeQueue(readQ[fd]);			readQ[fd] = 0;		}		/* wake up writers when not just POLLIN */		if (rev != POLLIN && writeQ[fd] != 0) {			resumeQueue(writeQ[fd]);			writeQ[fd] = 0;		}	}#else	for (i = 0; r > 0 && i <= maxFd; i++) {		if (readQ[i] != 0 && FD_ISSET(i, &rd)) {			needReschedule = true;			resumeQueue(readQ[i]);			readQ[i] = 0;			r--;		}		if (writeQ[i] != 0 && FD_ISSET(i, &wr)) {			needReschedule = true;			resumeQueue(writeQ[i]);			writeQ[i] = 0;			r--;		}	}#endif	return;}/* * A file I/O operation could not be completed. Sleep until we are woken up * by the SIGIO handler. * * Interrupts are disabled on entry and exit. * fd is assumed to be valid. * Returns true if operation was interrupted. */static intblockOnFile(int fd, int op, int timeout){	int rc = false;DBG(JTHREAD,	dprintf("blockOnFile(%d,%s)\n", fd, op == TH_READ ? "r":"w"); )	assert(intsDisabled());	BLOCKED_ON_EXTERNAL(currentJThread);	if (fd > maxFd) {		maxFd = fd;	}	if (op == TH_READ) {		FD_SET(fd, &readsPending);		rc = suspendOnQThread(currentJThread, &readQ[fd], timeout);		FD_CLR(fd, &readsPending);	}	else {		FD_SET(fd, &writesPending);		rc = suspendOnQThread(currentJThread, &writeQ[fd], timeout);		FD_CLR(fd, &writesPending);	}	return (rc);}/*============================================================================ *  * locking subsystem * */void jmutex_initialise(jmutex *lock){	lock->holder = lock->waiting = NULL;}voidjmutex_lock(jmutex *lock){	intsDisable();	while (lock->holder != NULL)		suspendOnQThread(jthread_current(), &lock->waiting, NOTIMEOUT);	lock->holder = jthread_current();				intsRestore();}voidjmutex_unlock(jmutex *lock){	intsDisable();	lock->holder = NULL;	if (lock->waiting != 0) {		jthread* tid;		tid = lock->waiting;		lock->waiting = tid->nextQ;		assert(tid->status != THREAD_RUNNING);		tid->blockqueue = 0;		resumeThread(tid);	}	intsRestore();}voidjmutex_destroy(jmutex *lock){	assert(lock->holder == NULL);	assert(lock->waiting == NULL);}voidjcondvar_initialise(jcondvar *cv){	*cv = NULL;}jbooljcondvar_wait(jcondvar *cv, jmutex *lock, jlong timeout){	jthread *current = jthread_current();	jbool r;	intsDisable();	/* give up mutex */	lock->holder = NULL;				if (lock->waiting != NULL) {		jthread* tid;		tid = lock->waiting;		lock->waiting = tid->nextQ;		assert(tid->status != THREAD_RUNNING);		tid->blockqueue = 0;		resumeThread(tid);	}#if defined(DETECTDEADLOCK)	/* a limited wait should not cause us to scream deadlock */	if (timeout != 0) {		BLOCKED_ON_EXTERNAL(currentJThread);	}#endif	/* wait to be signaled */	r = suspendOnQThread(current, cv, timeout);	/* reacquire mutex */	while (lock->holder != NULL) {		suspendOnQThread(current, &lock->waiting, NOTIMEOUT);	}	lock->holder = current;	intsRestore();	return (r);}voidjcondvar_signal(jcondvar *cv, jmutex *lock){	intsDisable();	if (*cv != NULL) {		jthread* tid;

⌨️ 快捷键说明

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