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

📄 thread-impl.c

📁 kaffe Java 解释器语言,源码,Java的子集系统,开放源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * thread-impl.c - pthread based ThreadInterface implementation * * Copyright (c) 1998 *      Transvirtual Technologies, Inc.  All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. */#include "config.h"#include "config-std.h"#include "config-signal.h"#include "config-setjmp.h"#include "config-io.h"#include "locks.h"#include "thread-impl.h"#include "debug.h"static char stat_act[]   = { ' ', 'a' };static char stat_susp[]  = { ' ', 's', ' ', 'r', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };static char stat_block[] = { ' ', 'T', 'm', ' ', 'c', ' ', ' ', ' ', 't', ' ', ' ' };#if defined(KAFFE_VMDEBUG)#define TMSG_SHORT(_msg,_nt)     \   dprintf(_msg" %p [tid:%4ld, java:%p]\n", \    _nt, _nt->tid, _nt->data.jlThread)#define TMSG_LONG(_msg,_nt)      \   dprintf(_msg" %p [tid:%4ld, java:%p], stack [%p..%p..%p], state: %c%c%c\n",         \        _nt, _nt->tid, _nt->data.jlThread, _nt->stackMin, _nt->stackCur, _nt->stackMax,  \        stat_act[_nt->active], stat_susp[_nt->suspendState], stat_block[_nt->blockState])#define CHECK_CURRENT_THREAD(_nt)                                          \  if ( ((uintp) &_nt < (uintp) _nt->stackMin) ||           \       ((uintp) &_nt > (uintp) _nt->stackMax) ) {          \    printf( "?? inconsistent current thread: %x [tid: %d, java: %x]\n",    \                    _nt, _nt->tid, _nt->data.jlThread);                                   \    tDump();                                                               \  }#endif /* KAFFE_VMDEBUG *//*********************************************************************** * typedefs & defines */#include <bits/local_lim.h>/* * This is the configurable section. Note that SCHED_FIFO is the only * schedule policy which conforms to the "old" Java thread model (with * stringent priorities), but it usually isn't available on desktop * OSes (or imposes certain restrictions, e.g. root privileges). */#define SCHEDULE_POLICY     SCHED_OTHER/* our upper create limit, to ensure we don't blow the system */#define MAX_SYS_THREADS     _POSIX_THREAD_THREADS_MAX - 1/* our upper limit for cached threads (0 = no caching at all) */#define MAX_CACHED_THREADS  MAX_SYS_THREADS - 3/* * Now it starts to get hackish - we have to pick some signals * for suspend/resume (enter/exitCritSect) which don't interfere * with pthread implementations. Note that we can't rely on when * a suspend signal is delivered, and it's therefore not safe * to mulitplex a sinle signal for both suspend & resume purposes */#if !defined(__SIGRTMIN) || (__SIGRTMAX - __SIGRTMIN < 3)#define          SIG_SUSPEND   SIGURG#define          SIG_RESUME    SIGTSTP#define          SIG_DUMP      SIGXCPU/* * Sneak these signal in from the thread library. */#define		 PSIG_RESTART	SIGUSR1#define		 PSIG_CANCEL	SIGUSR2#else#define          SIG_SUSPEND   SIGUSR1#define          SIG_RESUME    SIGUSR2#define          SIG_DUMP      SIGXCPU/* * Sneak these signal in from the thread library. */#define		 PSIG_RESTART	(__SIGRTMIN)#define		 PSIG_CANCEL	(__SIGRTMIN+1)#endif/*********************************************************************** * global data *//* We keep a list of all active threads, so that we can enumerate them */static jthread_t	activeThreads;/* We don't throw away threads when their user func terminates, but suspend * and cache them for later re-use */static jthread_t	cache;/* The notorious first thread, which has to be handled differently because * it isn't created explicitly */static jthread_t	firstThread;/* Number of active non-daemon threads (the last terminating nonDaemon * causes the process to shut down */static int		nonDaemons;/* Number of system threads (either running (activeThreads) or * blocked (cache). We need this to implement our own barrier, since * many kernel thread systems don't behave graceful on exceeding their limit */static int		nSysThreads;/* number of currently cached threads */static int		nCached;/* map the Java priority levels to whatever the pthreads impl gives us */static int		*priorities;/* thread-specific-data key to retrieve 'nativeData' */pthread_key_t		ntKey;/* our lock to protect list manipulation/iteration */static iStaticLock	tLock;/* a hint to avoid unnecessary pthread_creates (with pending exits) */static volatile int	pendingExits;/* level of critical sections (0 = none) */static int		critSection;/* helper semaphore to signal completion of critical section enter/exit */static sem_t		critSem;static sigset_t		suspendSet;/* an optional deadlock watchdog thread (not in the activeThread list), * activated by KAFFE_VMDEBUG topic JTHREAD */#ifdef KAFFE_VMDEBUGstatic pthread_t	deadlockWatchdog;#endif /* KAFFE_VMDEBUG */static void suspend_signal_handler ( int sig );static void resume_signal_handler ( int sig );static void tDispose ( jthread_t nt );static void* (*thread_malloc)(size_t);static void (*thread_free)(void*);#define TLOCK(_nt) do { \   (_nt)->blockState |= BS_THREAD; \   lockStaticMutex (&tLock); \} while(0)#define TUNLOCK(_nt) do { \   unlockStaticMutex (&tLock); \  (_nt)->blockState &= ~BS_THREAD; \} while(0)/*********************************************************************** * internal functions *//* * dump a thread list, marking the supposed to be current thread */voidtDumpList ( jthread_t cur, jthread_t list ){  int		i;  char		a1, a2, a3;  jthread_t	t;  for ( t=list, i=0; t; t=t->next, i++ ){	/* the supposed to be current thread? */	a1 = (t == cur) ? '*' : ' ';	/* the current thread from a stack point-of view? */	a2 = (((uintp)&i > (uintp)t->stackMin) &&		  ((uintp)&i < (uintp)t->stackMax)) ? 'S' : ' ';	/* the first one? */	a3 = (t == firstThread) ? '1' : ' ';	dprintf("%4d: %c%c%c %c%c%c   %p [tid: %4ld, java: %p]  "		"stack: [%p..%p..%p]\n",		i, a1, a2, a3,		stat_act[t->active], stat_susp[t->suspendState], stat_block[t->blockState],		t, t->tid, t->data.jlThread,		t->stackMin, t->stackCur, t->stackMax);  }}/* * dump the state of the threading system */voidtDump (void){  DBG(JTHREAD, {	jthread_t	cur = jthread_current();	void		*lock   = tLock.lock;	void		*holder = tLock.heavyLock.holder;	void		*mux    = tLock.heavyLock.mux;	//void		*muxNat = tLock.heavyLock.mux ? unhand(tLock.heavyLock.mux)->PrivateInfo : 0;	void		*cv     = tLock.heavyLock.cv;	//void		*cvNat  = tLock.heavyLock.cv ? unhand(tLock.heavyLock.cv)->PrivateInfo : 0;	int		iLockRoot;		TLOCK( cur); /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tLock */	dprintf("\n======================== thread dump =========================\n");	dprintf("state:  nonDaemons: %d, critSection: %d\n",					 nonDaemons, critSection);	/*	dprintf("tLock:       %p [holder: %p, mux: %p (native: %p), cv: %p (native: %p)]\n",					 lock, holder, mux, muxNat, cv, cvNat);	*/	dprintf("tLock:	      %p [holder: %p, mux: %p, cv: %p]\n",				lock, holder, mux, cv);	dprintf("active threads:\n");	tDumpList( cur, activeThreads);	dprintf("\ncached threads:\n");	tDumpList( cur, cache);	dprintf("====================== end thread dump =======================\n");	TUNLOCK( cur); /* ------------------------------------------------------ tLock */  })}/* * On demand debug signal to dump the current thread state(s) (requested * by a external "kill -s <SIG_DUMP> <proc-id>" */voiddump_signal_handler ( int sig ){  tDump();}#ifdef KAFFE_VMDEBUGstaticvoid* tWatchdogRun (void* p){  jthread_t t;  int life;  while ( nonDaemons ) {	life = 0;	for ( t=activeThreads; t != NULL; t = t->next ){	  /*	   * if we have a single thread that is not blocked at all, is in a	   * timeout wait, and is not suspended, we are still safe (even though	   * the timeout value might effectively be a deadlock)	   */	  if ( (!t->blockState || (t->blockState == BS_CV_TO)) && !t->suspendState ){		life = 1;		break;	  }	}	if ( !life ) {	  DBG( JTHREAD, dprintf("deadlock\n"))	  tDump();	  ABORT();	}	usleep( 5000);  }  return 0;}void tStartDeadlockWatchdog (void){  pthread_attr_t attr;  struct sched_param sp;  sp.sched_priority = priorities[0];  /* looow */  pthread_attr_init( &attr);  pthread_attr_setschedparam( &attr, &sp);  pthread_attr_setstacksize( &attr, 4096);  pthread_create( &deadlockWatchdog, &attr, tWatchdogRun, 0);}#endif /* KAFFE_VMDEBUG *//*********************************************************************** * thread system initialization *//* * static init of signal handlers */voidtInitSignalHandlers (void){  struct sigaction sigSuspend, sigResume, sigDump;  unsigned int flags = 0;#if defined(SA_RESTART)  flags |= SA_RESTART;#endif  sigSuspend.sa_flags = flags;  sigSuspend.sa_handler = suspend_signal_handler;  sigemptyset( &sigSuspend.sa_mask);  sigaddset( &sigSuspend.sa_mask, SIG_SUSPEND);  sigaddset( &sigSuspend.sa_mask, SIG_RESUME);  sigaddset( &sigSuspend.sa_mask, PSIG_RESTART);  sigaddset( &sigSuspend.sa_mask, PSIG_CANCEL);  sigaddset( &sigSuspend.sa_mask, SIGSTOP);  sigaddset( &sigSuspend.sa_mask, SIGCONT);  sigaddset( &sigSuspend.sa_mask, SIGWINCH);  sigaction( SIG_SUSPEND, &sigSuspend, NULL);  sigResume.sa_flags = 0; // Note that we do not want restart here.  sigResume.sa_handler = resume_signal_handler;  sigResume.sa_mask = sigSuspend.sa_mask;  sigaction( SIG_RESUME, &sigResume, NULL);#if defined(SIG_DUMP)  sigDump.sa_flags = flags;  sigDump.sa_handler = dump_signal_handler;  sigemptyset( &sigDump.sa_mask);  sigaction( SIG_DUMP, &sigDump, NULL);#endif}/* * static init set up of Java-to-pthread priority mapping (pthread prioritiy levels * are implementation dependent) */staticvoid tMapPriorities (int npr){  int     d, min, max, i;  float   r;  min = sched_get_priority_min( SCHEDULE_POLICY);  max = sched_get_priority_max( SCHEDULE_POLICY);  d = max - min;  r = (float)d / (float)npr;  for ( i=0; i<npr; i++ ) {	priorities[i] = (int)(i*r + 0.5) + min;  }}/* * per-native thread init of semaphore */staticvoidtInitLock ( jthread_t nt ){  /* init a non-shared (process-exclusive) semaphore with value '0' */  sem_init( &nt->sem, 0, 0);}/* * We must have a certain amount of credible thread information setup * as soon as possible. */staticvoidtSetupFirstNative(void){  jthread_t nt;  /*   * We need to have a native thread context available as soon as possible.   */  nt = thread_malloc( sizeof(struct _jthread));  nt->tid = pthread_self();  pthread_setspecific( ntKey, nt);  nt->stackMin  = (void*)0;  nt->stackMax  = (void*)-1;}/* * The global, one-time initialization goes here. This is a * alternative to scattered pthread_once() calls */voidjthread_init(int pre,

⌨️ 快捷键说明

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