/**********************************************************************/
/*                                                                    */
/* File name: uip_kernel_scheduler.c                                  */
/*                                                                    */
/* Since:     2007-02-25                                              */
/*                                                                    */
/* Version:   uip Kernel v1.09                                        */
/*            Copyright (C) 2006..2018 Wang Baojin.                   */
/*                                                                    */
/* Author:    Designed by Wang Baojin(王保进)                         */
/*                                                                    */
/*                                                                    */
/* Purpose:   Defines and functions used by the task scheduling.      */
/*                                                                    */
/* Distribution: This file is part of uip kernel.                     */
/*            uip Kernel is free software, you can redistribute it    */
/*            and/or modify it under the terms of the GNU General     */
/*            Public License as published by the Free Software        */
/*            Foundation either version 2, or (at your option)        */
/*            any later version.                                      */
/*                                                                    */
/*            uip Kernel is distributed in the hope that it will be   */
/*            useful, but WITHOUT ANY WARRANTY without even the       */
/*            implied warranty of MERCHANTABILITY or FITNESS FOR A    */
/*            PuipICULAR PURPOSE.  See the GNU General Public         */
/*            License for more details.                               */
/*                                                                    */
/*            You should have received a copy of the GNU General      */
/*            Public License along with gpsim see the file            */
/*            COPYING.txt. If not, write to the Free Software         */
/*            Foundation, 59 Temple Place - Suite 330,                */
/*            Boston, MA 02111-1307, USA.                             */
/*                                                                    */
/*          > A special exception to the GPL can be applied should    */
/*            you wish to distribute a combined work that includes    */
/*            uip Kernel, without being obliged to provide the        */
/*            source code for any proprietary components.             */
/*                                                                    */
/* History:                                                           */
/*   2007/02/25  [WBJ] Create this file.                              */
/*                                                                    */
/**********************************************************************/

#include "uip_kernel_api.h"

UIP_UCHAR  uipByteValue[] = {0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 
	                         1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 
	                         2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 
	                         1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 
	                         3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 
	                         1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 
	                         2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 
	                         1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 
	                         4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 
	                         1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};

/* Locked number of scheduler(disable preempt)  */
UIP_CHAR                              uipSchedulerLock; 
 
/* Interrupt nested number of system  */
UIP_UINT                              uipNestedInterrupts;

AppModeType                           uipSystemMode;

/* uipPrioGroup is a 32 bit unsigned long integer. Each bit corresponds to 
   eight degressive priority values. These eight prioriyt values is made up 
   of a priority group   */
UIP_UINT                              uipPrioGroup;

/* uipPrioGrpArray is an array of priority groups. Index 31 corresponds to priorities 
   247-255. Bit 0 of this element corresponds priority 247, and bit 7 corresponds 
   priority 255.  */
UIP_UCHAR                             uipPrioGrpArray[uipGrpMax];

/* TCD_Lowest_Set_Bit are lookup tables that is used to determine the highest priority task.  */
UIP_UCHAR                             uipLowHalfByteValue[]; // = {0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};

UIP_UCHAR                             uipHighHalfByteValue[];  // = {0, 4, 5, 4, 6, 4, 5, 4, 7, 4, 5, 4, 6, 4, 5, 4};

/* Pointer to currently running task's TCB */
uipTask                               *uipCurrentTaskTCBPtr;

/* Pointer to next running task's TCB. This task has the highest
   priority in ready tasks */
uipTask                               *uipNextRunningTaskTCBPtr;

VOID                                  *uipSystemStackPtr; 

/* Priority of current task */
UIP_UCHAR                             uipCurrentTaskPriority;                

/* Priority of next running task  */
UIP_UCHAR                             uipNextRunningTaskPriority;

