Wednesday, January 15, 2014

Rendezvous: Forward

① Forwarding rendezous to a port

You know in one port the accept and calling tasks meet and rendezous is created. Immedialtely, the accept tasks dispatches for execution and the calling task waits in the termination waiting state. Now, think that there can me multiple accept and calling waiting tasks in a single port. And, also think that the termination-waiting task can issue one more call to another accept-waiting task instead of simply sleeping till the previous accept waiting task ends the rendezous. So, a single task can be sleeping totally for all rendezous are ended. The rendezous is remembered at the accept-waiting task side and the data at the calling side will be overwritten.

② ITRON implementation of fwd_por

ER fwd_por(ID porid, RDVPTN calptn, RDVNO rdvno, VP msg, UINT cmsgsz)
{
        Sanity check on arguments
        Enter critical section (Interrupt Disable)
        Check whether a task exists specified by the given Rendezous number.
        Check whether the calling task is in termination-waiting state.
        Confirm whether that task currently waits on this rendezous only.
        Check whether argument message size is not bigger than the port and rendezous.
        (This argument is going to reuse the previous call's message buffer)
        Check whether the port's maximum receive size is not bigger than the rendezous
        Take the accept waiting task in the port;
        /* if there is a accept-waiting task in the port */
        for (each accept-waiting task) {
                Take the tcb;
                Get the accept pattern;
                if (accept pattern has match with calling pattern) {
                        Take the argument buffer pointer of the accept-waiting task from the TCB
                        Copy the message from the API to the aceept-waiting call's buffer
                        Set the message size to the return value field of the accept-wait task's TCB
                        Form the new rendezvous number and assign to both call and accept task tcbs;
                        Confirm the terminate-waiting task's status set as rendezous terminate-waiting
                        Overwrite the terminate-waiting task's pattern and message size with new as in arguments
                        /* Wake up processing for the accept waiting task */
                        if (aw-task is waiting in Timeout)
                                Remove from timer queue
                        Set aw-task status as Ready
                        if (the aw-task is NOT suspended) {
                                Change the aw-task to the Ready Queue of priority
                                If (the aw-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 aw-task from the receive wait queue
                                Exit critical section and return the error code from it (E_OK)
                                (return E_OK)
                        }
                }
        }
        /* No accept waiting tasks. So, change from termination waiting to call-waiting */
        Overwrite the termination-waiting state to calling-waiting state.
        Overwrite the previous call's message buffer with the current argument message content
        (Input message buffer content is changed)
        Overwrite the call-waiting task's message size
        Save the calling pattern in the TCB.
        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]
        Add the task to the Rendezous queue's call waiting Queue (It would be in no queue)
        Exit critical section and return the error code from it (E_OK)
        (return E_OK)
}
"Compelling a call request in the hands of a task which is waiting for a rendezvous to end."

No comments: