RMS调度器实现原理

sylixos提供两种类型的RMS调度器接口,一个是sylixos内核自带接口,一个是POSIX标准接口,这两类实现方式不同,效果也略有差异。

POSIX标准接口

POSIX标准接口实现比较简洁,而且周期精度较高。
现简单来讲,就是利用CLOCK_MONOTONIC时间和nanosleep延时,所以时间精度最高能到纳秒。CLOCK_MONOTONIC时间是系统启动后的累计时间,是单调递增的,好比一个时间轴,唤醒点在时间轴上是等间隔的。

/*********************************************************************************************************
  RMS 结构
*********************************************************************************************************/

typedef struct {
    int              PRMS_iStatus;
    struct timespec  PRMS_tsSave;
    void            *PRMS_pvPad[16];
} sched_rms_t;
/*********************************************************************************************************
** 函数名称: sched_rms_init
** 功能描述: 初始化 RMS 调度器
** 输 入  : prms      RMS 调度器
**           thread    需要调用 RMS 的线程.
** 输 出  : 是否初始化成功
*********************************************************************************************************/
int  sched_rms_init (sched_rms_t  *prms, pthread_t  thread)
{
    if (!prms) {
        errno = EINVAL;
        return  (PX_ERROR);
    }
    
    if (API_ThreadSetSchedParam(thread, LW_OPTION_SCHED_FIFO, 
                                LW_OPTION_RESPOND_IMMIEDIA)) {
        errno = ESRCH;
        return  (PX_ERROR);
    }
    
    lib_bzero(prms, sizeof(sched_rms_t));
    
    return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: sched_rms_destroy
** 功能描述: 删除 RMS 调度器
** 输 入  : prms      RMS 调度器
** 输 出  : 是否删除成功
*********************************************************************************************************/
int  sched_rms_destroy (sched_rms_t  *prms)
{
    if (!prms) {
        errno = EINVAL;
        return  (PX_ERROR);
    }
    
    prms->PRMS_iStatus = PRMS_STATUS_INACTIVE;
    
    return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: sched_rms_period
** 功能描述: 删除 RMS 调度器
** 输 入  : prms      RMS 调度器
**           period    RMS 周期
** 输 出  : 0 表示正确
**           error == EINTR    表示被信号激活.
*********************************************************************************************************/
int  sched_rms_period (sched_rms_t  *prms, const struct timespec *period)
{
    struct timespec temp;
    struct timespec etime;
    
    if (!prms || !period) {
        errno = EINVAL;
        return  (PX_ERROR);
    }
    
    switch (prms->PRMS_iStatus) {
    
    case PRMS_STATUS_INACTIVE:
        lib_clock_gettime(CLOCK_MONOTONIC, &prms->PRMS_tsSave);         /*  获得当前时间                */
        prms->PRMS_iStatus = PRMS_STATUS_ACTIVE;
        return  (ERROR_NONE);
        
    case PRMS_STATUS_ACTIVE:
        lib_clock_gettime(CLOCK_MONOTONIC, &temp);
        __timespecSub2(&etime, &temp, &prms->PRMS_tsSave);
        if (__timespecLeftTime(period, &etime)) {                       /*  执行时间超过周期            */
            lib_clock_gettime(CLOCK_MONOTONIC, &prms->PRMS_tsSave);     /*  获得当前时间                */
            errno = EOVERFLOW;
            return  (PX_ERROR);
        }
        
        __timespecSub2(&temp, period, &etime);
        
        /*
         *  注意: 这里直接加上周期是为了让每次测算都是以一个固定周期律进行
         *        提高周期精度. (不使用 lib_clock_gettime())
         */
        __timespecAdd(&prms->PRMS_tsSave, period);                      /*  以确定周期运行              */
        return  (nanosleep(&temp, LW_NULL));
        
    default:
        errno = ENOTSUP;
        return  (PX_ERROR);
    }
}

SylixOS内核自带接口

SylixOS内核自带接口是在内核实现的,利用的是系统心跳计数和休眠唤醒链表,时间精度是心跳周期。

RMS 对象也是系统资源,同其他系统资源一样通过单链表来进行分配和回收管理。

/*********************************************************************************************************
  RATE MONO SCHEDLER
*********************************************************************************************************/
typedef struct {
    LW_LIST_MONO         RMS_monoResrcList;                             /*  空闲资源表                  */
    
    UINT8                RMS_ucType;
    UINT8                RMS_ucStatus;                                  /*  状态                        */
    ULONG                RMS_ulTickNext;                                /*  激活时间                    */
    ULONG                RMS_ulTickSave;                                /*  系统时间保存                */
    PLW_CLASS_TCB        RMS_ptcbOwner;                                 /*  所有者                      */
    
    UINT16               RMS_usIndex;                                   /*  下标                        */

    CHAR                 RMS_cRmsName[LW_CFG_OBJECT_NAME_SIZE];         /*  名字                        */
} LW_CLASS_RMS;
typedef LW_CLASS_RMS    *PLW_CLASS_RMS;
__KERNEL_EXT LW_CLASS_RMS            _K_rmsBuffer[LW_CFG_MAX_RMSS];     /*  RMS 缓冲区                  */
__KERNEL_EXT LW_CLASS_OBJECT_RESRC   _K_resrcRms;                       /*  RMS 对象资源管理            */
/*********************************************************************************************************
** 函数名称: _Allocate_Rms_Object
** 功能描述: 从空闲 RMS 控件池中取出一个空闲 RMS
** 输 入  : 
** 输 出  : 获得的 RMS 地址,失败返回 NULL
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
PLW_CLASS_RMS  _Allocate_Rms_Object (VOID)
{
    REGISTER PLW_LIST_MONO             pmonoFree;
    REGISTER PLW_CLASS_RMS             prmsFree;
    
    if (_LIST_MONO_IS_EMPTY(_K_resrcRms.RESRC_pmonoFreeHeader)) {
        return  (LW_NULL);
    }
    
    pmonoFree = _list_mono_allocate_seq(&_K_resrcRms.RESRC_pmonoFreeHeader, 
                                        &_K_resrcRms.RESRC_pmonoFreeTail);
                                                                        /*  获得资源                    */
    prmsFree  = _LIST_ENTRY(pmonoFree, LW_CLASS_RMS, 
                            RMS_monoResrcList);                         /*  获得资源表容器地址          */
    
    _K_resrcRms.RESRC_uiUsed++;
    if (_K_resrcRms.RESRC_uiUsed > _K_resrcRms.RESRC_uiMaxUsed) {
        _K_resrcRms.RESRC_uiMaxUsed = _K_resrcRms.RESRC_uiUsed;
    }
    
    return  (prmsFree);
}
/*********************************************************************************************************
** 函数名称: _Free_Rms_Object
** 功能描述: 将 Rms 控制块交还缓冲池
** 输 入  : 
** 输 出  : 
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
VOID  _Free_Rms_Object (PLW_CLASS_RMS    prmsFree)
{
    REGISTER PLW_LIST_MONO    pmonoFree;
    
    pmonoFree = &prmsFree->RMS_monoResrcList;
    
    _list_mono_free_seq(&_K_resrcRms.RESRC_pmonoFreeHeader, 
                        &_K_resrcRms.RESRC_pmonoFreeTail, 
                        pmonoFree);
                        
    _K_resrcRms.RESRC_uiUsed--;
}
/*********************************************************************************************************
** 函数名称: _RmsActive
** 功能描述: 第一次激活 RMS 并开始对线程执行时间进行测量 (进入内核并关中断后被调用)
** 输 入  : 
** 输 出  : 
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
VOID  _RmsActive (PLW_CLASS_RMS  prms)
{
    prms->RMS_ucStatus = LW_RMS_ACTIVE;
    __KERNEL_TIME_GET_IGNIRQ(prms->RMS_ulTickSave, ULONG);
}
/*********************************************************************************************************
** 函数名称: _RmsGetExecTime
** 功能描述: 计算任务执行的时间 (进入内核并关中断后被调用)
** 输 入  : 
** 输 出  : 
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
ULONG   _RmsGetExecTime (PLW_CLASS_RMS  prms)
{
    REGISTER ULONG            ulThreadExecTime;
             ULONG            ulKernelTime;
    
    __KERNEL_TIME_GET_IGNIRQ(ulKernelTime, ULONG);
    ulThreadExecTime = (ulKernelTime >= prms->RMS_ulTickSave) ? 
                       (ulKernelTime -  prms->RMS_ulTickSave) :
                       (ulKernelTime + (__ARCH_ULONG_MAX - prms->RMS_ulTickSave) + 1);
                          
    return  (ulThreadExecTime);
}
/*********************************************************************************************************
** 函数名称: _RmsInitExpire
** 功能描述: 开始进行时间等待 (进入内核并关中断后被调用)
** 输 入  : 
** 输 出  : 
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
ULONG  _RmsInitExpire (PLW_CLASS_RMS  prms, ULONG  ulPeriod, ULONG  *pulWaitTick)
{
             PLW_CLASS_TCB    ptcbCur;
    REGISTER ULONG            ulThreadExecTime;                         /*  计算线程执行时间            */
             ULONG            ulKernelTime;
    
    LW_TCB_GET_CUR(ptcbCur);
    
    __KERNEL_TIME_GET_IGNIRQ(ulKernelTime, ULONG);
    ulThreadExecTime = (ulKernelTime >= prms->RMS_ulTickSave) ? 
                       (ulKernelTime -  prms->RMS_ulTickSave) :
                       (ulKernelTime + (__ARCH_ULONG_MAX - prms->RMS_ulTickSave) + 1);
                          
    if (ulThreadExecTime > ulPeriod) {
        __KERNEL_TIME_GET_IGNIRQ(prms->RMS_ulTickSave, ULONG);          /*  重新记录系统时钟            */
        return  (ERROR_RMS_TICK);
    }
    
    if (ulThreadExecTime == ulPeriod) {
        *pulWaitTick = 0;
        __KERNEL_TIME_GET_IGNIRQ(prms->RMS_ulTickSave, ULONG);          /*  重新记录系统时钟            */
        return  (ERROR_NONE);
    }
    
    *pulWaitTick = ulPeriod - ulThreadExecTime;                         /*  计算睡眠时间                */
    
    prms->RMS_ucStatus   = LW_RMS_EXPIRED;                              /*  改变状态                    */
    prms->RMS_ptcbOwner  = ptcbCur;                                     /*  记录当前TCB                 */
    
    __KERNEL_TIME_GET_IGNIRQ(prms->RMS_ulTickNext, ULONG);
    prms->RMS_ulTickNext += *pulWaitTick;                               /*  计算下次到时时间            */
                                                                        /*  自然溢出                    */
    
    return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: _RmsEndExpire
** 功能描述: 一个周期完毕,等待下一个周期 (进入内核后被调用)
** 输 入  : 
** 输 出  : 
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
ULONG  _RmsEndExpire (PLW_CLASS_RMS  prms)
{
    if (prms->RMS_ucStatus != LW_RMS_EXPIRED) {                         /*  被 cancel 或 删除了         */
        return  (ERROR_RMS_WAS_CHANGED);                                /*  被改变了                    */
    }
    
    prms->RMS_ucStatus = LW_RMS_ACTIVE;                                 /*  改变状态                    */
    __KERNEL_TIME_GET(prms->RMS_ulTickSave, ULONG);                     /*  重新记录系统时钟            */
    
    if (prms->RMS_ulTickNext != prms->RMS_ulTickSave) {                 /*  是否 TIME OUT               */
        return  (ERROR_THREAD_WAIT_TIMEOUT);
    
    } else {
        return  (ERROR_NONE);
    }
}
/*********************************************************************************************************
** 函数名称: API_RmsCreate
** 功能描述: 建立一个精度单调调度器
** 输 入  : 
**           pcName                        名字
**           ulOption                      选项
**           pulId                         Id 号
** 输 出  : 
*********************************************************************************************************/ 
LW_OBJECT_HANDLE  API_RmsCreate (CPCHAR             pcName,
                                 ULONG              ulOption,
                                 LW_OBJECT_ID      *pulId)
{
    REGISTER PLW_CLASS_RMS  prms;
    REGISTER ULONG          ulIdTemp;
    
    __KERNEL_MODE_PROC(
        prms = _Allocate_Rms_Object();
    );                                                                  /*  退出内核                    */
  
    
    prms->RMS_ucType     = LW_RMS_USED;
    prms->RMS_ucStatus   = LW_RMS_INACTIVE;
    prms->RMS_ulTickNext = 0ul;
    prms->RMS_ulTickSave = 0ul;
    
    if (pcName) {                                                       /*  拷贝名字                    */
        lib_strcpy(prms->RMS_cRmsName, pcName);
    } else {
        prms->RMS_cRmsName[0] = PX_EOS;                                 /*  清空名字                    */
    }
    
    ulIdTemp = _MakeObjectId(_OBJECT_RMS, 
                             LW_CFG_PROCESSOR_NUMBER, 
                             prms->RMS_usIndex);                        /*  构建对象 id                 */
    
    if (pulId) {
        *pulId = ulIdTemp;
    }
    
    return  (ulIdTemp);
}
/*********************************************************************************************************
** 函数名称: API_RmsPeriod
** 功能描述: 指定精度单调调度器开始按固定周期工作
** 输 入  : 
**           ulId                          RMS 句柄
**           ulPeriod                      程序段执行周期
** 输 出  : 
*********************************************************************************************************/
ULONG  API_RmsPeriod (LW_OBJECT_HANDLE  ulId, ULONG  ulPeriod)
{
             INTREG                    iregInterLevel;
             
             PLW_CLASS_TCB             ptcbCur;
	REGISTER PLW_CLASS_PCB             ppcb;

    REGISTER PLW_CLASS_RMS             prms;
    REGISTER UINT16                    usIndex;
    
    REGISTER ULONG                     ulErrorCode;
             ULONG                     ulWaitTime;
    
    usIndex = _ObjectGetIndex(ulId);
    
    LW_TCB_GET_CUR_SAFE(ptcbCur);                                       /*  当前任务控制块              */

    prms = &_K_rmsBuffer[usIndex];
    
    switch (prms->RMS_ucStatus) {                                       /*  状态机                      */
    
    case LW_RMS_INACTIVE:
        _RmsActive(prms);                                               /*  启动 RMS                    */
        __KERNEL_EXIT_IRQ(iregInterLevel);                              /*  退出内核                    */
        return  (ERROR_NONE);
        
    case LW_RMS_ACTIVE:                                                 /*  已将初始化完成              */
        ulErrorCode = _RmsInitExpire(prms, ulPeriod, &ulWaitTime);      /*  初始化“到期”数据          */
        if (ulErrorCode) {                                              /*  发生错误                    */
            __KERNEL_EXIT_IRQ(iregInterLevel);                          /*  退出内核                    */
            _ErrorHandle(ulErrorCode);
            return  (ulErrorCode);
        }
        
        if (!ulWaitTime) {                                              /*  时间刚刚好?                */
            __KERNEL_EXIT_IRQ(iregInterLevel);                          /*  退出内核                    */
            return  (ERROR_NONE);
        }
        
        /*
         *  当前线程开始睡眠
         */
        ppcb = _GetPcb(ptcbCur);
        __DEL_FROM_READY_RING(ptcbCur, ppcb);                           /*  从就绪表中删除              */

        ptcbCur->TCB_ulDelay = ulWaitTime;
        __ADD_TO_WAKEUP_LINE(ptcbCur);                                  /*  加入等待扫描链              */
        
        __KERNEL_EXIT_IRQ(iregInterLevel);                              /*  退出内核, 产生调度          */
        
        /*
         *  当前线程睡眠结束
         */
         __KERNEL_MODE_PROC(
            ulErrorCode = _RmsEndExpire(prms);                          /*  处理到期的 RMS              */
         );

        _ErrorHandle(ulErrorCode);
        return  (ulErrorCode);
        
    default:                                                            /*  转态机错误                  */
        __KERNEL_EXIT_IRQ(iregInterLevel);                              /*  退出内核                    */
        _ErrorHandle(ERROR_RMS_NULL);
        return  (ERROR_RMS_NULL);
    }
}
/*********************************************************************************************************
** 函数名称: API_RmsExecTimeGet
** 功能描述: 获得当前任务从调用 API_RmsPeriod() 函数到目前执行的时间,单位为: Tick.
** 输 入  : 
**           ulId                          RMS 句柄
**           pulExecTime                   运行时间
** 输 出  : 
*********************************************************************************************************/ 
ULONG   API_RmsExecTimeGet (LW_OBJECT_HANDLE  ulId, ULONG  *pulExecTime)
{
             INTREG         iregInterLevel;
    REGISTER PLW_CLASS_RMS  prms;
    REGISTER UINT16         usIndex;
    
    usIndex = _ObjectGetIndex(ulId);
    

    prms = &_K_rmsBuffer[usIndex];
    
    if (prms->RMS_ucStatus != LW_RMS_ACTIVE) {                          /*  状态错误                    */
        __KERNEL_EXIT_IRQ(iregInterLevel);                              /*  退出内核                    */
        _ErrorHandle(ERROR_RMS_STATUS);
        return  (ERROR_RMS_STATUS);
    }
    
    *pulExecTime = _RmsGetExecTime(prms);                               /*  获得运行时间                */

    return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: API_RmsCancel
** 功能描述: 指定精度单调调度器停止工作
** 输 入  : 
**           ulId                          RMS 句柄
** 输 出  : 
*********************************************************************************************************/
ULONG  API_RmsCancel (LW_OBJECT_HANDLE  ulId)
{
             INTREG         iregInterLevel;
    REGISTER PLW_CLASS_RMS  prms;
    REGISTER UINT16         usIndex;
    
    usIndex = _ObjectGetIndex(ulId);

    prms = &_K_rmsBuffer[usIndex];
    
    if (prms->RMS_ucStatus != LW_RMS_ACTIVE) {                          /*  状态错误                    */
        __KERNEL_EXIT_IRQ(iregInterLevel);                              /*  退出内核                    */
        _ErrorHandle(ERROR_RMS_STATUS);
        return  (ERROR_RMS_STATUS);
    }
    
    prms->RMS_ucStatus = LW_RMS_INACTIVE;                               /*  失效                        */
    
    return  (ERROR_NONE);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ScilogyHunter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值