/************************************************************************************************* * 功能:将线程从挂起状态转换到就绪态,使得线程能够参与内核调度 * * 参数:(1) pThread 线程结构地址 * * 返回:(1) eFailure * * (2) eSuccess * * 说明:函数名的前缀'u'(communal)表示本函数是全局函数 * *************************************************************************************************/ void uThreadResumeFromISR(TThread* pThread) { /* * 操作线程,完成线程队列和状态转换,注意只有中断处理时, * 当前线程才会处在内核线程辅助队列里(因为还没来得及线程切换) * 当前线程返回就绪队列时,一定要回到相应的队列头 * 当线程进出就绪队列时,不需要处理线程的时钟节拍数 */ if (pThread->Status == eThreadSuspended) { uThreadLeaveQueue(&ThreadAuxiliaryQueue, pThread); if (pThread == uKernelVariable.CurrentThread) { uThreadEnterQueue(&ThreadReadyQueue, pThread, eQuePosHead); pThread->Status = eThreadRunning; } else { uThreadEnterQueue(&ThreadReadyQueue, pThread, eQuePosTail); pThread->Status = eThreadReady; } } #if (TCLC_IRQ_ENABLE) else { if (pThread->Property &THREAD_PROP_ASR) { pThread->SyncValue = 1U; } } #endif }
/************************************************************************************************* * 功能:线程挂起函数 * * 参数:(1) pThread 线程结构地址 * * (2) status 线程当前状态,用于检查 * * (3) ticks 线程延时时间 * * (4) pError 保存操作结果 * * 返回:(1) eFailure * * (2) eSuccess * * 说明: * *************************************************************************************************/ TState uThreadSetUnready(TThread* pThread, TThreadStatus status, TTimeTick ticks, TError* pError) { TState state = eFailure; TError error = THREAD_ERR_STATUS; /* ISR不会调用本函数 */ KNL_ASSERT((uKernelVariable.State != eIntrState), ""); /* 如果操作的是当前线程,则需要首先检查内核是否允许调度 */ if (pThread->Status == eThreadRunning) { /* 如果内核此时禁止线程调度,那么当前线程不能被操作 */ if (uKernelVariable.Schedulable == eTrue) { uThreadLeaveQueue(&ThreadReadyQueue, pThread); uThreadEnterQueue(&ThreadAuxiliaryQueue, pThread, eQuePosTail); pThread->Status = status; /* 线程环境马上开始线程调度 */ uThreadSchedule(); error = THREAD_ERR_NONE; state = eSuccess; } else { error = THREAD_ERR_FAULT; } } else if (pThread->Status == eThreadReady) { /* 如果被操作的线程不是当前线程,则不会引起线程调度,所以直接处理线程和队列 */ uThreadLeaveQueue(&ThreadReadyQueue, pThread); uThreadEnterQueue(&ThreadAuxiliaryQueue, pThread, eQuePosTail); pThread->Status = status; error = THREAD_ERR_NONE; state = eSuccess; } else { error = error; } #if (TCLC_TIMER_ENABLE) if ((state == eSuccess) && (status == eThreadDelayed)) { /* 重置并启动线程定时器 */ uTimerConfig(&(pThread->Timer), eThreadTimer, ticks); uTimerStart(&(pThread->Timer), 0U); } #endif *pError = error; return state; }
/************************************************************************************************* * 功能:将线程放入资源阻塞队列 * * 参数:(1) pQueue 线程队列结构地址 * * (2) pThread 线程结构地址 * * (3) ticks 资源等待时限 * * 返回:无 * * 说明:对于线程进出相关队列的策略根据队列策略特性来进行 * *************************************************************************************************/ void uIpcBlockThread(TIpcContext* pContext, TIpcQueue* pQueue, TTimeTick ticks) { TThread* pThread; KNL_ASSERT((uKernelVariable.State != eIntrState), ""); /* 将线程放入内核线程辅助队列 */ pThread = (TThread*)(pContext->Owner); /* 只有处于就绪状态的线程才可以被阻塞 */ if (pThread->Status != eThreadRunning) { uDebugPanic("", __FILE__, __FUNCTION__, __LINE__); } uThreadLeaveQueue(uKernelVariable.ThreadReadyQueue, pThread); uThreadEnterQueue(uKernelVariable.ThreadAuxiliaryQueue, pThread, eQuePosTail); pThread->Status = eThreadBlocked; /* 将线程放入阻塞队列 */ EnterBlockedQueue(pQueue, pContext); /* 如果需要就初始化并且打开线程用于访问资源的时限定时器 */ #if (TCLC_TIMER_ENABLE && TCLC_IPC_TIMER_ENABLE) if ((pContext->Option & IPC_OPT_TIMED) && (ticks > 0U)) { /* 重新配置并启动线程定时器 */ uTimerConfig(&(pThread->Timer), eIpcTimer, ticks); uTimerStart(&(pThread->Timer), 0U); } #else ticks = ticks; #endif }
/************************************************************************************************* * 功能:将线程从指定的状态转换到就绪态,使得线程能够参与内核调度 * * 参数:(1) pThread 线程结构地址 * * (2) status 线程当前状态,用于检查 * * (3) pError 保存操作结果 * * 返回:(1) eFailure * * (2) eSuccess * * 说明:函数名的前缀'u'(communal)表示本函数是全局函数 * *************************************************************************************************/ static TState SetThreadReady(TThread* pThread, TThreadStatus status, TBool* pHiRP, TError* pError) { TState state = eFailure; TError error = THREAD_ERR_STATUS; /* 线程状态校验,只有状态符合的线程才能被操作 */ if (pThread->Status == status) { /* * 操作线程,完成线程队列和状态转换,注意只有中断处理时, * 当前线程才会处在内核线程辅助队列里(因为还没来得及线程切换) * 当前线程返回就绪队列时,一定要回到相应的队列头 * 当线程进出就绪队列时,不需要处理线程的时钟节拍数 */ uThreadLeaveQueue(&ThreadAuxiliaryQueue, pThread); if (pThread == uKernelVariable.CurrentThread) { uThreadEnterQueue(&ThreadReadyQueue, pThread, eQuePosHead); pThread->Status = eThreadRunning; } else { uThreadEnterQueue(&ThreadReadyQueue, pThread, eQuePosTail); pThread->Status = eThreadReady; } state = eSuccess; error = THREAD_ERR_NONE; /* 因为是在线程环境下,所以此时pThread一定不是当前线程 */ if (pThread->Priority < uKernelVariable.CurrentThread->Priority) { *pHiRP = eTrue; } #if (TCLC_TIMER_ENABLE) /* 如果是取消定时操作则需要停止线程定时器 */ if ((state == eSuccess) && (status == eThreadDelayed)) { uTimerStop(&(pThread->Timer)); } #endif } *pError = error; return state; }
/* 中断或者线程都有可能调用本函数 */ TState uThreadSetReady(TThread* pThread, TThreadStatus status, TError* pError) { TState state = eFailure; TError error = THREAD_ERR_STATUS; TBool HiRP = eFalse; /* 线程状态校验,只有状态符合的线程才能被操作 */ if (pThread->Status == status) { /* 操作线程,完成线程队列和状态转换,注意只有中断处理时, 当前线程才会处在内核线程辅助队列里(因为还没来得及线程切换) */ uThreadLeaveQueue(&ThreadAuxiliaryQueue, pThread); uThreadEnterQueue(&ThreadReadyQueue, pThread, eQuePosTail); /* 当线程离开就绪队列时,已经放弃它的本轮执行,哪怕时间片并未耗尽。 当线程再次进入就绪队列时,需要恢复线程的时钟节拍数,重新计算其分享处理器时间的能力 */ pThread->Ticks = pThread->BaseTicks; pThread->Status = eThreadReady; state = eSuccess; error = THREAD_ERR_NONE; /* 如果是在线程环境下,那么此时pThread一定不是当前线程; 如果是在中断环境下,那么 第一,当前线程不一定在就绪队列里,不能作为任务调度的比较标准 第二,中断在最后一级返回时统一做线程调度检查,这里得到的HiPR无意义 */ if (pThread->Priority < uKernelVariable.CurrentThread->Priority) { HiRP = eTrue; } /* 尝试发起线程抢占 */ uThreadPreempt(HiRP); #if (TCLC_TIMER_ENABLE) /* 如果是取消定时操作则需要停止线程定时器 */ if ((state == eSuccess) && (status == eThreadDelayed)) { uTimerStop(&(pThread->Timer)); } #endif } *pError = error; return state; }
void uThreadSuspendSelf(void) { /* 操作目标是当前线程 */ TThread* pThread = uKernelVariable.CurrentThread; /* 将当前线程挂起,如果内核此时禁止线程调度,那么当前线程不能被操作 */ if (uKernelVariable.Schedulable == eTrue) { uThreadLeaveQueue(&ThreadReadyQueue, pThread); uThreadEnterQueue(&ThreadAuxiliaryQueue, pThread, eQuePosTail); pThread->Status = eThreadSuspended; uThreadSchedule(); } else { uKernelVariable.Diagnosis |= KERNEL_DIAG_SCHED_ERROR; pThread->Diagnosis |= THREAD_DIAG_NORMAL; uDebugPanic("", __FILE__, __FUNCTION__, __LINE__); } }
/************************************************************************************************* * 功能:唤醒IPC阻塞队列中指定的线程 * * 参数:(1) pThread 线程地址 * * (2) state 线程资源访问返回结果 * * (3) error 详细调用结果 * * (4) pHiRP 是否因唤醒更高优先级而导致需要进行线程调度的标记 * * 返回:无 * * 说明: * *************************************************************************************************/ void uIpcUnblockThread(TIpcContext* pContext, TState state, TError error, TBool* pHiRP) { TThread* pThread; TQueuePos pos = eQuePosTail; TThreadStatus newStatus = eThreadReady; /* * 将线程从IPC资源的阻塞队列中移出,加入到内核线程就绪队列, * 如果当前线程刚刚被阻塞到阻塞队列中,但还未发生线程切换, * 而在此时被ISR打断并且ISR又将当前线程唤醒,则当前线程也不必返回就绪队列头 */ pThread = (TThread*)(pContext->Owner); /* 只有处于阻塞状态的线程才可以被解除阻塞 */ if (pThread->Status != eThreadBlocked) { uDebugPanic("", __FILE__, __FUNCTION__, __LINE__); } /* * 操作线程,完成线程队列和状态转换,注意只有中断处理时, * 当前线程才会处在内核线程辅助队列里(因为还没来得及线程切换) * 当前线程返回就绪队列时,一定要回到相应的队列头 * 当线程进出就绪队列时,不需要处理线程的时钟节拍数 */ uThreadLeaveQueue(uKernelVariable.ThreadAuxiliaryQueue, pThread); if (pThread == uKernelVariable.CurrentThread) { pos = eQuePosHead; newStatus = eThreadRunning; } uThreadEnterQueue(uKernelVariable.ThreadReadyQueue, pThread, pos); pThread->Status = newStatus; /* 将线程从阻塞队列移出 */ LeaveBlockedQueue(pContext->Queue, pContext); /* 设置线程访问资源的结果和错误代码 */ *(pContext->State) = state; *(pContext->Error) = error; /* 如果线程是以时限方式访问资源则取消该线程的时限定时器 */ #if ((TCLC_IPC_TIMER_ENABLE) && (TCLC_TIMER_ENABLE)) if ((pContext->Option & IPC_OPT_TIMED) && (error != IPC_ERR_TIMEO)) { KNL_ASSERT((pThread->Timer.Type == eIpcTimer), ""); uTimerStop(&(pThread->Timer)); } #endif /* 设置线程调度请求标记,此标记只在线程环境下有效。 在ISR里,当前线程可能在任何队列里, 跟当前线程相比较优先级也是无意义的 */ /* * 在线程环境下,如果当前线程的优先级已经不再是线程就绪队列的最高优先级, * 并且内核此时并没有关闭线程调度,那么就需要进行一次线程抢占 */ if (pThread->Priority < uKernelVariable.CurrentThread->Priority) { *pHiRP = eTrue; } }
/************************************************************************************************* * 功能:内核定时器执行处理函数 * * 参数:(1) pTimer 定时器 * * 返回:无 * * 说明: (1)线程延时的时候,线程被放入内核线程延时队列中 * * (2)线程以时限方式访问资源的时候,如果得不到资源会被放入资源的线程阻塞队列 * * 这里虽然有线程队列操作但是不进行调度,是因为这个函数是在中断中调用的, * * 在最后一层中断返回后,会尝试进行一次线程切换,所以在这里做切换的话是白白浪费时间 * *************************************************************************************************/ static void DispatchTimer(TTimer* pTimer) { TThread* pThread; #if ((TCLC_IPC_ENABLE) && (TCLC_IPC_TIMER_ENABLE)) TBool HiRP = eFalse; #endif /* 如果定时器是线程延时类型的定时器 */ if (pTimer->Type == eThreadTimer) { /* 将定时器从活动队列中移出,将定时器放到休眠队列里 */ uObjListRemoveNode(pTimer->ObjNode.Handle, &(pTimer->ObjNode)); uObjListAddNode(&(TimerList.DormantHandle), &(pTimer->ObjNode), eQuePosHead); pTimer->Status = eTimerDormant; /* 如果定时器所在的线程处于延时状态则把线程放入内核线程活动队列 */ pThread = (TThread*)(pTimer->Owner); KNL_ASSERT((pThread->Status == eThreadDelayed), ""); uThreadLeaveQueue(uKernelVariable.ThreadAuxiliaryQueue, pThread); uThreadEnterQueue(uKernelVariable.ThreadReadyQueue, pThread, eQuePosTail); /* 当线程离开就绪队列时,已经放弃它的本轮执行,哪怕时间片并未耗尽。 当线程再次进入就绪队列时,需要恢复线程的时钟节拍数, 重新计算其分享处理器时间的能力 */ pThread->Ticks = pThread->BaseTicks; pThread->Status = eThreadReady; } /* 如果定时器是用户定时器类型 */ else if (pTimer->Type == eUserTimer) { #if (TCLC_TIMER_DAEMON_ENABLE) /* 紧急的定时器直接在ISR里处理回调事务; 否则将定时器放入内核定时器期满列表,最后由定时器守护线程处理 */ if (pTimer->Property & TIMER_PROP_URGENT) { pTimer->Routine(pTimer->Argument); ResetTimer(pTimer); } else { uObjListRemoveNode(pTimer->ObjNode.Handle, &(pTimer->ObjNode)); uObjListAddNode(&(TimerList.ExpiredHandle), &(pTimer->ObjNode), eQuePosTail); pTimer->Status = eTimerExpired; } #else /* 在ISR里直接处理定时器回调事务 */ pTimer->Routine(pTimer->Argument); ResetTimer(pTimer); #endif } #if ((TCLC_IPC_ENABLE) && (TCLC_IPC_TIMER_ENABLE)) /* 如果定时器是线程阻塞类型的定时器(时限方式访问资源)则将线程从阻塞队列中唤醒 */ else if (pTimer->Type == eIpcTimer) { /* 将定时器从活动队列中移出,将定时器放到休眠队列里 */ uObjListRemoveNode(pTimer->ObjNode.Handle, &(pTimer->ObjNode)); uObjListAddNode(&(TimerList.DormantHandle), &(pTimer->ObjNode), eQuePosHead); pTimer->Status = eTimerDormant; /* IPC代码确保不会再次停止timer */ pThread = (TThread*)(pTimer->Owner); KNL_ASSERT((pThread->Status == eThreadBlocked), ""); uIpcUnblockThread(&(pThread->IpcContext), eFailure, IPC_ERR_TIMEO, &HiRP); } #endif else { uDebugPanic("", __FILE__, __FUNCTION__, __LINE__); } }
/************************************************************************************************* * 功能:更改线程优先级 * * 参数:(1) pThread 线程结构地址 * * (2) priority 线程优先级 * * (3) flag 是否被SetPriority API调用 * * (4) pError 保存操作结果 * * 返回:(1) eFailure 更改线程优先级失败 * * (2) eSuccess 更改线程优先级成功 * * 说明:如果是临时修改优先级,则不修改线程结构的基本优先级 * *************************************************************************************************/ TState uThreadSetPriority(TThread* pThread, TPriority priority, TBool flag, TError* pError) { TState state = eFailure; TError error = THREAD_ERR_PRIORITY; TPriority temp; /* 本函数只会被线程调用 */ KNL_ASSERT((uKernelVariable.State == eThreadState), ""); if (pThread->Priority != priority) { if (pThread->Status == eThreadBlocked) { uIpcSetPriority(&(pThread->IpcContext), priority); state = eSuccess; error = THREAD_ERR_NONE; } /* 就绪线程调整优先级时,可以直接调整其在就绪线程队列中的分队列 对于处于就绪线程队列中的当前线程,如果修改它的优先级, 因为不会把它移出线程就绪队列,所以即使内核不允许调度也没问题 */ else if (pThread->Status == eThreadReady) { uThreadLeaveQueue(&ThreadReadyQueue, pThread); pThread->Priority = priority; uThreadEnterQueue(&ThreadReadyQueue, pThread, eQuePosTail); if ((flag == eTrue) && (uKernelVariable.Schedulable == eTrue)) { /* 得到当前就绪队列的最高就绪优先级,因为就绪线程(包括当前线程) 在线程就绪队列内的折腾会导致当前线程可能不是最高优先级。 */ if (priority < uKernelVariable.CurrentThread->Priority) { uThreadSchedule(); } } state = eSuccess; error = THREAD_ERR_NONE; } else if (pThread->Status == eThreadRunning) { /* 假设当前线程优先级最高且唯一,假如调低它的优先级之后仍然是最高, 但是在新的优先级里有多个就绪线程,那么最好把当前线程放在新的就绪队列 的头部,这样不会引起隐式的时间片轮转;当前线程先后被多次调整优先级时,只有 每次都把它放在队列头才能保证它最后一次调整优先级后还处在队列头。 */ uThreadLeaveQueue(&ThreadReadyQueue, pThread); pThread->Priority = priority; uThreadEnterQueue(&ThreadReadyQueue, pThread, eQuePosHead); if ((flag == eTrue) && (uKernelVariable.Schedulable == eTrue)) { /* 因为当前线程在线程就绪队列内的折腾会导致当前线程可能不是最高优先级, 所以需要重新计算当前就绪队列的最高就绪优先级。*/ uThreadCalcHiRP(&temp); if (temp < uKernelVariable.CurrentThread->Priority) { pThread->Status = eThreadReady; uThreadSchedule(); } } state = eSuccess; error = THREAD_ERR_NONE; } else { /*其它状态的线程都在辅助队列里,可以直接修改优先级*/ pThread->Priority = priority; state = eSuccess; error = THREAD_ERR_NONE; } /* 如果需要则修改线程固定优先级 */ if (flag == eTrue) { pThread->BasePriority = priority; } } *pError = error; return state; }
/************************************************************************************************* * 功能:线程结构初始化函数 * * 参数:(1) pThread 线程结构地址 * * (2) status 线程的初始状态 * * (3) property 线程属性 * * (4) acapi 对线程管理API的许可控制 * * (5) pEntry 线程函数地址 * * (6) TArgument线程函数参数 * * (7) pStack 线程栈地址 * * (8) bytes 线程栈大小,以字为单位 * * (9) priority 线程优先级 * * (10) ticks 线程时间片长度 * * 返回:(1) eFailure * * (2) eSuccess * * 说明:注意栈起始地址、栈大小和栈告警地址的字节对齐问题 * * 说明:函数名的前缀'u'(Universal)表示本函数为模块间通用函数 * *************************************************************************************************/ void uThreadCreate(TThread* pThread, TThreadStatus status, TProperty property, TBitMask acapi, TThreadEntry pEntry, TArgument argument, void* pStack, TBase32 bytes, TPriority priority, TTimeTick ticks) { TThreadQueue* pQueue; /* 设置线程栈相关数据和构造线程初始栈栈帧 */ KNL_ASSERT((bytes >= TCLC_CPU_MINIMAL_STACK), ""); /* 栈大小向下4byte对齐 */ bytes &= (~((TBase32)0x3)); pThread->StackBase = (TBase32)pStack + bytes; /* 清空线程栈空间 */ if (property &THREAD_PROP_CLEAN_STACK) { memset(pStack, 0U, bytes); } /* 构造(伪造)线程初始栈帧,这里将线程结构地址作为参数传给线程监管函数 */ CpuBuildThreadStack(&(pThread->StackTop), pStack, bytes, (void*)(&xSuperviseThread), (TArgument)pThread); /* 计算线程栈告警地址 */ #if (TCLC_THREAD_STACK_CHECK_ENABLE) pThread->StackAlarm = (TBase32)pStack + bytes - (bytes* TCLC_THREAD_STACK_ALARM_RATIO) / 100; pThread->StackBarrier = (TBase32)pStack; (*(TAddr32*)pStack) = TCLC_THREAD_STACK_BARRIER_VALUE; #endif /* 设置线程时间片相关参数 */ pThread->Ticks = ticks; pThread->BaseTicks = ticks; pThread->Jiffies = 0U; /* 设置线程优先级 */ pThread->Priority = priority; pThread->BasePriority = priority; /* 设置线程唯一ID数值 */ pThread->ThreadID = uKernelVariable.ObjID; uKernelVariable.ObjID++; /* 设置线程入口函数和线程参数 */ pThread->Entry = pEntry; pThread->Argument = argument; /* 设置线程所属队列信息 */ pThread->Queue = (TThreadQueue*)0; /* 设置线程定时器信息 */ #if (TCLC_TIMER_ENABLE) uTimerCreate(&(pThread->Timer), (TProperty)0, eThreadTimer, TCLM_MAX_VALUE64, (TTimerRoutine)0, (TArgument)0, (void*)pThread); #endif /* 清空线程IPC阻塞上下文 */ #if (TCLC_IPC_ENABLE) uIpcInitContext(&(pThread->IpcContext), (void*)pThread); #endif /* 清除线程占有的锁(MUTEX)队列 */ #if ((TCLC_IPC_ENABLE) && (TCLC_IPC_MUTEX_ENABLE)) pThread->LockList = (TObjNode*)0; #endif /* 初始线程运行诊断信息 */ pThread->Diagnosis = THREAD_DIAG_NORMAL; /* 设置线程能够支持的线程管理API */ pThread->ACAPI = acapi; /* 设置线程链表节点信息,线程此时不属于任何线程队列 */ pThread->ObjNode.Owner = (void*)pThread; pThread->ObjNode.Data = (TBase32*)(&(pThread->Priority)); pThread->ObjNode.Prev = (TObjNode*)0; pThread->ObjNode.Next = (TObjNode*)0; pThread->ObjNode.Handle = (TObjNode**)0; /* 将线程加入内核线程队列,设置线程状态 */ pQueue = (status == eThreadReady) ? (&ThreadReadyQueue): (&ThreadAuxiliaryQueue); uThreadEnterQueue(pQueue, pThread, eQuePosTail); pThread->Status = status; /* 标记线程已经完成初始化 */ property |= THREAD_PROP_READY; pThread->Property = property; }
/************************************************************************************************* * 功能:更改线程优先级 * * 参数:(1) pThread 线程结构地址 * * (2) priority 线程优先级 * * (3) flag 是否被SetPriority API调用 * * (4) pError 保存操作结果 * * 返回:(1) eFailure 更改线程优先级失败 * * (2) eSuccess 更改线程优先级成功 * * 说明:如果是临时修改优先级,则不修改线程结构的基本优先级 * *************************************************************************************************/ TState uThreadSetPriority(TThread* pThread, TPriority priority, TBool flag, TBool* pHiRP, TError* pError) { TState state = eFailure; TError error = THREAD_ERR_PRIORITY; TPriority newPrio; if (pThread->Priority != priority) { if (pThread->Status == eThreadBlocked) { uIpcSetPriority(&(pThread->IpcContext), priority); state = eSuccess; error = THREAD_ERR_NONE; } /* * 就绪线程调整优先级时,可以直接调整其在就绪线程队列中的分队列 * 对于处于就绪线程队列中的当前线程,如果修改它的优先级, * 因为不会把它移出线程就绪队列,所以即使内核不允许调度也没问题 */ else if (pThread->Status == eThreadReady) { uThreadLeaveQueue(&ThreadReadyQueue, pThread); pThread->Priority = priority; uThreadEnterQueue(&ThreadReadyQueue, pThread, eQuePosTail); /* * 得到当前就绪队列的最高就绪优先级,因为就绪线程(包括当前线程) * 在线程就绪队列内的折腾会导致当前线程可能不是最高优先级。 */ if (priority < uKernelVariable.CurrentThread->Priority) { *pHiRP = eTrue; } state = eSuccess; error = THREAD_ERR_NONE; } else if (pThread->Status == eThreadRunning) { /* * 假设当前线程优先级最高且唯一,假如调低它的优先级之后仍然是最高, * 但是在新的优先级里有多个就绪线程,那么最好把当前线程放在新的就绪队列 * 的头部,这样不会引起隐式的时间片轮转;当前线程先后被多次调整优先级时,只有 * 每次都把它放在队列头才能保证它最后一次调整优先级后还处在队列头。 */ uThreadLeaveQueue(&ThreadReadyQueue, pThread); pThread->Priority = priority; uThreadEnterQueue(&ThreadReadyQueue, pThread, eQuePosHead); /* * 因为当前线程在线程就绪队列内的折腾会导致当前线程可能不是最高优先级, * 所以需要重新计算当前就绪队列的最高就绪优先级。 */ CalcThreadHiRP(&newPrio); if (newPrio < uKernelVariable.CurrentThread->Priority) { *pHiRP = eTrue; } state = eSuccess; error = THREAD_ERR_NONE; } else { /*其它状态的线程都在辅助队列里,可以直接修改优先级*/ pThread->Priority = priority; state = eSuccess; error = THREAD_ERR_NONE; } /* 如果需要则修改线程固定优先级 */ if (flag == eTrue) { pThread->BasePriority = priority; } } *pError = error; return state; }