Example #1
0
// timeout == 0 means infinite time
int thread_suspend_self(unsigned long long timeout)
{
  num_suspended_threads++;
  num_runnable_threads--;
  sanity_check_threadcounts();
  current_thread->state = SUSPENDED;
  return thread_yield_internal(TRUE, timeout);
}
Example #2
0
/*
 * fork_create_child
 *
 * Description:	Common operations associated with the creation of a child
 *		process
 *
 * Parameters:	parent_task		parent task
 *		child_proc		child process
 *		inherit_memory		TRUE, if the parents address space is
 *					to be inherited by the child
 *		is64bit			TRUE, if the child being created will
 *					be associated with a 64 bit process
 *					rather than a 32 bit process
 *
 * Note:	This code is called in the fork() case, from the execve() call
 *		graph, if implementing an execve() following a vfork(), from
 *		the posix_spawn() call graph (which implicitly includes a
 *		vfork() equivalent call, and in the system bootstrap case.
 *
 *		It creates a new task and thread (and as a side effect of the
 *		thread creation, a uthread), which is then associated with the
 *		process 'child'.  If the parent process address space is to
 *		be inherited, then a flag indicates that the newly created
 *		task should inherit this from the child task.
 *
 *		As a special concession to bootstrapping the initial process
 *		in the system, it's possible for 'parent_task' to be TASK_NULL;
 *		in this case, 'inherit_memory' MUST be FALSE.
 */
thread_t
fork_create_child(task_t parent_task, proc_t child_proc, int inherit_memory, int is64bit)
{
	thread_t	child_thread = NULL;
	task_t		child_task;
	kern_return_t	result;

	/* Create a new task for the child process */
	result = task_create_internal(parent_task,
					inherit_memory,
					is64bit,
					&child_task);
	if (result != KERN_SUCCESS) {
		printf("execve: task_create_internal failed.  Code: %d\n", result);
		goto bad;
	}

	/* Set the child process task to the new task */
	child_proc->task = child_task;

	/* Set child task process to child proc */
	set_bsdtask_info(child_task, child_proc);

	/* Propagate CPU limit timer from parent */
	if (timerisset(&child_proc->p_rlim_cpu))
		task_vtimer_set(child_task, TASK_VTIMER_RLIM);

	/* Set/clear 64 bit vm_map flag */
	if (is64bit)
		vm_map_set_64bit(get_task_map(child_task));
	else
		vm_map_set_32bit(get_task_map(child_task));

#if CONFIG_MACF
	/* Update task for MAC framework */
	/* valid to use p_ucred as child is still not running ... */
	mac_task_label_update_cred(child_proc->p_ucred, child_task);
#endif

	/*
	 * Set child process BSD visible scheduler priority if nice value
	 * inherited from parent
	 */
	if (child_proc->p_nice != 0)
		resetpriority(child_proc);

	/* Create a new thread for the child process */
	result = thread_create(child_task, &child_thread);
	if (result != KERN_SUCCESS) {
		printf("execve: thread_create failed. Code: %d\n", result);
		task_deallocate(child_task);
		child_task = NULL;
	}
bad:
	thread_yield_internal(1);

	return(child_thread);
}
Example #3
0
static void thread_init() 
{
  static int init_done = 0;

  capriccio_main_pid = getpid();

  // read config info from the environemtn
  read_config();

  //assert(0);
  if(init_done) 
    return;
  init_done = 1;

  // make sure the clock init is already done, so we don't wind up w/
  // a dependancy loop b/w perfctr and the rest of the code.
  init_cycle_clock();
  init_debug();

  // start main timer
  init_timer(&main_timer);
  register_timer("total", &main_timer);
  start_timer(&main_timer);

  init_timer(&scheduler_timer);
  register_timer("sheduler", &scheduler_timer);

  init_timer(&app_timer);
  register_timer("app", &app_timer);

  // init scheduler function pointers
  pick_scheduler();

  // init the scheduler code
  sched_init();

  // create the main thread
  main_thread = malloc(sizeof(thread_t));  
  assert(main_thread);
  bzero(main_thread, sizeof(thread_t));
  main_thread->name = "main_thread";
  main_thread->coro = co_main;
  main_thread->initial_arg = NULL;
  main_thread->initial_func = NULL;
  main_thread->tid = 0;   // fixed value
  main_thread->sleep = -1;
  current_thread = main_thread;

  // create the scheduler thread
#ifndef NO_SCHEDULER_THREAD
  scheduler_thread = (thread_t*) malloc( sizeof(thread_t) ); 
  assert(scheduler_thread);
  bzero(scheduler_thread, sizeof(thread_t));
  scheduler_thread->name = "scheduler";
  scheduler_thread->coro = co_create(do_scheduler, 0, SCHEDULER_STACK_SIZE);
  scheduler_thread->tid = -1;
#endif

  // don't exit when main exits - wait for threads to die
#ifndef NO_ATEXIT
  atexit(exit_func);
#endif

  // intialize blocking graph functions
  init_blocking_graph();

  // set stats for the main thread
  {
    bg_dummy_node->num_here++;
    current_thread->curr_stats.node = bg_dummy_node;
    current_thread->curr_stats.files = 0;
    current_thread->curr_stats.sockets = 0;
    current_thread->curr_stats.heap = 0;
    bg_set_current_stats( &current_thread->curr_stats );

    current_thread->prev_stats = current_thread->curr_stats;
  }

  // create thread list
  threadlist = new_pointer_list("thread_list");
  // add main thread to the list
  pl_add_tail(threadlist, main_thread);
  num_runnable_threads++;
  
  // create sleep queue
  sleepq = new_pointer_list("sleep_queue");
  max_sleep_time = 0;
  last_check_time = 0;
  first_wake_usecs = 0;
 
  start_usec = current_usecs();
  
  // make sure the scheduler runs.  NOTE: this is actually very
  // important, as it prevents a degenerate case in which the main
  // thread exits before the scheduler is ever called.  This will
  // actually cause a core dump, b/c the current_thead_exited flag
  // will be set, and incorrectly flag the first user thread for
  // deletion, rather than the main thread.
  thread_yield_internal(FALSE, 0);

  // things are all set up, so now turn on the syscall overrides
  cap_override_rw = 1;
}
Example #4
0
void thread_yield()
{
  CAP_SET_SYSCALL();
  thread_yield_internal( FALSE, 0 );
  CAP_CLEAR_SYSCALL();
}
Example #5
0
/*
 * fork_create_child
 *
 * Description:	Common operations associated with the creation of a child
 *		process
 *
 * Parameters:	parent_task		parent task
 *		parent_coalitions	parent's set of coalitions
 *		child_proc		child process
 *		inherit_memory		TRUE, if the parents address space is
 *					to be inherited by the child
 *		is64bit			TRUE, if the child being created will
 *					be associated with a 64 bit process
 *					rather than a 32 bit process
 *
 * Note:	This code is called in the fork() case, from the execve() call
 *		graph, if implementing an execve() following a vfork(), from
 *		the posix_spawn() call graph (which implicitly includes a
 *		vfork() equivalent call, and in the system bootstrap case.
 *
 *		It creates a new task and thread (and as a side effect of the
 *		thread creation, a uthread) in the parent coalition set, which is
 *		then associated with the process 'child'.  If the parent
 *		process address space is to be inherited, then a flag
 *		indicates that the newly created task should inherit this from
 *		the child task.
 *
 *		As a special concession to bootstrapping the initial process
 *		in the system, it's possible for 'parent_task' to be TASK_NULL;
 *		in this case, 'inherit_memory' MUST be FALSE.
 */
thread_t
fork_create_child(task_t parent_task, coalition_t *parent_coalitions, proc_t child_proc, int inherit_memory, int is64bit)
{
	thread_t	child_thread = NULL;
	task_t		child_task;
	kern_return_t	result;

	/* Create a new task for the child process */
	result = task_create_internal(parent_task,
					parent_coalitions,
					inherit_memory,
					is64bit,
					&child_task);
	if (result != KERN_SUCCESS) {
		printf("%s: task_create_internal failed.  Code: %d\n",
		    __func__, result);
		goto bad;
	}

	/* Set the child process task to the new task */
	child_proc->task = child_task;

	/* Set child task process to child proc */
	set_bsdtask_info(child_task, child_proc);

	/* Propagate CPU limit timer from parent */
	if (timerisset(&child_proc->p_rlim_cpu))
		task_vtimer_set(child_task, TASK_VTIMER_RLIM);

	/* Set/clear 64 bit vm_map flag */
	if (is64bit)
		vm_map_set_64bit(get_task_map(child_task));
	else
		vm_map_set_32bit(get_task_map(child_task));

	/*
	 * Set child process BSD visible scheduler priority if nice value
	 * inherited from parent
	 */
	if (child_proc->p_nice != 0)
		resetpriority(child_proc);

	/* Create a new thread for the child process */
	result = thread_create_with_continuation(child_task, &child_thread, (thread_continue_t)proc_wait_to_return);
	if (result != KERN_SUCCESS) {
		printf("%s: thread_create failed. Code: %d\n",
		    __func__, result);
		task_deallocate(child_task);
		child_task = NULL;
	}

	/*
         * Tag thread as being the first thread in its task.
         */
	thread_set_tag(child_thread, THREAD_TAG_MAINTHREAD);

bad:
	thread_yield_internal(1);

	return(child_thread);
}