/************************************************************************************************* * 功能:消息队列阻塞终止函数,将指定的线程从消息队列的阻塞队列中终止阻塞并唤醒 * * 参数:(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) 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) 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) HiRP 是否已经得到比当前线程优先级高的线程 * * 返回:无 * * 说明: * *************************************************************************************************/ void uThreadPreempt(TBool HiRP) { /* 在线程环境下,如果当前线程的优先级已经不再是线程就绪队列的最高优先级, 并且内核此时并没有关闭线程调度,那么就需要进行一次线程抢占 */ if ((uKernelVariable.State == eThreadState) && (uKernelVariable.Schedulable == eTrue) && (HiRP == eTrue)) { uThreadSchedule(); } }
/************************************************************************************************* * 功能:线程级线程调度函数,当前线程主动让出处理器(保持就绪状态) * * 参数:(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; }
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__); } }
/************************************************************************************************* * 功能:消息队列广播函数,向所有读阻塞队列中的线程广播消息 * * 参数:(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) 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) 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; }