/***************************************************************************
 * Copyright (c) 2024 Microsoft Corporation
 * Copyright (c) 2026-present Eclipse ThreadX contributors
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License which is available at
 * https://opensource.org/licenses/MIT.
 *
 * SPDX-License-Identifier: MIT
 **************************************************************************/


/**************************************************************************/
/**************************************************************************/
/**                                                                       */
/** ThreadX Component                                                     */
/**                                                                       */
/**   Initialize                                                          */
/**                                                                       */
/**************************************************************************/
/**************************************************************************/

#define TX_SOURCE_CODE
#define TX_THREAD_SMP_SOURCE_CODE


/* Include necessary system files.  */

#include "tx_api.h"
#include "tx_initialize.h"
#include "tx_thread.h"
#include "tx_timer.h"


/* Define any port-specific scheduling data structures.  */

TX_PORT_SPECIFIC_DATA


#ifdef TX_SAFETY_CRITICAL
TX_SAFETY_CRITICAL_EXCEPTION_HANDLER
#endif


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _tx_initialize_kernel_enter                        PORTABLE SMP     */
/*                                                           6.3.0        */
/*  AUTHOR                                                                */
/*                                                                        */
/*    William E. Lamie, Microsoft Corporation                             */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function is the first ThreadX function called during           */
/*    initialization.  It is called from the application's "main()"       */
/*    function.  It is important to note that this routine never          */
/*    returns.  The processing of this function is relatively simple:     */
/*    it calls several ThreadX initialization functions (if needed),      */
/*    calls the application define function, and then invokes the         */
/*    scheduler.                                                          */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _tx_thread_smp_high_level_initialize  SMP initialization            */
/*    _tx_thread_smp_current_state_set  Set system state for all cores    */
/*    _tx_initialize_low_level          Low-level initialization          */
/*    _tx_initialize_high_level         High-level initialization         */
/*    tx_application_define             Application define function       */
/*    _tx_thread_scheduler              ThreadX scheduling loop           */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    main                              Application main program          */
/*                                                                        */
/**************************************************************************/
VOID  _tx_initialize_kernel_enter(VOID)
{

ULONG   other_core_status, i;


    /* Determine if the compiler has pre-initialized ThreadX.  */
    if (_tx_thread_system_state[0] != TX_INITIALIZE_ALMOST_DONE)
    {

        /* No, the initialization still needs to take place.  */

        /* Ensure that the system state variable is set to indicate
           initialization is in progress.  Note that this variable is
           later used to represent interrupt nesting.  */
        _tx_thread_smp_current_state_set(TX_INITIALIZE_IN_PROGRESS);

        /* Call any port specific preprocessing.  */
        TX_PORT_SPECIFIC_PRE_INITIALIZATION

        /* Invoke the low-level initialization to handle all processor specific
           initialization issues.  */
        _tx_initialize_low_level();

        /* Call the high-level SMP  Initialization.  */
        _tx_thread_smp_high_level_initialize();

        /* Invoke the high-level initialization to exercise all of the
           ThreadX components and the application's initialization
           function.  */
        _tx_initialize_high_level();

        /* Call any port specific post-processing.  */
        TX_PORT_SPECIFIC_POST_INITIALIZATION
    }

    /* Optional processing extension.  */
    TX_INITIALIZE_KERNEL_ENTER_EXTENSION

    /* Ensure that the system state variable is set to indicate
       initialization is in progress.  Note that this variable is
       later used to represent interrupt nesting.  */
    _tx_thread_system_state[0] =  TX_INITIALIZE_IN_PROGRESS;

    /* Optional random number generator initialization.  */
    TX_INITIALIZE_RANDOM_GENERATOR_INITIALIZATION

    /* Call the application provided initialization function.  Pass the
       first available memory address to it.  */
    tx_application_define(_tx_initialize_unused_memory);

    /* Call any port specific pre-scheduler processing.  */
    TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION

    /* Now wait for all cores to become ready for scheduling.  */
    do
    {

        /* Release the other cores from initialization.  */
        _tx_thread_smp_release_cores_flag =  TX_TRUE;

        /* Add all the status together...  Other cores must clear their system
           state before they they are released.  */
        other_core_status =  ((ULONG) 0);

#ifndef TX_THREAD_SMP_DYNAMIC_CORE_MAX
        for (i = ((ULONG) 1); i < ((ULONG) TX_THREAD_SMP_MAX_CORES); i++)
#else
        for (i = ((ULONG) 1); i < _tx_thread_smp_max_cores; i++)
#endif
        {


            /* Call port-specific memory synchronization primitive.  */
            TX_PORT_SPECIFIC_MEMORY_SYNCHRONIZATION

            /* Add the states of each subsequent core.  */
            other_core_status =  other_core_status + _tx_thread_system_state[i];
        }

    } while (other_core_status != ((ULONG) 0));

    /* Set the system state in preparation for entering the thread
       scheduler.  */
    _tx_thread_system_state[0] =  TX_INITIALIZE_IS_FINISHED;

    /* Call port-specific memory synchronization primitive.  */
    TX_PORT_SPECIFIC_MEMORY_SYNCHRONIZATION

    /* Enter the scheduling loop to start executing threads!  */
    _tx_thread_schedule();

#ifdef TX_SAFETY_CRITICAL

    /* If we ever get here, raise safety critical exception.  */
    TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0);
#endif
}

