コード例 #1
0
ファイル: tcl.thread.c プロジェクト: gmphoenix/trochili
/*************************************************************************************************
 *  功能:线程运行监理函数,线程的运行都以它为基础                                               *
 *  参数:(1) pThread  线程地址                                                                  *
 *  返回:无                                                                                     *
 *  说明:这里处理线程的非法退出问题                                                             *
 *  说明:函数名的前缀'x'(eXtreme)表示本函数需要处理临界区代码                                   *
 *************************************************************************************************/
static void xSuperviseThread(TThread* pThread)
{
    TState state;
    TError error;
    TReg32 imask;

    /* 调用用户ASR线程主函数,这类函数的特点是解挂后一次性执行,然后立刻挂起,等待下次调用。
    虽然Irq和Timer守护线程也是中断服务线程,但不是做为ASR在此处理。
    这两个函数自己处理挂起问题 */
    if ((pThread->Property &THREAD_PROP_RUNASR))
    {
        while (eTrue)
        {
            /* 执行线程函数 */
            pThread->Entry(pThread->Argument);

            /* 线程运行结束后直接挂起,等待再次被执行 */
            CpuEnterCritical(&imask);
            state = uThreadSetUnready(pThread, eThreadSuspended, 0U, &error);
            if (state == eFailure)
            {
                uKernelVariable.Diagnosis |= KERNEL_DIAG_THREAD_ERROR;
                pThread->Diagnosis |= THREAD_DIAG_INVALID_STATE;
                uDebugPanic("", __FILE__, __FUNCTION__, __LINE__);
            }
            CpuLeaveCritical(imask);
        }
    }
    /* 处理RUN TO COMPLETION 线程退出问题, 防止退出后处理器执行到非法(未知)指令 */
    else if (pThread->Property &THREAD_PROP_RUN2COMPLETION)
    {
        /* 执行线程函数 */
        pThread->Entry(pThread->Argument);

        /* 线程运行结束后直接挂起,等待后继处理 */
        CpuEnterCritical(&imask);
        state = uThreadSetUnready(pThread, eThreadDormant, 0U, &error);
        if (state == eFailure)
        {
            uKernelVariable.Diagnosis |= KERNEL_DIAG_THREAD_ERROR;
            pThread->Diagnosis |= THREAD_DIAG_INVALID_STATE;
            uDebugPanic("", __FILE__, __FUNCTION__, __LINE__);
        }
        CpuLeaveCritical(imask);
    }
    else
    {
        /* 执行用户线程函数 */
        pThread->Entry(pThread->Argument);

        /* 防止RUNFOREVER线程不小心退出导致非法指令等死机的问题 */
        uKernelVariable.Diagnosis |= KERNEL_DIAG_THREAD_ERROR;
        pThread->Diagnosis |= THREAD_DIAG_INVALID_EXIT;
        uDebugPanic("", __FILE__, __FUNCTION__, __LINE__);
    }
}
コード例 #2
0
ファイル: tcl.irq.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:内核中的IRQ守护线程函数                                                                *
 *  参数:(1) argument IRQ守护线程的用户参数                                                     *
 *  返回:无                                                                                     *
 *  说明:                                                                                       *
 *************************************************************************************************/
static void xIrqDaemonEntry(TArgument argument)
{
    TReg32    imask;
    TIrq*     pIRQ;
    TIrqEntry pEntry;
    TArgument data;

    /*
     * 从队列中逐个获得IRQ请求兵在线程环境下处理该IRQ回调事务
     * 如果IRQ请求队列为空则将IRQ守护线程挂起
     */
    while(eTrue)
    {
        CpuEnterCritical(&imask);

        if (IrqReqList.Handle == (TObjNode*)0)
        {
            uThreadSuspendSelf();
            CpuLeaveCritical(imask);
        }
        else
        {
            pIRQ   = (TIrq*)(IrqReqList.Handle->Owner);
            pEntry = pIRQ->Entry;
            data   = pIRQ->Argument;
            uObjListRemoveNode(pIRQ->ObjNode.Handle, &(pIRQ->ObjNode));
            memset(pIRQ, 0, sizeof(TIrq));
            CpuLeaveCritical(imask);

            pEntry(data);
        }
    }
}
コード例 #3
0
ファイル: tcl.timer.c プロジェクト: gmphoenix/trochili
/*************************************************************************************************
 *  功能:用户定时器初始化函数                                                                   *
 *  参数:(1) pTimer   定时器地址                                                                *
 *        (2) property 定时器属性                                                                *
 *        (3) ticks    定时器滴答数目                                                            *
 *        (4) pRoutine 用户定时器回调函数                                                        *
 *        (5) data     用户定时器回调函数参数                                                    *
 *        (6) pError   详细调用结果                                                              *
 *  返回: (1) eSuccess 操作成功                                                                  *
 *        (2) eFailure 操作失败                                                                  *
 *  说明                                                                                         *
 *************************************************************************************************/
TState xTimerCreate(TTimer* pTimer, TProperty property, TTimeTick ticks,
                    TTimerRoutine pRoutine, TArgument data, TError* pError)
{
    TState state = eFailure;
    TError error = TIMER_ERR_FAULT;
    TReg32 imask;

    CpuEnterCritical(&imask);

    /* 检查定时器就绪属性 */
    if (!(pTimer->Property & TIMER_PROP_READY))
    {
        if (ticks > 0U)
        {
            uTimerCreate(pTimer, property, eUserTimer, ticks, pRoutine, data, (void*)0);
            error = TIMER_ERR_NONE;
            state = eSuccess;
        }
    }

    CpuLeaveCritical(imask);

    *pError = error;
    return state;
}
コード例 #4
0
ファイル: tcl.irq.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:提交中断请求                                                                           *
 *  参数:(1) pIRQ      中断请求结构地址                                                         *
 *        (2) priority  中断请求优先级                                                           *
 *        (3) pEntry    中断处理回调函数                                                         *
 *        (4) data      中断处理回调参数                                                         *
 *  返回: (1) eFailure  操作失败                                                                 *
 *        (2) eSuccess  操作成功                                                                 *
 *  说明:                                                                                       *
 *************************************************************************************************/
TState xIrqPostRequest(TIrq* pIRQ, TPriority priority, TIrqEntry pEntry, TArgument data,
                       TError* pError)
{
    TState state = eFailure;
    TError error = IRQ_ERR_FAULT;
    TReg32 imask;

    CpuEnterCritical(&imask);

    if (!(pIRQ->Property & IRQ_PROP_READY))
    {
        pIRQ->Property       = IRQ_PROP_READY;
        pIRQ->Entry          = pEntry;
        pIRQ->Argument       = data;
        pIRQ->Priority       = priority;
        pIRQ->ObjNode.Next   = (TObjNode*)0;
        pIRQ->ObjNode.Prev   = (TObjNode*)0;
        pIRQ->ObjNode.Handle = (TObjNode**)0;
        pIRQ->ObjNode.Data   = (TBase32*)(&(pIRQ->Priority));
        pIRQ->ObjNode.Owner  = (void*)pIRQ;
        uObjListAddPriorityNode(&(IrqReqList.Handle), &(pIRQ->ObjNode));

        error = IRQ_ERR_NONE;
        state = eSuccess;
    }

    CpuLeaveCritical(imask);

    *pError = error;
    return state;
}
コード例 #5
0
ファイル: tcl.irq.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:清空中断向量函数                                                                       *
 *  参数:(1) irqn 中断编号                                                                      *
 *  返回:无                                                                                     *
 *  说明:                                                                                       *
 *************************************************************************************************/
