Saturday, November 16, 2013

Data Queue Vs MailBox: Receive data

① Difference between receiving data from Data Queue and Mailbox

Data Queue not only should receive the data at the head, but also if there is sending tasks queued, wake up one to place the data at the tail.

② ITRON implementation of receiving data over data queue

ER rcv_dtq(ID dtqid, VP_INT *p_datat)
{
        Sanity check on arguments
        Enter critical section (Interrupt Disable)
        if (data count in queue == 0) {
                /* synchronous message passing */
                Check send task waiting queue;
                if (No task is sleeping) {
                        /* No data, no sending, so got to waiting */
                        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 receive wait queue, Check for Timeout'
                         } else (Wait forever) {
                                 Set TCB flags that 'Waiting forever for receive wait queue'
                         }
                         Set data queue ID in TCB
                         Store the data in context
                         Change the task from ReadyQueue to the Data queue's receive 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)
                }
                else { /* some task is sleeping */
                        /* need to wake up with the data */
                        Get the data from task's context and store it in the pointer argument;
                         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 send wait queue
                                 Exit critical section and return the error code from it (E_OK)
                                 (return E_OK)
                         }
                }
        }
        /* Some data is in the data queue. Just receive it */
        Get the data from the read pointer and store it in the pointer argument;
        Update the read pointer;
        decrement the data count;
        /* check for send tasks waiting for to get free space in queue */
        Check send task waiting queue;
        if (any task is waiting) {
                take the data from the task's context;
                add the data at the write pointer of data queue and update the pointer;
                increment the data count of data queue;
                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 send wait queue
                        Exit critical section and return the error code from it (E_OK)
                        (return E_OK)
                }
        }
        Exit critical section and return the error code from it (E_OK)
}

② ITRON implementation of receiving data over data queue

ER rcv_mbx(ID mbxid, T_MSG **ppk_msg)
{
        Sanity check on arguments
        Enter critical section (Interrupt Disable)
        /* Reception of message. First, just checking the message queue for each
           message priority level. If message, just take the pointer and return E_OK */
        for (each message priority level, get message queue pointer) {
                if (there is valid message) {
                        Unlink the message on top from the message list;
                        assign the message to the pointer received as argument;
                        Exit critical section and return the error code from it (E_OK)
                }
        }
        /* No message. What to do? */
        if (polling) {
                return E_TMOUT;
        }
        if (called from ISR, Dispatch disabled state or Timer Handlers) {
            return E_CTX;
        }
        /* Make the task waiting */
        If (Timeout value is specified) {
                Add task into timer queue;
                Set TCB flags that 'Waiting for receive wait queue, Check for Timeout'
        } else (Wait forever) {
                Set TCB flags that 'Waiting forever for receive wait queue'
        }
        Store the pointer to the message in the task's context;
        Store the mail box ID in the task's context;
        Select Queue according to queueing order
        If (Tasks should be granted in FIFO order)
                Select receive wait queue->Queue[0] as Queue
        Else (Should be granted in Priority order)
                Select receive wait queue->Queue[Current Tasks Priority]
        Change the task from ReadyQueue to the mail box's receive 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)
}
 

No comments: