① Task exception handling routine
② uITRON implementation of def_tex()
ER def_tex(ID tskid, T_DTEX *pk_dtex)
{
Sanity check on arguments
Enter critical section (Interrupt Disable)
Take task ID if the the task is self
if (the task does not have exception handler already defined) {
Assume pending pattern = 0;
Assume status is Disabled.
Assume stack pointer is NULL;
Set the pending pattern = 0;
Set the status Disabled;
Set the stack pointer as NULL;
Assign the exception handler given in parameter;
} else {
Just overwrite the exception handler given in parameter;
}
/* If both are null, then nothing to do. */
Exit critical section and return E_OK;
}
③ uITRON implementation of ras_tex()
ER ras_tex(ID tskid, TEXPTN rasptn)
{
Sanity check on arguments
Enter critical section (Interrupt Disable)
Take task ID if the the task is self
Get the Task Control Block from the Task ID
Logical OR the pattern given in the parameter with TCB's exception pattern
If task exception status is not disabled and not inside task exception handler
{
/* Execute the exception handler or do preparation to execute in future */
Preserve the task's context pointer in the exception block
/* Mainly the exception handler needs to be executed in task's context */
If (the task itself raising task exception) {
/* Task status is ready and */
/* Task ID is at the head of ready queue and */
/* But, Not in interrupt context. */
/* This is the context to run exception handler. */
/* So, Just call as a function call before returning to task */
/* till all pending patterns are cleared */
Take the extended information pointer from the TCB
while (there are pending exceptions) {
Take the pending pattern from TCB;
Make the pending pattern to zero in the TCB
Take the exception handler pointer
exit from critical section
Call the exception handler with pending pattern and extended information
enter critical section
}
/* its over */
Assign the exception block's context to NULL;
/* I'm out of exception handler */
} else {
/* In the following two contexts, it enters here */
/* 1) This task is Ready. But, now inside interrupt handler. */
/* Just volatile registers are inside the context. Anyhow, the */
/* exception handler needs to be executed in the task's context */
/* just after coming out of interrupt handler */
/* 2) The task is preempted. The task has all registers and */
/* shared context variables inside the context. The handler */
/* needs to be executed when the task is yielded to run */
/* For the exception handler, the register set is not needed. */
/* But, all other context is required. There are some processing of */
/* creating new context for exception handler and switching of context */
/* is required. So, internal wrapper function is assigned to execute when */
/* the task become ready to run. */
Assign internal wrapper function
Calculate the pointer one context unit down to currently saved
Initialize the new context for exception handler.
if (task is preempted) {
/* task is not ready */
Take copy of the shared context variables into exception handler's
}
Set the internal handler function as execution function
Set the new context pointer as task's context
}
}
/* otherwise nothing to do now */
Exit critical section and return E_OK;
}
void wrapper_internal(ER ercd)
{
/* Remember that you should not forget take in the error code updated */
/* in other contexts. It is the only shared context variable to updated. */
/* All others are read-only */
Take tcb of the task executing
Take the exception block
Enter critical section
Take the pending pattern from TCB;
Take the extended information
If (task was preempted one)
/* shared context variables are saved by this exception module */
Update the error code in the task's context
Make the pending pattern to zero in the TCB
for each valid bit in the pending pattern {
till (there are pending exceptions) {
/* Till all pending pattern is cleared */
Take the exception handler
exit critical section
execute the exception handler
enter critical section
Take the pending pattern from TCB;
Make the pending pattern to zero in the TCB
}
Restore back the task's context pointer from the exception block
Reschedule the tasks;
}
A soft interrupt...
Task exception handling routine will run in the same task's context that means in the same priority, stack and with the same context variables which are shared between other tasks such as error code. But, in the view point of the task itself, it is a out-of-myway execution which means the execution path of exception handler is completely independent and asynchronous similar to interrupt handler. So, from the view point of task itself, a separate context which is independent of the task's context is reserved for the exception handler except when the task itself raises the exception handling. When the task itself raises the exception handling the system call executes the exception handler before returning to the task. So, it is more like function call which synchronous to the task execution. So, separate context is not reserved in this case.
② uITRON implementation of def_tex()
ER def_tex(ID tskid, T_DTEX *pk_dtex)
{
Sanity check on arguments
Enter critical section (Interrupt Disable)
Take task ID if the the task is self
if (the task does not have exception handler already defined) {
Assume pending pattern = 0;
Assume status is Disabled.
Assume stack pointer is NULL;
Set the pending pattern = 0;
Set the status Disabled;
Set the stack pointer as NULL;
Assign the exception handler given in parameter;
} else {
Just overwrite the exception handler given in parameter;
}
/* If both are null, then nothing to do. */
Exit critical section and return E_OK;
}
③ uITRON implementation of ras_tex()
ER ras_tex(ID tskid, TEXPTN rasptn)
{
Sanity check on arguments
Enter critical section (Interrupt Disable)
Take task ID if the the task is self
Get the Task Control Block from the Task ID
Logical OR the pattern given in the parameter with TCB's exception pattern
If task exception status is not disabled and not inside task exception handler
{
/* Execute the exception handler or do preparation to execute in future */
Preserve the task's context pointer in the exception block
/* Mainly the exception handler needs to be executed in task's context */
If (the task itself raising task exception) {
/* Task status is ready and */
/* Task ID is at the head of ready queue and */
/* But, Not in interrupt context. */
/* This is the context to run exception handler. */
/* So, Just call as a function call before returning to task */
/* till all pending patterns are cleared */
Take the extended information pointer from the TCB
while (there are pending exceptions) {
Take the pending pattern from TCB;
Make the pending pattern to zero in the TCB
Take the exception handler pointer
exit from critical section
Call the exception handler with pending pattern and extended information
enter critical section
}
/* its over */
Assign the exception block's context to NULL;
/* I'm out of exception handler */
} else {
/* In the following two contexts, it enters here */
/* 1) This task is Ready. But, now inside interrupt handler. */
/* Just volatile registers are inside the context. Anyhow, the */
/* exception handler needs to be executed in the task's context */
/* just after coming out of interrupt handler */
/* 2) The task is preempted. The task has all registers and */
/* shared context variables inside the context. The handler */
/* needs to be executed when the task is yielded to run */
/* For the exception handler, the register set is not needed. */
/* But, all other context is required. There are some processing of */
/* creating new context for exception handler and switching of context */
/* is required. So, internal wrapper function is assigned to execute when */
/* the task become ready to run. */
Assign internal wrapper function
Calculate the pointer one context unit down to currently saved
Initialize the new context for exception handler.
if (task is preempted) {
/* task is not ready */
Take copy of the shared context variables into exception handler's
}
Set the internal handler function as execution function
Set the new context pointer as task's context
}
}
/* otherwise nothing to do now */
Exit critical section and return E_OK;
}
void wrapper_internal(ER ercd)
{
/* Remember that you should not forget take in the error code updated */
/* in other contexts. It is the only shared context variable to updated. */
/* All others are read-only */
Take tcb of the task executing
Take the exception block
Enter critical section
Take the pending pattern from TCB;
Take the extended information
If (task was preempted one)
/* shared context variables are saved by this exception module */
Update the error code in the task's context
Make the pending pattern to zero in the TCB
for each valid bit in the pending pattern {
till (there are pending exceptions) {
/* Till all pending pattern is cleared */
Take the exception handler
exit critical section
execute the exception handler
enter critical section
Take the pending pattern from TCB;
Make the pending pattern to zero in the TCB
}
Restore back the task's context pointer from the exception block
Reschedule the tasks;
}
A soft interrupt...
No comments:
Post a Comment