TState xIrqCleanVector(TIndex irqn, TError* pError)
{
    TState state = eFailure;
    TError error = IRQ_ERR_FAULT;
    TReg32 imask;
    TIrqVector* pVector;

    CpuEnterCritical(&imask);

    /* 找到该中断向量并且清空相关信息 */
    if (IrqMapTable[irqn] != (TAddr32)0)
    {
        pVector = (TIrqVector*)(IrqMapTable[irqn]);
        if ((pVector->Property & IRQ_VECTOR_PROP_READY) &&
                (pVector->IRQn == irqn))
        {
            if (!(pVector->Property & IRQ_VECTOR_PROP_LOCKED))
            {
                IrqMapTable[irqn] = (TAddr32)0;
                memset(pVector, 0, sizeof(TIrqVector));
                error = IRQ_ERR_NONE;
                state = eSuccess;
            }
            else
            {
                error = IRQ_ERR_LOCKED;
            }
        }
    }

    CpuLeaveCritical(imask);

    *pError = error;
    return state;
}
コード例 #6
0
ファイル: tcl.timer.c プロジェクト: gmphoenix/trochili
/*************************************************************************************************
 *  功能:停止用户定时器函数                                                                     *
 *  参数:(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;
}
コード例 #7
0
ファイル: tcl.thread.c プロジェクト: gmphoenix/trochili
/*************************************************************************************************
 *  功能:线程结构初始化函数                                                                     *
 *  参数:(1)  pThread  线程结构地址                                                             *
 *        (2)  status   线程的初始状态                                                           *
 *        (3)  property 线程属性                                                                 *
 *        (4)  acapi    对线程管理API的许可控制                                                  *
 *        (5)  pEntry   线程函数地址                                                             *
 *        (6)  pArg     线程函数参数                                                             *
 *        (7)  pStack   线程栈地址                                                               *
 *        (8)  bytes    线程栈大小,以字为单位                                                   *
 *        (9)  priority 线程优先级                                                               *
 *        (10) ticks    线程时间片长度                                                           *
 *        (11) pError   详细调用结果                                                             *
 *  返回:(1)  eFailure                                                                          *
 *        (2)  eSuccess                                                                          *
 *  说明:函数名的前缀'x'(eXtreme)表示本函数需要处理临界区代码                                   *
 *************************************************************************************************/
TState xThreadCreate(TThread* pThread, TThreadStatus status, TProperty property, TBitMask acapi,
                     TThreadEntry pEntry, TArgument argument, void* pStack, TBase32 bytes,
                     TPriority priority, TTimeTick ticks, TError* pError)
{
    TState state = eFailure;
    TError error = THREAD_ERR_FAULT;
    TReg32 imask;

    CpuEnterCritical(&imask);

    /* 只允许在非中断代码调用本函数 */
    if (uKernelVariable.State != eIntrState)
    {
        /* 检查线程是否已经被初始化 */
        if (!(pThread->Property &THREAD_PROP_READY))
        {
            uThreadCreate(pThread, status, property, acapi, pEntry, argument, pStack, bytes,
                          priority, ticks);
            error = THREAD_ERR_NONE;
            state = eSuccess;
        }
    }

    CpuLeaveCritical(imask);

    *pError = error;
    return state;
}
コード例 #8
0
ファイル: tcl.timer.c プロジェクト: gmphoenix/trochili
/*************************************************************************************************
 *  功能:重置定时器类型和定时时间                                                               *
 *  参数:(1) pTimer 定时器结构地址                                                              *
 *        (2) ticks  定时器时钟节拍数目                                                          *
 *        (3) pError 详细调用结果                                                                *
 *  返回:无                                                                                     *
 *  说明                                                                                         *
 *************************************************************************************************/
TState xTimerConfig(TTimer* pTimer, TTimeTick ticks, TError* pError)
{
    TState state = eFailure;
    TError error = TIMER_ERR_UNREADY;
    TReg32 imask;

    CpuEnterCritical(&imask);

    /* 检查定时器就绪属性 */
    if (pTimer->Property & TIMER_PROP_READY)
    {
        /* 定时器类型检查,然后保持定时器类型不变,稍有啰嗦 */
        if (pTimer->Type == eUserTimer)
        {
            uTimerConfig(pTimer, eUserTimer, ticks);
            error = TIMER_ERR_NONE;
            state = eSuccess;
        }
        else
        {
            error = TIMER_ERR_FAULT;
        }
    }
    CpuLeaveCritical(imask);

    *pError = error;
    return state;
}
コード例 #9
0
ファイル: tcl.timer.c プロジェクト: gmphoenix/trochili
/*************************************************************************************************
 *  功能:内核中的定时器守护线程函数                                                             *
 *  参数:(1) argument 定时器线程的用户参数                                                      *
 *  返回:无                                                                                     *
 *  说明:                                                                                       *
 *************************************************************************************************/
