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

📄 thread-impl.c

📁 kaffe Java 解释器语言,源码,Java的子集系统,开放源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        int maxpr, int minpr,        void *(*_allocator)(size_t),        void (*_deallocator)(void*),        void *(*_reallocator)(void*,size_t),        void (*_destructor1)(void*),        void (*_onstop)(void),        void (*_ondeadlock)(void)){  DBG(JTHREAD, dprintf("initialized\n"))  thread_malloc = _allocator;  thread_free = _deallocator;  pthread_key_create( &ntKey, NULL);  sem_init( &critSem, 0, 0);  priorities = (int *)_allocator ((maxpr+1) * sizeof(int));  tMapPriorities(maxpr+1);  tInitSignalHandlers();  sigfillset( &suspendSet);  sigdelset( &suspendSet, SIG_RESUME);  tSetupFirstNative();  DBG( JTHREAD, tStartDeadlockWatchdog() )}jthread_tjthread_createfirst(size_t mainThreadStackSize, unsigned char pri, 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;  /* Get stack boundaries. Note that this is just an approximation   * which should cover all gc-relevant stack locations   */#if defined(STACK_GROWS_UP)  nt->stackMin  = (void*) (uintp)(&nt - 0x100);  nt->stackMax  = (void*) ((uintp) nt->stackMin + mainThreadStackSize);#else  nt->stackMax  = (void*) (uintp)(&nt + 0x100);  nt->stackMin  = (void*) ((uintp) nt->stackMax - mainThreadStackSize);#endif  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);}void jthread_interrupt(jthread_t tid){	/* We need to send some signal to interrupt syscalls. */	pthread_kill(tid->tid, SIG_RESUME);}bool jthread_attach_current_thread (bool daemon){  jthread_t		nt;  /* create the jthread* thingy */  nt = thread_malloc( sizeof(struct _jthread) );  nt->func         = 0;  nt->suspendState = 0;  nt->stackMin     = (void *)((uintp)&nt - 0x8000);  nt->stackMax     = (void *)((uintp)&nt + 0x400);  nt->stackCur     = 0;   nt->daemon       = daemon;  /* link everything together */  nt->tid = pthread_self();  pthread_setspecific( ntKey, nt);  /* and done */  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;  int		iLockRoot;  /* 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 */  sem_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))	TLOCK( cur); /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tLock */	/* 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 = 0;	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--;	TUNLOCK( cur); /* ---------------------------------------------------- tLock */	if ( nCached >= MAX_CACHED_THREADS ){	  break;	}	/* Wait until we get re-used (by TcreateThread). No need to update the	 * blockState, since we aren't active anymore */	sem_wait( &cur->sem);	/*	 * 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 0;}/* * 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 char pri, void* func, int daemon, void* jlThread, size_t threadStackSize ){  jthread_t		cur = jthread_current();  jthread_t		nt;  struct sched_param	sp;  int			iLockRoot;  /* 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();  }  sp.sched_priority = priorities[pri];  if ( !daemon ) 	nonDaemons++;  if ( cache ) {	TLOCK( cur); /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tLock */	/* 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 = daemon;	nt->func = func;	nt->stackCur = 0;	pthread_setschedparam( nt->tid, SCHEDULE_POLICY, &sp);	DBG( JTHREAD, TMSG_SHORT( "create recycled ", nt))	/* resurrect it */	nt->active = 1;	sem_post( &nt->sem);	TUNLOCK( cur); /* ---------------------------------------------------- tLock */  }  else {	if ( nSysThreads++ > MAX_SYS_THREADS ){	  // bail out, we exceeded our physical thread limit	  DBG( JTHREAD, dprintf( "too many threads (%d)\n", nSysThreads))	  return (0);	}	nt = thread_malloc( sizeof(struct _jthread) );	pthread_attr_init( &nt->attr);	pthread_attr_setschedparam( &nt->attr, &sp);	pthread_attr_setschedpolicy( &nt->attr, SCHEDULE_POLICY);	pthread_attr_setstacksize( &nt->attr, threadStackSize);	nt->data.jlThread       = jlThread;	nt->func         = func;	nt->suspendState = 0;	nt->stackMin     = 0;	nt->stackMax     = 0;	nt->stackCur     = 0;	nt->daemon	 = daemon;	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)	 */	TLOCK( cur); /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tLock */	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	 */	pthread_create( &nt->tid, &nt->attr, tRun, nt);	/* wait until the thread specific data has been set, and the new thread	 * is in a suspendable state */	sem_wait( &nt->sem);	TUNLOCK( cur); /* ---------------------------------------------------- tLock */  }  return (nt);}/*********************************************************************** * thread exit & cleanup *//* * Native thread cleanup. This is just called in case a native thread * is not cached */staticvoid tDispose ( jthread_t nt ){  pthread_detach( nt->tid);  sem_destroy( &nt->sem);  thread_free( nt);}/* * Function to be called (by threads.c firstStartThread) when the thread leaves * the user thread function */voidjthread_exit ( void ){  jthread_t	cur = jthread_current();  jthread_t	t;  int		iLockRoot;  /*   * We are leaving the thread user func, which means we are not   * subject to GC, anymore (has to be marked here because the first thread   * never goes through tRun)   */  cur->active = 0;  DBG( JTHREAD, TMSG_SHORT( "exit ", cur))  DBG( JTHREAD, dprintf("exit with %d non daemons (%x)\n", nonDaemons, cur->daemon))  if ( !cur->daemon ) {	/* the last non daemon should shut down the process */	if ( --nonDaemons == 0 ) {	  TLOCK( cur); /* ++++++++++++++++++++++++++++++++++++++++++++++++++++ tLock */	  DBG( JTHREAD, dprintf("exit on last nonDaemon\n"))	  /*	   * be a nice citizen, try to cancel all other threads before we	   * bail out, to give them a chance to run their cleanup handlers	   */	  for ( t=cache; t != NULL; t = t->next ){		pthread_cancel( t->tid);	  }	  for ( t=activeThreads; t != NULL; t = t->next ){		if ( t != cur ) {		  pthread_cancel( t->tid);		}	  }#if defined(KAFFE_VMDEBUG)	  if ( deadlockWatchdog ){		pthread_cancel( deadlockWatchdog);	  }#endif	  if ( (cur != firstThread) && (firstThread->active == 0) ) {		/* if the firstThread has already been frozen, it's not in the cache list */		pthread_cancel( firstThread->tid);	  }	  pthread_exit( 0);	  /* pretty useless, but clean */

⌨️ 快捷键说明

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