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

📄 thread-impl.c

📁 java virtual machince kaffe
💻 C
📖 第 1 页 / 共 4 页
字号:
      psigCancel  = SIGRTMIN+1;      sigInterrupt = SIGRTMIN+2;    }}/* * static init set up of Java-to-pthread priority mapping (pthread prioritiy levels * are implementation dependent) */staticvoid tMapPriorities (int npr){  int     d, max, min, i;  float   r;#if defined(HAVE_SCHED_GET_PRIORITY_MIN) && defined(SCHEDULE_POLICY)  min = sched_get_priority_min( SCHEDULE_POLICY);#else  min = 0;#endif /* defined(HAVE_SCHED_GET_PRIORITY_MIN) */#if defined(HAVE_SCHED_GET_PRIORITY_MAX) && defined(SCHEDULE_POLICY)  max = sched_get_priority_max( SCHEDULE_POLICY);#else  max = 0;#endif /* defined(HAVE_SCHED_GET_PRIORITY_MAX) */  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' */  repsem_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));  KGC_addRef(threadCollector, nt);  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 UNUSED,        int maxpr, int minpr UNUSED,	Collector *thread_collector,	void (*destructor)(void *),        void (*_onstop)(void) UNUSED,        void (*_ondeadlock)(void) UNUSED){  DBG(JTHREAD, dprintf("initialized\n"));  threadCollector = thread_collector;  threadDestructor = destructor;  tInitSignals();  pthread_key_create( &ntKey, NULL);  repsem_init( &critSem, 0, 0);  priorities = (int *)KGC_malloc (threadCollector, (maxpr+1) * sizeof(int), KGC_ALLOC_STATIC_THREADDATA);  tMapPriorities(maxpr+1);  tInitSignalHandlers();  sigemptyset( &suspendSet);  sigaddset( &suspendSet, sigResume);  tSetupFirstNative();  jthreadInitialized = true;  DBG( JTHREAD, tStartDeadlockWatchdog() );}jthread_tjthread_createfirst(size_t mainThreadStackSize, unsigned int pri UNUSED,		    void* jlThread){  jthread_t      nt;  int            oldCancelType;  nt = jthread_current();  /* we can't use nt->attr, because it wasn't used to create this thread */  pthread_attr_init( &nt->attr);  nt->tid    = pthread_self();  nt->data.jlThread = jlThread;  nt->suspendState = 0;  nt->active = 1;  nt->func   = NULL;  nt->next   = NULL;  nt->daemon = false;  pthread_mutex_init(&nt->suspendLock, NULL);  /* Get stack boundaries. Note that this is just an approximation   * which should cover all gc-relevant stack locations   */  KaffePThread_detectStackBoundaries(nt, mainThreadStackSize);  DBG( JTHREAD, TMSG_SHORT( "create first ", nt));  /* init our cv and mux fields for locking */  tInitLock( nt);  /* Link native and Java thread objects   * We already are executing in the right thread, so we can set the specific   * data straight away   */  pthread_setspecific( ntKey, nt);  pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, &oldCancelType);    /* if we aren't the first one, we are in trouble */  assert( activeThreads == 0);   activeThreads = firstThread = nt;  nonDaemons=1;  nSysThreads=1;  return (nt);}/** * Interrupt a thread. *  * If tid is currently blocked its interrupted flag is set * and the blocking operation is canceled. */void jthread_interrupt(jthread_t tid){  pthread_mutex_lock(&tid->suspendLock);  tid->interrupting = 1;  if ((tid->blockState & (BS_CV|BS_CV_TO)) != 0)    {      pthread_cond_signal (&tid->data.sem.cv);    }  else if (tid->blockState == 0 || (tid->blockState & BS_SYSCALL) != 0)    {      /* We need to send some signal to interrupt syscalls. */      pthread_kill(tid->tid, sigInterrupt);    }  pthread_mutex_unlock(&tid->suspendLock);}/** * Peek at the interrupted flag of a thread. * * @return true iff jt was interrupted. */int jthread_is_interrupted(jthread_t jt){  return jt->interrupting;}/** * Read and clear the interrupted flag of a thread. * * @return true iff jt was interrupted. */int jthread_interrupted(jthread_t jt){  int i = jt->interrupting;  jt->interrupting = 0;  return i;}bool jthread_attach_current_thread (bool isDaemon){  jthread_t		nt;  rlim_t		stackSize;  if (jthread_current() != NULL)    return false;  /* create the jthread* thingy */  nt = thread_malloc( sizeof(struct _jthread) );  nt->func         = NULL;  nt->suspendState = 0;#if defined(KAFFEMD_STACKSIZE)  stackSize = mdGetStackSize();    if (stackSize == KAFFEMD_STACK_ERROR)    {      fprintf(stderr, "WARNING: Impossible to retrieve the real stack size\n");      fprintf(stderr, "WARNING: You may experience deadlocks\n");    }  else if (stackSize == KAFFEMD_STACK_INFINITE)    {      fprintf(stderr, "WARNING: Kaffe may experience problems with unlimited\n"	      "WARNING: stack sizes (e.g. deadlocks).\n");      stackSize = MAINSTACKSIZE;    }#else  stackSize = MAINSTACKSIZE;#endif  /* link everything together */  nt->tid = pthread_self();  pthread_setspecific( ntKey, nt);  KaffePThread_detectThreadStackBoundaries(nt);  tInitSignalHandlers();  nt->stackCur     = NULL;   nt->daemon       = isDaemon;  /* and done */  return true;}bool jthread_detach_current_thread (void){  jthread_t	cur = jthread_current ();  tDispose (cur);  return true;}/* * This is our thread function wrapper, which we need because of two * reasons. First, there is no way to set thread specific data from * outside the current thread (and it should be propperly set before we * enter the *real* thread func). Second, this is a better place to handle * the recycle looping than Texit (would be strange to loop in there) */staticvoid* tRun ( void* p ){  jthread_t	cur = (jthread_t)p;  jthread_t	t;  size_t	ss;  int		oldCancelType;  /* get the stack boundaries */  pthread_attr_getstacksize( &cur->attr, &ss);#if defined(STACK_GROWS_UP)  cur->stackMin = &cur;  cur->stackMax = (void*) ((unsigned long)cur->stackMin + ss);#else  cur->stackMax = &cur;  cur->stackMin = (void*) ((unsigned long)cur->stackMax - ss);#endif  pthread_setspecific( ntKey, cur);  pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, &oldCancelType);  cur->tid = pthread_self();  /* we are reasonably operational now, flag our creator that it's safe to give   * up the thread lock */  repsem_post( &cur->sem);  while ( 1 ) {	DBG( JTHREAD, TMSG_LONG( "calling user func of: ", cur));	/* Now call our thread function, which happens to be firstStartThread(),	 * which will call TExit before it returns */	cur->func(cur->data.jlThread);	DBG( JTHREAD, TMSG_LONG( "exiting user func of: ", cur));	if (threadDestructor)	  threadDestructor(cur->data.jlThread);	protectThreadList(cur);	/* remove from active list */	if ( cur == activeThreads ){	  activeThreads = cur->next;	}	else {	  for ( t=activeThreads; t->next && (t->next != cur); t=t->next );	  assert( t->next != 0 );	  t->next = cur->next;	}	/* unlink Java and native thread */	cur->data.jlThread = NULL;	cur->suspendState = 0;	/* link into cache list (if still within limit) */	if ( ++nCached < MAX_CACHED_THREADS ){	  cur->next = cache;	  cache = cur;	  DBG( JTHREAD, TMSG_SHORT( "cached thread ", cur));	}	pendingExits--;	unprotectThreadList(cur);	if ( nCached >= MAX_CACHED_THREADS ){	  break;	}	if (cur->status == THREAD_KILL)	  break;	/* Wait until we get re-used (by TcreateThread). No need to update the	 * blockState, since we aren't active anymore */	repsem_wait( &cur->sem);	if (cur->status == THREAD_KILL)	  break;	/*	 * we have already been moved back to the activeThreads list by	 * Tcreate (saves us a lock)	 */	DBG( JTHREAD, TMSG_SHORT( "reused thread ", cur));  }  tDispose( cur);  return NULL;}/* * Create a new native thread for a given Java Thread object. Note * that we are called from Thread.start(), i.e. we are already allowed to * call func() (which happens to be threads.c:firstStartThread) * * Our call graph looks like this: * *     Thread.start *       startThread *         Kaffe_ThreadInterface.create (firstStartThread) == Tcreate *           pthread_create(..tRun..) *                                                 creator-thread *   -------------------------------------------------------------- *                                                 created-thread *     tRun *       firstStartThread *         Thread.run *         exitThread *           Thread.finish *           Kaffe_ThreadInterface.exit == Texit */jthread_tjthread_create ( unsigned int pri, void* func, int isDaemon, void* jlThread, size_t threadStackSize ){  jthread_t		cur = jthread_current();  jthread_t		nt;#if defined(SCHEDULE_POLICY)  struct sched_param	sp;#endif  /* if we are the first one, it's seriously broken */  assert( activeThreads != 0 );  /*   * This is a safeguard to avoid creating too many new threads   * because of a high Tcreate call frequency from a high priority   * thread (which doesn't give exiters a chance to aquire the lock   * to update the cache list).   */  if ( cache == 0 ) {	while ( pendingExits && (cache == 0) )	  sched_yield();  }#if defined(SCHEDULE_POLICY)  sp.sched_priority = priorities[pri];#endif  protectThreadList(cur);  if ( !isDaemon ) 	nonDaemons++;  unprotectThreadList(cur);  if ( cache ) {	protectThreadList(cur);	/* move thread from the cache to the active list */	nt = cache;	cache = cache->next;	nCached--;	nt->next = activeThreads;	activeThreads = nt;	nt->data.jlThread = jlThread;	nt->daemon = isDaemon;	nt->func = func;	nt->stackCur = NULL;	nt->status = THREAD_RUNNING;#if defined(SCHEDULE_POLICY)	pthread_setschedparam( nt->tid, SCHEDULE_POLICY, &sp);#endif	DBG( JTHREAD, TMSG_SHORT( "create recycled ", nt));	/* resurrect it */	nt->active = 1;	repsem_post( &nt->sem);	unprotectThreadList(cur);  }  else {	int creation_succeeded;	nt = thread_malloc( sizeof(struct _jthread) );	KGC_addRef(threadCollector, nt);	pthread_attr_init( &nt->attr);#if defined(SCHEDULE_POLICY)	pthread_attr_setschedparam( &nt->attr, &sp);#if defined(HAVE_PTHREAD_ATTR_SETSCHEDPOLICY)	pthread_attr_setschedpolicy( &nt->attr, SCHEDULE_POLICY);#endif /* defined(HAVE_PTHREAD_ATTR_SETSCHEDPOLICY) */#endif /* defined(SCHEDULE_POLICY) */	pthread_attr_setstacksize( &nt->attr, threadStackSize);	nt->data.jlThread       = jlThread;	nt->func         = func;	nt->suspendState = 0;	nt->stackMin     = NULL;	nt->stackMax     = NULL;	nt->stackCur     = NULL;	nt->daemon	 = isDaemon;	nt->status = THREAD_RUNNING;	pthread_mutex_init(&nt->suspendLock, NULL);		DBG( JTHREAD, TMSG_SHORT( "create new ", nt));	/* init our cv and mux fields for locking */	tInitLock( nt);	/* Link the new one into the activeThreads list. We lock until	 * the newly created thread is set up correctly (i.e. is walkable)	 */	protectThreadList(cur);	nt->active = 1;	nt->next = activeThreads;	activeThreads = nt;	/* Note that we don't directly start 'func' because we (a) still need to	 * set the thread specifics, and (b) we need a looper for our thread	 * recycling. We create the new thread while still holding the lock, because	 * we otherwise might have a invalid tid in the activeList. The new thread	 * in turn doesn't need the lock until it exits	 */	creation_succeeded = pthread_create( &nt->tid, &nt->attr, tRun, nt);	/* If the creation of the new thread failed for some reason,	 * print the reason, clean up and bail out.

⌨️ 快捷键说明

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