static void TimerDaemonEntry(TArgument argument)
{
    TState        state;
    TError        error;
    TBase32       imask;
    TTimer*       pTimer;
    TTimerRoutine pRoutine;
    TArgument     data;

    while(eTrue)
    {
        CpuEnterCritical(&imask);

        /* 如果期满定时器队列为空则将定时器守护线程休眠 */
        if (TimerList.ExpiredHandle == (TObjNode*)0)
        {
            state = uThreadSetUnready(&TimerDaemonThread, eThreadSuspended, 0U, &error);
            state = state;
            CpuLeaveCritical(imask);
        }
        else
        {
            /* 逐个处理用户定时器 */
            pTimer = (TTimer*)(TimerList.ExpiredHandle->Owner);
            pRoutine = pTimer->Routine;
            data = pTimer->Argument;
            ResetTimer(pTimer);
            CpuLeaveCritical(imask);

            /* 在线程环境下处理定时器回调事务 */
            pRoutine(data);
        }
    }
}
コード例 #10
0
ファイル: tcl.thread.c プロジェクト: gmphoenix/trochili
/*************************************************************************************************
 *  功能:线程延时取消函数                                                                       *
 *  参数:(1) pThread 线程结构地址                                                               *
 *        (2) pError  详细调用结果                                                               *
 *  返回:(1) eSuccess                                                                           *
 *        (2) eFailure                                                                           *
 *  说明:(1) 这个函数对以时限等待方式阻塞在IPC线程阻塞队列上的线程无效                          *
 *************************************************************************************************/
TState xThreadUndelay(TThread* pThread, TError* pError)
{
    TState state = eFailure;
    TError error = THREAD_ERR_FAULT;
    TReg32 imask;

    CpuEnterCritical(&imask);

    /* 只允许在非中断代码调用本函数 */
    if (uKernelVariable.State != eIntrState)
    {
        /* 检查线程是否已经被初始化 */
        if (pThread->Property &THREAD_PROP_READY)
        {
            /* 检查线程是否接收相关API调用 */
            if (pThread->ACAPI &THREAD_ACAPI_UNDELAY)
            {
                state = uThreadSetReady(pThread, eThreadDelayed, &error);
            }
            else
            {
                error = THREAD_ERR_ACAPI;
            }
        }
        else
        {
            error = THREAD_ERR_UNREADY;
        }
    }
    CpuLeaveCritical(imask);

    *pError = error;
    return state;
}
コード例 #11
0
ファイル: tcl.message.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:消息队列初始化函数                                                                     *
 *  输入:(1) pMsgQue   消息队列结构地址                                                         *
 *        (2) pPool2    消息数组地址                                                             *
 *        (3) capacity  消息队列容量,即消息数组大小                                             *
 *        (4) policy    消息队列线程调度策略                                                     *
 *        (5) pError    详细调用结果                                                             *
 *  返回:(1) eSuccess  操作成功                                                                 *
 *        (2) eFailure  操作失败                                                                 *
 *  说明:                                                                                       *
 *************************************************************************************************/
TState xMQCreate(TMsgQueue* pMsgQue, void** pPool2, TBase32 capacity, TProperty property,
                 TError* pError)
{
    TState state = eFailure;
    TError error = IPC_ERR_FAULT;
    TReg32 imask;

    CpuEnterCritical(&imask);

    if (!(pMsgQue->Property & IPC_PROP_READY))
    {
        property |= IPC_PROP_READY;
        pMsgQue->Property = property;
        pMsgQue->Capacity = capacity;
        pMsgQue->MsgPool = pPool2;
        pMsgQue->MsgEntries = 0U;
        pMsgQue->Head = 0U;
        pMsgQue->Tail = 0U;
        pMsgQue->Status = eMQEmpty;

        pMsgQue->Queue.PrimaryHandle   = (TObjNode*)0;
        pMsgQue->Queue.AuxiliaryHandle = (TObjNode*)0;
        pMsgQue->Queue.Property        = &(pMsgQue->Property);

        error = IPC_ERR_NONE;
        state = eSuccess;
    }

    CpuLeaveCritical(imask);

    *pError = error;
    return state;
}
コード例 #12
0
ファイル: tcl.message.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:消息队列阻塞终止函数,将指定的线程从消息队列的阻塞队列中终止阻塞并唤醒                  *
 *  参数:(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;
}
コード例 #13
0
ファイル: tcl.irq.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:中断处理函数总入口                                                                     *
 *  参数:(1) irqn 中断号                                                                        *
 *  返回:无                                                                                     *
 *  说明:                                                                                       *
 *************************************************************************************************/
