Synchronization Akos Ledeczi EECE 6354, Fall 2013 Vanderbilt University
Semaphores They work for synchronization too ISR to Task or Task to Task
Unilateral Rendezvous Task calling Pend() does not need to know about the details: the Pend() call will return when the event has occurred Maximizes use of CPU; no busy waiting Event (i.e., Post()) will cause the waiting task to run immediately (assuming it has the highest priority)
Credit Tracking Semaphore accumulates the number of times Post() has been called /without a corresponding Pend()/
Broadcasting Multiple tasks waiting on a semaphore OS_OPT_POST_ALL All waiting tasks become ready to run Care must be taken because some of the tasks may not have called Pend() yet
Task Semaphores In µC/OS-III each task has a built-in semaphore More efficient OSTaskSemPend(); OSTaskSemPost(); etc. Post()-er (ISR or Task) needs to know which task to notify
Bilateral Rendezvous void Task1(void *p_arg) { … OSTaskSemPost(&Task2_TCB, OS_OPT_POST_1, &err); OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,&ts,&err); … } void Task2(void *p_arg) { … OSTaskSemPost(&Task1_TCB, OS_OPT_POST_1, &err); OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,&ts,&err); … } Only between tasks, as an ISR cannot Pend()
Event Flags When tasks need to synchronize on multiple events When any of the events is enough: disjunctive synchronization (OR) When all events are needed: conjunctive synchronization (AND) OSFlag???(); OSFlagPendGetFlagsRdy(): which flags caused task to become ready
EventFlags Example #define TEMP_LOW (OS_FLAGS)0x01 #define BATT_LOW (OS_FLASG)0x02 #define SW_PRESSED(OS_FLAGS)0x04 OS_FLAG_GRP MyEventFlagGrp; void main() { … OSFlagCreate(&MyEventFlagGrp, “My flags”,0,&err); … } void Task1(void *p_arg) { … for( ; ; ) { OSFlagPend(&MyEventFlagGrp, TEMP_LOW + BATT_LOW, 0 OS_OPT_PEND_FLAG_SET_ANY, ts,&err); … } void Task2(void *p_arg) { … for ( ; ; ) { OSFlagPost(&MyEventFlagGrp, BATT_LOW, OS_OPT_POST_FLAG_SET, &err); } … }
Status and Transient Events Typically: – Status info monitored by one task, handled by another task using a non-blocking call – A transient event is generated by an ISR or task and handled and consumed by a task using a blocking call
Event Flag Internals struct os_flag_grp { OS_OBJ_TYPE Type CPU_CHAR *NamePtr OS_PEND_LIST PendList; OS_FLAGS Flags CPU_TS TS }; OSFlagPost(&flagGrp, (OS_FLAGS)0x0C, OS_OPT_FLAG_SET, &err); Pend list is not in priority order as all tasks need to be looked at anyways Look at code on the left: If OS_OPT_FLAG_SET and flags contain 0x03, result will be 0x0F If OS_OPT_FLAG_CLR and flags contain 0x0F, result will be 0x03
Synchronizing Multiple Tasks