Tuesday, July 16, 2013

Event flag Vs Semaphore: Setting flag/Signalling semaphore

① Difference between setting event flag and signalling semaphore

When the event flag has the attribute of TA_CLR, it resembles the operation of signalling a binary semaphore. It means it wakes up only one waiting task, clears the bit and returns.
But, when TA_CLR is not specified, it wakes up all tasks waiting for the event. Also it logical ORs the pattern argument with existing pattern. Any further task checking for the event will be returned E_OK, till the event bit is cleared by clr_flg(). This behaviour makes the flags different from Semaphore.
 
Signaling semaphore will wake up at least one waiting task. But, in event flag, it depends on the condition each task is waiting for. If the task is waiting for other bits to be set, then the task would not been waken up.
 
In implementation perspective, Semaphore seems to have less processing than event flags. In event flags, the arguments in the API are more than the semaphore. So, obviously the kernel needs to save all the parameters in the task context of calling the API. Also, since each task has different conditions for waiting, the set_flg API has more processing to check the tasks that meets the condition. In case of semaphore, since it manages homogeneous resources, it does not have much processing compared to flags.
So, in case of selecting between flag and semaphore for an application, semaphore can be preferred.

② ITRON implementation to set flag

ER set_flg(ID flgid, UINT setptn)
{
        Sanity check on arguments
        Enter critical section (Interrupt Disable)
        If (the pattern is already set) {
                /* then No task should be waiting */
                Exit critical section
                return E_OK;
        }
        Check flag queue for any task waiting
        If (there is a waiting task) {
                if (there is only one task can be waiting for the flag (TA_WMUL not set)) {
                        Take the pattern from context for which task is waiting
                        Logical OR the existing pattern in flag and pattern passed in this function
                        if (ORed pattern satisfies waiting pattern according to TA_ORW or TA_ANDW){
                                Store ORed pattern in the pattern pointer saved in the context
                                if (waiting task had TA_CLR attribute in wai_flg) {
                                        Reset the flag's pattern to 0
                                } else {
                                        Store ORed pattern in the flag as existing pattern
                                }
                                if (task is waiting in Timeout) {
                                        Remove from timer queue
                                }
                                Set task status ad Ready
                                if (the task is NOT suspended) {
                                        Change the task to the Ready Queue of corresponding priority
                                        If (the task priority is higher than the current){
                                                call scheduler
                                                return error code from scheduler
                                        } else {
                                                Exit critical section and return the error code from it
                                        }
                                } else {
                                        Just delete the task from the flag queue
                                        Exit critical section and return the error code from it
                                }
                        }
                        Store ORed pattern in the flag as existing pattern
                        Exit critical section and return the error code from it
                }
                else { /* Multiple tasks can be waiting (TA_WMUL) */
                        Logical OR the existing pattern in flag and the pattern passed in this function
                        for (every task in the flag queue) {
                                Take the pattern from context for which the task is waiting
                                if (ORed pattern satisfies waiting pattern according to TA_ORW or TA_ANDW){
                                        Store ORed pattern in the pattern pointer saved in the context
                                        if (task is waiting in Timeout) {
                                                Remove from timer queue
                                        }
                                        Set task status ad Ready
                                        if (the task is NOT suspended) {
                                                If (the task priority is higher than the current)
                                                        Set to call scheduler when quitting this function
                                                Change the task to the Ready Queue of corresponding priority
                                        } else {
                                                Just delete the task from the Flag queue
                                        }
                                        if (waiting task had TA_CLR attribute in wai_flg) {
                                                Reset the flag's pattern to 0
                                                if (set to call scheduler) {
                                                        Call scheduler
                                                        Return error code that is set in scheduler
                                                }
                                                Otherwise, exit critical section and return error code
                                        }
                                }
                        }
                        Store ORed pattern in the flag as existing pattern
                        if (set to call scheduler) {
                                Call scheduler
                                Return error code that is set in scheduler
                        }
                        Otherwise, exit critical section and return error code
                }
        }
        Replace the existing pattern with logical ORed value of it with pattern passed in this function
        Exit critical section
        return E_OK;
}

No comments: