Exemple #1
0
void thread_exit(void *ret)
{
  thread_t *t = current_thread;

  sanity_check_threadcounts();
  tdebug("current=%s\n", current_thread?current_thread->name : "NULL");

  if (current_thread == main_thread && main_exited == 0) {
	// the case when the user calls thread_exit() in main thread is complicated
	// we cannot simply terminate the main thread, because we need that stack to terminate the
	// whole program normally.  so we call exit() to make the c runtime help us get the stack
	// context where we can just return to terminate the whole program
	// this will call exit_func() and in turn call thread_exit() again
    main_exited = 1;
  	exit (0);		
  }

  // note the thread exit in the blocking graph
  t->curr_stats.node = bg_exit_node;
  current_thread->prev_stats.node->num_here--;
  current_thread->curr_stats.node->num_here++;
  if( bg_save_stats ) {
    bg_update_stats();
  }
    
  // update thread counts
  num_runnable_threads--;
  if( t->daemon ) num_daemon_threads--;

  t->state = ZOMBIE;
  num_zombie_threads++;

  // deallocate the TCB
  // keep the thread, if the thread is Joinable, and we want the return value for something
  if ( !( t->joinable ) ) {
    // tell the scheduler thread to delete the current one
    current_thread_exited = 1;
  } else {
    t->ret = ret;
    if (t->join_thread)
      thread_resume(t->join_thread);
  }

  sanity_check_threadcounts();

  // squirrel away the stack limit--not that we'll need it again
  current_thread->stack_bottom = stack_bottom;
  current_thread->stack_fingerprint = stack_fingerprint;

  // give control back to the scheduler
#ifdef NO_SCHEDULER_THREAD
  do_scheduler(NULL);
#else
  co_call(scheduler_thread->coro, NULL);
#endif
}
Exemple #2
0
static void do_service(config_t *cpe, config_t *config, struct rs_config *rs_config)
{
	struct rs_start *rs_start = &rs_config->rs_start;
	config_t *cp;

	/* At this point we expect one sublist that contains the varios
	 * resource allocations
	 */
	if (!(cpe->flags & CFG_SUBLIST))
	{
		fatal("do_service: expected list at %s:%d",
			cpe->file, cpe->line);
	}
	if (cpe->next != NULL)
	{
		cpe= cpe->next;
		fatal("do_service: expected end of list at %s:%d",
			cpe->file, cpe->line);
	}
	cpe= cpe->list;

	/* Process the list */
	for (cp= cpe; cp; cp= cp->next)
	{
		if (!(cp->flags & CFG_SUBLIST))
		{
			fatal("do_service: expected list at %s:%d",
				cp->file, cp->line);
		}
		cpe= cp->list;
		if ((cpe->flags & CFG_STRING) || (cpe->flags & CFG_SUBLIST))
		{
			fatal("do_service: expected word at %s:%d",
				cpe->file, cpe->line);
		}

		if (strcmp(cpe->word, KW_CLASS) == 0)
		{
			do_class(cpe->next, config, rs_config);
			continue;
		}
		if (strcmp(cpe->word, KW_UID) == 0)
		{
			do_uid(cpe->next, rs_start);
			continue;
		}
		if (strcmp(cpe->word, KW_SIGMGR) == 0)
		{
			do_sigmgr(cpe->next, rs_start);
			continue;
		}
		if (strcmp(cpe->word, KW_TYPE) == 0)
		{
			do_type(cpe->next, rs_config);
			continue;
		}
		if (strcmp(cpe->word, KW_DESCR) == 0)
		{
			do_descr(cpe->next, rs_config);
			continue;
		}
		if (strcmp(cpe->word, KW_SCHEDULER) == 0)
		{
			do_scheduler(cpe->next, rs_start);
			continue;
		}
		if (strcmp(cpe->word, KW_PRIORITY) == 0)
		{
			do_priority(cpe->next, rs_start);
			continue;
		}
		if (strcmp(cpe->word, KW_QUANTUM) == 0)
		{
			do_quantum(cpe->next, rs_start);
			continue;
		}
		if (strcmp(cpe->word, KW_CPU) == 0)
		{
			do_cpu(cpe->next, rs_start);
			continue;
		}
		if (strcmp(cpe->word, KW_IRQ) == 0)
		{
			do_irq(cpe->next, rs_start);
			continue;
		}
		if (strcmp(cpe->word, KW_IO) == 0)
		{
			do_io(cpe->next, rs_start);
			continue;
		}
		if (strcmp(cpe->word, KW_PCI) == 0)
		{
			do_pci(cpe->next, rs_start);
			continue;
		}
		if (strcmp(cpe->word, KW_SYSTEM) == 0)
		{
			do_system(cpe->next, rs_start);
			continue;
		}
		if (strcmp(cpe->word, KW_IPC) == 0)
		{
			do_ipc(cpe->next, rs_start);
			continue;
		}
		if (strcmp(cpe->word, KW_VM) == 0)
		{
			do_vm(cpe->next, rs_start);
			continue;
		}
		if (strcmp(cpe->word, KW_CONTROL) == 0)
		{
			do_control(cpe->next, rs_start);
			continue;
		}
	}
}
Exemple #3
0
/**
 * perform necessary management to yield the current thread
 * if suspended == TRUE && timeout != 0 -> the thread is added 
 * to the sleep queue and later waken up when the clock times out
 * returns FALSE if time-out actually happens, TRUE if waken up
 * by other threads, INTERRUPTED if interrupted by a signal
 **/