void xIrqEnterISR(TIndex irqn)
{
    TReg32      imask;

    TIrqVector* pVector;
    TISR        pISR;
    TArgument   data;
    TBitMask    retv = IRQ_ISR_DONE;

    KNL_ASSERT((irqn < TCLC_CPU_IRQ_NUM), "");
    CpuEnterCritical(&imask);

    /* 获得和中断号对应的中断向量 */
    pVector = (TIrqVector*)(IrqMapTable[irqn]);
    if ((pVector != (TIrqVector*)0) &&
            (pVector->Property & IRQ_VECTOR_PROP_READY))
    {
        /* 在处理中断对应的向量时,禁止其他代码修改向量 */
        pVector->Property |= IRQ_VECTOR_PROP_LOCKED;

        /* 在线程环境下调用低级中断处理函数 */
        if (pVector->ISR != (TISR)0)
        {
            pISR = pVector->ISR;
            data = pVector->Argument;
            CpuLeaveCritical(imask);
            retv = pISR(data);
            CpuEnterCritical(&imask);
        }

        /* 如果需要则调用中断处理线程ASR(用户中断处理线程或者内核中断守护线程),
           注意此时ASR可能处于eThreadReady状态 */
        if ((retv & IRQ_CALL_ASR) &&
                (pVector->ASR != (TThread*)0))
        {
            uThreadResumeFromISR(pVector->ASR);
        }

        pVector->Property &= (~IRQ_VECTOR_PROP_LOCKED);
    }

    CpuLeaveCritical(imask);
}
コード例 #14
0
ファイル: tcl.thread.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:更改线程优先级                                                                         *
 *  参数:(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;

}
コード例 #15
0
ファイル: tcl.thread.c プロジェクト: gmphoenix/trochili
/*************************************************************************************************
 *  功能:修改线程时间片长度                                                                     *
 *  参数:(1) pThread 线程结构地址                                                               *
 *        (2) slice   线程时间片长度                                                             *
 *        (3) pError  详细调用结果                                                               *
 *  返回:(1) eSuccess                                                                           *
 *        (2) eFailure                                                                           *
 *  说明:                                                                                       *
 *************************************************************************************************/
TState xThreadSetTimeSlice(TThread* pThread, TTimeTick ticks, TError* pError)
{
    TState state = eFailure;
    TError error = THREAD_ERR_FAULT;
    TReg32 imask;

    CpuEnterCritical(&imask);

    /* 只允许在非中断代码调用本函数 */
    if (uKernelVariable.State != eIntrState)
    {
        /* 如果没有给出被操作的线程地址,则强制使用当前线程 */
        if (pThread == (TThread*)0)
        {
            pThread = uKernelVariable.CurrentThread;
        }

        /* 检查线程是否已经被初始化 */
        if (pThread->Property &THREAD_PROP_READY)
        {
            /* 检查线程是否接收相关API调用 */
            if (pThread->ACAPI &THREAD_ACAPI_SET_SLICE)
            {
                /* 调整线程时间片长度 */
                if (pThread->BaseTicks > ticks)
                {
                    pThread->Ticks = (pThread->Ticks < ticks) ? (pThread->Ticks): ticks;
                }
                else
                {
                    pThread->Ticks += (ticks - pThread->BaseTicks);
                }
                pThread->BaseTicks = ticks;

                error = THREAD_ERR_NONE;
                state = eSuccess;
            }
            else
            {
                error = THREAD_ERR_ACAPI;
            }
        }
        else
        {
            error = THREAD_ERR_UNREADY;
        }
    }

    CpuLeaveCritical(imask);

    *pError = error;
    return state;
}
コード例 #16
0
ファイル: tcl.thread.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:线程级线程调度函数,当前线程主动让出处理器(保持就绪状态)                               *
 *  参数:(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;
}
コード例 #17
0
ファイル: tcl.thread.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:线程解挂函数                                                                           *
 *  参数:(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;
}
コード例 #18
0
ファイル: tcl.thread.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:线程挂起函数                                                                           *
 *  参数:(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;
}
コード例 #19
0
ファイル: tcl.thread.c プロジェクト: gmphoenix/trochili
/*************************************************************************************************
 *  功能:线程解挂函数                                                                           *
 *  参数:(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;
}
コード例 #20
0
ファイル: tcl.irq.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:撤销中断请求                                                                           *
 *  参数:(1) pIRQ      中断请求结构地址                                                         *
 *  返回: (1) eFailure  操作失败                                                                 *
 *        (2) eSuccess  操作成功                                                                 *
 *  说明:                                                                                       *
 *************************************************************************************************/