/**********************************************************************/ 
/*                                                                    */ 
/*  Function name                                       Version       */ 
/*                                                                    */ 
/*    uipGetNextTask                                     1.09         */ 
/*                                                                    */ 
/*  Author                                                            */ 
/*                                                                    */ 
/*    Wang Baojin                                                     */ 
/*                                                                    */ 
/*  Description                                                       */ 
/*                                                                    */ 
/*    This function determine the highest priority                    */
/*    in ready tasks table, and get it's TCB pointer                  */
/*                                                                    */ 
/*  Parameter(In)                                                     */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Parameter(Out)                                                    */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Return Status                                                     */ 
/*                                                                    */ 
/*    None                                                            */
/*                                                                    */ 
/*  Call functions                                                    */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Called by                                                         */ 
/*                                                                    */ 
/*    UIP_TerminateTask()                                             */ 
/*                                                                    */ 
/*  Release                                                           */ 
/*                                                                    */ 
/*  author name         release date              Description         */ 
/*                                                                    */ 
/*  Wang Baojin          2007.02.25            Initial Version 1.0    */ 
/*                                                                    */ 
/**********************************************************************/ 
VOID uipGetNextTask(VOID)
{
    UIP_UCHAR          grpBitValue;
    UIP_UCHAR          tempValue;
    TaskType           taskID;

    /* Determine the highest priority in ready tasks table */
    
    /* If there are some ready tasks */
    if (uipPrioGroup != 0)
    {
        /* Calculate group index value of the highest priority task 
          in ready tasks table */        
        if (uipPrioGroup & uipPrioIndexMASKHigh)
        {
            tempValue = 0;
        }
        else if (uipPrioGroup & uipPrioIndexMASKHMiddle)
        { 
            tempValue = 8;
        }
        else if (uipPrioGroup & uipPrioIndexMASKLMiddle)
        {
            tempValue = 16;
        }
        else
        { 
            tempValue = 24;
        } 

        tempValue += (UIP_UCHAR)uipByteValue[((UIP_UINT)(uipPrioGroup >> tempValue) 
                                                          & uipPrioIndexMASKHigh)];

        grpBitValue = uipPrioGrpArray[tempValue];

        /* Calculate the highest priority of ready tasks */
        uipNextRunningTaskPriority = (tempValue << 3) + uipByteValue[grpBitValue];

        /* Get task ID from priority of task */
        taskID = uipPriorityToTaskID[uipNextRunningTaskPriority];

        /* Get task TCB pointer from task ID */
        uipNextRunningTaskTCBPtr = (uipTaskPtr)(&uipTCBArray[taskID]);            
    } /* if(uipPrioGroup != 0) */
    /* If there are no other ready tasks */
    else
    {
        uipNextRunningTaskPriority = uipMinPriority;	   
    	uipNextRunningTaskTCBPtr = uip_NULL;       
    } /* end of else ( of if(uipPrioGroup != 0))*/
} /* end */        

/**********************************************************************/ 
/*                                                                    */ 
/*  Function name                                       Version       */ 
/*                                                                    */ 
/*    uipGetNextPriority                                  1.09        */ 
/*                                                                    */ 
/*  Author                                                            */ 
/*                                                                    */ 
/*    Wang Baojin                                                     */ 
/*                                                                    */ 
/*  Description                                                       */ 
/*                                                                    */ 
/*    This function determine the highest priority                    */
/*    in ready tasks table.                                           */
/*                                                                    */ 
/*  Parameter(In)                                                     */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Parameter(Out)                                                    */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Return Status                                                     */ 
/*                                                                    */ 
/*    None                                                            */
/*                                                                    */ 
/*  Call functions                                                    */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Called by                                                         */ 
/*                                                                    */ 
/*    UIP_TerminateTask()                                             */ 
/*                                                                    */ 
/*  Release                                                           */ 
/*                                                                    */ 
/*  author name         release date              Description         */ 
/*                                                                    */ 
/*  Wang Baojin          2007.02.25            Initial Version 1.0    */ 
/*                                                                    */ 
/**********************************************************************/ 
UIP_UCHAR uipGetNextPriority(VOID)
{
    UIP_UCHAR          grpBitValue;
    UIP_UCHAR          tempValue;
    UIP_UCHAR          taskPriority;           

    /* Calculate group index value of the highest priority task 
      in ready tasks table */        
    if (uipPrioGroup & uipPrioIndexMASKHigh)
    {
        tempValue = 0;
    }
    else if (uipPrioGroup & uipPrioIndexMASKHMiddle)
    { 
        tempValue = 8;
    }
    else if (uipPrioGroup & uipPrioIndexMASKLMiddle)
    {
        tempValue = 16;
    }
    else
    { 
        tempValue = 24;
    } 

    tempValue += (UIP_UCHAR)uipByteValue[((UIP_UINT)(uipPrioGroup >> tempValue) 
                                                          & uipPrioIndexMASKHigh)];

    grpBitValue = uipPrioGrpArray[tempValue];

    /* Calculate the highest priority of ready tasks */
    taskPriority = (tempValue << 3) + uipByteValue[grpBitValue];
       
    return(taskPriority);
} /* end */

