/************************************************************************************************* * 功能:线程运行监理函数,线程的运行都以它为基础 * * 参数:(1) pThread 线程地址 * * 返回:无 * * 说明:这里处理线程的非法退出问题 * * 说明:函数名的前缀'x'(eXtreme)表示本函数需要处理临界区代码 * *************************************************************************************************/ static void xSuperviseThread(TThread* pThread) { TState state; TError error; TReg32 imask; /* 调用用户ASR线程主函数,这类函数的特点是解挂后一次性执行,然后立刻挂起,等待下次调用。 虽然Irq和Timer守护线程也是中断服务线程,但不是做为ASR在此处理。 这两个函数自己处理挂起问题 */ if ((pThread->Property &THREAD_PROP_RUNASR)) { while (eTrue) { /* 执行线程函数 */ pThread->Entry(pThread->Argument); /* 线程运行结束后直接挂起,等待再次被执行 */ CpuEnterCritical(&imask); state = uThreadSetUnready(pThread, eThreadSuspended, 0U, &error); if (state == eFailure) { uKernelVariable.Diagnosis |= KERNEL_DIAG_THREAD_ERROR; pThread->Diagnosis |= THREAD_DIAG_INVALID_STATE; uDebugPanic("", __FILE__, __FUNCTION__, __LINE__); } CpuLeaveCritical(imask); } } /* 处理RUN TO COMPLETION 线程退出问题, 防止退出后处理器执行到非法(未知)指令 */ else if (pThread->Property &THREAD_PROP_RUN2COMPLETION) { /* 执行线程函数 */ pThread->Entry(pThread->Argument); /* 线程运行结束后直接挂起,等待后继处理 */ CpuEnterCritical(&imask); state = uThreadSetUnready(pThread, eThreadDormant, 0U, &error); if (state == eFailure) { uKernelVariable.Diagnosis |= KERNEL_DIAG_THREAD_ERROR; pThread->Diagnosis |= THREAD_DIAG_INVALID_STATE; uDebugPanic("", __FILE__, __FUNCTION__, __LINE__); } CpuLeaveCritical(imask); } else { /* 执行用户线程函数 */ pThread->Entry(pThread->Argument); /* 防止RUNFOREVER线程不小心退出导致非法指令等死机的问题 */ uKernelVariable.Diagnosis |= KERNEL_DIAG_THREAD_ERROR; pThread->Diagnosis |= THREAD_DIAG_INVALID_EXIT; uDebugPanic("", __FILE__, __FUNCTION__, __LINE__); } }
/************************************************************************************************* * 功能:内核中的IRQ守护线程函数 * * 参数:(1) argument IRQ守护线程的用户参数 * * 返回:无 * * 说明: * *************************************************************************************************/ static void xIrqDaemonEntry(TArgument argument) { TReg32 imask; TIrq* pIRQ; TIrqEntry pEntry; TArgument data; /* * 从队列中逐个获得IRQ请求兵在线程环境下处理该IRQ回调事务 * 如果IRQ请求队列为空则将IRQ守护线程挂起 */ while(eTrue) { CpuEnterCritical(&imask); if (IrqReqList.Handle == (TObjNode*)0) { uThreadSuspendSelf(); CpuLeaveCritical(imask); } else { pIRQ = (TIrq*)(IrqReqList.Handle->Owner); pEntry = pIRQ->Entry; data = pIRQ->Argument; uObjListRemoveNode(pIRQ->ObjNode.Handle, &(pIRQ->ObjNode)); memset(pIRQ, 0, sizeof(TIrq)); CpuLeaveCritical(imask); pEntry(data); } } }
/************************************************************************************************* * 功能:用户定时器初始化函数 * * 参数:(1) pTimer 定时器地址 * * (2) property 定时器属性 * * (3) ticks 定时器滴答数目 * * (4) pRoutine 用户定时器回调函数 * * (5) data 用户定时器回调函数参数 * * (6) pError 详细调用结果 * * 返回: (1) eSuccess 操作成功 * * (2) eFailure 操作失败 * * 说明 * *************************************************************************************************/ TState xTimerCreate(TTimer* pTimer, TProperty property, TTimeTick ticks, TTimerRoutine pRoutine, TArgument data, TError* pError) { TState state = eFailure; TError error = TIMER_ERR_FAULT; TReg32 imask; CpuEnterCritical(&imask); /* 检查定时器就绪属性 */ if (!(pTimer->Property & TIMER_PROP_READY)) { if (ticks > 0U) { uTimerCreate(pTimer, property, eUserTimer, ticks, pRoutine, data, (void*)0); error = TIMER_ERR_NONE; state = eSuccess; } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:提交中断请求 * * 参数:(1) pIRQ 中断请求结构地址 * * (2) priority 中断请求优先级 * * (3) pEntry 中断处理回调函数 * * (4) data 中断处理回调参数 * * 返回: (1) eFailure 操作失败 * * (2) eSuccess 操作成功 * * 说明: * *************************************************************************************************/ TState xIrqPostRequest(TIrq* pIRQ, TPriority priority, TIrqEntry pEntry, TArgument data, TError* pError) { TState state = eFailure; TError error = IRQ_ERR_FAULT; TReg32 imask; CpuEnterCritical(&imask); if (!(pIRQ->Property & IRQ_PROP_READY)) { pIRQ->Property = IRQ_PROP_READY; pIRQ->Entry = pEntry; pIRQ->Argument = data; pIRQ->Priority = priority; pIRQ->ObjNode.Next = (TObjNode*)0; pIRQ->ObjNode.Prev = (TObjNode*)0; pIRQ->ObjNode.Handle = (TObjNode**)0; pIRQ->ObjNode.Data = (TBase32*)(&(pIRQ->Priority)); pIRQ->ObjNode.Owner = (void*)pIRQ; uObjListAddPriorityNode(&(IrqReqList.Handle), &(pIRQ->ObjNode)); error = IRQ_ERR_NONE; state = eSuccess; } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:清空中断向量函数 * * 参数:(1) irqn 中断编号 * * 返回:无 * * 说明: * *************************************************************************************************/ TState xIrqCleanVector(TIndex irqn, TError* pError) { TState state = eFailure; TError error = IRQ_ERR_FAULT; TReg32 imask; TIrqVector* pVector; CpuEnterCritical(&imask); /* 找到该中断向量并且清空相关信息 */ if (IrqMapTable[irqn] != (TAddr32)0) { pVector = (TIrqVector*)(IrqMapTable[irqn]); if ((pVector->Property & IRQ_VECTOR_PROP_READY) && (pVector->IRQn == irqn)) { if (!(pVector->Property & IRQ_VECTOR_PROP_LOCKED)) { IrqMapTable[irqn] = (TAddr32)0; memset(pVector, 0, sizeof(TIrqVector)); error = IRQ_ERR_NONE; state = eSuccess; } else { error = IRQ_ERR_LOCKED; } } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:停止用户定时器函数 * * 参数:(1) pTimer 定时器地址 * * (2) pError 详细调用结果 * * 返回: (1) eSuccess 操作成功 * * (2) eFailure 操作失败 * * (3) pError 详细调用结果 * * 说明: * *************************************************************************************************/ TState xTimerStop(TTimer* pTimer, TError* pError) { TState state = eFailure; TError error = TIMER_ERR_UNREADY; TReg32 imask; CpuEnterCritical(&imask); /* 检查定时器就绪属性 */ if (pTimer->Property & TIMER_PROP_READY) { if (pTimer->Type == eUserTimer) { uTimerStop(pTimer); error = TIMER_ERR_NONE; state = eSuccess; } else { error = TIMER_ERR_FAULT; } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:线程结构初始化函数 * * 参数:(1) pThread 线程结构地址 * * (2) status 线程的初始状态 * * (3) property 线程属性 * * (4) acapi 对线程管理API的许可控制 * * (5) pEntry 线程函数地址 * * (6) pArg 线程函数参数 * * (7) pStack 线程栈地址 * * (8) bytes 线程栈大小,以字为单位 * * (9) priority 线程优先级 * * (10) ticks 线程时间片长度 * * (11) pError 详细调用结果 * * 返回:(1) eFailure * * (2) eSuccess * * 说明:函数名的前缀'x'(eXtreme)表示本函数需要处理临界区代码 * *************************************************************************************************/ TState xThreadCreate(TThread* pThread, TThreadStatus status, TProperty property, TBitMask acapi, TThreadEntry pEntry, TArgument argument, void* pStack, TBase32 bytes, TPriority priority, TTimeTick ticks, TError* pError) { TState state = eFailure; TError error = THREAD_ERR_FAULT; TReg32 imask; CpuEnterCritical(&imask); /* 只允许在非中断代码调用本函数 */ if (uKernelVariable.State != eIntrState) { /* 检查线程是否已经被初始化 */ if (!(pThread->Property &THREAD_PROP_READY)) { uThreadCreate(pThread, status, property, acapi, pEntry, argument, pStack, bytes, priority, ticks); error = THREAD_ERR_NONE; state = eSuccess; } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:重置定时器类型和定时时间 * * 参数:(1) pTimer 定时器结构地址 * * (2) ticks 定时器时钟节拍数目 * * (3) pError 详细调用结果 * * 返回:无 * * 说明 * *************************************************************************************************/ TState xTimerConfig(TTimer* pTimer, TTimeTick ticks, TError* pError) { TState state = eFailure; TError error = TIMER_ERR_UNREADY; TReg32 imask; CpuEnterCritical(&imask); /* 检查定时器就绪属性 */ if (pTimer->Property & TIMER_PROP_READY) { /* 定时器类型检查,然后保持定时器类型不变,稍有啰嗦 */ if (pTimer->Type == eUserTimer) { uTimerConfig(pTimer, eUserTimer, ticks); error = TIMER_ERR_NONE; state = eSuccess; } else { error = TIMER_ERR_FAULT; } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:内核中的定时器守护线程函数 * * 参数:(1) argument 定时器线程的用户参数 * * 返回:无 * * 说明: * *************************************************************************************************/ static void TimerDaemonEntry(TArgument argument) { TState state; TError error; TBase32 imask; TTimer* pTimer; TTimerRoutine pRoutine; TArgument data; while(eTrue) { CpuEnterCritical(&imask); /* 如果期满定时器队列为空则将定时器守护线程休眠 */ if (TimerList.ExpiredHandle == (TObjNode*)0) { state = uThreadSetUnready(&TimerDaemonThread, eThreadSuspended, 0U, &error); state = state; CpuLeaveCritical(imask); } else { /* 逐个处理用户定时器 */ pTimer = (TTimer*)(TimerList.ExpiredHandle->Owner); pRoutine = pTimer->Routine; data = pTimer->Argument; ResetTimer(pTimer); CpuLeaveCritical(imask); /* 在线程环境下处理定时器回调事务 */ pRoutine(data); } } }
/************************************************************************************************* * 功能:线程延时取消函数 * * 参数:(1) pThread 线程结构地址 * * (2) pError 详细调用结果 * * 返回:(1) eSuccess * * (2) eFailure * * 说明:(1) 这个函数对以时限等待方式阻塞在IPC线程阻塞队列上的线程无效 * *************************************************************************************************/ TState xThreadUndelay(TThread* pThread, TError* pError) { TState state = eFailure; TError error = THREAD_ERR_FAULT; TReg32 imask; CpuEnterCritical(&imask); /* 只允许在非中断代码调用本函数 */ if (uKernelVariable.State != eIntrState) { /* 检查线程是否已经被初始化 */ if (pThread->Property &THREAD_PROP_READY) { /* 检查线程是否接收相关API调用 */ if (pThread->ACAPI &THREAD_ACAPI_UNDELAY) { state = uThreadSetReady(pThread, eThreadDelayed, &error); } else { error = THREAD_ERR_ACAPI; } } else { error = THREAD_ERR_UNREADY; } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:消息队列初始化函数 * * 输入:(1) pMsgQue 消息队列结构地址 * * (2) pPool2 消息数组地址 * * (3) capacity 消息队列容量,即消息数组大小 * * (4) policy 消息队列线程调度策略 * * (5) pError 详细调用结果 * * 返回:(1) eSuccess 操作成功 * * (2) eFailure 操作失败 * * 说明: * *************************************************************************************************/ TState xMQCreate(TMsgQueue* pMsgQue, void** pPool2, TBase32 capacity, TProperty property, TError* pError) { TState state = eFailure; TError error = IPC_ERR_FAULT; TReg32 imask; CpuEnterCritical(&imask); if (!(pMsgQue->Property & IPC_PROP_READY)) { property |= IPC_PROP_READY; pMsgQue->Property = property; pMsgQue->Capacity = capacity; pMsgQue->MsgPool = pPool2; pMsgQue->MsgEntries = 0U; pMsgQue->Head = 0U; pMsgQue->Tail = 0U; pMsgQue->Status = eMQEmpty; pMsgQue->Queue.PrimaryHandle = (TObjNode*)0; pMsgQue->Queue.AuxiliaryHandle = (TObjNode*)0; pMsgQue->Queue.Property = &(pMsgQue->Property); error = IPC_ERR_NONE; state = eSuccess; } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:消息队列阻塞终止函数,将指定的线程从消息队列的阻塞队列中终止阻塞并唤醒 * * 参数:(1) pMsgQue 消息队列结构地址 * * (2) option 参数选项 * * (3) pThread 线程地址 * * (4) pError 详细调用结果 * * 返回:(1) eSuccess 成功 * * (2) eFailure 失败 * * 说明: * *************************************************************************************************/ TState xMQFlush(TMsgQueue* pMsgQue, TError* pError) { TState state = eFailure; TError error = IPC_ERR_UNREADY; TReg32 imask; TBool HiRP = eFalse; CpuEnterCritical(&imask); if (pMsgQue->Property & IPC_PROP_READY) { /* 将消息队列阻塞队列上的所有等待线程都释放,所有线程的等待结果都是TCLE_IPC_FLUSH */ uIpcUnblockAll(&(pMsgQue->Queue), eFailure, IPC_ERR_FLUSH, (void**)0, &HiRP); /* * 在线程环境下,如果当前线程的优先级已经不再是线程就绪队列的最高优先级, * 并且内核此时并没有关闭线程调度,那么就需要进行一次线程抢占 */ if ((uKernelVariable.State == eThreadState) && (uKernelVariable.Schedulable == eTrue) && (HiRP == eTrue)) { uThreadSchedule(); } state = eSuccess; error = IPC_ERR_NONE; } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:中断处理函数总入口 * * 参数:(1) irqn 中断号 * * 返回:无 * * 说明: * *************************************************************************************************/ void xIrqEnterISR(TIndex irqn) { TReg32 imask; TIrqVector* pVector; TISR pISR; TArgument data; TBitMask retv = IRQ_ISR_DONE; KNL_ASSERT((irqn < TCLC_CPU_IRQ_NUM), ""); CpuEnterCritical(&imask); /* 获得和中断号对应的中断向量 */ pVector = (TIrqVector*)(IrqMapTable[irqn]); if ((pVector != (TIrqVector*)0) && (pVector->Property & IRQ_VECTOR_PROP_READY)) { /* 在处理中断对应的向量时,禁止其他代码修改向量 */ pVector->Property |= IRQ_VECTOR_PROP_LOCKED; /* 在线程环境下调用低级中断处理函数 */ if (pVector->ISR != (TISR)0) { pISR = pVector->ISR; data = pVector->Argument; CpuLeaveCritical(imask); retv = pISR(data); CpuEnterCritical(&imask); } /* 如果需要则调用中断处理线程ASR(用户中断处理线程或者内核中断守护线程), 注意此时ASR可能处于eThreadReady状态 */ if ((retv & IRQ_CALL_ASR) && (pVector->ASR != (TThread*)0)) { uThreadResumeFromISR(pVector->ASR); } pVector->Property &= (~IRQ_VECTOR_PROP_LOCKED); } CpuLeaveCritical(imask); }
/************************************************************************************************* * 功能:更改线程优先级 * * 参数:(1) pThread 线程结构地址 * * (2) priority 线程优先级 * * (3) pError 详细调用结果 * * 返回:(1) eFailure 更改线程优先级失败 * * (2) eSuccess 更改线程优先级成功 * * 说明:(1) 如果是临时修改优先级,则不修改线程结构的基本优先级数据 * * (2) 互斥量实施优先级继承协议的时候不受AUTHORITY控制 * *************************************************************************************************/ TState xThreadSetPriority(TThread* pThread, TPriority priority, TError* pError) { TState state = eFailure; TError error = THREAD_ERR_FAULT; TBool HiRP = eFalse; TReg32 imask; CpuEnterCritical(&imask); /* 只允许在线程代码里调用本函数 */ if (uKernelVariable.State == eThreadState) { /* 如果没有给出被操作的线程地址,则强制使用当前线程 */ if (pThread == (TThread*)0) { pThread = uKernelVariable.CurrentThread; } /* 检查线程是否已经被初始化 */ if (pThread->Property &THREAD_PROP_READY) { /* 检查线程是否接收相关API调用 */ if (pThread->ACAPI &THREAD_ACAPI_SET_PRIORITY) { if ((!(pThread->Property & THREAD_PROP_PRIORITY_FIXED)) && (pThread->Property & THREAD_PROP_PRIORITY_SAFE)) { state = uThreadSetPriority(pThread, priority, eTrue, &HiRP, &error); if ((uKernelVariable.Schedulable == eTrue) && (HiRP == eTrue)) { uThreadSchedule(); } else { error = THREAD_ERR_FAULT; state = eFailure; } } else { error = THREAD_ERR_ACAPI; } } else { error = THREAD_ERR_UNREADY; } } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:修改线程时间片长度 * * 参数:(1) pThread 线程结构地址 * * (2) slice 线程时间片长度 * * (3) pError 详细调用结果 * * 返回:(1) eSuccess * * (2) eFailure * * 说明: * *************************************************************************************************/ TState xThreadSetTimeSlice(TThread* pThread, TTimeTick ticks, TError* pError) { TState state = eFailure; TError error = THREAD_ERR_FAULT; TReg32 imask; CpuEnterCritical(&imask); /* 只允许在非中断代码调用本函数 */ if (uKernelVariable.State != eIntrState) { /* 如果没有给出被操作的线程地址,则强制使用当前线程 */ if (pThread == (TThread*)0) { pThread = uKernelVariable.CurrentThread; } /* 检查线程是否已经被初始化 */ if (pThread->Property &THREAD_PROP_READY) { /* 检查线程是否接收相关API调用 */ if (pThread->ACAPI &THREAD_ACAPI_SET_SLICE) { /* 调整线程时间片长度 */ if (pThread->BaseTicks > ticks) { pThread->Ticks = (pThread->Ticks < ticks) ? (pThread->Ticks): ticks; } else { pThread->Ticks += (ticks - pThread->BaseTicks); } pThread->BaseTicks = ticks; error = THREAD_ERR_NONE; state = eSuccess; } else { error = THREAD_ERR_ACAPI; } } else { error = THREAD_ERR_UNREADY; } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:线程级线程调度函数,当前线程主动让出处理器(保持就绪状态) * * 参数:(1) pError 详细调用结果 * * 返回:(1) eFailure * * (2) eSuccess * * 说明:因为不能破坏最高就绪优先级占用处理器的原则, * * 所以Yield操作只能在拥有最高就绪优先级的线程之间操作 * *************************************************************************************************/ TState xThreadYield(TError* pError) { TState state = eFailure; TError error = THREAD_ERR_FAULT; TReg32 imask; TPriority priority; TThread* pThread; CpuEnterCritical(&imask); /* 只能在线程环境下同时内核允许线程调度的条件下才能调用本函数 */ if ((uKernelVariable.State == eThreadState) && (uKernelVariable.Schedulable == eTrue)) { /* 操作目标是当前线程 */ pThread = uKernelVariable.CurrentThread; priority = pThread->Priority; /* 检查线程是否已经被初始化 */ if (pThread->Property &THREAD_PROP_READY) { /* 检查线程是否接收相关API调用 */ if (pThread->ACAPI &THREAD_ACAPI_YIELD) { /* * 调整当前线程所在队列的头指针 * 当前线程所在线程队列也可能只有当前线程唯一1个线程 */ ThreadReadyQueue.Handle[priority] = (ThreadReadyQueue.Handle[priority])->Next; pThread->Status = eThreadReady; uThreadSchedule(); error = THREAD_ERR_NONE; state = eSuccess; } else { error = THREAD_ERR_ACAPI; } } else { error = THREAD_ERR_UNREADY; } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:线程解挂函数 * * 参数:(1) pThread 线程结构地址 * * (2) pError 详细调用结果 * * 返回:(1) eFailure * * (2) eSuccess * * 说明: * *************************************************************************************************/ TState xThreadUnblock(TThread* pThread, TError* pError) { TState state = eFailure; TError error = THREAD_ERR_UNREADY; TBool HiRP = eFalse; TReg32 imask; CpuEnterCritical(&imask); /* 检查线程是否已经被初始化 */ if (pThread->Property &THREAD_PROP_READY) { /* 检查线程是否接收相关API调用 */ if (pThread->ACAPI &THREAD_ACAPI_UNBLOCK) { if (pThread->Status == eThreadBlocked) { /* * 将阻塞队列上的指定阻塞线程释放 * 在线程环境下,如果当前线程的优先级已经不再是线程就绪队列的最高优先级, * 并且内核此时并没有关闭线程调度,那么就需要进行一次线程抢占 */ uIpcUnblockThread(&(pThread->IpcContext), eFailure, IPC_ERR_ABORT, &HiRP); if ((uKernelVariable.State == eThreadState) && (uKernelVariable.Schedulable == eTrue) && (HiRP == eTrue)) { uThreadSchedule(); } error = THREAD_ERR_NONE; state = eSuccess; } else { error = THREAD_ERR_STATUS; } } else { error = THREAD_ERR_ACAPI; } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:线程挂起函数 * * 参数:(1) pThread 线程结构地址 * * (2) pError 详细调用结果 * * 返回:(1) eFailure * * (2) eSuccess * * 说明:(1) 内核初始化线程不能被挂起 * *************************************************************************************************/ TState xThreadSuspend(TThread* pThread, TError* pError) { TState state = eFailure; TError error = THREAD_ERR_FAULT; TBool HiRP = eFalse; TReg32 imask; CpuEnterCritical(&imask); /* 只允许在线程代码里调用本函数 */ if (uKernelVariable.State == eThreadState) { /* 如果没有给出被操作的线程地址,则强制使用当前线程 */ if (pThread == (TThread*)0) { pThread = uKernelVariable.CurrentThread; } /* 检查线程是否已经被初始化 */ if (pThread->Property &THREAD_PROP_READY) { /* 检查线程是否接收相关API调用 */ if (pThread->ACAPI &THREAD_ACAPI_SUSPEND) { state = SetThreadUnready(pThread, eThreadSuspended, 0U, &HiRP, &error); if (HiRP == eTrue) { uThreadSchedule(); } } else { error = THREAD_ERR_ACAPI; } } else { error = THREAD_ERR_UNREADY; } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:线程解挂函数 * * 参数:(1) pThread 线程结构地址 * * (2) pError 详细调用结果 * * 返回:(1) eFailure * * (2) eSuccess * * 说明: * *************************************************************************************************/ TState xThreadUnblock(TThread* pThread, TError* pError) { TState state = eFailure; TError error = THREAD_ERR_UNREADY; TBool HiRP = eFalse; TReg32 imask; CpuEnterCritical(&imask); /* 检查线程是否已经被初始化 */ if (pThread->Property &THREAD_PROP_READY) { /* 检查线程是否接收相关API调用 */ if (pThread->ACAPI &THREAD_ACAPI_UNBLOCK) { if (pThread->Status == eThreadBlocked) { /* 将阻塞队列上的指定阻塞线程释放 */ uIpcUnblockThread(&(pThread->IpcContext), eFailure, IPC_ERR_ABORT, &HiRP); /* 尝试发起线程抢占 */ uThreadPreempt(HiRP); error = THREAD_ERR_NONE; state = eSuccess; } else { error = THREAD_ERR_STATUS; } } else { error = THREAD_ERR_ACAPI; } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:撤销中断请求 * * 参数:(1) pIRQ 中断请求结构地址 * * 返回: (1) eFailure 操作失败 * * (2) eSuccess 操作成功 * * 说明: * *************************************************************************************************/ TState xIrqCancelRequest(TIrq* pIRQ, TError* pError) { TState state = eFailure; TError error = IRQ_ERR_UNREADY; TReg32 imask; CpuEnterCritical(&imask); if (pIRQ->Property & IRQ_PROP_READY) { uObjListRemoveNode( pIRQ->ObjNode.Handle, &(pIRQ->ObjNode)); memset(pIRQ, 0, sizeof(TIrq)); error = IRQ_ERR_NONE; state = eSuccess; } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:消息队列广播函数,向所有读阻塞队列中的线程广播消息 * * 参数:(1) pMsgQue 消息队列结构地址 * * (2) pMsg2 保存消息结构地址的指针变量 * * (3) pError 详细调用结果 * * 返回:(1) eSuccess 成功广播发送消息 * * (2) eFailure 广播发送消息失败 * * 说明:只有队列有读消息队列的时候,才能把消息发送给队列中的线程 * *************************************************************************************************/ TState xMQBroadcast(TMsgQueue* pMsgQue, TMessage* pMsg2, TError* pError) { TState state = eFailure; TError error = IPC_ERR_UNREADY; TReg32 imask; TBool HiRP = eFalse; CpuEnterCritical(&imask); if (pMsgQue->Property & IPC_PROP_READY) { /* 判断消息队列是否可用,只有消息队列空并且有线程等待读取消息的时候才能进行广播 */ if (pMsgQue->Status == eMQEmpty) { /* 向消息队列的读阻塞队列中的线程广播数据 */ uIpcUnblockAll(&(pMsgQue->Queue), eSuccess, IPC_ERR_NONE, (void**)pMsg2, &HiRP); /* * 在线程环境下,如果当前线程的优先级已经不再是线程就绪队列的最高优先级, * 并且内核此时并没有关闭线程调度,那么就需要进行一次线程抢占 */ if ((uKernelVariable.State == eThreadState) && (uKernelVariable.Schedulable == eTrue) && (HiRP == eTrue)) { uThreadSchedule(); } error = IPC_ERR_NONE; state = eSuccess; } else { error = IPC_ERR_INVALID_STATUS; } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:线程运行监理函数,线程的运行都以它为基础 * * 参数:(1) pThread 线程地址 * * 返回:无 * * 说明:函数名的前缀'x'(eXtreme)表示本函数需要处理临界区代码 * *************************************************************************************************/ static void xSuperviseThread(TThread* pThread) { TReg32 imask; KNL_ASSERT((pThread == uKernelVariable.CurrentThread), ""); #if (TCLC_IRQ_ENABLE) if (pThread->Property &THREAD_PROP_ASR) { while (eTrue) { /* * 调用用户ASR线程主函数,这类函数的特点是唤醒执行后, * 会被系统自动挂起,等待下次唤醒。 */ pThread->Entry(pThread->Argument); /* * 当ASR之行结束后,准备挂起时,此时ISR可能会又一次进入尝试唤醒ASR, * 不巧此时ASR为运行状态。为了避免ASR丢失下轮的唤醒请求,在这里略纠结 * 的添加了检查 */ CpuEnterCritical(&imask); if (pThread->SyncValue == 0U) { uThreadSuspendSelf(); } else { pThread->SyncValue = 0U; } CpuLeaveCritical(imask); } } #endif /* 普通线程需要注意用户不小心退出导致非法指令等死机的问题 */ pThread->Entry(pThread->Argument); uKernelVariable.Diagnosis |= KERNEL_DIAG_THREAD_ERROR; pThread->Diagnosis |= THREAD_DIAG_INVALID_EXIT; uDebugPanic("", __FILE__, __FUNCTION__, __LINE__); }
/************************************************************************************************* * 功能:线程注销 * * 参数:(1) pThread 线程结构地址 * * (2) pError 详细调用结果 * * 返回:(1) eFailure * * (2) eSuccess * * 说明:IDLE线程、中断处理线程和定时器线程不能被注销 * *************************************************************************************************/ TState xThreadDelete(TThread* pThread, TError* pError) { TState state = eFailure; TError error = THREAD_ERR_FAULT; TReg32 imask; CpuEnterCritical(&imask); /* 只允许在非中断代码调用本函数 */ if (uKernelVariable.State != eIntrState) { /* 如果没有给出被操作的线程地址,则强制使用当前线程 */ if (pThread == (TThread*)0) { pThread = uKernelVariable.CurrentThread; } /* 检查线程是否已经被初始化 */ if (pThread->Property &THREAD_PROP_READY) { /* 检查线程是否接收相关API调用 */ if (pThread->ACAPI &THREAD_ACAPI_DEINIT) { state = uThreadDelete(pThread, &error); } else { error = THREAD_ERR_ACAPI; } } else { error = THREAD_ERR_UNREADY; } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能: 清除消息队列阻塞队列 * * 参数: (1) pMsgQue 消息队列结构地址 * * (2) pError 详细调用结果 * * 返回:(1) eSuccess 操作成功 * * (2) eFailure 操作失败 * * 说明: * *************************************************************************************************/ TState xMQReset(TMsgQueue* pMsgQue, TError* pError) { TState state = eFailure; TError error = IPC_ERR_UNREADY; TBool HiRP = eFalse; TReg32 imask; CpuEnterCritical(&imask); if (pMsgQue->Property & IPC_PROP_READY) { /* 将阻塞队列上的所有等待线程都释放,所有线程的等待结果都是TCLE_IPC_RESET */ uIpcUnblockAll(&(pMsgQue->Queue), eFailure, IPC_ERR_RESET, (void**)0, &HiRP); /* 重新设置消息队列结构 */ pMsgQue->Property &= IPC_RESET_MQUE_PROP; pMsgQue->MsgEntries = 0U; pMsgQue->Head = 0U; pMsgQue->Tail = 0U; pMsgQue->Status = eMQEmpty; /* * 在线程环境下,如果当前线程的优先级已经不再是线程就绪队列的最高优先级, * 并且内核此时并没有关闭线程调度,那么就需要进行一次线程抢占 */ if ((uKernelVariable.State == eThreadState) && (uKernelVariable.Schedulable == eTrue) && (HiRP == eTrue)) { uThreadSchedule(); } error = IPC_ERR_NONE; state = eSuccess; } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:线程解挂函数 * * 参数:(1) pThread 线程结构地址 * * (2) pError 详细调用结果 * * 返回:(1) eFailure * * (2) eSuccess * * 说明: * *************************************************************************************************/ TState xThreadResume(TThread* pThread, TError* pError) { TState state = eFailure; TError error = THREAD_ERR_FAULT; TBool HiRP = eFalse; TReg32 imask; CpuEnterCritical(&imask); /* 只允许在线程代码里调用本函数 */ if (uKernelVariable.State == eThreadState) { /* 检查线程是否已经被初始化 */ if (pThread->Property &THREAD_PROP_READY) { /* 检查线程是否接收相关API调用 */ if (pThread->ACAPI &THREAD_ACAPI_RESUME) { state = SetThreadReady(pThread, eThreadSuspended, &HiRP, &error); if ((uKernelVariable.Schedulable == eTrue) && (HiRP == eTrue)) { uThreadSchedule(); } } else { error = THREAD_ERR_ACAPI; } } else { error = THREAD_ERR_UNREADY; } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:消息队列重置函数 * * 输入:(1) pMsgQue 消息队列结构地址 * * (2) pError 详细调用结果 * * 返回:(1) eSuccess 操作成功 * * (2) eFailure 操作失败 * * 说明: * *************************************************************************************************/ TState xMQDelete(TMsgQueue* pMsgQue, TError* pError) { TState state = eFailure; TError error = IPC_ERR_UNREADY; TBool HiRP = eFalse; TReg32 imask; CpuEnterCritical(&imask); if (pMsgQue->Property & IPC_PROP_READY) { /* 向阻塞队列中的线程分发消息 */ uIpcUnblockAll(&(pMsgQue->Queue), eFailure, IPC_ERR_DELETE, (void**)0, &HiRP); /* 清除消息队列对象的全部数据 */ memset(pMsgQue, 0U, sizeof(TMsgQueue)); /* * 在线程环境下,如果当前线程的优先级已经不再是线程就绪队列的最高优先级, * 并且内核此时并没有关闭线程调度,那么就需要进行一次线程抢占 */ if ((uKernelVariable.State == eThreadState) && (uKernelVariable.Schedulable == eTrue) && (HiRP == eTrue)) { uThreadSchedule(); } error = IPC_ERR_NONE; state = eSuccess; } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能: 用于线程/ISR向消息队列中发送消息 * * 参数: (1) pMsgQue 消息队列结构地址 * * (2) pMsg2 保存消息结构地址的指针变量 * * (3) option 访问消息队列的模式 * * (4) timeo 时限阻塞模式下访问邮箱的时限长度 * * (5) pError 详细调用结果 * * 返回: (1) eFailure 操作失败 * * (2) eSuccess 操作成功 * * 说明: * *************************************************************************************************/ TState xMQSend(TMsgQueue* pMsgQue, TMessage* pMsg2, TOption option, TTimeTick timeo, TError* pError) { TState state = eFailure; TError error = IPC_ERR_UNREADY; TBool HiRP = eFalse; TIpcContext* pContext; TMsgType type; TReg32 imask; CpuEnterCritical(&imask); if (pMsgQue->Property & IPC_PROP_READY) { /* * 如果是中断程序调用本函数则只能以非阻塞方式发送消息, * 并且暂时不考虑线程调度问题。 * 在中断中,当前线程未必是最高就绪优先级线程,也未必处于内核就绪线程队列, * 所以在此处得到的HiRP标记无任何意义。 */ type = (option & IPC_OPT_UARGENT) ? eUrgentMessage : eNormalMessage; state = SendMessage(pMsgQue, (void**)pMsg2, type, &HiRP, &error); /* 如果没有声明不需要调度则进入线程调度处理流程 */ if (option & IPC_OPT_NO_SCHED) { if ((uKernelVariable.State == eThreadState) && (uKernelVariable.Schedulable == eTrue)) { /* 如果当前线程解除了更高优先级线程的阻塞则进行调度。*/ if (state == eSuccess) { if (HiRP == eTrue) { uThreadSchedule(); } } else { /* * 如果当前线程不能发送消息,并且采用的是等待方式, * 那么当前线程必须阻塞在消息队列中 */ if (option & IPC_OPT_WAIT) { if (option & IPC_OPT_UARGENT) { option |= IPC_OPT_USE_AUXIQ; } /* 得到当前线程的IPC上下文结构地址 */ pContext = &(uKernelVariable.CurrentThread->IpcContext); /* 保存线程挂起信息 */ option |= IPC_OPT_MSGQUEUE | IPC_OPT_WRITE_DATA; uIpcSaveContext(pContext, (void*)pMsgQue, (TBase32)pMsg2, sizeof(TBase32), option, &state, &error); /* 当前线程阻塞在该消息队列的阻塞队列,时限或者无限等待,由IPC_OPT_TIMED参数决定 */ uIpcBlockThread(pContext, &(pMsgQue->Queue), timeo); /* 当前线程被阻塞,其它线程得以执行 */ uThreadSchedule(); CpuLeaveCritical(imask); /* * 因为当前线程已经阻塞在IPC对象的线程阻塞队列,所以处理器需要执行别的线程。 * 当处理器再次处理本线程时,从本处继续运行。 */ CpuEnterCritical(&imask); /* 清除线程挂起信息 */ uIpcCleanContext(pContext); } } } } } CpuLeaveCritical(imask); *pError = error; return state; }
/************************************************************************************************* * 功能:设置中断向量函数 * * 参数:(1) irqn 中断号 * * (2) pISR ISR处理函数 * * (3) pASR 中断处理线程 * * (4) data 应用提供的回调数据 * * (5) pError 详细调用结果 * * 返回: (1) eFailure 操作失败 * * (2) eSuccess 操作成功 * * 说明: * *************************************************************************************************/ TState xIrqSetVector(TIndex irqn, TISR pISR, TThread* pASR, TArgument data, TError* pError) { TState state = eFailure; TError error = IRQ_ERR_FAULT; TReg32 imask; TIndex index; TIrqVector* pVector; CpuEnterCritical(&imask); /* 如果指定的中断号已经注册过中断向量,那么直接更新 */ if (IrqMapTable[irqn] != (TAddr32)0) { pVector = (TIrqVector*)(IrqMapTable[irqn]); /* 更新之前确保没有被锁定 */ if ((pVector->Property & IRQ_VECTOR_PROP_LOCKED)) { error = IRQ_ERR_LOCKED; } else { error = IRQ_ERR_NONE; state = eSuccess; } } else { /* 为该中断号申请中断向量项 */ for (index = 0; index < TCLC_IRQ_VECTOR_NUM; index++) { pVector = (TIrqVector*)IrqVectorTable + index; if (!(pVector->Property & IRQ_VECTOR_PROP_READY)) { /* 建立中断号和对应的中断向量的联系 */ IrqMapTable[irqn] = (TAddr32)pVector; pVector->IRQn = irqn; pVector->Property = IRQ_VECTOR_PROP_READY; error = IRQ_ERR_NONE; state = eSuccess; break; } } } /* 设置中断向量对应的中断服务程序,中断服务线程(如果没有则默认为IrqDaemon线程) */ if (state == eSuccess) { #if (TCLC_IRQ_DAEMON_ENABLE) if (pASR == (TThread*)0) { pASR = uKernelVariable.IrqDaemon; } #endif pVector->ISR = pISR; pVector->ASR = pASR; pVector->Argument = data; } CpuLeaveCritical(imask); *pError = error; return state; }