X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/fe8ab488e9161c46dd9885d58fc52996dc0249ff..490019cf9519204c5fb36b2fba54ceb983bb6b72:/osfmk/kern/syscall_subr.c diff --git a/osfmk/kern/syscall_subr.c b/osfmk/kern/syscall_subr.c index 6f614474c..1ebf39e4f 100644 --- a/osfmk/kern/syscall_subr.c +++ b/osfmk/kern/syscall_subr.c @@ -98,14 +98,7 @@ __unused struct pfz_exit_args *args) * swtch and swtch_pri both attempt to context switch (logic in * thread_block no-ops the context switch if nothing would happen). * A boolean is returned that indicates whether there is anything - * else runnable. - * - * This boolean can be used by a thread waiting on a - * lock or condition: If FALSE is returned, the thread is justified - * in becoming a resource hog by continuing to spin because there's - * nothing else useful that the processor could do. If TRUE is - * returned, the thread should make one more check on the - * lock and then be a good citizen and really suspend. + * else runnable. That's no excuse to spin, though. */ static void @@ -255,7 +248,8 @@ kern_return_t thread_switch( struct thread_switch_args *args) { - register thread_t thread, self = current_thread(); + thread_t thread = THREAD_NULL; + thread_t self = current_thread(); mach_port_name_t thread_name = args->thread_name; int option = args->option; mach_msg_timeout_t option_time = args->option_time; @@ -303,11 +297,11 @@ thread_switch( /* * Translate the port name if supplied. */ - if (thread_name != MACH_PORT_NULL) { - ipc_port_t port; + if (thread_name != MACH_PORT_NULL) { + ipc_port_t port; if (ipc_port_translate_send(self->task->itk_space, - thread_name, &port) == KERN_SUCCESS) { + thread_name, &port) == KERN_SUCCESS) { ip_reference(port); ip_unlock(port); @@ -315,16 +309,11 @@ thread_switch( ip_release(port); if (thread == self) { - (void)thread_deallocate_internal(thread); + thread_deallocate(thread); thread = THREAD_NULL; } } - else - thread = THREAD_NULL; } - else - thread = THREAD_NULL; - if (option == SWITCH_OPTION_OSLOCK_DEPRESS || option == SWITCH_OPTION_OSLOCK_WAIT) { if (thread != THREAD_NULL) { @@ -336,16 +325,18 @@ thread_switch( * a thread in another task) */ - (void)thread_deallocate_internal(thread); + thread_deallocate(thread); thread = THREAD_NULL; } else { /* * Attempt to kick the lock owner up to our same IO throttling tier. * If the thread is currently blocked in throttle_lowpri_io(), * it will immediately break out. + * + * TODO: SFI break out? */ int new_policy = proc_get_effective_thread_policy(self, TASK_POLICY_IO); - + set_thread_iotier_override(thread, new_policy); } } @@ -355,62 +346,43 @@ thread_switch( * Try to handoff if supplied. */ if (thread != THREAD_NULL) { - processor_t processor; - spl_t s; + spl_t s = splsched(); - s = splsched(); - thread_lock(thread); + /* This may return a different thread if the target is pushing on something */ + thread_t pulled_thread = thread_run_queue_remove_for_handoff(thread); KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED,MACH_SCHED_THREAD_SWITCH)|DBG_FUNC_NONE, - thread_tid(thread), thread->state, 0, 0, 0); - - /* - * Check that the thread is not bound - * to a different processor, and that realtime - * is not involved. - * - * Next, pull it off its run queue. If it - * doesn't come, it's not eligible. - */ - processor = current_processor(); - if (processor->current_pri < BASEPRI_RTQUEUES && - thread->sched_pri < BASEPRI_RTQUEUES && - (thread->bound_processor == PROCESSOR_NULL || - thread->bound_processor == processor) && - thread_run_queue_remove(thread) ) { - /* - * Hah, got it!! - */ - thread_unlock(thread); - - (void)thread_deallocate_internal(thread); + thread_tid(thread), thread->state, + pulled_thread ? TRUE : FALSE, 0, 0); + + if (pulled_thread != THREAD_NULL) { + /* We can't be dropping the last ref here */ + thread_deallocate_safe(thread); if (wait_option) assert_wait_timeout((event_t)assert_wait_timeout, THREAD_ABORTSAFE, - option_time, scale_factor); - else - if (depress_option) + option_time, scale_factor); + else if (depress_option) thread_depress_ms(option_time); self->saved.swtch.option = option; self->saved.swtch.reenable_workq_callback = reenable_workq_callback; - thread_run(self, (thread_continue_t)thread_switch_continue, NULL, thread); + thread_run(self, (thread_continue_t)thread_switch_continue, NULL, pulled_thread); /* NOTREACHED */ + panic("returned from thread_run!"); } - thread_unlock(thread); splx(s); thread_deallocate(thread); } - + if (wait_option) assert_wait_timeout((event_t)assert_wait_timeout, THREAD_ABORTSAFE, option_time, scale_factor); - else - if (depress_option) + else if (depress_option) thread_depress_ms(option_time); - + self->saved.swtch.option = option; self->saved.swtch.reenable_workq_callback = reenable_workq_callback; @@ -443,6 +415,14 @@ thread_depress_abstime( processor_t myprocessor = self->last_processor; self->sched_pri = DEPRESSPRI; + + KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_SCHED_CHANGE_PRIORITY), + (uintptr_t)thread_tid(self), + self->base_pri, + self->sched_pri, + 0, /* eventually, 'reason' */ + 0); + myprocessor->current_pri = self->sched_pri; self->sched_flags |= TH_SFLAG_DEPRESS; @@ -482,7 +462,7 @@ thread_depress_expire( thread_lock(thread); if (--thread->depress_timer_active == 0) { thread->sched_flags &= ~TH_SFLAG_DEPRESSED_MASK; - SCHED(compute_priority)(thread, FALSE); + thread_recompute_sched_pri(thread, FALSE); } thread_unlock(thread); splx(s); @@ -503,7 +483,7 @@ thread_depress_abort_internal( if (!(thread->sched_flags & TH_SFLAG_POLLDEPRESS)) { if (thread->sched_flags & TH_SFLAG_DEPRESSED_MASK) { thread->sched_flags &= ~TH_SFLAG_DEPRESSED_MASK; - SCHED(compute_priority)(thread, FALSE); + thread_recompute_sched_pri(thread, FALSE); result = KERN_SUCCESS; } @@ -538,6 +518,14 @@ thread_poll_yield( thread_lock(self); if (!(self->sched_flags & TH_SFLAG_DEPRESSED_MASK)) { self->sched_pri = DEPRESSPRI; + + KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_SCHED, MACH_SCHED_CHANGE_PRIORITY), + (uintptr_t)thread_tid(self), + self->base_pri, + self->sched_pri, + 0, /* eventually, 'reason' */ + 0); + myprocessor->current_pri = self->sched_pri; } self->computation_epoch = abstime;