① 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)
}
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:
Post a Comment