// 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); }
/* * 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); }
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( ¤t_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; }
void thread_yield() { CAP_SET_SYSCALL(); thread_yield_internal( FALSE, 0 ); CAP_CLEAR_SYSCALL(); }
/* * 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); }