Ejemplo n.º 1
0
/*************************************************************************************************
 *  功能:选择唤醒阻塞队列中的全部线程                                                           *
 *  参数:(1) pQueue  线程队列结构地址                                                           *
 *        (2) state   线程资源访问返回结果                                                       *
 *        (3) error   详细调用结果                                                               *
 *        (4) pData   线程访问IPC得到的数据                                                      *
 *        (5) pHiRP  线程是否需要调度的标记                                                      *
 *  返回:                                                                                       *
 *  说明:只有邮箱和消息队列广播时才会传递pData2参数                                             *
 *************************************************************************************************/
void uIpcUnblockAll(TIpcQueue* pQueue, TState state, TError error, void** pData2, TBool* pHiRP)
{
    TIpcContext* pContext;

    /* 辅助队列中的线程首先被解除阻塞 */
    while (pQueue->AuxiliaryHandle != (TObjNode*)0)
    {
        pContext = (TIpcContext*)(pQueue->AuxiliaryHandle->Owner);
        uIpcUnblockThread(pContext, state, error, pHiRP);

        if ((pData2 != (void**)0) && (pContext->Data.Addr2 != (void**)0))
        {
            *(pContext->Data.Addr2) = *pData2;
        }
    }

    /* 基本队列中的线程随后被解除阻塞 */
    while (pQueue->PrimaryHandle != (TObjNode*)0)
    {
        pContext = (TIpcContext*)(pQueue->PrimaryHandle->Owner);
        uIpcUnblockThread(pContext, state, error, pHiRP);

        if ((pData2 != (void**)0) && (pContext->Data.Addr2 != (void**)0))
        {
            *(pContext->Data.Addr2) = *pData2;
        }
    }
}
Ejemplo n.º 2
0
/*************************************************************************************************
 *  功能:线程/ISR尝试向消息队列中发送消息                                                       *
 *  参数:(1) pMsgQue 消息队列的地址                                                             *
 *        (2) pMsg2   保存消息结构地址的指针变量                                                 *
 *        (3) type    消息类型                                                                   *
 *        (4) pHiRP   是否需要线程调度标记                                                       *
 *        (5) pError  详细调用结果                                                               *
 *  返回: (1) eFailure   操作失败                                                                *
 *        (2) eSuccess   操作成功                                                                *
 *  说明:                                                                                       *
 *************************************************************************************************/
static TState SendMessage(TMsgQueue* pMsgQue, void** pMsg2, TMsgType type, TBool* pHiRP,
                          TError* pError)
{
    TState state = eSuccess;
    TError error = IPC_ERR_NONE;
    TIpcContext* pContext = (TIpcContext*)0;

    /* 检查消息队列状态,如果消息队列满则返回失败 */
    if (pMsgQue->Status == eMQFull)
    {
        error = IPC_ERR_INVALID_STATUS;
        state = eFailure;
    }
    else if (pMsgQue->Status == eMQEmpty)
    {
        /* 尝试唤醒写阻塞队列中的一个线程 */
        if (pMsgQue->Property & IPC_PROP_PRIMQ_AVAIL)
        {
            pContext = (TIpcContext*)(pMsgQue->Queue.PrimaryHandle->Owner);
        }

        /* 在消息队列为空的情况下,如果队列中有线程等待,则说明是读阻塞队列,
        保持消息队列状态不变 */
        if (pContext != (TIpcContext*)0)
        {
            uIpcUnblockThread(pContext, eSuccess, IPC_ERR_NONE, pHiRP);

            /* 将消息发送给该线程 */
            *(pContext->Data.Addr2) = *pMsg2;
        }
        else
        {
            /* 将线程发送的消息写入消息队列 */
            SaveMessage(pMsgQue, pMsg2, type);
            pMsgQue->Status = (pMsgQue->Tail == pMsgQue->Head) ? eMQFull : eMQPartial;
        }
    }
    else
        /* if (mq->Status == eMQPartial) */
    {
        /* 将线程发送的消息写入消息队列 */
        SaveMessage(pMsgQue, pMsg2, type);

        /* 消息队列空的情况,如果是消息队列的容量是1,那么它的状态从空直接到 eMQFull,
           否则消息队列进入 eMQPartial 状态 */
        /* 消息队列普通的情况,消息对列写操作可能导致消息队列进入 eMQFull
           状态或者保持 eMQPartial 状态 */
        pMsgQue->Status = (pMsgQue->Tail == pMsgQue->Head) ? eMQFull : eMQPartial;
    }

	  *pError = error;
    return state;
}
Ejemplo n.º 3
0
/*************************************************************************************************
 *  功能:线程解挂函数                                                                           *
 *  参数:(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;
}
Ejemplo n.º 4
0
/*************************************************************************************************
 *  功能:线程解挂函数                                                                           *
 *  参数:(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;
}
Ejemplo n.º 5
0
/* 处理消息队列读数据的情况
   (1) 处理消息队列为满的情况:如果是容量是1的消息队列,读取操作会导致消息队列状态从满直接到空,
       否则消息队列进入 eMQPartial 状态
   (2) 处理消息队列普通的情况:如果消息队列中只有1个消息,对列读取操作可能导致消息队列进入空状态
       否则消息队列保持 eMQPartial 状态
   (3) 无论是消息队列满还是消息队列普通状态:最终状态只有普通和空。
 */