/**********************************************************************/ 
/*                                                                    */ 
/*  Function name                                       Version       */ 
/*                                                                    */ 
/*    uipResetPrioGrpAndArrayBit                          1.09        */ 
/*                                                                    */ 
/*  Author                                                            */ 
/*                                                                    */ 
/*    Wang Baojin                                                     */ 
/*                                                                    */ 
/*  Description                                                       */ 
/*                                                                    */ 
/*    This function reset priority group and priority group array.    */
/*                                                                    */ 
/*  Parameter(In)                                                     */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Parameter(Out)                                                    */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Return Status                                                     */ 
/*                                                                    */ 
/*    None                                                            */
/*                                                                    */ 
/*  Call functions                                                    */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Called by                                                         */ 
/*                                                                    */ 
/*    uipScheduler()                                                  */ 
/*                                                                    */ 
/*  Release                                                           */ 
/*                                                                    */ 
/*  author name         release date              Description         */ 
/*                                                                    */ 
/*  Wang Baojin          2007.02.25            Initial Version 1.0    */ 
/*                                                                    */ 
/**********************************************************************/ 
#ifdef MixPreemption
VOID uipResetPrioGrpAndArrayBit(VOID)
{       
    /* All interrupts have been disabled in scheduler */

    /* Set ready task's dispatch priority index bit in uipPrioGroup */
    uipPrioGroup |= (uipCurrentTaskTCBPtr -> uipDispPrioGrpBit);

    /* Set the ready task's dispatch priority corresponding bit in uipPrioGrpArray[] */
    uipPrioGrpArray[uipCurrentTaskTCBPtr -> uipDispPrioGrpArrayIndex] |= 
                                                uipCurrentTaskTCBPtr -> uipDispPrioGrpArrayBit;
	uipNextRunningTaskPriority = uipCurrentTaskTCBPtr -> uipDispatchPrio;   
} /* end */
#endif

/**********************************************************************/ 
/*                                                                    */ 
/*  Function name                                       Version       */ 
/*                                                                    */ 
/*    uipClearPrioGrpAndArrayBit                          1.09        */ 
/*                                                                    */ 
/*  Author                                                            */ 
/*                                                                    */ 
/*    Wang Baojin                                                     */ 
/*                                                                    */ 
/*  Description                                                       */ 
/*                                                                    */ 
/*    This function clear correspoing bit of some task in priority    */
/*    group and priority group array.                                 */
/*                                                                    */ 
/*  Parameter(In)                                                     */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Parameter(Out)                                                    */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Return Status                                                     */ 
/*                                                                    */ 
/*    None                                                            */
/*                                                                    */ 
/*  Call functions                                                    */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Called by                                                         */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Release                                                           */ 
/*                                                                    */ 
/*  author name         release date              Description         */ 
/*                                                                    */ 
/*  Wang Baojin          2007.02.25            Initial Version 1.0    */ 
/*                                                                    */ 
/**********************************************************************/ 
VOID uipClearPrioGrpAndArrayBit(uipTaskPtr suspendTaskPtr)
{
    uipTaskPtr         taskPtr;
    
    taskPtr = (uipTaskPtr)suspendTaskPtr;

#ifdef MixPreemption
    /* Check to see if task's ready priority is difference from dispatch priority */
    /* Yes */
    if ((taskPtr -> uipDispatchPrio) != (taskPtr -> uipReadyPrio))
    {
        /* Clear the ready task's dispatch priority corresponding bit in uipPrioGrpArray[] */
        uipPrioGrpArray[taskPtr -> uipDispPrioGrpArrayIndex] &=
                                  ~(taskPtr -> uipDispPrioGrpArrayBit);
        if(uipPrioGrpArray[taskPtr -> uipDispPrioGrpArrayIndex] == 0x00)
        {
            /* Clear ready task's index bit in uipPrioGroup */
            uipPrioGroup &= ~(taskPtr -> uipDispPrioGrpBit);
        }
    } /* end of if((taskPtr -> uipDispatchPrio) != (taskPtr -> uipReadyPrio)) */
#endif
    /* Clear the ready task's ready priority corresponding bit in uipPrioGrpArray[] */
    uipPrioGrpArray[taskPtr -> uipRdyPrioGrpArrayIndex] &=
                              ~(taskPtr -> uipRdyPrioGrpArrayBit);
    if (uipPrioGrpArray[taskPtr -> uipRdyPrioGrpArrayIndex] == 0x00)
    {
        /* Clear ready task's index bit in uipPrioGroup */
        uipPrioGroup &= ~(taskPtr -> uipRdyPrioGrpBit);
    }
} /* end */

/**********************************************************************/ 
/*                                                                    */ 
/*  Function name                                       Version       */ 
/*                                                                    */ 
/*    uipPreContexSwitch                                  1.09        */ 
/*                                                                    */ 
/*  Author                                                            */ 
/*                                                                    */ 
/*    Wang Baojin(王保进)                                             */ 
/*                                                                    */ 
/*  Description                                                       */ 
/*                                                                    */ 
/*    在任务切换中断处理程序中被调用，执行相关全局变量的赋值以及      */
/*    结构体中成员变量的更改.                                         */
/*    Called in context switch handler, set global management var     */
/*    and vars in TCB                                                 */ 
/*                                                                    */ 
/*                                                                    */ 
/*  Parameter(In)                                                     */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Parameter(Out)                                                    */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Return Status                                                     */ 
/*                                                                    */ 
/*    None                                                            */
/*                                                                    */ 
/*  Call functions                                                    */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Called by                                                         */ 
/*                                                                    */ 
/*    None                                                            */ 
/*                                                                    */ 
/*  Release                                                           */ 
/*                                                                    */ 
/*  author name         release date              Description         */ 
/*                                                                    */ 
/*  Wang Baojin(王保进)  2013.09.16            Initial Version 1.09   */ 
/*                                                                    */ 
/**********************************************************************/ 
VOID uipPreContexSwitch(VOID)
{    
    /* 设置当前执行任务控制块指针 */

    uipCurrentTaskTCBPtr = uipNextRunningTaskTCBPtr;
    
    uipCurrentTaskPriority = uipNextRunningTaskPriority;
    
#ifdef MixPreemption

    /* 比较将被执行任务的就绪优先级与执行优先级，不同时需要复位优先级组 */    
    /* Comparing ready priority and dispatch priority of next runing task,
       reseting when not same */   
    if (uipCurrentTaskTCBPtr -> uipDispatchPrio != uipCurrentTaskTCBPtr -> uipReadyPrio) {
        uipResetPrioGrpAndArrayBit();    
    }

#endif
            
    uipCurrentTaskTCBPtr -> uipTaskState &= uip_TASK_EXTENDED;
    uipCurrentTaskTCBPtr -> uipTaskState |= RUNNING_STATE;        
} /* end */

/* VOID uipEnterScheduler(VOID) 见 uip_kernel_api.h 中的宏定义 (macro definition in .h file) */

/* VOID uipScheduler(VOID) 见 uip_kernel_api.h 中的宏定义 (macro definition in .h file) */

/***************************************************************************************/
/*                       End of File : uip_kernel_scheduler.c                          */
/***************************************************************************************/
