Thursday, February 06, 2014

uITRON: Task Exception Handler - Define and Raise

① Task exception handling routine

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: