Exemplo n.º 1
0
/*********************************************************************************************************
** 函数名称: _SchedTick
** 功能描述: 时间片处理 (tick 中断服务程序中被调用, 进入内核且关闭中断状态)
** 输 入  : NONE
** 输 出  : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
VOID  _SchedTick (VOID)
{
    REGISTER PLW_CLASS_CPU  pcpu;
    REGISTER PLW_CLASS_TCB  ptcb;
    UINT8          ucPriority;
    INT            i;

#if LW_CFG_SMP_EN > 0
    for (i = 0; i < LW_NCPUS; i++) {
#else
    i = 0;
#endif                                                                  /*  LW_CFG_SMP_EN               */

        pcpu = LW_CPU_GET(i);
        if (LW_CPU_IS_ACTIVE(pcpu)) {                                   /*  CPU 必须激活                */
            ptcb = pcpu->CPU_ptcbTCBCur;
            if (ptcb->TCB_ucSchedPolicy == LW_OPTION_SCHED_RR) {        /*  round-robin 线程            */
                if (ptcb->TCB_usSchedCounter == 0) {                    /*  时间片已经耗尽              */
                    if (LW_CAND_ROT(pcpu) == LW_FALSE) {
                        if (_SchedSeekPriority(pcpu, &ucPriority) &&    /*  就绪未运行任务的最高优先级  */
                                LW_PRIO_IS_HIGH_OR_EQU(ucPriority,
                                                       ptcb->TCB_ucPriority)) {
                            LW_CAND_ROT(pcpu) = LW_TRUE;                /*  下次调度时检查轮转          */
                        }
                    }
                } else {
                    ptcb->TCB_usSchedCounter--;
                }
            }
        }

#if LW_CFG_SMP_EN > 0
    }