TState xIrqCancelRequest(TIrq* pIRQ, TError* pError)
{
    TState state = eFailure;
    TError error = IRQ_ERR_UNREADY;
    TReg32 imask;

    CpuEnterCritical(&imask);
    if (pIRQ->Property & IRQ_PROP_READY)
    {
        uObjListRemoveNode( pIRQ->ObjNode.Handle, &(pIRQ->ObjNode));
        memset(pIRQ, 0, sizeof(TIrq));

        error = IRQ_ERR_NONE;
        state = eSuccess;
    }
    CpuLeaveCritical(imask);

    *pError = error;
    return state;
}
コード例 #21
0
ファイル: tcl.message.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:消息队列广播函数,向所有读阻塞队列中的线程广播消息                                      *
 *  参数:(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;
}
コード例 #22
0
ファイル: tcl.thread.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:线程运行监理函数,线程的运行都以它为基础                                               *
 *  参数:(1) pThread  线程地址                                                                  *
 *  返回:无                                                                                     *
 *  说明:函数名的前缀'x'(eXtreme)表示本函数需要处理临界区代码                                   *
 *************************************************************************************************/
static void xSuperviseThread(TThread* pThread)
{
    TReg32 imask;
    KNL_ASSERT((pThread == uKernelVariable.CurrentThread), "");

#if (TCLC_IRQ_ENABLE)
    if (pThread->Property &THREAD_PROP_ASR)
    {
        while (eTrue)
        {
            /*
            * 调用用户ASR线程主函数,这类函数的特点是唤醒执行后,
            * 会被系统自动挂起,等待下次唤醒。
            */
            pThread->Entry(pThread->Argument);

            /*
            * 当ASR之行结束后,准备挂起时,此时ISR可能会又一次进入尝试唤醒ASR,
            * 不巧此时ASR为运行状态。为了避免ASR丢失下轮的唤醒请求,在这里略纠结
            * 的添加了检查
            */
            CpuEnterCritical(&imask);
            if (pThread->SyncValue == 0U)
            {
                uThreadSuspendSelf();
            }
            else
            {
                pThread->SyncValue = 0U;
            }
            CpuLeaveCritical(imask);
        }
    }
#endif

    /* 普通线程需要注意用户不小心退出导致非法指令等死机的问题 */
    pThread->Entry(pThread->Argument);
    uKernelVariable.Diagnosis |= KERNEL_DIAG_THREAD_ERROR;
    pThread->Diagnosis |= THREAD_DIAG_INVALID_EXIT;
    uDebugPanic("", __FILE__, __FUNCTION__, __LINE__);
}
コード例 #23
0
ファイル: tcl.thread.c プロジェクト: gmphoenix/trochili
/*************************************************************************************************
 *  功能:线程注销                                                                               *
 *  参数:(1) pThread 线程结构地址                                                               *
 *        (2) pError  详细调用结果                                                               *
 *  返回:(1) eFailure                                                                           *
 *        (2) eSuccess                                                                           *
 *  说明:IDLE线程、中断处理线程和定时器线程不能被注销                                           *
 *************************************************************************************************/
