Wednesday, January 08, 2014

Rendezvous: Calling Vs Accepting

① Difference between Calling and Accepting

Both may wait for each. Once met, caller will definitely wait for result, but accepter will not. Whoever comes first creates a unique Rendezvous context from local memory(?).

② ITRON implementation of cal_por()

ER_UINT cal_por(ID porid, RDVPTN calptn, VP msg, UINT cmsgsz)
{
        Sanity check on arguments
        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;
        Enter critical section (Interrupt Disable)
        If there is task waiting for accept {
                for (every task in the accept-waiting queue) {
                        Take TCB of accept-waiting task
                        Take accept pattern
                        if (call pattern & accept pattern) {
                                Take this calling task id
                                Take TCB of this calling task
                                Copy the message argument to the accept-waiting task message buffer
                                Set the return value of the accept-waiting task to the message size
                                Create unique rendezous number
                                Assign the rendezous number to the unique local copy created and shared by
                                        accept-waiting task through pointer stored in the context
                                /* Wake up 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)
                                }
                                /* This calling task is going to sleep */
                                /* Save the args & rendezous parameters locally and save the pointer to this calling task's context */
                                Save 'msg' & 'cmsgsz'arguments, port's maximum rx size and created rendezous number
                                Save the calling pattern argument too.
                                If (Timeout value is specified) {
                                        Add task into timer queue;
                                        Set TCB flags that 'Waiting for rendezous termination, Check for Timeout'
                                } else (Wait forever) {
                                        Set TCB flags that 'Waiting forever for rendezous termination'
                                }
                                /* Anyway wait for result (Termination-waiting) */
                                Delete the task from ReadyQueue (Not kept in any queue since accepting task remembers this task)
                                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 accept-waiting tasks. So, go to sleep */
        Take the TCB of this calling task
        If (Timeout value is specified) {
                Add task into timer queue;
                Set TCB flags that 'Waiting in call waiting queue, Check for Timeout'
        } else (Wait forever) {
                Set TCB flags that 'Waiting forever for call waiting queue'
        }
        /* Save the args & rendezous parameters locally and save the pointer to this calling task's context */
        Save 'msg' & 'cmsgsz'arguments, port's maximum rx size and set rendezous number to zero
        Save the calling pattern and porid arguments too in this calling task's 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 Rendezous queue's call waiting 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 waking-up task(waking-up task directly set return value before scheduled)
}
③ ITRON implementation of acp_por()

ER_UINT acp_por(ID porid, RDVPTN acpptn, RDVNO *p_rdvno, VP msg, TMO tmout)
{
        Sanity check on arguments
        Enter critical section (Interrupt Disable)
        for (every task waiting in the call-waiting queue) {
                /* Traversed each list under each priority from Highest priority */
                /* List is circular; so, traversed till the prev node of first entry is reached */
                Take the call pattern from the cw-task's context
                if (call pattern & accept pattern) {
                        Copy the message from the calling cw-task's context to 'msg' argument;
                        Create unique rendezous number
                        Assign the rendezous number to the unique local copy created and shared by
                                calling-waiting task through pointer stored in the context
                        Assign the redezous number in the 'p_rdvno' argument too.
                        if (cw-task is waiting in the timer queue) {
                                Change TCB flags that 'Waiting for rendezous termination, Check for Timeout'
                        } else {
                                Change TCB flags that 'Waiting forever for rendezous termination'
                        }
                        Delete from call waiting Queue(Not kept in any queue other queue since rendezous no remembers this task)
                        Exit critical section and return message size
                }
        }
        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 in port accept-wait queue, Check for Timeout'
        } else (Wait forever) {
                Set TCB flags that 'Waiting forever in port accept-wait queue'
        }
        /* Save the args & rendezous parameters locally and save the pointer to this calling task's context */
        Save 'msg' & 'p_rdvno'arguments
        Save the accept pattern and porid arguments too in this calling task's context.
        Change the task from ReadyQueue to this port's accept-waiting 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 waking-up task(waking-up task directly set return value before scheduled)
}

 

No comments: