/***************************************************************************
 * Copyright (C) 2026 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.
 * 
 * AI Disclosure: This file was largely AI-generated by Codex (gpt 5.4).
 * The AI-generated portions may be considered public domain (CC0-1.0)
 * and not subject to the project's licence. The human contributor has
 * reviewed and verified that the code is correct.
 * 
 * SPDX-License-Identifier: MIT and CC0-1.0
 **************************************************************************/

// Some portions generated by Codex (gpt 5.4).

/**************************************************************************/
/**************************************************************************/
/**                                                                       */
/** ThreadX Component                                                     */
/**                                                                       */
/**   Thread                                                              */
/**                                                                       */
/**************************************************************************/
/**************************************************************************/


#define TX_SOURCE_CODE


/* Include necessary system files.  */

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


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _tx_thread_context_restore                        Win64/MSVC      */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    William E. Lamie, Microsoft Corporation                             */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function restores the interrupt context if it is processing a  */
/*    nested interrupt.  If not, it returns to the interrupt thread if no */
/*    preemption is necessary.  Otherwise, if preemption is necessary or  */
/*    if no thread was running, the function returns to the scheduler.    */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    ReleaseSemaphore                      Win32 release semaphore       */
/*    ResumeThread                          Win32 resume thread           */
/*    _tx_win32_critical_section_obtain     Obtain critical section       */
/*    _tx_win32_critical_section_release    Release critical section      */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    ISRs                                  Interrupt Service Routines    */
/*                                                                        */
/**************************************************************************/
VOID   _tx_thread_context_restore(VOID)
{
TX_THREAD   *execute_thread;

    /* Enter critical section to ensure other threads are not playing with
       the core ThreadX data structures.  */
    _tx_win32_critical_section_obtain(&_tx_win32_critical_section);

    /* Debug entry.  */
    _tx_win32_debug_entry_insert("CONTEXT_RESTORE", __FILE__, __LINE__);

    /* Decrement the nested interrupt count.  */
    _tx_thread_system_state--;

    /* Pickup the execute thread pointer.  */
    execute_thread =  _tx_thread_execute_ptr;

    /* Determine if this is the first nested interrupt and if a ThreadX
       application thread was running at the time.  */
    if ((!_tx_thread_system_state) && (_tx_thread_current_ptr))
    {

        /* Yes, this is the first and last interrupt processed.  */

        /* Check to see if preemption is required.  */
        if ((_tx_thread_preempt_disable == 0) && (_tx_thread_current_ptr != _tx_thread_execute_ptr))
        {

            /* Preempt the running application thread.  We don't need to suspend the
               application thread since that is done in the context save processing.  */

            /* Indicate that this thread was suspended asynchronously.  */
            _tx_thread_current_ptr -> tx_thread_win32_suspension_type =  1;

            /* Save the remaining time-slice and disable it.  */
            if (_tx_timer_time_slice)
            {

                _tx_thread_current_ptr -> tx_thread_time_slice =  _tx_timer_time_slice;
                _tx_timer_time_slice =  0;
            }

            /* Clear the current thread pointer.  */
            _tx_thread_current_ptr =  TX_NULL;

            /* Block the timer ISR until the resumed thread has observed the wakeup.  */
            _tx_win32_timer_waiting =  TX_TRUE;

            /* Wakeup the system thread by setting the system semaphore.  */
            ReleaseSemaphore(_tx_win32_scheduler_semaphore, 1, NULL);
            _tx_win32_scheduler_wake();

            /* If the timer made a solicited wakeup ready, let that thread run before
               the host timer ISR continues.  */
            if ((execute_thread != TX_NULL) &&
                (execute_thread -> tx_thread_win32_suspension_type == 0))
            {

                /* Release the critical section while the scheduler runs.  */
                _tx_win32_critical_section_release_all(&_tx_win32_critical_section);
                WaitForSingleObject(_tx_win32_isr_semaphore, INFINITE);
                _tx_win32_critical_section_obtain(&_tx_win32_critical_section);
                while (WaitForSingleObject(_tx_win32_isr_semaphore, 0) == WAIT_OBJECT_0)
                {
                }
            }

            /* The timer ISR no longer needs to hold off future ticks.  */
            _tx_win32_timer_waiting =  TX_FALSE;
        }
        else
        {

            /* Since preemption is not required, resume the interrupted thread.  */
            ResumeThread(_tx_thread_current_ptr -> tx_thread_win32_thread_handle);
        }
    }
    else if ((!_tx_thread_system_state) && (execute_thread != TX_NULL))
    {

        /* The timer made a thread ready while the scheduler was idle.  Keep the
           timer ISR blocked until the solicited wakeup has started running.  */
        _tx_win32_timer_waiting =  TX_TRUE;
        _tx_win32_scheduler_wake();

        if (execute_thread -> tx_thread_win32_suspension_type == 0)
        {

            /* Release the critical section while the scheduler runs.  */
            _tx_win32_critical_section_release_all(&_tx_win32_critical_section);
            WaitForSingleObject(_tx_win32_isr_semaphore, INFINITE);
            _tx_win32_critical_section_obtain(&_tx_win32_critical_section);
            while (WaitForSingleObject(_tx_win32_isr_semaphore, 0) == WAIT_OBJECT_0)
            {
            }
        }

        _tx_win32_timer_waiting =  TX_FALSE;
    }

    /* Leave Win32 critical section.  */
    _tx_win32_critical_section_release_all(&_tx_win32_critical_section);
}


