


















Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Slides on: priority preemption, task switching,
Typology: Study notes
1 / 26
This page cannot be seen from the preview
Don't miss anything!



















void **thread_main; **thread_a; void *stack_a[1024];
int main(void) { thread_a = init_stack(stack_a, task_a); printf(“now in thread_main\n”); context_switch(thread_a,&thread_main); printf(“back in main_thread\n”); }
void task_a(void) { print(“now in thread_a\n“); context_switch(thread_main,&thread_a); }
void **thread_main; **thread_a; void *stack_a[1024]; int thread_id;
void isr_timer(void) { if (thread_id == 0) { thread_id = 1; context_switch(thread_a,&thread_main); } else { thread_id = 0; context_switch(thread_main,&thread_a); } }
Demo ..
(x32_projects.tgz: slicing.c)
In an RTOS task switching is performed by the RTOS
RTOS scheduler decides which task to run (continue)
Scheduling based on the state of all tasks:
blocked
running
ready
event occurred
waiting for event
highest prio ready
preempted by higher prio
The block construct in vButtonTask is a call to the RTOS to deschedule the task until event has occurred This implies that another thread must eventually post this event, i.e., notifies the RTOS that the event has occurred, again by calling the RTOS Once the RTOS is notified it will unblock vButtonTask (i.e., move it’s state from blocked to ready) Thus, two RTOS functions are needed: (^) OS_Pend(event) // block, go execute some other task (^) OS_Post(event) // unblock the blocked task (eventually)
void OS_Pend(int event) { !! old_id = current task_id !! task_state[old_id] = BLOCKED !! event_task[event] = old_id; !! figure out which task to run -> new_id !! context_switch(task[new_id],&(task[old_id])) !! return // to task[old_id], once !! rescheduled to run }
void isr_buttons(void) // ISR: be quick! only post { if (peripherals[BUTTONS] & 0x01) // button 0 OS_Post(event); // signal event }
void vButtonTask(void) // task: do the slow printing { while (TRUE) { OS_Pend(event); // wait for event printf(“current float levels: \n”); !! list them } }
vLevelsTask
button IRQ
button ISR
vButtonTask
OS_Pend OS_Post
OS_Pend
highest priority task starts first
context switch
Each task (thread) has its own context: PC, stack, regs (SP, other ..)
The rest is shared between all tasks
Shared data allows inter-task communication
Tasks can be preempted by another task (just like preemption by an ISR): shared data problem!
void vButtonTask(void) // high priority { while (TRUE) { !! block until button push event !! print tankdata[i].lTimeUpdated !! print tankdata[i].lTankLevel } }
void vLevelsTask(void) // low priority { while (TRUE) { !! read + calculate tankdata[i].lTimeUpdated = !! time tankdata[i].lTankLevel = !! calc result } }
OS_Post
void task1(void) void task2(void) { { ..; vAdd(9); ..; ..; vAdd(11); ..; } }
void vAdd(int cInc) // NOT reentrant! { cErrors = cErrors + cInc; }
task task cErrors + cInc cErrors = ..
14 16 14
16 14
atomic
context switch
NOT atomic
Just use local vars: no shared data problem, reentrancy guaranteed, no need for atomicity
But local vars don’t get you very far, at some point need to share data: make critical sections atomic In the case of interrupts we used {EN|DIS}ABLE_INT
Now we need to stop RTOS to preempt: OS_XXX() Classic OS service: semaphores P()/V(), pend()/post(), take()/release(), ..
cf. OS_Pend()/OS_Post() we saw earlier