kernel/sys/process.c
/**
 * @brief Yield the processor to the next available task.
 *
 * Yields the current process, allowing the next to run. Can be called both as
 * part of general preemption or from blocking tasks; in the latter case,
 * the process should be added to a scheduler queue to be awakoen later when the
 * blocking operation is completed and @p reschedule should be set to 0.
 *
 * @param reschedule Non-zero if this process should be added to the ready queue.
 */
@brief Yield the processor to the next available task.
Yields the current process, allowing the next to run. Can be called both as
part of general preemption or from blocking tasks; in the latter case,
the process should be added to a scheduler queue to be awakoen later when the
blocking operation is completed and @p reschedule should be set to 0.

@param reschedule Non-zero if this process should be added to the ready queue.
@brief Yield the processor to the next available task . Yields the current process allowing the next to run . Can be called both as part of general preemption or from blocking tasks ; in the latter case the process should be added to a scheduler queue to be awakoen later when the blocking operation is completed and @p reschedule should be set to 0 . @param reschedule Non - zero if this process should be added to the ready queue .
void switch_task(uint8_t reschedule) {
	if (!this_core->current_process) return;
	if (this_core->current_process == this_core->kernel_idle_task && __builtin_return_address(0) != &_ret_from_preempt_source) {
		arch_fatal_prepare();
		printf("Context switch from kernel_idle_task triggered from somewhere other than pre-emption source. Halting.\n");
		printf("This generally means that a driver responding to interrupts has attempted to yield in its interrupt context.\n");
		printf("Ensure that all device drivers which respond to interrupts do so with non-blocking data structures.\n");
		printf("   Return address of switch_task: %p\n", __builtin_return_address(0));
		arch_dump_traceback();
		arch_fatal();
	}
	if (!(this_core->current_process->flags & PROC_FLAG_RUNNING) || (this_core->current_process == this_core->kernel_idle_task)) {
		switch_next();
		return;
	}
	arch_save_floating((process_t*)this_core->current_process);
	if (arch_save_context(&this_core->current_process->thread) == 1) {
		arch_restore_floating((process_t*)this_core->current_process);
		fix_signal_stacks();
		if (!(this_core->current_process->flags & PROC_FLAG_FINISHED)) {
			if (this_core->current_process->signal_queue->length > 0) {
				node_t * node = list_dequeue(this_core->current_process->signal_queue);
				signal_t * sig = node->value;
				free(node);
				handle_signal((process_t*)this_core->current_process,sig);
			}
		}
		return;
	}
	if (reschedule) {
		make_process_ready((process_t*)this_core->current_process);
	}
	switch_next();
}
void switch_task ( uint8_t reschedule ) { if ( ! this_core -> current_process ) return ; if ( this_core -> current_process == this_core -> kernel_idle_task && __builtin_return_address ( 0 ) != & _ret_from_preempt_source ) { arch_fatal_prepare ( ) ; printf ( " \n " ) ; printf ( " \n " ) ; printf ( " \n " ) ; printf ( " \n " , __builtin_return_address ( 0 ) ) ; arch_dump_traceback ( ) ; arch_fatal ( ) ; } if ( ! ( this_core -> current_process -> flags & PROC_FLAG_RUNNING ) || ( this_core -> current_process == this_core -> kernel_idle_task ) ) { switch_next ( ) ; return ; } arch_save_floating ( ( process_t * ) this_core -> current_process ) ; if ( arch_save_context ( & this_core -> current_process -> thread ) == 1 ) { arch_restore_floating ( ( process_t * ) this_core -> current_process ) ; fix_signal_stacks ( ) ; if ( ! ( this_core -> current_process -> flags & PROC_FLAG_FINISHED ) ) { if ( this_core -> current_process -> signal_queue -> length > 0 ) { node_t * node = list_dequeue ( this_core -> current_process -> signal_queue ) ; signal_t * sig = node -> value ; free ( node ) ; handle_signal ( ( process_t * ) this_core -> current_process , sig ) ; } } return ; } if ( reschedule ) { make_process_ready ( ( process_t * ) this_core -> current_process ) ; } switch_next ( ) ; }
@brief Yield the processor to the next available task.
@brief Yield the processor to the next available task .
/* switch_task() called but the scheduler isn't enabled? Resume... this is probably a bug. */ /* If a process got to switch_task but was not marked as running, it must be exiting and we don't
	 * want to waste time saving context for it. Also, kidle is always resumed from the top of its
	 * loop function, so we don't save any context for it either. */ /* 'setjmp' - save the execution context. When this call returns '1' we are back
	 * from a task switch and have been awoken if we were sleeping. */ /* If this is a normal yield, we reschedule.
	 * XXX: Is this going to work okay with SMP? I think this whole thing
	 *      needs to be wrapped in a lock, but also what if we put the
	 *      thread into a schedule queue previously but a different core
	 *      picks it up before we saved the thread context or the FPU state... */ /* @ref switch_next() does not return. */