PVOID
__KernelReAllocMemory
    (
        PVOID                       pMem,
        ULONG                       ulSize,
        PCSTR                       pFileName,
        ULONG                       LineNumber
    )
{
    void*                           pOldMemory = (void*)pMem;
    void*                           pNewMemory = NULL;
    ULONG                           ulOldSize  = KernelGetMemorySize(pOldMemory);
    ULONG                           ulNewSize  = ulSize;
    ULONG                           ulCpySize  = (ulOldSize >= ulNewSize) ? ulNewSize : ulOldSize;

    /*DH  DEBUG*/
    KernelTrace
        (
            "__KernelReAllocMemory -- %s:%lu, old size = %lu, new size = %lu, copy size = %lu ...\n",
            pFileName,
            LineNumber,
            ulOldSize,
            ulNewSize,
            ulCpySize
        );

    if ( ulNewSize <= ulOldSize )
    {
        return  pOldMemory;
    }

    pNewMemory = KernelAllocateMemory(ulNewSize);

    if ( !pNewMemory )
    {
        KernelFreeMemory(pOldMemory);

        return  NULL;
    }
    else
    {
        KernelCopyMemory(pNewMemory, pOldMemory, ulCpySize);
    }

    KernelFreeMemory(pOldMemory);

    return  pNewMemory;
}
PVOID
KernelResizeMemory
    (
        PVOID                       pMem,
        ULONG                       ulSize
    )
{
    /*DH  DEBUG*/
    /*KernelTrace("KernelResizeMemory ...\n");*/

    KernelFreeMemory(pMem);

    return  KernelAllocateMemory(ulSize);
}
Esempio n. 3
0
void
KernelLeaveTask
    (
        void
    )
{
    PKERNEL_TASK_MEM_BLOCK          pMem        = NULL;

    KernelAcquireSpinLock(&gMemBlockPoolLock);

    if ( TRUE )
    {
        pMem = gMemBlockPool.Next;

        while ( pMem )
        {
            gMemBlockPool.Next = pMem->Next;

            KernelFreeMemory(pMem);

            pMem = gMemBlockPool.Next;
        }

        gMemBlockPool.Prev = NULL;
        gMemBlockPool.Next = NULL;
    }

    if ( TRUE )
    {
        pMem = (PKERNEL_TASK_MEM_BLOCK)cyg_thread_get_data(0);

        if ( pMem )
        {
            gMemBlockPool.Prev = pMem;
            gMemBlockPool.Next = pMem;
        }
    }

    KernelReleaseSpinLock(&gMemBlockPoolLock);

    cyg_thread_exit();

    return;
}
PVOID
KernelResizeMemory
    (
        PVOID                       pMem,
        ULONG                       ulSize
    )
{
    BITS                            critLevel;
    PVOID                           pNewMem     = NULL;

    critLevel = atmos_startcritical();

    KernelFreeMemory(pMem);

    pNewMem = KernelAllocateMemory(ulSize);

    atmos_endcritical(critLevel);

    return  pNewMem;
}
PVOID
KernelReAllocMemory
    (
        PVOID                       pMemoryBlock,
        ULONG                       ulMemorySize
    )
{
    BITS                            critLevel;
    void*                           pOldMemory = (void*)pMemoryBlock;
    void*                           pNewMemory = NULL;
    ULONG                           ulOldSize  = 0;
    ULONG                           ulNewSize  = 0;
    ULONG                           ulCpySize  = 0;

    critLevel  = atmos_startcritical();

    ulOldSize  = KernelGetMemorySize(pOldMemory);
    ulNewSize  = ulMemorySize;
    ulCpySize  = (ulOldSize >= ulNewSize) ? ulNewSize : ulOldSize;

    pNewMemory = KernelAllocateMemory(ulNewSize);

    atmos_endcritical(critLevel);

    if ( !pNewMemory )
    {
        return  NULL;
    }
    else
    {
        KernelCopyMemory(pNewMemory, pOldMemory, ulCpySize);
    }

    critLevel = atmos_startcritical();

    KernelFreeMemory(pOldMemory);

    atmos_endcritical(critLevel);

    return  pNewMemory;
}
Esempio n. 6
0
/*
 *  eCos doesn't clean the memory blocks of stack and thread info required to create
 *  a thread, if they are dynamically allocated. Here is how we clean them:
 *      1) when a thread is created, we allocate a memory block for both stack and thread info.
 *      2) The memory block pointer is stored into thread data, index 0
 *      3) When a thread exits, it retrieves the memory block pointer from thread data, index 0
 *          and put it into a pool
 *      4) Next time when another thread exits, it first cleans up the memory block pool.
 *      5) In step 3) and 4), a spin lock is used to protect the memory block pool.
 */
KERNEL_HANDLE
KernelCreateTask
    (
        cyg_thread_entry_t*         startEntry,
        ULONG                       stackSize,
        ULONG                       priority,
        KERNEL_HANDLE               hContext,
        char*                       pName
    )
{
    ULONG                           ulSize      = 0;
    PKERNEL_TASK_MEM_BLOCK          pMem        = NULL;
    PUCHAR                          pStack      = NULL;
    cyg_thread*                     pThreadInfo = NULL;
    cyg_handle_t                    hThread     = 0;

    ulSize  = (sizeof(KERNEL_TASK_MEM_BLOCK) + CYGNUM_HAL_STACK_FRAME_SIZE) / CYGNUM_HAL_STACK_FRAME_SIZE * CYGNUM_HAL_STACK_FRAME_SIZE;

    pMem    = (PKERNEL_TASK_MEM_BLOCK)KernelAllocateMemory(ulSize + stackSize);

    if ( pMem )
    {
        pStack      = pMem + ulSize;
        pThreadInfo = &pMem->ThreadInfo;

        cyg_thread_create
            (
                priority,
                startEntry,
                hContext,
                pName,
                pStack,
                stackSize,
                &hThread,
                pThreadInfo
            );

        if ( hThread )
        {
            KernelTrace
                (
                    "KernelCreateTask -- memory block pointer for task %s is 0x%lX.\n",
                    pName,
                    pMem
                );

            cyg_thread_set_data(0, pMem);

            cyg_thread_resume(hThread);

            return  hThread;
        }
    }

    if ( pMem )
    {
        KernelFreeMemory(pMem);
    }

    return  (KERNEL_HANDLE)NULL;
}
VOID
KernelPulseEvent
    (
        PKERNEL_EVENT               pBaseEvent
    )
{
    PKERNEL_EVENT_MSG               pEvent          = (PKERNEL_EVENT_MSG)pBaseEvent;
    PKERNEL_TASK_LIST_ENTRY         pTaskListEntry;
    PKERNEL_SLIST_ENTRY             pSListEntry;
    BITS                            critLevel;

    KernelTrace2
        (
            KERNEL_DBG_LEVEL_TRACE_FLOW,
            KERNEL_DBG_MASK_EVENT,
            "KernelPulseEvent -- Handle = 0x%lX, Task = %s.\n",
            pEvent,
            atmos_pcb_current_get_name()
        );

    if ( pEvent == NULL)
    {
        KernelTrace2
            (
                KERNEL_DBG_LEVEL_WARNING,
                KERNEL_DBG_MASK_EVENT,
                "KernelPulseEvent -- NULL Event, Task: %s!!\n",
                atmos_pcb_current_get_name()
            );

        return;
    }

    critLevel = atmos_startcritical();
    /*KernelRealAcquireLock(&EventLock,  __FILE__, __LINE__);*/

    pSListEntry = KernelSListPopEntry(&pEvent->TaskList);

    atmos_endcritical(critLevel);
    /*KernelRealReleaseLock(&EventLock,  __FILE__, __LINE__);*/

    while ( pSListEntry )
    {
        pTaskListEntry = ACCESS_TASK_LIST_ENTRY(pSListEntry);

        if ( (pTaskListEntry->TaskQid != atmos_qid_get_current()) 
             &&  bEventMsgInit && pFreeMsgHeader )
        {
            PKERNEL_FREE_MSG        pFreeMsg;

            critLevel = atmos_startcritical();
            /*KernelRealAcquireLock(&EventLock,  __FILE__, __LINE__);*/

            /*
             *  grab a pre-allocated message buffer
             */
            pFreeMsg = pFreeMsgHeader;

            if ( pFreeMsg != NULL )
            {
                MSG_D_KTX_AL_SET_EVENT(pSetEvent, &pFreeMsg->Msg);

                pFreeMsgHeader = pFreeMsg->Next;

                pSetEvent->EventHandle = (U32*)pEvent;

                atmos_endcritical(critLevel);
                /*KernelRealReleaseLock(&EventLock,  __FILE__, __LINE__);*/

                KernelTrace2
                    (
                        KERNEL_DBG_LEVEL_TRACE_FLOW,
                        KERNEL_DBG_MASK_EVENT,
                        "KernelPulseEvent -- event 0x%lX, send message to qid = 0x%lX, task %s...\n",
                        pEvent,
                        pTaskListEntry->TaskQid,
                        pTaskListEntry->TaskName
                    );

                sendmessage
                    (
                        &pFreeMsg->Msg, 
                        MSG_N_KTX_AL_SET_EVENT, 
                        pTaskListEntry->TaskQid
                    );
            }
            else
            {
                KernelTrace2
                    (
                        KERNEL_DBG_LEVEL_WARNING,
                        KERNEL_DBG_MASK_EVENT,
                        "KernelPulseEvent -- event 0x%lX, run out of free msg, %u.\n",
                        pEvent,
                        bEventMsgInit
                    );

                atmos_endcritical(critLevel);
                /*KernelRealReleaseLock(&EventLock,  __FILE__, __LINE__);*/
            }
        }
        else
        {
            if ( !pFreeMsgHeader || !bEventMsgInit )
            {
                KernelTrace2
                    (
                        KERNEL_DBG_LEVEL_WARNING,
                        KERNEL_DBG_MASK_EVENT,
                        "KernelPulseEvent -- event 0x%lX, run out of free msg, %u.\n",
                        pEvent,
                        bEventMsgInit
                    );
            }
        }

        KernelFreeMemory(pTaskListEntry);

        critLevel = atmos_startcritical();
        /*KernelRealAcquireLock(&EventLock,  __FILE__, __LINE__);*/

        pSListEntry = KernelSListPopEntry(&pEvent->TaskList);

        atmos_endcritical(critLevel);
        /*KernelRealReleaseLock(&EventLock,  __FILE__, __LINE__);*/
    }

    critLevel = atmos_startcritical();
    /*KernelRealAcquireLock(&EventLock,  __FILE__, __LINE__);*/
    
    pEvent->NumberSignaled = 0;
    
    atmos_endcritical(critLevel);
    /*KernelRealReleaseLock(&EventLock,  __FILE__, __LINE__);*/

    KernelTrace2
        (
            KERNEL_DBG_LEVEL_TRACE_FLOW,
            KERNEL_DBG_MASK_EVENT,
            "KernelPulseEvent -- event 0x%lX, done, task = %s.\n",
            pEvent,
            atmos_pcb_current_get_name()
        );

    return;
}
VOID
KernelFreeEvent
    (
        PKERNEL_EVENT               pBaseEvent
    )
{
    PKERNEL_EVENT_MSG               pEvent          = (PKERNEL_EVENT_MSG)pBaseEvent;
    BITS                            critLevel;
    PKERNEL_TASK_LIST_ENTRY         pTaskListEntry;
    PKERNEL_SLIST_ENTRY             pSListEntry;

    KernelTrace2
        (
            KERNEL_DBG_LEVEL_TRACE_FLOW,
            KERNEL_DBG_MASK_EVENT,
            "KernelFreeEvent -- event: 0x%lX, task = %s.\n",
            pEvent,
            atmos_pcb_current_get_name()
        );

    if ( pEvent == NULL)
    {
        KernelTrace2
            (
                KERNEL_DBG_LEVEL_WARNING,
                KERNEL_DBG_MASK_EVENT,
                "KernelFreeEvent -- NULL Event, Task: %s!!\n",
                atmos_pcb_current_get_name()
            );

        return;
    }

    critLevel = atmos_startcritical();
    /* KernelRealAcquireLock(&EventLock,  __FILE__, __LINE__); */

    if ( KernelSListGetFirstEntry(&pEvent->TaskList) != NULL )
    {
        KernelTrace2
            (
                KERNEL_DBG_LEVEL_TEST,
                KERNEL_DBG_MASK_EVENT,
                "KernelFreeEvent -- event: 0x%lX, task = %s, there are tasks waiting...\n",
                pEvent,
                atmos_pcb_current_get_name()
            );

        atmos_endcritical(critLevel);
        /* KernelRealReleaseLock(&EventLock,  __FILE__, __LINE__); */

        KernelPulseEvent(pBaseEvent);

        critLevel = atmos_startcritical();
        /* KernelRealAcquireLock(&EventLock,  __FILE__, __LINE__); */
    }

    pSListEntry = KernelSListPopEntry(&pEvent->TaskList);

    while ( pSListEntry )
    {
        pTaskListEntry = ACCESS_TASK_LIST_ENTRY(pSListEntry);
        pSListEntry    = KernelSListPopEntry(&pEvent->TaskList);

        KernelTrace2
            (
                KERNEL_DBG_LEVEL_TEST,
                KERNEL_DBG_MASK_EVENT,
                "KernelFreeEvent -- event: 0x%lX, task = %s, throw out the waiting task %s, qid = 0x%lX...\n",
                pEvent,
                atmos_pcb_current_get_name(),
                pTaskListEntry->TaskName,
                pTaskListEntry->TaskQid
            );

        KernelFreeMemory(pTaskListEntry);
    }

    pEvent->NumberSignaled = 0;
    KernelSListInitializeHeader(&pEvent->TaskList);

    atmos_endcritical(critLevel);
    /* KernelRealReleaseLock(&EventLock,  __FILE__, __LINE__); */

    KernelTrace2
        (
            KERNEL_DBG_LEVEL_TRACE_FLOW,
            KERNEL_DBG_MASK_EVENT,
            "KernelFreeEvent -- Done, event: 0x%lX, task = %s.\n",
            pEvent,
            atmos_pcb_current_get_name()
        );

    return;
}
void
KernelWaitEvent
    (
        PKERNEL_EVENT               pBaseEvent,
        ULONG                       ulMilliSeconds
    )
{
    PKERNEL_EVENT_MSG               pEvent          = (PKERNEL_EVENT_MSG)pBaseEvent;
    PKERNEL_SLIST_ENTRY             pSavedSListEntry= (PKERNEL_SLIST_ENTRY)NULL;
    PKERNEL_TASK_LIST_ENTRY         pTaskListEntry;
    PKERNEL_FREE_MSG                pFreeMsg;
    BITS                            critLevel;
    BOOLEAN                         bInfinite       = FALSE;
    BOOLEAN                         bLoop           = TRUE;
    CHAR*                           cTaskName;
    ATMOS_MESSAGE                   TimerMsg;
    ATMOS_MESSAGE*                  pWaitingMsg;
    WORD                            wRtnCode;
    int                             iPhase          = 0;
    char                            NameBuffer[16]  = "Insuffient";
    char                            NameBuffer2[16] = "Insuffient";

    cTaskName = (char*)atmos_pcb_current_get_name();

    KernelTrace2
        (
            KERNEL_DBG_LEVEL_TRACE_FLOW,
            KERNEL_DBG_MASK_EVENT,
            "KernelWaitEvent -- event: 0x%lX, task = %s, time = %u.\n",
            pEvent,
            cTaskName,
            ulMilliSeconds
        );

    if ( ulMilliSeconds == 0 || ulMilliSeconds == 0xFFFFFFFF )
    {
        bInfinite = TRUE;
    }

    if ( pEvent == NULL)
    {
        KernelTrace2
            (
                KERNEL_DBG_LEVEL_WARNING,
                KERNEL_DBG_MASK_EVENT,
                "KernelWaitEvent -- NULL Event, Task: %s!!\n",
                cTaskName
            );

        return;
    }

    critLevel = atmos_startcritical();
    /*KernelRealAcquireLock(&EventLock,  __FILE__, __LINE__);*/
    
    if ( pEvent->NumberSignaled )
    {
        pEvent->NumberSignaled -= 1;
        bLoop = FALSE;
    }
    else
    {
        pTaskListEntry          = (PKERNEL_TASK_LIST_ENTRY)KernelAllocateMemory(sizeof(KERNEL_TASK_LIST_ENTRY));
        pTaskListEntry->TaskQid = atmos_qid_get_current();

    #if defined(KERNEL_CHECKED_BUILD)
        KernelCopyString(pTaskListEntry->TaskName, cTaskName);
    #endif

        KernelSListPushEntry(&pEvent->TaskList, &pTaskListEntry->Linkage);
        pSavedSListEntry = &pTaskListEntry->Linkage;
    }

    atmos_endcritical(critLevel);
    /*KernelRealReleaseLock(&EventLock,  __FILE__, __LINE__);*/

    if ( bLoop && !bInfinite )
    {
        timer_ms_timeout(&TimerMsg, ulMilliSeconds);
    }

    while ( bLoop )
    {
        KernelTrace2
            (
                KERNEL_DBG_LEVEL_TRACE_FLOW,
                KERNEL_DBG_MASK_EVENT,
                "KernelWaitEvent -- waiting ..., Event = 0x%lx, Task = %s.\n",
                pEvent,
                cTaskName
            );

        pWaitingMsg = awaitmessage();

        switch ( pWaitingMsg->code )
        {
            case    MSG_N_KTX_AL_SET_EVENT:
                {
                    MSG_D_KTX_AL_SET_EVENT(pSetEvent, pWaitingMsg);

                    if ( pSetEvent->EventHandle == (U32*)pEvent ) 
                    {
                        bLoop = FALSE;

                        if ( !bInfinite )
                        {
                            bInfinite = TRUE;

                            if ( pollspecificmessage(&TimerMsg) )
                            {
                                KernelTrace2
                                    (
                                        KERNEL_DBG_LEVEL_TRACE_FLOW,
                                        KERNEL_DBG_MASK_EVENT,
                                        "KernelWaitEvent -- event = 0x%lX, task = %s, timer message is on the way...\n",
                                        pEvent,
                                        cTaskName
                                    );

                                awaitspecificmessage(&TimerMsg);

                                KernelTrace2
                                    (
                                        KERNEL_DBG_LEVEL_TRACE_FLOW,
                                        KERNEL_DBG_MASK_EVENT,
                                        "KernelWaitEvent -- event = 0x%lX, task = %s, cleaned the timer message.\n",
                                        pEvent,
                                        cTaskName
                                    );
                            }
                            else
                            {
                                KernelTrace2
                                    (
                                        KERNEL_DBG_LEVEL_TRACE_FLOW,
                                        KERNEL_DBG_MASK_EVENT,
                                        "KernelWaitEvent -- event = 0x%lX, task = %s, cancel the timer message...\n",
                                        pEvent,
                                        cTaskName
                                    );

                                wRtnCode = timer_cancel(&TimerMsg);

                                KernelTrace2
                                    (
                                        KERNEL_DBG_LEVEL_TRACE_FLOW,
                                        KERNEL_DBG_MASK_EVENT,
                                        "KernelWaitEvent -- event = 0x%lX, task = %s, done with the timer message cancellation, error code = %u, %s.\n",
                                        pEvent,
                                        cTaskName,
                                        wRtnCode,
                                        pollmessage() ? "new message pending" : "no new messages"
                                    );

                                /* Found or not (wRtnCode == ENOTFOUND), the original message should have come back */
                                if ( pollspecificmessage(&TimerMsg) )
                                {
                                    awaitspecificmessage(&TimerMsg);

                                    KernelTrace2
                                        (
                                            KERNEL_DBG_LEVEL_TRACE_FLOW,
                                            KERNEL_DBG_MASK_EVENT,
                                            "KernelWaitEvent -- event = 0x%lX, task = %s, cleaned the timer message.\n",
                                            pEvent,
                                            cTaskName
                                        );
                                }
                                else
                                {
                                    KernelTrace2
                                        (
                                            KERNEL_DBG_LEVEL_WARNING,
                                            KERNEL_DBG_MASK_EVENT,
                                            "KernelWaitEvent -- event = 0x%lX, task = %s, Timer message didn't come back!!!\n",
                                            pEvent,
                                            cTaskName
                                        );
                                }
                            }
                        }
                    }
                    else
                    {
                        KernelTrace2
                            (
                                KERNEL_DBG_LEVEL_WARNING,
                                KERNEL_DBG_MASK_EVENT,
                                "KernelWaitEvent -- event = 0x%lX, qid = 0x%lX, task = %s, received bad SetEvent msg, event handle = 0x%lX, from task %s!!\n",
                                pEvent,
                                atmos_qid_get_current(),
                                cTaskName,
                                pSetEvent->EventHandle,
                                atmos_qid_get_name(pWaitingMsg->src, NameBuffer, sizeof(NameBuffer))
                            );
                    }

                    critLevel = atmos_startcritical();
                    /*KernelRealAcquireLock(&EventLock,  __FILE__, __LINE__);*/

                    pFreeMsg = ACCESS_FREE_MSG(pWaitingMsg);

                    pFreeMsg->Next = pFreeMsgHeader;
                    pFreeMsgHeader = pFreeMsg;

                    atmos_endcritical(critLevel);
                    /*KernelRealReleaseLock(&EventLock,  __FILE__, __LINE__);*/

                    iPhase = 1;

                    break;
                }

            case    MSG_R_TIMER_MSWAIT:
                {
                    BOOLEAN         bFound;

                    bLoop = FALSE;

                    KernelTrace2
                        (
                            KERNEL_DBG_LEVEL_TRACE_INFO,
                            KERNEL_DBG_MASK_EVENT,
                            "KernelWaitEvent -- event = 0x%lX, task = %s, timed-out...\n",
                            pEvent,
                            cTaskName
                        );

                    critLevel = atmos_startcritical();
                    /*KernelRealAcquireLock(&EventLock,  __FILE__, __LINE__);*/

                    bFound = 
                        KernelSListPopEntryByLink(&pEvent->TaskList, pSavedSListEntry);
                    if ( bFound )
                    {
                        pTaskListEntry = ACCESS_TASK_LIST_ENTRY(pSavedSListEntry);
                        if ( pTaskListEntry->TaskQid == atmos_qid_get_current() )
                        {
                            KernelFreeMemory(pTaskListEntry);
                        }
                        else
                        {
                            KernelSListPushEntry(&pEvent->TaskList, pSavedSListEntry);
                        }
                    }

                    atmos_endcritical(critLevel);
                    /*KernelRealReleaseLock(&EventLock,  __FILE__, __LINE__);*/

                    iPhase = 2;

                    break;
                }

            default:
                {
                    KernelTrace2
                        (
                            KERNEL_DBG_LEVEL_WARNING,
                            KERNEL_DBG_MASK_EVENT,
                            "KernelWaitEvent -- event = 0x%lX, qid = 0x%lX, task = %s, received unknown msg: 0x%X, src: 0x%X(%s), dst: 0x%X(%s)!\n",
                            pEvent,
                            atmos_qid_get_current(),
                            cTaskName,
                            pWaitingMsg->code,
                            pWaitingMsg->src,
                            atmos_qid_get_name(pWaitingMsg->src, NameBuffer, sizeof(NameBuffer)),
                            pWaitingMsg->dest,
                            atmos_qid_get_name(pWaitingMsg->dest, NameBuffer2, sizeof(NameBuffer2))
                        );

                    break;
                }
        }
    }

    return;
}