#endif                                                                  /*  LW_CFG_SMP_EN               */
}
Exemplo n.º 2
0
LW_API  
ULONG  API_CpuDown (ULONG  ulCPUId)
{
    INTREG          iregInterLevel;
    PLW_CLASS_CPU   pcpu;

    if ((ulCPUId == 0) || (ulCPUId >= LW_NCPUS)) {
        _ErrorHandle(EINVAL);
        return  (EINVAL);
    }
    
    __KERNEL_ENTER();
    pcpu = LW_CPU_GET(ulCPUId);
    if (!LW_CPU_IS_ACTIVE(pcpu) || 
        (LW_CPU_GET_IPI_PEND2(pcpu) & LW_IPI_DOWN_MSK)) {
        __KERNEL_EXIT();
        return  (ERROR_NONE);
    }
    
    LW_SPIN_LOCK_QUICK(&pcpu->CPU_slIpi, &iregInterLevel);
    LW_CPU_ADD_IPI_PEND2(pcpu, LW_IPI_DOWN_MSK);
    LW_SPIN_UNLOCK_QUICK(&pcpu->CPU_slIpi, iregInterLevel);
    
    _ThreadOffAffinity(pcpu);                                           /*  关闭与此 CPU 有关的亲和度   */
    __KERNEL_EXIT();
    
    _SmpSendIpi(ulCPUId, LW_IPI_DOWN, 0, LW_FALSE);                     /*  使用核间中断通知 CPU 停止   */
    
    return  (ERROR_NONE);
}
Exemplo n.º 3
0
/*********************************************************************************************************
** 函数名称: _ReadyTableDel
** 功能描述: 指定线程退出就绪表
** 输 入  : ptcb      线程控制块
** 输 出  : NONE
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
VOID  _ReadyTableDel (PLW_CLASS_TCB  ptcb)
{
    PLW_CLASS_PCBBMAP   ppcbbmap;
    
#if LW_CFG_SMP_EN > 0
    if (ptcb->TCB_bCPULock) {
        ppcbbmap = LW_CPU_RDY_PCBBMAP(LW_CPU_GET(ptcb->TCB_ulCPULock));
    } else 
#endif                                                                  /*  LW_CFG_SMP_EN > 0           */    
    {
        ppcbbmap = LW_GLOBAL_RDY_PCBBMAP();
    }
    
    _BitmapDel(&ppcbbmap->PCBM_bmap, ptcb->TCB_ucPriority);
}
Exemplo n.º 4
0
VOID  _SchedYield (PLW_CLASS_TCB  ptcb, PLW_CLASS_PCB  ppcb)
{
    UINT8          ucPriority;
    REGISTER PLW_CLASS_CPU  pcpu;

    if (__LW_THREAD_IS_RUNNING(ptcb)) {                                 /*  必须正在执行                */
        pcpu = LW_CPU_GET_CUR();
        if (_SchedSeekPriority(pcpu, &ucPriority) &&                    /*  就绪未运行任务的最高优先级  */
                LW_PRIO_IS_HIGH_OR_EQU(ucPriority,
                                       ptcb->TCB_ucPriority)) {
            ptcb->TCB_usSchedCounter = 0;                               /*  没收剩余时间片              */
            LW_CAND_ROT(LW_CPU_GET(ptcb->TCB_ulCPUId)) = LW_TRUE;       /*  下次调度时检查轮转          */
        }
    }
}
Exemplo n.º 5
0
/*********************************************************************************************************
** 函数名称: API_KernelTicksContext
** 功能描述: 处理系统时钟中断. (此函数必须在中断中被调用)
** 输 入  : 
** 输 出  : 
** 全局变量: 
** 调用模块: 
** 注  意  : vprocTickHook() 可能会激活新的任务, 会在中断退出时会尝试调度. 
             所以这里允许在 QUICK 操作中打开中断.

                                           API 函数
*********************************************************************************************************/
LW_API
VOID  API_KernelTicksContext (VOID)
{
             INTREG         iregInterLevel;
    REGISTER INT            i;
             PLW_CLASS_CPU  pcpu;
             PLW_CLASS_TCB  ptcb;
             
    LW_SPIN_KERN_LOCK_QUICK(&iregInterLevel);                           /*  锁定内核并关闭中断          */
    
#if LW_CFG_RTC_EN > 0
    __kernelTODUpdate();                                                /*  更新 TOD 时间               */
#endif                                                                  /*  LW_CFG_RTC_EN > 0           */
    __kernelTickUpdate();                                               /*  更新 TICK 时间              */
    
    KN_INT_ENABLE(iregInterLevel);                                      /*  允许其他中断进入            */
    
#if LW_CFG_SMP_EN > 0
    for (i = 0; i < LW_NCPUS; i++) {                                    /*  遍历所有的核                */
#else
    i = 0;
#endif                                                                  /*  LW_CFG_SMP_EN               */

        pcpu = LW_CPU_GET(i);
        if (LW_CPU_IS_ACTIVE(pcpu)) {                                   /*  CPU 必须被激活              */
            ptcb = pcpu->CPU_ptcbTCBCur;
            ptcb->TCB_ulCPUTicks++;
            if (pcpu->CPU_iKernelCounter) {
                ptcb->TCB_ulCPUKernelTicks++;
            }
            __LW_TICK_CPUUSAGE_UPDATE(ptcb, pcpu);                      /*  更新所有 CPU 利用率         */
#if LW_CFG_MODULELOADER_EN > 0
            vprocTickHook(ptcb, pcpu);                                  /*  测算进程执行时间            */
#endif
        }
        
#if LW_CFG_SMP_EN > 0
    }
#endif                                                                  /*  LW_CFG_SMP_EN               */
    
    iregInterLevel = KN_INT_DISABLE();                                  /*  关闭中断                    */
    
    _SchedTick();                                                       /*  处理所有 CPU 线程的时间片   */
    
    LW_SPIN_KERN_UNLOCK_QUICK(iregInterLevel);                          /*  退出内核并打开中断          */
}
Exemplo n.º 6
0
/*********************************************************************************************************
** 函数名称: _PriorityInit
** 功能描述: 初始化优先级控制块.
** 输 入  : NONE
** 输 出  : NONE
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
VOID  _PriorityInit (VOID)
{
    REGISTER ULONG    i;
    
#if LW_CFG_SMP_EN > 0
    REGISTER ULONG    j;
    
    for (i = 0; i < LW_CFG_MAX_PROCESSORS; i++) {
        for (j = 0; j < (LW_PRIO_LOWEST + 1); j++) {
            LW_CPU_RDY_PPCB(LW_CPU_GET(i), j)->PCB_ucPriority = (UINT8)j;
        }
    }
#endif                                                                  /*  LW_CFG_SMP_EN > 0           */
    
    for (i = 0; i < (LW_PRIO_LOWEST + 1); i++) {
        LW_GLOBAL_RDY_PPCB(i)->PCB_ucPriority = (UINT8)i;
    }
}
Exemplo n.º 7
0
/*********************************************************************************************************
** 函数名称: API_CpuIsUp
** 功能描述: 指定 CPU 是否启动.
** 输 入  : ulCPUId       CPU ID
** 输 出  : ERROR
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API  
BOOL  API_CpuIsUp (ULONG  ulCPUId)
{
    PLW_CLASS_CPU   pcpu;
    
    if (ulCPUId >= LW_NCPUS) {
        _ErrorHandle(EINVAL);
        return  (LW_FALSE);
    }
    
    KN_SMP_MB();
    pcpu = LW_CPU_GET(ulCPUId);
    if (LW_CPU_IS_ACTIVE(pcpu)) {
        return  (LW_TRUE);
    
    } else {
        return  (LW_FALSE);
    }
}
Exemplo n.º 8
0
/*********************************************************************************************************
** 函数名称: _SmpSendIpi
** 功能描述: 发送一个除自定义以外的核间中断给指定的 CPU 
             关中断情况下被调用, 如果需要等待, 则必须保证其他 CPU 已经运行.
** 输 入  : ulCPUId       CPU ID
**           ulIPIVec      核间中断类型 (除自定义类型中断以外)
**           iWait         是否等待处理结束 (LW_IPI_SCHED 绝不允许等待, 否则会死锁)
** 输 出  : NONE
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
VOID  _SmpSendIpi (ULONG  ulCPUId, ULONG  ulIPIVec, INT  iWait)
{
    PLW_CLASS_CPU   pcpuDst = LW_CPU_GET(ulCPUId);
    ULONG           ulMask  = (ULONG)(1 << ulIPIVec);
    
    if (!LW_CPU_IS_ACTIVE(pcpuDst)) {                                   /*  CPU 必须被激活              */
        return;
    }
    
    LW_SPIN_LOCK_IGNIRQ(&pcpuDst->CPU_slIpi);                           /*  锁定目标 CPU                */
    LW_CPU_ADD_IPI_PEND(ulCPUId, ulMask);                               /*  添加 PEND 位                */
    LW_SPIN_UNLOCK_IGNIRQ(&pcpuDst->CPU_slIpi);                         /*  解锁目标 CPU                */
    
    archMpInt(ulCPUId);
    
    if (iWait && (ulIPIVec != LW_IPI_SCHED)) {
        while (LW_CPU_GET_IPI_PEND(ulCPUId) & ulMask) {                 /*  等待结束                    */
            LW_SPINLOCK_DELAY();
        }
    }
}
Exemplo n.º 9
0
/*********************************************************************************************************
** 函数名称: _SmpCallIpi
** 功能描述: 发送一个自定义核间中断给指定的 CPU
             关中断情况下被调用, 如果需要等待, 则必须保证其他 CPU 已经运行.
** 输 入  : ulCPUId       CPU ID
**           pipim         核间中断参数
** 输 出  : 调用返回值
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
static INT  _SmpCallIpi (ULONG  ulCPUId, PLW_IPI_MSG  pipim)
{
    PLW_CLASS_CPU   pcpuDst = LW_CPU_GET(ulCPUId);
    
    if (!LW_CPU_IS_ACTIVE(pcpuDst)) {                                   /*  CPU 必须被激活              */
        return  (ERROR_NONE);
    }
    
    LW_SPIN_LOCK_IGNIRQ(&pcpuDst->CPU_slIpi);                           /*  锁定目标 CPU                */
    _List_Ring_Add_Last(&pipim->IPIM_ringManage, &pcpuDst->CPU_pringMsg);
    pcpuDst->CPU_uiMsgCnt++;
    LW_CPU_ADD_IPI_PEND(ulCPUId, LW_IPI_CALL_MSK);
    LW_SPIN_UNLOCK_IGNIRQ(&pcpuDst->CPU_slIpi);                         /*  解锁目标 CPU                */
    
    archMpInt(ulCPUId);
    
    while (pipim->IPIM_iWait) {                                         /*  等待结束                    */
        LW_SPINLOCK_DELAY();
    }
    
    return  (pipim->IPIM_iRet);
}
Exemplo n.º 10
0
/*********************************************************************************************************
** 函数名称: API_CpuUp
** 功能描述: 开启一个 CPU. (非 0 号 CPU)
** 输 入  : ulCPUId       CPU ID
** 输 出  : ERROR
** 全局变量: 
** 调用模块: 
                                           API 函数
*********************************************************************************************************/
LW_API  
ULONG  API_CpuUp (ULONG  ulCPUId)
{
    INTREG          iregInterLevel;
    PLW_CLASS_CPU   pcpu;

    if ((ulCPUId == 0) || (ulCPUId >= LW_NCPUS)) {
        _ErrorHandle(EINVAL);
        return  (EINVAL);
    }
    
    KN_SMP_MB();
    pcpu = LW_CPU_GET(ulCPUId);
    if (LW_CPU_IS_ACTIVE(pcpu) || 
        (LW_CPU_GET_IPI_PEND2(pcpu) & LW_IPI_DOWN_MSK)) {
        return  (ERROR_NONE);
    }
    
    iregInterLevel = KN_INT_DISABLE();
    bspCpuUp(ulCPUId);
    KN_INT_ENABLE(iregInterLevel);
    
    return  (ERROR_NONE);
}
Exemplo n.º 11
0
/*********************************************************************************************************
** 函数名称: _ThreadStatusChange
** 功能描述: 改变线程状态 (进入内核状态被调用)
** 输 入  : ptcb          线程控制块
**           uiStatusReq   状态 (LW_TCB_REQ_SUSPEND / LW_TCB_REQ_WDEATH / LW_TCB_REQ_STOP)
** 输 出  : ERROR
** 全局变量: 
** 调用模块: 
** 注  意  : 此函数已经预置的阻塞点, 最后一次退出内核时, 将阻塞等待目标线程状态改变完毕.
*********************************************************************************************************/
ULONG  _ThreadStatusChange (PLW_CLASS_TCB  ptcb, UINT  uiStatusReq)
{
    INTREG         iregInterLevel;
    PLW_CLASS_PCB  ppcb;
    PLW_CLASS_TCB  ptcbCur;
    
    iregInterLevel = KN_INT_DISABLE();                                  /*  关闭中断                    */
    
    LW_TCB_GET_CUR(ptcbCur);
    
#if LW_CFG_SMP_EN > 0
    if (ptcb == ptcbCur) {                                              /*  改变自己的状态              */
        goto    __change1;
    
    } else if (!__LW_THREAD_IS_READY(ptcb)) {                           /*  任务没有就绪                */
        goto    __change2;
    
    } else {                                                            /*  目标任务处于就绪状态        */
        if (LW_CPU_GET_CUR_NESTING()) {
            KN_INT_ENABLE(iregInterLevel);                              /*  打开中断                    */
            return  (ERROR_KERNEL_IN_ISR);                              /*  中断状态下无法完成此工作    */
        }
        
        if (!__LW_THREAD_IS_RUNNING(ptcb)) {                            /*  目标任务不是正在执行        */
            ppcb = _GetPcb(ptcb);
            __DEL_FROM_READY_RING(ptcb, ppcb);                          /*  从就绪表中删除              */
            goto    __change2;
        
        } else {                                                        /*  目标任务正在执行            */
            _SmpUpdateIpi(LW_CPU_GET(ptcb->TCB_ulCPUId));               /*  发送核间中断通知改变状态    */
            _ThreadWaitStatus(ptcbCur, ptcb, uiStatusReq);              /*  设置等待对方完成状态        */
        }
        
        KN_INT_ENABLE(iregInterLevel);                                  /*  打开中断                    */
        return  (ERROR_NONE);                                           /*  退出内核时开始等待          */
    }
    
__change1:
#endif                                                                  /*  LW_CFG_SMP_EN               */
    
    if (__LW_THREAD_IS_READY(ptcb)) {
        ppcb = _GetPcb(ptcb);
        __DEL_FROM_READY_RING(ptcb, ppcb);                              /*  从就绪表中删除              */
    }
    
#if LW_CFG_SMP_EN > 0
__change2:
#endif                                                                  /*  LW_CFG_SMP_EN               */
    
    ptcbCur->TCB_uiStatusChangeReq = 0;                                 /*  状态修改操作执行成功        */
    
    switch (uiStatusReq) {
    
    case LW_TCB_REQ_SUSPEND:
        ptcb->TCB_ulSuspendNesting++;
        ptcb->TCB_usStatus |= LW_THREAD_STATUS_SUSPEND;
        break;
        
    case LW_TCB_REQ_STOP:
        ptcb->TCB_ulStopNesting++;
        ptcb->TCB_usStatus |= LW_THREAD_STATUS_STOP;
        break;
        
    case LW_TCB_REQ_WDEATH:
        ptcb->TCB_usStatus |= LW_THREAD_STATUS_WDEATH;
        break;
    }
        
    KN_INT_ENABLE(iregInterLevel);
    return  (ERROR_NONE);
}