资讯详情

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);
}

标签: 24ppcb板公整套连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台