Tuesday, September 15, 2015

Timer Management: Timeout handler vs Cyclic Handler vs Alarm Handler


The Time management functions are called from idle task whenenver there is Timer interrupt. When there is timer interrupt, the priority of the Idle task (System task) is raised to the highest (0) and scheduling returns to the counting loop of the idle task. It skips the counting loop and disables the interupt to create the critical section and increments the timer count. And, it processes the timer tasks further.

Alarm handler and Cyclic handler are just executing handler at interrupt enabled context. Cyclic handler is cyclic. Alarm is just once. But, other timeout handler is not handler. Instead, waking up tasks sleeping at various resources and system calls with various reasons.

But, why two timeout redundant values? 1) Timeout queue 2) TCB timeout

System Dispatch Service

ER System Dispatch Functions(void)
{
        If (there is system error)
                return system error;
        Enable dispatch;
        Initializes internal strucutres;
        /* Enter endless loop */
        for (;;) {
                This task is assigned lowest priority in the system.
                Maximum priority + 1;
                If (Dispatch is disabled)
                        Special Dispatch task = Previous running task
                else
                        No special request
                Schedule and dispatch;

                if (overrun handler conndition )
                        Call Overrun handler

                /* counter loop */
                for (;;) {
                        count down and stay here if reached zero;
                        Poll for Timer interrup flag;
                        if (timer interrrupt flag is set )
                                break;
                }
                Get idle count;
                Enter critical section;/* diable interrupt */
                for (till number of pending timer interrupts reaches zero)
                        Update system clock;
                        check timer queue - Timeout check processing;
                        check cyclic handler management
                        check alarm handler management
                }
        }
}

Timeout check processing

void timeout_check_processing(void)
{

        Take queue corresponding to lower 32 bit of system time

        for (till there is valid entry in the head of the queue) {
                Take taskid in the head of the queue
                if (task id is zero)
                        return;
                Take TCB
                for (till an entry matching the timeout value is reached) {
                        if (matching) { /* ?? I think this will match always */
                                Remove the task from the timer queue;
                                Take backup of the task status
                                Assign the task status as READY
                                Assign the return code based on previous status
                                if (in Timer queue due to dly_tsk(DLY)) {
                                        Assign return code as E_OK
                                } else {
                                Assign return code as E_TIMEOUT
                                if (waiting for any resource) {
                                        delete from the resource's waiting queue
                                        if (resource is Mutex) {
                                                Get the Mutex ID
                                                if (Mutex is INHERITENCE and
                                                  priority is higher or equal
                                                        ceiling priority)
                                                        Adjust Mutex priority
                                        } else if (resource is Message buffer)
                                                adjust resource allocation
                                        } else if (resource is variable m-pool)
                                                adjust resource allocation
                                        }
                                }
                                if (not suspended) {
                                        Take priority
                                        if (priority is higher than current Application priority)
                                                Add to delayed Dispatch
                                                /* As this function won't call dispatch */
                                        Add to Ready queue of the task's priority
                                }
                                temporarily open and close critical
                                        section to open up the door for dispatch
                                break; /* Again go to head for check */
                                        /* Anything might have happened when you opened up the door */
                        }
                        if (reached end of queue)
                                return;
                        move to next task in the queue chain
                }
        }
}

Cyclic Handler Processing

void Cyclic_handler_processing(void)
{

        Take the cyclic handler queue corresponding to the system time low 32 bit
        for (till valid entry in the head of the queue) {
                Take the cyclic handler ID at the queue head
                if (cyclic handler ID is 0)
                        return;
                for (till an entry which matches with time stamp) {
                        if (deadline matches with time stamp) {
                                delete from cyclic handler queue
                                calculate new target time as it is cyclic handler
                                add to the new queue of new target time
                                temporarily enable interrupt
                                if (cyclic hander is ON now) {
                                        Execute cyclic handler
                                }
                                disable interrupt again
                                break; /* Restart from head again */
                                /* anything is possible in the cycle gap */
                        }
                        if (reached end of queue)
                                return;
                        move to next cyclic handler in the same queue
                }
        }
}

Alarm Handler Processing

void alarm_handler_processing(void)
{
        Take alarm handler queue corresponding to the system time low 32 bit
        for (till valid entry in the head of the queue) {
                for (till an entry which matches with time stamp) {
                        if (deadline matches with time stamp) {
                                delete from alarm handler queue
                                reset the alarm handler entry fields
                                temporarily enable interrupt
                                Execute alarm handler
                                disable interrupt again
                                break; /* Restart from head again */
                                /* anything is possible in the cycle gap */
                        }
                        if (reached end of queue)
                                return;
                        move to next alarm handler in the same queue
                }
        }
}

Accumulating or queuing inside system processing is not real-time. Realtime never accumulates in production center. Always, wherever there is a change in the system state, it opens the gate and put the car on the road. It is like Toyota. Never keep the doors closed.
Whether the car runs on the road or stands depends on the user program. But, kernel will pass the message always at real time.

1 comment:

Jissa said...
This comment has been removed by a blog administrator.