/************************************************************************************************* * 功能:停止用户定时器函数 * * 参数:(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) 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; }
/************************************************************************************************* * 功能:唤醒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; } }