/* * Suspend execution of the specified thread. * This is a recursive-style suspension of the thread, a count of * suspends is maintained. * * Called with thread mutex held. */ void thread_hold( register thread_t thread) { if (thread->suspend_count++ == 0) { install_special_handler(thread); if (thread->started) thread_wakeup_one(&thread->suspend_count); } }
/* * Suspend execution of the specified thread. * This is a recursive-style suspension of the thread, a count of * suspends is maintained. * * Called with act_lock held. */ void thread_hold( register thread_act_t act) { thread_t thread = act->thread; if (act->suspend_count++ == 0) { install_special_handler(act); if ( act->started && thread != THREAD_NULL && thread->top_act == act ) thread_wakeup_one(&act->suspend_count); } }
kern_return_t thread_suspend( register thread_act_t act) { thread_t thread; if (act == THR_ACT_NULL || act->task == kernel_task) return (KERN_INVALID_ARGUMENT); thread = act_lock_thread(act); if (!act->active) { act_unlock_thread(act); return (KERN_TERMINATED); } if ( act->user_stop_count++ == 0 && act->suspend_count++ == 0 ) { install_special_handler(act); if ( thread != current_thread() && thread != THREAD_NULL && thread->top_act == act ) { assert(act->started); thread_wakeup_one(&act->suspend_count); act_unlock_thread(act); thread_wait(thread); } else act_unlock_thread(act); } else act_unlock_thread(act); return (KERN_SUCCESS); }
/* * Process an AST_SWAPOUT. */ void swapout_ast() { spl_t s; thread_act_t act; thread_t thread; act = current_act(); /* * Task is being swapped out. First mark it as suspended * and halted, then call thread_swapout_enqueue to put * the thread on the queue for task_swap_swapout_threads * to swap out the thread. */ /* * Don't swap unswappable threads */ thread = act_lock_thread(act); s = splsched(); if (thread) thread_lock(thread); if ((act->ast & AST_SWAPOUT) == 0) { /* * Race with task_swapin. Abort swapout. */ task_swap_ast_aborted++; /* not locked XXX */ if (thread) thread_unlock(thread); splx(s); act_unlock_thread(act); } else if (act->swap_state == TH_SW_IN) { /* * Mark swap_state as TH_SW_TASK_SWAPPING to avoid * race with thread swapper, which will only * swap thread if swap_state is TH_SW_IN. * This way, the thread can only be swapped by * the task swapping mechanism. */ act->swap_state |= TH_SW_TASK_SWAPPING; /* assert(act->suspend_count == 0); XXX ? */ if (thread) thread_unlock(thread); if (act->suspend_count++ == 0) /* inline thread_hold */ install_special_handler(act); /* self->state |= TH_HALTED; */ thread_ast_clear(act, AST_SWAPOUT); /* * Initialize the swap_queue fields to allow an extra * queue_remove() in task_swapin if we lose the race * (task_swapin can be called before we complete * thread_swapout_enqueue). */ queue_init((queue_t) &act->swap_queue); splx(s); act_unlock_thread(act); /* this must be called at normal interrupt level */ thread_swapout_enqueue(act); } else { /* thread isn't swappable; continue running */ assert(act->swap_state == TH_SW_UNSWAPPABLE); if (thread) thread_unlock(thread); thread_ast_clear(act, AST_SWAPOUT); splx(s); act_unlock_thread(act); } }