/***************************************************************************
 * 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 <stdio.h>


/* Prototype for new thread entry function.  */

DWORD WINAPI _tx_win32_thread_entry(LPVOID p);


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _tx_thread_stack_build                            Win64/MSVC      */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    William E. Lamie, Microsoft Corporation                             */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function builds a stack frame on the supplied thread's stack.  */
/*    The stack frame results in a fake interrupt return to the supplied  */
/*    function pointer.                                                   */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    thread_ptr                            Pointer to thread control blk */
/*    function_ptr                          Pointer to return function    */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    CreateThread                          Win32 create thread           */
/*    ResumeThread                          Win32 resume thread           */
/*    SetThreadPriority                     Win32 set thread priority     */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _tx_thread_create                     Create thread service         */
/*    _tx_thread_reset                      Reset thread service          */
/*                                                                        */
/**************************************************************************/
VOID   _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID))
{

    /* Create a Win32 thread for the application thread.  */
    thread_ptr -> tx_thread_win32_thread_handle =
        CreateThread(NULL, 0, _tx_win32_thread_entry, (LPVOID) thread_ptr, CREATE_SUSPENDED,
                        &(thread_ptr -> tx_thread_win32_thread_id));

    /* Check for a good thread create.  */
    if (!thread_ptr -> tx_thread_win32_thread_handle)
    {

        /* Display an error message.  */
        printf("ThreadX Win32 error creating thread!\n");
        while(1)
        {
        }
    }

    /* Otherwise, we have a good thread create.  Now set the priority to
       a lower level.  */
    SetThreadPriority(thread_ptr -> tx_thread_win32_thread_handle, THREAD_PRIORITY_LOWEST);

    /* Create the run semaphore for the thread.  This will allow the scheduler
       control over when the thread actually runs.  */
    thread_ptr -> tx_thread_win32_thread_run_semaphore =  CreateSemaphore(NULL, 0, 1, NULL);

    /* Determine if the run semaphore was created successfully.  */
    if (!thread_ptr -> tx_thread_win32_thread_run_semaphore)
    {

        /* Display an error message.  */
        printf("ThreadX Win32 error creating thread running semaphore!\n");
        while(1)
        {
        }
    }

    /* Create the scheduler acknowledgement semaphore for this thread.  */
    thread_ptr -> tx_thread_win32_thread_start_semaphore =  CreateSemaphore(NULL, 0, 1, NULL);

    /* Determine if the start semaphore was created successfully.  */
    if (!thread_ptr -> tx_thread_win32_thread_start_semaphore)
    {

        /* Display an error message.  */
        printf("ThreadX Win32 error creating thread start semaphore!\n");
        while(1)
        {
        }
    }

    /* Setup the thread suspension type to solicited thread suspension.
       Pseudo interrupt handlers will suspend with this field set to 1.  */
    thread_ptr -> tx_thread_win32_suspension_type =  0;

    /* Clear the disabled count that will keep track of the
       tx_interrupt_control nesting.  */
    thread_ptr -> tx_thread_win32_int_disabled_flag =  0;

    /* Setup a fake thread stack pointer.   */
    thread_ptr -> tx_thread_stack_ptr =  (VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8);

    /* Clear the first word of the stack.  */
    *(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) =  0;

    /* Make the thread initially ready so it will run to the initial wait on
       its run semaphore.  */
    ResumeThread(thread_ptr -> tx_thread_win32_thread_handle);

    /* Wait until the host thread is parked at the controlled handoff point
       before ThreadX can schedule it.  */
    if (WaitForSingleObject(thread_ptr -> tx_thread_win32_thread_start_semaphore, INFINITE) != WAIT_OBJECT_0)
    {

        /* Display an error message.  */
        printf("ThreadX Win32 error synchronizing thread startup!\n");
        while(1)
        {
        }
    }
}


DWORD WINAPI _tx_win32_thread_entry(LPVOID ptr)
{

TX_THREAD   *thread_ptr;
TX_THREAD   *current_thread_ptr;
HANDLE      threadhandle;
int         threadpriority;
DWORD       threadid;

    /* Pickup the current thread pointer.  */
    thread_ptr =  (TX_THREAD *) ptr;

    /* Tell the creator that this host thread has reached the controlled
       handoff point and is ready to be scheduled.  */
    ReleaseSemaphore(thread_ptr -> tx_thread_win32_thread_start_semaphore, 1, NULL);

    /* Now suspend the thread initially.  If the thread has already
       been scheduled, this will return immediately.  */
    WaitForSingleObject(thread_ptr -> tx_thread_win32_thread_run_semaphore, INFINITE);

    /* Acknowledge that the host thread is now able to execute ThreadX code.  */
    ReleaseSemaphore(thread_ptr -> tx_thread_win32_thread_start_semaphore, 1, NULL);

    /* A deleted host thread can be released only to let it exit.  In notify-enabled
       builds, the first TX_DISABLE in _tx_thread_shell_entry catches this path.
       When callbacks are disabled, perform the same check before the shell calls
       the stale ThreadX entry function.  */
    _tx_win32_critical_section_obtain(&_tx_win32_critical_section);
    threadhandle =       GetCurrentThread();
    threadpriority =     GetThreadPriority(threadhandle);
    threadid =           GetCurrentThreadId();
    current_thread_ptr = _tx_thread_current_ptr;
    if ((threadpriority == THREAD_PRIORITY_LOWEST) &&
        ((current_thread_ptr == TX_NULL) || (current_thread_ptr -> tx_thread_win32_thread_id != threadid)))
    {
        _tx_win32_critical_section_release_all(&_tx_win32_critical_section);
        ExitThread(0);
    }
    _tx_win32_critical_section_release(&_tx_win32_critical_section);

    /* Call ThreadX thread entry point.  */
    _tx_thread_shell_entry();

    return EXIT_SUCCESS;
}