TState xThreadDelete(TThread* pThread, TError* pError)
{
    TState state = eFailure;
    TError error = THREAD_ERR_FAULT;
    TReg32 imask;

    CpuEnterCritical(&imask);

    /* 只允许在非中断代码调用本函数 */
    if (uKernelVariable.State != eIntrState)
    {
        /* 如果没有给出被操作的线程地址,则强制使用当前线程 */
        if (pThread == (TThread*)0)
        {
            pThread = uKernelVariable.CurrentThread;
        }

        /* 检查线程是否已经被初始化 */
        if (pThread->Property &THREAD_PROP_READY)
        {
            /* 检查线程是否接收相关API调用 */
            if (pThread->ACAPI &THREAD_ACAPI_DEINIT)
            {
                state = uThreadDelete(pThread, &error);
            }
            else
            {
                error = THREAD_ERR_ACAPI;
            }
        }
        else
        {
            error = THREAD_ERR_UNREADY;
        }
    }

    CpuLeaveCritical(imask);

    *pError = error;
    return state;
}
コード例 #24
0
ファイル: tcl.message.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能: 清除消息队列阻塞队列                                                                   *
 *  参数: (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;
}
コード例 #25
0
ファイル: tcl.thread.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:线程解挂函数                                                                           *
 *  参数:(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;
}
コード例 #26
0
ファイル: tcl.message.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:消息队列重置函数                                                                       *
 *  输入:(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;
}
コード例 #27
0
ファイル: tcl.message.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能: 用于线程/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;
}
コード例 #28
0
ファイル: tcl.irq.c プロジェクト: Arcko/trochili
/*************************************************************************************************
 *  功能:设置中断向量函数                                                                       *
 *  参数:(1) irqn     中断号                                                                    *
 *        (2) pISR     ISR处理函数                                                               *
 *        (3) pASR     中断处理线程                                                              *
 *        (4) data     应用提供的回调数据                                                        *
 *        (5) pError   详细调用结果                                                              *
 *  返回: (1) eFailure 操作失败                                                                  *
 *        (2) eSuccess 操作成功                                                                  *
 *  说明:                                                                                       *
 *************************************************************************************************/
TState xIrqSetVector(TIndex irqn, TISR pISR, TThread* pASR, TArgument data, TError* pError)
{
    TState state = eFailure;
    TError error = IRQ_ERR_FAULT;
    TReg32 imask;
    TIndex index;
    TIrqVector* pVector;

    CpuEnterCritical(&imask);

    /* 如果指定的中断号已经注册过中断向量,那么直接更新 */
    if (IrqMapTable[irqn] != (TAddr32)0)
    {
        pVector = (TIrqVector*)(IrqMapTable[irqn]);

        /* 更新之前确保没有被锁定 */
        if ((pVector->Property & IRQ_VECTOR_PROP_LOCKED))
        {
            error = IRQ_ERR_LOCKED;
        }
        else
        {
            error = IRQ_ERR_NONE;
            state = eSuccess;
        }
    }
    else
    {
        /* 为该中断号申请中断向量项 */
        for (index = 0; index < TCLC_IRQ_VECTOR_NUM; index++)
        {
            pVector = (TIrqVector*)IrqVectorTable + index;
            if (!(pVector->Property & IRQ_VECTOR_PROP_READY))
            {
                /* 建立中断号和对应的中断向量的联系 */
                IrqMapTable[irqn] = (TAddr32)pVector;
                pVector->IRQn       = irqn;
                pVector->Property   = IRQ_VECTOR_PROP_READY;

                error = IRQ_ERR_NONE;
                state = eSuccess;
                break;
            }
        }
    }

    /* 设置中断向量对应的中断服务程序,中断服务线程(如果没有则默认为IrqDaemon线程) */
    if (state == eSuccess)
    {
#if (TCLC_IRQ_DAEMON_ENABLE)
        if (pASR == (TThread*)0)
        {
            pASR = uKernelVariable.IrqDaemon;
        }
#endif
        pVector->ISR      = pISR;
        pVector->ASR      = pASR;
        pVector->Argument = data;
    }

    CpuLeaveCritical(imask);

    *pError = error;
    return state;
}