Saturday, December 14, 2013

Message Buffer Vs Data Queue: Send Message


① Implementation difference between Send Data Queue and Send Message Buffer

Message buffer has one more parameter to save that is message length. Similarly, in synchronous message passing the length needs to be passed to the contexts error code so that it would be returned in the rcv_mbf();

② ITRON implementation of sending message buffer

ER snd_mbf(ID mbfid, VP msg, UINT msgsz)
{
        Sanity check on arguments
        Enter critical section (Interrupt Disable)
        /* Check any Rx task is waiting. Can copy message directly (synchronous message passing) */
        Check head of receive wait queue
        If there is valid task id {
                Get the pointer to store data from task's context and copy the message;
                Get the register for return error code and store the size of the message in it;
                if task is waiting in Timeout
                        remove from timer queue
                Set task status as Ready
                if the task is NOT suspended {
                        Change the task to the Ready Queue of priority
                        If (the task priority is higher than the current){
                                call scheduler
                                return error code from scheduler
                        } else {
                                Exit critical section and return error code from it (E_OK)
                                (return E_OK)
                        }
                } else {
                        Just delete the task from the receive wait queue
                        Exit critical section and return the error code from it (E_OK)
                        (return E_OK)
                }
        }
        /* No Rx task is waiting here */
        /* if have valid data length, need to put over the buffer */
        If (have valid message size to send) {
                Check sending wait queue for any waiting task at head of each priority level
                if (No send task is waiting) {
                        /* No sending task; so put the message in the buffer */
                        /* if you could put successfully, then return. Otherwise, wait go and wait */
                        /* Try to put the message in the buffer as follows */
                        Just separate the count as signle and multiple
                        /* Because, if maximum message size is 1, then it will be very much
                        similar to the Data Queue. No separate count mechanism inside the buffer is needed */
                        If free size is 0, then set message copying = Failure;
                        Decrement the free count
                        Place the data
                        Update the put pointer
                        /* Otherwise extra data of two bytes are needed just to remeber the number of valid bytes placed on the buffer */
                        Reduce the free buffer count;
                        Put each and each byte of the length by checking the boundary of the buffer and wrapping.
                        Place the data with consideration of Wrapping the buffer out
                        message copying = Success;
                        If (message is copied successfully) {
                                Exit critical section and return the error code from it (E_OK)
                                return E_OK;
                        }
                        /* Otherwise go down for waiting. If message is longer than buffer, all calls may wait */
                }
                /* Some task is already waiting. You also need to wait */
                If (polling mode)
                        Exit critical section and return E_TMOUT;
                If (this function is called from interrupt context) or
                If (called from task independent state ex: timer handlers) or
                If (called from dispatch disabled state)
                        Return E_CTX;
                If (Timeout value is specified) {
                        Add task into timer queue;
                        Set TCB flags that 'Waiting for send message buffer, Check for Timeout'
                } else (Wait forever) {
                        Set TCB flags that 'Waiting forever for send message buffer'
                }
                Set data queue ID in TCB
                Store the message pointer in context
                Store the message size in context
                Select Queue according to queueing order
                If (Tasks should be granted in FIFO order)
                        Select send wait queue->Queue[0] as Queue
                Else (Should be granted in Priority order)
                        Select send wait queue->Queue[Current Tasks Priority]
                Change the task from ReadyQueue to the Data queue's send wait Queue
                Schedule the tasks, since this task is going to sleep
                (Once the task is released, execution will return here)
                Return the value set by scheduler(Scheduler directly set return value before return here)
        }
        Exit critical section and return the error code from it (E_OK)
        return E_OK;
}
 

No comments: