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

📄 thread-impl.c

📁 kaffe Java 解释器语言,源码,Java的子集系统,开放源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	  TUNLOCK( cur); /* -------------------------------------------------- tLock */	  /* we shouldn't get here, this is a last safeguard */	  EXIT(0);	}  }  if ( cur == firstThread ) {	/*	 * We don't cache this one, but we have to remove it from the active list. Note	 * that the firstThread always has to be the last entry in the activeThreads list	 * (we just add new entries at the head)	 */	TLOCK( cur); /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tLock */	/* if we would be the head, we would have been the last, too (and already exited) */	assert( cur != activeThreads);	for ( t=activeThreads; (t != NULL) && (t->next != cur); t=t->next );	assert( t != NULL);	t->next = 0;	TUNLOCK( cur); /* ---------------------------------------------------- tLock */	/*	 * Put us into a permanent freeze to avoid shut down of the whole process (it's	 * not clear if this is common pthread behavior or just a implementation	 * linux-threads "feature")	 */	sem_wait( &cur->sem);  }  else {	/* flag that we soon will get a new cache entry (would be annoying to	 * create a new thread in the meantime) */	pendingExits++;  }}/* * Thread is being finalized - free any held resource. */voidjthread_destroy (jthread_t cur){  DBG( JTHREAD, TMSG_SHORT( "finalize ", cur))}void jthread_sleep (jlong timeout) {	struct timespec time;	time.tv_sec  = timeout / 1000;	time.tv_nsec = (timeout % 1000) * 1000000;	nanosleep (&time, NULL);}/*********************************************************************** * scheduling and query *//* * Change the scheduler priority of a running thread. Since we aren't * called directly, we can assume that 'prio' is within [MIN_PRIORITY..MAX_PRIORITY] */voidjthread_setpriority (jthread_t cur, jint prio){  struct sched_param   sp;  if ( cur ) {	sp.sched_priority = priorities[prio];	DBG( JTHREAD, dprintf("set priority: %p [tid: %4ld, java: %p) to %d (%d)\n",			      cur, cur->tid, cur->data.jlThread, prio, priorities[prio]))	pthread_setschedparam( cur->tid, SCHEDULE_POLICY, &sp);  }}/******************************************************************************* * the suspend/resume mechanism *//* * The suspend signal handler, which we need to implement critical sections. * It is used for two purposes: (a) to block all active threads which might * get rescheduled during a critical section (we can't rely on priority-fifo * scheduling, it might be SCHED_OTHER), and (b) to get a GC-limit of the current * thread stack so that we don't have to scan the whole thing. Since this * assumes that we execute on the threads normal stack, make sure we have no * SA_ONSTACK / signalstack() in effect */voidsuspend_signal_handler ( int sig ){  jthread_t   cur = jthread_current();  DBG( JTHREADDETAIL, dprintf("suspend signal handler: %p\n", cur))  /* signals are global things and might come from everywhere, anytime */  if ( !cur || !cur->active )	return;  if ( cur->suspendState == SS_PENDING_SUSPEND ){	JTHREAD_JMPBUF env;	/*	 * Note: We're not gonna do a longjmp to this place, we just want	 * to do something that will save all of the registers onto the stack.	 */	JTHREAD_SETJMP(env);	/* assuming we are executing on the thread stack, we record our current pos */	cur->stackCur     = (void*)&env;	cur->suspendState = SS_SUSPENDED;	/* notify the critSect owner that we are now suspending in the handler */	sem_post( &critSem);	/* freeze until we get a subsequent SIG_RESUME */	while( cur->suspendState == SS_SUSPENDED )		sigsuspend( &suspendSet);	DBG( JTHREADDETAIL, dprintf("sigsuspend return: %p\n", cur))	cur->stackCur     = 0;	cur->suspendState = 0;	/* notify the critSect owner we are leaving the handler */	sem_post( &critSem);  }}/* * The resume signal handler, which we mainly need to get the implicit sigreturn * call (i.e. to unblock a preceeding sigsuspend). */voidresume_signal_handler ( int sig ){  /* we don't do anything, here - all the action is in the suspend handler */}/* * Temporarily suspend all threads but the current one. This is * a dangerous operation, but it is more safe than to rely on * fixed priority scheduling (which most desktop OSes don't provide). * Make sure no suspended thread blocks on a resource (mutexed non-reentrant * lib func) we use within the critical section, or we have a classical deadlock. * Critical section can be nested, but that's usually not a good idea (increases * chances for deadlocks or trojan threads) */voidjthread_suspendall (void){  int		stat;  jthread_t	cur = jthread_current();  jthread_t	t;  int		iLockRoot;   //int           nSuspends;  /* don't allow any new thread to be created or recycled until this is done */  TLOCK( cur); /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tLock */  DBG( JTHREAD, dprintf("enter crit section[%d] from: %p [tid:%4ld, java:%p)\n",			critSection, cur, cur->tid, cur->data.jlThread))  if ( ++critSection == 1 ){	//nSuspends = 0;	for ( t=activeThreads; t; t = t->next ){	  /*	   * make sure we don't suspend ourselves, and we don't expect suspend	   * signals handled by threads which are blocked on someting else	   * than the thread lock (which we soon release)	   */	  if ( (t != cur) && (t->suspendState == 0) && (t->active) ) {		DBG( JTHREADDETAIL, dprintf("signal suspend: %p (susp: %d blk: %d)\n",					    t, t->suspendState, t->blockState))		t->suspendState = SS_PENDING_SUSPEND;		if ( (stat = pthread_kill( t->tid, SIG_SUSPEND)) ){		  DBG( JTHREAD, dprintf("error sending SUSPEND signal to %p: %d\n", t, stat))		}		else {		  //nSuspends++;		  /* BAD: Empirical workaround for lost signals (with accumulative syncing)		   * It shouldn't be necessary (posix sems are accumulative), and it		   * is bad, performancewise (at least n*2 context switches per suspend)		   * but it works more reliably on linux 2.2.x */		  sem_wait( &critSem);		}	  }	}#ifdef NEVER	/* wait until all signals we've sent out have been handled */	while ( nSuspends ){	  sem_wait( &critSem);	  nSuspends--;	}#endif  }  TUNLOCK( cur); /* ------------------------------------------------------ tLock */  DBG( JTHREAD, dprintf("critical section (%d) established\n", critSection))}/* * Resume all temporarily suspended threads. Just take action if this * is the outmost exit */voidjthread_unsuspendall (void){  jthread_t	cur = jthread_current();  jthread_t	t;  int		stat;  int		iLockRoot;  //int          nResumes;  if ( !critSection )	return;  if ( --critSection == 0 ){	//nResumes = 0;	/* No need to sync, there's nobody else running. It's just a matter of	 * defensive programming (and we use our fast locks)	 */	TLOCK( cur); /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tLock */	for ( t=activeThreads; t; t = t->next ){	  if ( t->suspendState & (SS_PENDING_SUSPEND | SS_SUSPENDED) ){		//nResumes++;		DBG( JTHREAD, dprintf("signal resume: %p (sus: %d blk: %d)\n",				      t, t->suspendState, t->blockState))		t->suspendState = SS_PENDING_RESUME;		stat = pthread_kill( t->tid, SIG_RESUME);		if ( stat ) {		  DBG( JTHREAD, dprintf("error sending RESUME signal to %p: %d\n", t, stat))		}		/* ack wait workaround, see TentercritSect remarks */		sem_wait( &critSem);	  }	}#ifdef NEVER	/* wait until all signals we've sent out have been handled */	while ( nResumes ){	  sem_wait( &critSem);	  nResumes--;	}#endif	TUNLOCK( cur); /*----------------------------------------------------- tLock */  }  DBG( JTHREAD, dprintf("exit crit section (%d)\n", critSection))}/******************************************************************************* * GC related stuff *//* * Walk stacks of all threads, except of the current one (doesn't * make much sense since that's the GC itself, and it's task is to * get rid of garbage, not to pin it down - besides the fact that * its stack is a moving target). * * The call chain looks like this * *  startGC *    Kaffe_ThreadInterface.GcWalkThreads == TwalkThreads *      walkMemory *        gcFunctions[..].walk == walkThread * */voidjthread_walkLiveThreads (void(*func)(jthread_t)){  jthread_t t;  DBG( JTHREAD, dprintf("start walking threads\n"))  for ( t = activeThreads; t != NULL; t = t->next) {	func(t);  }  DBG( JTHREAD, dprintf("end walking threads\n"))}voidjthread_set_blocking (int fd, int blocking){  int r;  /* This code has been copied from jthreadedFileDescriptor in     unix-jthreads/jthread.c  */  if (!blocking) {    /* Make non-blocking */    if ((r = fcntl(fd, F_GETFL, 0)) < 0) {      perror("F_GETFL");      return;    }        /*     * Apparently, this can fail, for instance when we stdout is      * redirected to /dev/null. (On FreeBSD)     */    fcntl(fd, F_SETFL, r | O_NONBLOCK #if defined(O_ASYNC)	  | O_ASYNC#elif defined(FASYNC)	  | FASYNC#endif	  );  } else {    /* clear nonblocking flag */    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);  }}#if 0/* * Walk the thread's internal context. The stack is actually "walked down" * [base+size..base]. * ? how useful is this for the GC thread itself ? */voidTwalkThread ( Hjava_lang_Thread* thread ){  nativeThread  *t;  nativeThread  *nt = NATIVE_THREAD( thread);  void          *base;  long          size;  if ( !nt || !nt->active || !nt->stackMin ){	return;  }  DBG( vm_thread, TMSG_LONG( "walking ", nt));  if ( !nt->suspendState && !nt->blockState ){	t = GET_CURRENT_THREAD(&t);	if ( t == nt ){	  /* Ok, we do walk the gcMan for now, but just up to this point */	  nt->stackCur = &t;	}	else {	  /* everything else should be blocked or suspended by now */	  DBG( vm_thread, ("walking a running thread %p\n", nt));	  //tDump();	  //ABORT();	  return;	}  }  else if ( nt->suspendState == SS_PENDING_SUSPEND ){	DBG( vm_thread, ("pending suspend, walk whole stack\n"));	/*	 * Assuming the very next thing after a context switch to this thread	 * would be calling the signal handler, we accept that case. Unfortunately,	 * we don't have a stackCur, yet	 */#if defined(STACK_GROWS_UP)	nt->stackCur = nt->stackMax;#else	nt->stackCur = nt->stackMin;#endif  }  if ( ((uintp) nt->stackCur < (uintp) nt->stackMin) ||	   (((uintp) nt->stackCur > (uintp) nt->stackMax)) ) {	DBG( vm_thread, ("inconsistent stack\n"));	tDump();	ABORT();  }#if defined(STACK_GROWS_UP)  base = nt->stackMin;  size = (unsigned long)nt->stackCur - (unsigned long) base;#else  base = nt->stackCur;  size = (uintp)nt->stackMax - (uintp) base;#endif  walkConservative( base, size);}#endif

⌨️ 快捷键说明

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