static void signal_default(struct task *current, int signum) { /* Init ignores every signal */ if (current->pid == 1) return ; switch (signum) { case SIGCHLD: case SIGCONT: case SIGWINCH: /* Ignore */ break; case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU: kp(KP_TRACE, "task %d: Handling stop (%d)\n", current->pid, signum); current->ret_signal = TASK_SIGNAL_STOP | signum; current->state = TASK_STOPPED; if (current->parent) scheduler_task_wake(current->parent); scheduler_task_yield(); break; default: current->ret_signal = signum; sys_exit(0); } }
static int packet_process_thread(void *p) { while (1) { using_spinlock(&packet_queue_lock) { kp(KP_NORMAL, "packet-queue awake\n"); while (!list_empty(&packet_queue)) { struct packet *packet = list_take_first(&packet_queue, struct packet, packet_entry); kp(KP_NORMAL, "Recieved packet! len: %d\n", packet_len(packet)); kp(KP_NORMAL, "Packets in queue: %d\n", --packet_queue_length); not_using_spinlock(&packet_queue_lock) packet_linklayer_rx(packet); } sleep { if (list_empty(&packet_queue)) { not_using_spinlock(&packet_queue_lock) scheduler_task_yield(); } } } } return 0; }
/* * task_yield * This function is used to yield the current task. This can be called from any * task. Depending on task priority the current task will be preempted or * continue to run after this is called. This function will also enable * interrupts when required. */ void task_yield(void) { INT_LVL interrupt_level; uint8_t in_isr = FALSE; /* If we are in an interrupt. */ if (current_task == NULL) { /* Return task should not be null. */ ASSERT(return_task == NULL); /* Pick the return task. */ current_task = return_task; /* We are in an interrupt. */ in_isr = TRUE; } /* Check if we can actually yield the current task. */ if (current_task->lock_count == 0) { /* Disable interrupts. */ interrupt_level = GET_INTERRUPT_LEVEL(); DISABLE_INTERRUPTS(); /* Re-enqueue/schedule this task in the scheduler. */ scheduler_task_yield(current_task, YIELD_MANUAL); /* Schedule next task and enable interrupts. */ CONTROL_TO_SYSTEM(); /* Restore old interrupt level. */ SET_INTERRUPT_LEVEL(interrupt_level); } else { /* Set the flag that we need to process a context switch. */ current_task->flags |= TASK_SCHED_DRIFT; } if (in_isr == TRUE) { /* Save the return task. */ return_task = current_task; /* Clear current task. */ current_task = NULL; } } /* task_yield */
/* * scheduler_task_add * @tcb: Task control block that is needed to be added in the system. * @priority: Priority for this task. * This function adds a task in the system, the task must be initialized before * adding. */ void scheduler_task_add(TASK *tcb, uint8_t priority) { INT_LVL interrupt_level; /* Disable interrupts. */ interrupt_level = GET_INTERRUPT_LEVEL(); DISABLE_INTERRUPTS(); /* Update the task control block. */ tcb->priority = priority; /* Enqueue this task in the ready list. */ scheduler_task_yield(tcb, YIELD_INIT); #ifdef TASK_STATS /* Append this task to the global task list. */ sll_append(&sch_task_list, tcb, OFFSETOF(TASK, next_global)); #endif /* TASK_STATS */ /* Restore old interrupt level. */ SET_INTERRUPT_LEVEL(interrupt_level); } /* scheduler_task_add */