static TState ReceiveMessage(TMsgQueue* pMsgQue, void** pMsg2, TBool* pHiRP, TError* pError)
{
    TState state = eSuccess;
    TError error = IPC_ERR_NONE;
    TMsgType type;
    TIpcContext* pContext = (TIpcContext*)0;

    /* 检查消息队列状态 */
    if (pMsgQue->Status == eMQEmpty)
    {
        error = IPC_ERR_INVALID_STATUS;
        state = eFailure;
    }
    else if (pMsgQue->Status == eMQFull)
    {
        /* 从消息队列中读取一个消息给当前线程 */
        ConsumeMessage(pMsgQue, pMsg2);

        /* 
			   * 在消息队列满并且有线程阻塞在写队列中的情况下,
         * 需要将合适的线程接触阻塞并且将该线程携带的消息写入队列,
         * 所以保持消息队列状态不变 
			   */
        if (pMsgQue->Property & IPC_PROP_AUXIQ_AVAIL)
        {
            pContext = (TIpcContext*)(pMsgQue->Queue.AuxiliaryHandle->Owner);
        }
        else
        {
            if (pMsgQue->Property & IPC_PROP_PRIMQ_AVAIL)
            {
                pContext = (TIpcContext*)(pMsgQue->Queue.PrimaryHandle->Owner);
            }
        }

        if (pContext !=  (TIpcContext*)0)
        {
            uIpcUnblockThread(pContext, eSuccess, IPC_ERR_NONE, pHiRP);

            /* 根据线程所处的分队列判断消息类型 */
            type = ((pContext->Option) & IPC_OPT_UARGENT) ? eUrgentMessage : eNormalMessage;

            /* 并且将该线程发送的消息写入消息队列 */
            SaveMessage(pMsgQue, pContext->Data.Addr2, type);
        }
        else
        {
            pMsgQue->Status = (pMsgQue->Tail == pMsgQue->Head) ? eMQEmpty : eMQPartial;
        }
    }
    else
        /* if (mq->Status == eMQPartial) */
    {
        /* 从消息队列中读取一个消息给当前线程 */
        ConsumeMessage(pMsgQue, pMsg2);
        pMsgQue->Status = (pMsgQue->Tail == pMsgQue->Head) ? eMQEmpty : eMQPartial;
    }

	*pError = error;
    return state;
}
Ejemplo n.º 6
0
/*************************************************************************************************
 *  功能:内核定时器执行处理函数                                                                 *
 *  参数:(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__);
    }
}