bool sched_addreadytorun(FAR _TCB *btcb) { FAR _TCB *rtcb = (FAR _TCB*)g_readytorun.head; bool ret; /* Check if pre-emption is disabled for the current running task and if * the new ready-to-run task would cause the current running task to be * preempted. */ if (rtcb->lockcount && rtcb->sched_priority < btcb->sched_priority) { /* Yes. Preemption would occur! Add the new ready-to-run task to the * g_pendingtasks task list for now. */ sched_addprioritized(btcb, (FAR dq_queue_t*)&g_pendingtasks); btcb->task_state = TSTATE_TASK_PENDING; ret = false; } /* Otherwise, add the new task to the g_readytorun task list */ else if (sched_addprioritized(btcb, (FAR dq_queue_t*)&g_readytorun)) { /* Information the instrumentation logic that we are switching tasks */ sched_note_switch(rtcb, btcb); /* The new btcb was added at the head of the g_readytorun list. It * is now to new active task! */ ASSERT(!rtcb->lockcount && btcb->flink != NULL); btcb->task_state = TSTATE_TASK_RUNNING; btcb->flink->task_state = TSTATE_TASK_READYTORUN; ret = true; } else { /* The new btcb was added in the middle of the g_readytorun list */ btcb->task_state = TSTATE_TASK_READYTORUN; ret = false; } return ret; }
void sched_addblocked(FAR _TCB *btcb, tstate_t task_state) { /* Make sure that we received a valid blocked state */ ASSERT(task_state >= FIRST_BLOCKED_STATE && task_state <= LAST_BLOCKED_STATE); /* Add the TCB to the blocked task list associated with this state. * First, determine if the task is to be added to a prioritized task * list */ if (g_tasklisttable[task_state].prioritized) { /* Add the task to a prioritized list */ sched_addprioritized(btcb, (FAR dq_queue_t*)g_tasklisttable[task_state].list); } else { /* Add the task to a non-prioritized list */ dq_addlast((FAR dq_entry_t*)btcb, (FAR dq_queue_t*)g_tasklisttable[task_state].list); } /* Make sure the TCB's state corresponds to the list */ btcb->task_state = task_state; }
int sched_setpriority(FAR struct tcb_s *tcb, int sched_priority) { FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head; tstate_t task_state; irqstate_t saved_state; /* Verify that the requested priority is in the valid range */ if (sched_priority < SCHED_PRIORITY_MIN || sched_priority > SCHED_PRIORITY_MAX) { set_errno(EINVAL); return ERROR; } /* We need to assure that there there is no interrupt activity while * performing the following. */ saved_state = irqsave(); /* There are four cases that must be considered: */ task_state = tcb->task_state; switch (task_state) { /* CASE 1. The task is running or ready-to-run and a context switch * may be caused by the re-prioritization */ case TSTATE_TASK_RUNNING: /* A context switch will occur if the new priority of the running * task becomes less than OR EQUAL TO the next highest priority * ready to run task. */ if (sched_priority <= tcb->flink->sched_priority) { /* A context switch will occur. */ up_reprioritize_rtr(tcb, (uint8_t)sched_priority); } /* Otherwise, we can just change priority since it has no effect */ else { /* Change the task priority */ tcb->sched_priority = (uint8_t)sched_priority; } break; /* CASE 2. The task is running or ready-to-run and a context switch * may be caused by the re-prioritization */ case TSTATE_TASK_READYTORUN: /* A context switch will occur if the new priority of the ready-to * run task is (strictly) greater than the current running task */ if (sched_priority > rtcb->sched_priority) { /* A context switch will occur. */ up_reprioritize_rtr(tcb, (uint8_t)sched_priority); } /* Otherwise, we can just change priority and re-schedule (since it * have no other effect). */ else { /* Remove the TCB from the ready-to-run task list */ ASSERT(!sched_removereadytorun(tcb)); /* Change the task priority */ tcb->sched_priority = (uint8_t)sched_priority; /* Put it back into the ready-to-run task list */ ASSERT(!sched_addreadytorun(tcb)); } break; /* CASE 3. The task is not in the ready to run list. Changing its * Priority cannot effect the currently executing task. */ default: /* CASE 3a. The task resides in a prioritized list. */ if (g_tasklisttable[task_state].prioritized) { /* Remove the TCB from the prioritized task list */ dq_rem((FAR dq_entry_t*)tcb, (FAR dq_queue_t*)g_tasklisttable[task_state].list); /* Change the task priority */ tcb->sched_priority = (uint8_t)sched_priority; /* Put it back into the prioritized list at the correct * position */ sched_addprioritized(tcb, (FAR dq_queue_t*)g_tasklisttable[task_state].list); } /* CASE 3b. The task resides in a non-prioritized list. */ else { /* Just change the task's priority */ tcb->sched_priority = (uint8_t)sched_priority; } break; } irqrestore(saved_state); return OK; }