static int thread_yield_internal(int suspended, unsigned long long timeout)
{
// now we use a per-thread errno stored in thread_t
   int savederrno;
  int rv = OK;

  tdebug("current_thread=%p\n",current_thread);

  savederrno = errno;

  // decide what to do with the thread
  if( !suspended ) // just add it to the runlist
    sched_add_thread( current_thread );
  else if( timeout ) // add to the sleep list
    sleepq_add_thread( current_thread, timeout);

  {
#ifdef SHOW_EDGE_TIMES
    cpu_tick_t start, end, rstart, rend;
    GET_CPU_TICKS(start);
    GET_REAL_CPU_TICKS(rstart);
#endif

    // figure out the current node in the graph
    if( !conf_no_stacktrace )
      bg_backtrace_set_node();
    // FIXME: fake out what cil would do...  current_thread->curr_stats.node = bg_dummy_node;

    // we should already have been told the node by CIL or directly by the programmer
    assert( current_thread->curr_stats.node != NULL );
    
    // update node counts
    current_thread->prev_stats.node->num_here--;
    current_thread->curr_stats.node->num_here++;
    
    // update the blocking graph info
    if( bg_save_stats )
      bg_update_stats();
  
#ifdef SHOW_EDGE_TIMES
    GET_CPU_TICKS(end);
    GET_REAL_CPU_TICKS(rend);
    {
      thread_stats_t *curr = &current_thread->curr_stats;
      thread_stats_t *prev = &current_thread->prev_stats;
      output(" %3d -> %-3d     %7lld ticks  (%lld ms)   %7lld rticks (%lld ms)    ", 
             prev->node->node_num,  curr->node->node_num, 
             curr->cpu_ticks - prev->cpu_ticks,
             (curr->cpu_ticks - prev->cpu_ticks) / ticks_per_millisecond,
# ifdef USE_PERFCTR
             curr->real_ticks - prev->real_ticks,
             (curr->real_ticks - prev->real_ticks) / ticks_per_millisecond
# else
             curr->cpu_ticks - prev->cpu_ticks,
             (curr->cpu_ticks - prev->cpu_ticks) / ticks_per_millisecond
# endif
             );

      output("update bg node %d:   %lld   (%lld ms)   real: %lld (%lld ms)\n", 
             current_thread->curr_stats.node->node_num, 
             (end-start), (end-start)/ticks_per_millisecond, 
             (rend-rstart), (rend-rstart)/ticks_per_millisecond);
    }
#endif
  }

  // squirrel away the stack limit for next time
  current_thread->stack_bottom = stack_bottom;
  current_thread->stack_fingerprint = stack_fingerprint;

  // switch to the scheduler thread
#ifdef NO_SCHEDULER_THREAD
  do_scheduler(NULL);
#else
  co_call(scheduler_thread->coro, NULL);
#endif
  
  // set up stack limit for new thread
  stack_bottom = current_thread->stack_bottom;
  stack_fingerprint = current_thread->stack_fingerprint;

  // rotate the stats
  if( bg_save_stats ) {
    current_thread->prev_stats = current_thread->curr_stats;
    
    // update thread time, to skip time asleep
    GET_CPU_TICKS( current_thread->prev_stats.cpu_ticks );
    current_thread->prev_stats.cpu_ticks -= ticks_diff;  // FIXME: subtract out time to do debug output
#ifdef USE_PERFCTR
    GET_REAL_CPU_TICKS( current_thread->prev_stats.real_ticks );
    current_thread->prev_stats.real_ticks -= ticks_rdiff;  // FIXME: subtract out time to do debug output
#endif    
  } else {
    current_thread->prev_stats.node = current_thread->curr_stats.node;
  }
  
  // check whether time-out happens
  if (suspended && timeout && current_thread->timeout) {
    rv = TIMEDOUT;
    current_thread->timeout = 0;
  }

  // check for and process pending signals
  if ( likely(!current_thread->sig_waiting) ) {
  	if (sig_process_pending())
		rv = INTERRUPTED;
  } else {
	// if sig_waiting is 1, sigwait() itself will handle the remaining	
	rv = INTERRUPTED;
  }
  
  errno = savederrno;
  return rv;
}