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); }
/********************************************************************************************************* ** 函数名称: _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 */ }
/********************************************************************************************************* ** 函数名称: _SmpUpdateIpi ** 功能描述: 产生一个 IPI ** 输 入 : pcpuCur CPU 控制块 ** 输 出 : NONE ** 全局变量: ** 调用模块: *********************************************************************************************************/ VOID _SmpUpdateIpi (PLW_CLASS_CPU pcpu) { if (!LW_CPU_IS_ACTIVE(pcpu)) { /* CPU 必须被激活 */ return; } archMpInt(pcpu->CPU_ulCPUId); }
/********************************************************************************************************* ** 函数名称: 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); /* 退出内核并打开中断 */ }
/********************************************************************************************************* ** 函数名称: 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); } }
/********************************************************************************************************* ** 函数名称: _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(); } } }
/********************************************************************************************************* ** 函数名称: _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); }
/********************************************************************************************************* ** 函数名称: 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); }