/********************************************************************************************************* ** 函数名称: archSpinInit ** 功能描述: 初始化一个 spinlock ** 输 入 : psl spinlock 指针 ** 输 出 : NONE ** 全局变量: ** 调用模块: *********************************************************************************************************/ VOID archSpinInit (spinlock_t *psl) { psl->SL_sltData = 0; /* 0: 未锁定状态 1: 锁定状态 */ psl->SL_pcpuOwner = LW_NULL; psl->SL_ulCounter = 0ul; /* 重入锁计数 */ KN_SMP_WMB(); }
/********************************************************************************************************* ** 函数名称: __smpProcCallfunc ** 功能描述: 处理核间中断调用函数 ** 输 入 : pcpuCur 当前 CPU ** 输 出 : NONE ** 全局变量: ** 调用模块: *********************************************************************************************************/ static VOID __smpProcCallfunc (PLW_CLASS_CPU pcpuCur) { #define LW_KERNEL_OWN_CPU() (PLW_CLASS_CPU)(_K_klKernel.KERN_pvCpuOwner) UINT i, uiCnt; PLW_IPI_MSG pipim; PLW_LIST_RING pringTemp; PLW_LIST_RING pringDelete; VOIDFUNCPTR pfuncAsync; PVOID pvAsync; LW_SPIN_LOCK_IGNIRQ(&pcpuCur->CPU_slIpi); /* 锁定 CPU */ pringTemp = pcpuCur->CPU_pringMsg; uiCnt = pcpuCur->CPU_uiMsgCnt; for (i = 0; i < uiCnt; i++) { _BugHandle((!pcpuCur->CPU_pringMsg), LW_TRUE, "ipi call func error!\r\n"); pipim = _LIST_ENTRY(pringTemp, LW_IPI_MSG, IPIM_ringManage); if ((LW_KERNEL_OWN_CPU() == pcpuCur) && (pipim->IPIM_iOption & IPIM_OPT_NOKERN)) { /* 此函数不能再内核锁定状态执行*/ pringTemp = _list_ring_get_next(pringTemp); continue; } pringDelete = pringTemp; pringTemp = _list_ring_get_next(pringTemp); _List_Ring_Del(pringDelete, &pcpuCur->CPU_pringMsg); /* 删除一个节点 */ pcpuCur->CPU_uiMsgCnt--; if (pipim->IPIM_pfuncCall) { pipim->IPIM_iRet = pipim->IPIM_pfuncCall(pipim->IPIM_pvArg);/* 执行同步调用 */ } pfuncAsync = pipim->IPIM_pfuncAsyncCall; pvAsync = pipim->IPIM_pvAsyncArg; KN_SMP_MB(); pipim->IPIM_iWait = 0; /* 调用结束 */ KN_SMP_WMB(); LW_SPINLOCK_NOTIFY(); if (pfuncAsync) { pfuncAsync(pvAsync); /* 执行异步调用 */ } } KN_SMP_MB(); if (pcpuCur->CPU_pringMsg == LW_NULL) { LW_CPU_CLR_IPI_PEND2(pcpuCur, LW_IPI_CALL_MSK); /* 清除 */ } LW_SPIN_UNLOCK_IGNIRQ(&pcpuCur->CPU_slIpi); /* 解锁 CPU */ LW_SPINLOCK_NOTIFY(); }
/********************************************************************************************************* ** 函数名称: _SmpCallIpiAllOther ** 功能描述: 发送一个自定义核间中断给其他所有 CPU 关中断情况下被调用, 如果需要等待, 则必须保证其他 CPU 已经运行. ** 输 入 : pipim 核间中断参数 ** 输 出 : NONE (无法确定返回值) ** 全局变量: ** 调用模块: *********************************************************************************************************/ static VOID _SmpCallIpiAllOther (PLW_IPI_MSG pipim) { ULONG i; ULONG ulCPUId; INT iWaitSave = pipim->IPIM_iWait; ulCPUId = LW_CPU_GET_CUR_ID(); KN_SMP_WMB(); for (i = 0; i < LW_NCPUS; i++) { if (ulCPUId != i) { _SmpCallIpi(i, pipim); KN_SMP_MB(); pipim->IPIM_iWait = iWaitSave; KN_SMP_WMB(); } } }
/********************************************************************************************************* ** 函数名称: _SmpSendIpiAllOther ** 功能描述: 发送一个除自定义以外的核间中断给所有其他 CPU 关中断情况下被调用, 如果需要等待, 则必须保证其他 CPU 已经运行. ** 输 入 : ulIPIVec 核间中断类型 (除自定义类型中断以外) ** iWait 是否等待处理结束 (LW_IPI_SCHED 绝不允许等待, 否则会死锁) ** 输 出 : NONE ** 全局变量: ** 调用模块: *********************************************************************************************************/ VOID _SmpSendIpiAllOther (ULONG ulIPIVec, INT iWait) { ULONG i; ULONG ulCPUId; ulCPUId = LW_CPU_GET_CUR_ID(); KN_SMP_WMB(); for (i = 0; i < LW_NCPUS; i++) { if (ulCPUId != i) { _SmpSendIpi(i, ulIPIVec, iWait); } } }
/********************************************************************************************************* ** 函数名称: archSpinUnlock ** 功能描述: spinlock 解锁 ** 输 入 : psl spinlock 指针 ** 输 出 : 0: 没有获取 ** 1: 正常解锁 ** 全局变量: ** 调用模块: *********************************************************************************************************/ INT archSpinUnlock (spinlock_t *psl) { if (psl->SL_pcpuOwner != LW_CPU_GET_CUR()) { return (0); /* 没有权利释放 */ } if (psl->SL_ulCounter) { psl->SL_ulCounter--; /* 减少重复调用次数 */ return (1); } psl->SL_pcpuOwner = LW_NULL; /* 没有 CPU 获取 */ KN_SMP_WMB(); armSpinUnlock(&psl->SL_sltData); /* 解锁 */ return (1); }
/********************************************************************************************************* ** 函数名称: API_InterEnter ** 功能描述: 内核中断入口函数 (在关中断的情况下被调用) ** 输 入 : ** 输 出 : 中断层数 ** 全局变量: ** 调用模块: API 函数 *********************************************************************************************************/ LW_API ULONG API_InterEnter (VOID) { PLW_CLASS_CPU pcpu; pcpu = LW_CPU_GET_CUR(); if (pcpu->CPU_ulInterNesting != LW_CFG_MAX_INTER_SRC) { pcpu->CPU_ulInterNesting++; } KN_SMP_WMB(); /* 等待以上操作完成 */ #if LW_CFG_CPU_FPU_EN > 0 if (LW_KERN_FPU_EN_GET()) { /* 中断状态允许使用浮点运算 */ __fpuInterEnter(pcpu); } #endif /* LW_CFG_CPU_FPU_EN > 0 */ return (pcpu->CPU_ulInterNesting); }
/********************************************************************************************************* ** 函数名称: API_InterExit ** 功能描述: 内核中断出口函数 (在关中断的情况下被调用) ** 输 入 : NONE ** 输 出 : NONE ** 全局变量: ** 调用模块: API 函数 *********************************************************************************************************/ LW_API VOID API_InterExit (VOID) { PLW_CLASS_CPU pcpu; pcpu = LW_CPU_GET_CUR(); #if LW_CFG_INTER_INFO > 0 if (pcpu->CPU_ulInterNestingMax < pcpu->CPU_ulInterNesting) { pcpu->CPU_ulInterNestingMax = pcpu->CPU_ulInterNesting; } #endif /* LW_CFG_INTER_INFO > 0 */ if (pcpu->CPU_ulInterNesting) { /* 系统中断嵌套层数-- */ pcpu->CPU_ulInterNesting--; } KN_SMP_WMB(); /* 等待以上操作完成 */ if (pcpu->CPU_ulInterNesting) { /* 查看系统是否在中断嵌套中 */ #if LW_CFG_CPU_FPU_EN > 0 /* 恢复上一等级中断 FPU CTX */ if (LW_KERN_FPU_EN_GET()) { __fpuInterExit(pcpu); } #endif /* LW_CFG_CPU_FPU_EN > 0 */ return; } __KERNEL_SCHED_INT(pcpu); /* 中断中的调度 */ #if LW_CFG_CPU_FPU_EN > 0 if (LW_KERN_FPU_EN_GET()) { __fpuInterExit(pcpu); } #endif /* LW_CFG_CPU_FPU_EN > 0 */ }
/********************************************************************************************************* ** 函数名称: _SmpSpinInit ** 功能描述: 自旋锁初始化 ** 输 入 : psl 自旋锁 ** 输 出 : NONE ** 全局变量: ** 调用模块: *********************************************************************************************************/ VOID _SmpSpinInit (spinlock_t *psl) { __ARCH_SPIN_INIT(psl); KN_SMP_WMB(); }