/* * thread_depress_priority * * Depress thread's priority to lowest possible for specified period. * Intended for use when thread wants a lock but doesn't know which * other thread is holding it. As with thread_switch, fixed * priority threads get exactly what they asked for. Users access * this by the SWITCH_OPTION_DEPRESS option to thread_switch. A Time * of zero will result in no timeout being scheduled. */ void thread_depress_priority( thread_t thread, mach_msg_timeout_t depress_time) { unsigned int ticks; spl_t s; /* convert from milliseconds to ticks */ ticks = convert_ipc_timeout_to_ticks(depress_time); s = splsched(); thread_lock(thread); /* * If thread is already depressed, override previous depression. */ reset_timeout_check(&thread->depress_timer); /* * Save current priority, then set priority and * sched_pri to their lowest possible values. */ thread->depress_priority = thread->priority; thread->priority = 31; thread->sched_pri = 31; if (ticks != 0) set_timeout(&thread->depress_timer, ticks); thread_unlock(thread); (void) splx(s); }
/* * thread_depress_abort: * * Prematurely abort priority depression if there is one. */ kern_return_t thread_depress_abort(thread_t thread) { spl_t s; if (thread == THREAD_NULL) return(KERN_INVALID_ARGUMENT); s = splsched(); thread_lock(thread); /* * Only restore priority if thread is depressed. */ if (thread->depress_priority >= 0) { reset_timeout_check(&thread->depress_timer); thread->priority = thread->depress_priority; thread->depress_priority = -1; compute_priority(thread, FALSE); } thread_unlock(thread); (void) splx(s); return(KERN_SUCCESS); }
void thread_go( thread_t thread) { int state; spl_t s; s = splsched(); thread_lock(thread); reset_timeout_check(&thread->timer); state = thread->state; switch (state & TH_SCHED_STATE) { case TH_WAIT | TH_SUSP | TH_UNINT: case TH_WAIT | TH_UNINT: case TH_WAIT: /* * Sleeping and not suspendable - put * on run queue. */ thread->state = (state &~ TH_WAIT) | TH_RUN; thread->wait_result = THREAD_AWAKENED; thread_setrun(thread, TRUE); break; case TH_WAIT | TH_SUSP: case TH_RUN | TH_WAIT: case TH_RUN | TH_WAIT | TH_SUSP: case TH_RUN | TH_WAIT | TH_UNINT: case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT: /* * Either already running, or suspended. */ thread->state = state & ~TH_WAIT; thread->wait_result = THREAD_AWAKENED; break; default: /* * Not waiting. */ break; } thread_unlock(thread); splx(s); }
boolean_t mk_deliver_result(thread_t thread, int result) { boolean_t rc; int state, s; s = splsched(); thread_lock(thread); state = thread->state; reset_timeout_check(&thread->timer); switch (state & TH_SCHED_STATE) { case TH_WAIT | TH_SUSP | TH_UNINT: case TH_WAIT | TH_UNINT: case TH_WAIT: /* * Sleeping and not suspendable - put on run queue. */ thread->state = (state &~ TH_WAIT) | TH_RUN; thread->wait_result = (kern_return_t) result; simpler_thread_setrun(thread, TRUE); rc = TRUE; break; case TH_WAIT | TH_SUSP: case TH_RUN | TH_WAIT: case TH_RUN | TH_WAIT | TH_SUSP: case TH_RUN | TH_WAIT | TH_UNINT: case TH_RUN | TH_WAIT | TH_SUSP | TH_UNINT: /* * Either already running, or suspended. */ thread->state = state &~ TH_WAIT; thread->wait_result = (kern_return_t) result; rc = FALSE; break; default: /* * Not waiting. */ rc = FALSE; break; } thread_unlock(thread); splx(s); return rc; }
void task_swapper(void) { task_t outtask, intask; int timeout; int loopcnt = 0; boolean_t start_swapping; boolean_t stop_swapping; int local_page_free_avg; extern int hz; thread_swappable(current_act(), FALSE); stack_privilege(current_thread()); spllo(); for (;;) { local_page_free_avg = vm_page_free_avg; while (TRUE) { #if 0 if (task_swap_debug) printf("task_swapper: top of loop; cnt = %d\n",loopcnt); #endif intask = pick_intask(); start_swapping = ((vm_pageout_rate_avg > swap_start_pageout_rate) || (vm_grab_rate_avg > max_grab_rate)); stop_swapping = (vm_pageout_rate_avg < swap_stop_pageout_rate); /* * If a lot of paging is going on, or another task should come * in but memory is tight, find something to swap out and start * it. Don't swap any task out if task swapping is disabled. * vm_page_queue_free_lock protects the vm globals. */ outtask = TASK_NULL; if (start_swapping || (!stop_swapping && intask && ((local_page_free_avg / AVE_SCALE) < vm_page_free_target)) ) { if (task_swap_enable && (outtask = pick_outtask()) && (task_swapout(outtask) == KERN_SUCCESS)) { unsigned long rss; #if TASK_SW_DEBUG if (task_swap_debug) print_pid(outtask, local_page_free_avg / AVE_SCALE, vm_page_free_target, "<", "out"); #endif rss = outtask->swap_rss; if (outtask->swap_nswap == 1) rss /= 2; /* divide by 2 if never out */ local_page_free_avg += (rss/short_avg_interval) * AVE_SCALE; } if (outtask != TASK_NULL) task_deallocate(outtask); } /* * If there is an eligible task to bring in and there are at * least vm_page_free_target free pages, swap it in. If task * swapping has been disabled, bring the task in anyway. */ if (intask && ((local_page_free_avg / AVE_SCALE) >= vm_page_free_target || stop_swapping || !task_swap_enable)) { if (task_swapin(intask, FALSE) == KERN_SUCCESS) { unsigned long rss; #if TASK_SW_DEBUG if (task_swap_debug) print_pid(intask, local_page_free_avg / AVE_SCALE, vm_page_free_target, ">=", "in"); #endif rss = intask->swap_rss; if (intask->swap_nswap == 1) rss /= 2; /* divide by 2 if never out */ local_page_free_avg -= (rss/short_avg_interval) * AVE_SCALE; } } /* * XXX * Here we have to decide whether to continue swapping * in and/or out before sleeping. The decision should * be made based on the previous action (swapin/out) and * current system parameters, such as paging rates and * demand. * The function, compute_vm_averages, which does these * calculations, depends on being called every second, * so we can't just do the same thing. */ if (++loopcnt < MAX_LOOP) continue; /* * Arrange to be awakened if paging is still heavy or there are * any tasks partially or completely swapped out. (Otherwise, * the wakeup will come from the external trigger(s).) */ timeout = 0; if (start_swapping) timeout = task_swap_cycle_time; else { task_swapper_lock(); if (!queue_empty(&swapped_tasks)) timeout = min_swap_time; task_swapper_unlock(); } assert_wait((event_t)&swapped_tasks, FALSE); if (timeout) { if (task_swap_debug) printf("task_swapper: set timeout of %d\n", timeout); thread_set_timeout(timeout*hz); } if (task_swap_debug) printf("task_swapper: blocking\n"); thread_block((void (*)(void)) 0); if (timeout) { reset_timeout_check(¤t_thread()->timer); } /* reset locals */ loopcnt = 0; local_page_free_avg = vm_page_free_avg; } } }