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

📄 thread-impl.c

📁 java virtual machince kaffe
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * thread-impl.c - pthread based ThreadInterface implementation * * Copyright (c) 1998 *      Transvirtual Technologies, Inc.  All rights reserved. * * Copyright (c) 2005, 2006 *      Kaffe.org contributors.  See ChangeLog for details.  *      All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. */#include "lerrno.h"#include <limits.h>#include "config.h"#include "config-std.h"#include "config-signal.h"#include "config-setjmp.h"#include "config-io.h"#ifdef HAVE_STRING_H#include <string.h>#endif#ifdef HAVE_SYS_TYPES_H#include <sys/types.h>#endif#ifdef HAVE_SYS_TIME_H#include <sys/time.h>#endif#ifdef HAVE_SYS_RESOURCE_H#include <sys/resource.h>#endif#include "locks.h"#include "thread-impl.h"#include "debug.h"#include "md.h"#include "gc.h"#include "thread.h"#ifdef KAFFE_BOEHM_GC#include <gc/gc.h>#endif/* define _GNU_SOURCE for pthread_yield on linux */#ifndef _GNU_SOURCE#define _GNU_SOURCE#endif#include <pthread.h>#if !defined(HAVE_PTHREAD_YIELD) && defined(HAVE_SCHED_YIELD)#if defined(HAVE_SCHED_H)#include <sched.h>#endif // SCHED_H#endif // SCHED_YIELD && !PTHREAD_YIELD#ifndef MAINSTACKSIZE#define MAINSTACKSIZE (1024*1024)#endif#if defined(KAFFE_VMDEBUG)static char stat_act[]   = { ' ', 'a' };static char stat_susp[]  = { ' ', 's', ' ', 'r', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };static char stat_block[] = { ' ', 'T', 'm', ' ', 'c', ' ', ' ', ' ', 't', ' ', ' ' };#define TMSG_SHORT(_msg,_nt)     \   dprintf(_msg" %p [java:%p]\n", \    _nt, _nt->data.jlThread)#define TMSG_LONG(_msg,_nt)      \   dprintf(_msg" %p [java:%p], stack [%p..%p..%p], state: %c%c%c\n",         \        _nt, _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 [java: %x]\n",    \                    _nt, _nt->data.jlThread);                                   \    tDump();                                                               \  }#endif /* KAFFE_VMDEBUG *//*********************************************************************** * typedefs & defines *//* * 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). */#if defined(HAVE_SCHED_OTHER_IN_SCHED) && !(defined(__FreeBSD_kernel__) && defined(__GLIBC__))#define SCHEDULE_POLICY     SCHED_OTHER#else#undef SCHEDULE_POLICY#endif/* our upper limit for cached threads (0 = no caching at all) */#define MAX_CACHED_THREADS 0/* * Flag to say whether the thread subsystem has been initialized. */static char jthreadInitialized = false;/* * Signal to use to suspend all threads. */static int sigSuspend;/* * Signal to use to resume all threads. */static int sigResume;/* * Signal to use to dump thread internal state. */static int sigDump;/* * Signal to use to produce an interrupt. */static int sigInterrupt;/* * Signals used by the thread system to restard/cancel threads. */static int psigRestart;static int psigCancel;/** * This variable holds a pointer to the garbage collector which * will be used to allocate thread data. */static Collector *threadCollector;/*********************************************************************** * global data *//** We keep a list of all active threads, so that we can enumerate them */static jthread_t	activeThreads;/** This mutex lock prevents somebody to modify or read the active thread * concurrently with some other threads. This prevents some bug that may appear  * when a thread die, is created or is being walked. */static pthread_mutex_t		activeThreadsLock = PTHREAD_MUTEX_INITIALIZER;/** This mutex lock protects calls into non-reentrant system services. */static pthread_mutex_t		systemMutex = PTHREAD_MUTEX_INITIALIZER;/** 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;/** 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 repsem_t		critSem;/** Signal set which contains important signals for suspending threads. */static sigset_t		suspendSet;/** This callback is to be called when a thread exits. */static void (*threadDestructor)(void *);/** This callback is called when all non-daemon threads exit. */static void (*runOnExit)(void);#ifdef KAFFE_VMDEBUG/** an optional deadlock watchdog thread (not in the activeThread list), * activated by KAFFE_VMDEBUG topic JTHREAD */static pthread_t	deadlockWatchdog;/** * This is a debugging variable to analyze possible deadlock when dumping thread states. * It retains a pointer to the thread holding the thread list lock. */static jthread_t        threadListOwner;#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 bytes){	return KGC_malloc(threadCollector, bytes, KGC_ALLOC_THREADCTX);}static inline voidprotectThreadList(jthread_t cur){  cur->blockState |= BS_THREAD;  jmutex_lock(&activeThreadsLock);#ifdef KAFFE_VMDEBUG  threadListOwner = cur;#endif}static inline voidunprotectThreadList(jthread_t cur){#ifdef KAFFE_VMDEBUG  threadListOwner = NULL;#endif  jmutex_unlock(&activeThreadsLock);  cur->blockState &= ~BS_THREAD;}/*********************************************************************** * internal functions */#if defined(KAFFE_VMDEBUG)/* * dump a thread list, marking the supposed to be current thread */static 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, (long)t->tid, t->data.jlThread,		t->stackMin, t->stackCur, t->stackMax);  }}#endif /* defined(KAFFE_VMDEBUG) *//* * dump the state of the threading system */static voidtDump (void){  DBG(JTHREAD, {	jthread_t	cur = jthread_current();	dprintf("\n======================== thread dump =========================\n");	dprintf("thread list lock owner: %p\n", threadListOwner);	protectThreadList(cur);	dprintf("state:  nonDaemons: %d, critSection: %d\n",					 nonDaemons, critSection);	dprintf("active threads:\n");	tDumpList( cur, activeThreads);	dprintf("\ncached threads:\n");	tDumpList( cur, cache);	unprotectThreadList(cur);	dprintf("====================== end thread dump =======================\n");  });}/* * On demand debug signal to dump the current thread state(s) (requested * by a external "kill -s <sigDump> <proc-id>" */staticvoiddump_signal_handler (int sig UNUSED){  tDump();}#ifdef KAFFE_VMDEBUGstaticvoid* tWatchdogRun (void* p UNUSED){  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_SYSCALL) || (t->blockState == BS_CV_TO)) && !t->suspendState ){		life = 1;		break;	  }	}	if ( !life ) {	  DBG( JTHREAD, dprintf("deadlock\n"));	  tDump();	  KAFFEVM_ABORT();	}	usleep( 5000);  }  return NULL;}staticvoid tStartDeadlockWatchdog (void){  pthread_attr_t attr;#if defined(SCHEDULE_POLICY)  struct sched_param sp;  sp.sched_priority = priorities[0];  /* looow */#endif  pthread_attr_init( &attr);#if defined(SCHEDULE_POLICY)  pthread_attr_setschedparam( &attr, &sp);#endif  pthread_attr_setstacksize( &attr, 4096);  pthread_create( &deadlockWatchdog, &attr, tWatchdogRun, NULL);}#endif /* KAFFE_VMDEBUG *//*********************************************************************** * thread system initialization *//** * Static initialisation of signal handlers. This function is called once. */static voidtInitSignalHandlers (void){  struct sigaction saSuspend, saResume, saInterrupt, saDump;  unsigned int flags = 0;#if defined(SA_RESTART)  flags |= SA_RESTART;#endif  saSuspend.sa_flags = flags;  saSuspend.sa_handler = suspend_signal_handler;  sigemptyset( &saSuspend.sa_mask);  sigaddset( &saSuspend.sa_mask, sigSuspend);  sigaddset( &saSuspend.sa_mask, sigResume);  if (psigRestart > 0)    sigaddset( &saSuspend.sa_mask, psigRestart);  if (psigCancel > 0)    sigaddset( &saSuspend.sa_mask, psigCancel);  sigaddset( &saSuspend.sa_mask, SIGSTOP);  sigaddset( &saSuspend.sa_mask, SIGCONT);  sigaddset( &saSuspend.sa_mask, SIGWINCH);#ifndef KAFFE_BOEHM_GC  sigaction( sigSuspend, &saSuspend, NULL);#endif  saResume.sa_flags = 0; /* Note that we do not want restart here. */  saResume.sa_handler = resume_signal_handler;  saResume.sa_mask = saSuspend.sa_mask;#if !defined(KAFFE_BOEHM_GC) && !defined(KAFFE_BUGGY_NETBSD_SIGWAIT)  sigaction( sigResume, &saResume, NULL);#endif  saInterrupt.sa_flags = flags;  saInterrupt.sa_handler = SIG_IGN;  sigemptyset(&saInterrupt.sa_mask);  sigaction( sigInterrupt, &saInterrupt, NULL);  saDump.sa_flags = flags;  saDump.sa_handler = dump_signal_handler;  sigemptyset( &saDump.sa_mask);  sigaction( sigDump, &saDump, NULL);}/** * Initialize signal numbers to use depending of realtime signal availabilities. * * ORIGINAL NOTE: * * 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 */static voidtInitSignals(void){#if !defined(SIGRTMIN)#define SIGRTMIN -1#define SIGRTMAX -1#endif  if (SIGRTMAX - SIGRTMIN < 7)    {#if defined(OLD_LINUXTHREADS) && !defined(__CYGWIN__)      sigSuspend = SIGURG;      sigResume  = SIGTSTP;      sigDump    = SIGXCPU;/* * Sneak these signal in from the thread library. */      psigRestart = SIGUSR1;      psigCancel  = SIGUSR2;#else // OLD_LINUXTHREADS      sigSuspend  = SIGUSR1;      sigResume   = SIGUSR2;      sigDump     = SIGURG;// PSIG_RESTART and PSIG_CANCEL are left undefined.      psigRestart = -1;      psigCancel  = -1;#endif      sigInterrupt = SIGCONT;    }  else    {      sigSuspend = SIGRTMIN+6;      sigResume  = SIGRTMIN+5;      sigDump    = SIGURG;/* * Sneak these signal in from the thread library. */      psigRestart = SIGRTMIN;

⌨️ 快捷键说明

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