/************************************************************************************************* * 功能:更改线程优先级 * * 参数:(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) 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; }