mirror of
https://github.com/eclipse-threadx/threadx.git
synced 2026-08-17 09:33:32 +08:00
Windows x64 port and regression suite This PR adds the Windows x64 (Win64) simulation port for both the standalone and SMP variants of ThreadX, along with the full CMake build and test infrastructure needed to run the regression suite on Windows. New ports Win64 standalone (ports/win64/vs_2022): self-contained Windows simulation port using Win32 threading primitives as virtual cores. Includes CMake integration, build/test scripts, and MSVC project files. Win64 SMP (ports/win64_smp/vs_2022): multi-core Windows simulation port. Supports up to 4 virtual cores backed by Windows host threads. Scheduler and timer improvements The initial port used coarse polling and synchronous SuspendThread/ResumeThread pairs throughout the scheduler hot path. Several rounds of optimization reduced the SMP regression suite runtime from ~150 s to ~78 s (-48%), with no regressions: - Replaced scheduler polling with an event-driven wake path; switched the simulated timer to one-shot rearming to eliminate catch-up ticks. - Skip SuspendThread when _tx_thread_preempt_disable != 0 (new suspension type 3) -- the primary optimization, yielding up to 7.9x speedup on preemption-heavy tests. - Skip SuspendThread when a thread is spinning on the Win32 critical section (suspension type 4), and fix a stale-TLS bug in _tx_win32_critical_section_obtain that could stamp mutex_access on the wrong virtual core. - Added a 2 ms scheduler event timeout (matching the Linux SMP port) to prevent stalls on any missed SetEvent. - Enabled high-resolution waitable timers (SetWaitableTimerEx) for accurate 100 Hz tick cadence. - Increased TX_WIN32_CONTENTION_PAUSE_COUNT from 64 to 256 to reduce SwitchToThread overhead under heavy CS contention. Build and test infrastructure - Hardened the Windows build wrapper (scripts/build_tx.ps1): invoke Ninja directly for Ninja build trees, fix timeout detection, add a default build timeout, and limit fallback replay to real timeout cases. - Added -Clean support to Windows test scripts to remove stale CTest state before each run. - Skip Visual Studio DevShell re-entry when the active MSVC environment already matches the requested architecture. - Fixed scripts/build_tx.sh (Linux) regression source generation: replaced brittle exact-string insertion with line-based matching so the interrupt dispatcher hook is inserted reliably for both simulator ports. Test suite updates - Introduced test/tx/regression/threadx_test_port.h with portable macros (TX_TEST_POINTER_WORD, TX_TEST_STORE_POINTER) for storing pointers in test arrays on 64-bit targets where ULONG remains 32-bit. - Adjusted pool-capacity and pointer-storage patterns in regression tests to use ALIGN_TYPE-sized slots, making the suite correct on 64-bit hosts. - Restored stricter event flag, sleep, and timer expectations now that port-level fixes make prior Windows accommodations unnecessary. - Tightened SMP watchdog and clean-build timeout defaults. Version metadata Updated Win32, Win64, and Win64 SMP port version strings to 6.5.1.202602. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Codex (gpt 5.5) <codex@openai.com>
300 lines
10 KiB
C
300 lines
10 KiB
C
/***************************************************************************
|
|
* 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 */
|
|
/** */
|
|
/** Timer */
|
|
/** */
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
#define TX_SOURCE_CODE
|
|
|
|
|
|
/* Include necessary system files. */
|
|
|
|
#include "tx_api.h"
|
|
#include "tx_thread.h"
|
|
#include "tx_timer.h"
|
|
|
|
|
|
/* Check for the TX_NO_TIMER option. When defined, do not define all of the
|
|
timer component global variables. */
|
|
|
|
#ifndef TX_NO_TIMER
|
|
|
|
|
|
/* Define the system clock value that is continually incremented by the
|
|
periodic timer interrupt processing. */
|
|
|
|
volatile ULONG _tx_timer_system_clock;
|
|
|
|
|
|
/* Define the time-slice expiration flag. This is used to indicate that a time-slice
|
|
has happened. */
|
|
|
|
UINT _tx_timer_expired_time_slice;
|
|
|
|
|
|
/* Define the thread and application timer entry list. This list provides a direct access
|
|
method for insertion of times less than TX_TIMER_ENTRIES. */
|
|
|
|
TX_TIMER_INTERNAL *_tx_timer_list[TX_TIMER_ENTRIES];
|
|
|
|
|
|
/* Define the boundary pointers to the list. These are setup to easily manage
|
|
wrapping the list. */
|
|
|
|
TX_TIMER_INTERNAL **_tx_timer_list_start;
|
|
TX_TIMER_INTERNAL **_tx_timer_list_end;
|
|
|
|
|
|
/* Define the current timer pointer in the list. This pointer is moved sequentially
|
|
through the timer list by the timer interrupt handler. */
|
|
|
|
TX_TIMER_INTERNAL **_tx_timer_current_ptr;
|
|
|
|
|
|
/* Define the timer expiration flag. This is used to indicate that a timer
|
|
has expired. */
|
|
|
|
UINT _tx_timer_expired;
|
|
|
|
|
|
/* Define the created timer list head pointer. */
|
|
|
|
TX_TIMER *_tx_timer_created_ptr;
|
|
|
|
|
|
/* Define the created timer count. */
|
|
|
|
ULONG _tx_timer_created_count;
|
|
|
|
|
|
/* Define the pointer to the timer that has expired and is being processed. */
|
|
|
|
TX_TIMER_INTERNAL *_tx_timer_expired_timer_ptr;
|
|
|
|
|
|
#ifndef TX_TIMER_PROCESS_IN_ISR
|
|
|
|
/* Define the timer thread's control block. */
|
|
|
|
TX_THREAD _tx_timer_thread;
|
|
|
|
|
|
/* Define the variable that holds the timer thread's starting stack address. */
|
|
|
|
VOID *_tx_timer_stack_start;
|
|
|
|
|
|
/* Define the variable that holds the timer thread's stack size. */
|
|
|
|
ULONG _tx_timer_stack_size;
|
|
|
|
|
|
/* Define the variable that holds the timer thread's priority. */
|
|
|
|
UINT _tx_timer_priority;
|
|
|
|
/* Define the system timer thread's stack. The default size is defined
|
|
in tx_port.h. */
|
|
|
|
ULONG _tx_timer_thread_stack_area[(((UINT) TX_TIMER_THREAD_STACK_SIZE)+((sizeof(ULONG))- ((UINT) 1)))/(sizeof(ULONG))];
|
|
|
|
#else
|
|
|
|
|
|
/* Define the busy flag that will prevent nested timer ISR processing. */
|
|
|
|
UINT _tx_timer_processing_active;
|
|
|
|
#endif
|
|
|
|
#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
|
|
|
|
/* Define the total number of timer activations. */
|
|
|
|
ULONG _tx_timer_performance_activate_count;
|
|
|
|
|
|
/* Define the total number of timer reactivations. */
|
|
|
|
ULONG _tx_timer_performance_reactivate_count;
|
|
|
|
|
|
/* Define the total number of timer deactivations. */
|
|
|
|
ULONG _tx_timer_performance_deactivate_count;
|
|
|
|
|
|
/* Define the total number of timer expirations. */
|
|
|
|
ULONG _tx_timer_performance_expiration_count;
|
|
|
|
|
|
/* Define the total number of timer expiration adjustments. These are required
|
|
if the expiration time is greater than the size of the timer list. In such
|
|
cases, the timer is placed at the end of the list and then reactivated
|
|
as many times as necessary to finally achieve the resulting timeout. */
|
|
|
|
ULONG _tx_timer_performance__expiration_adjust_count;
|
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/* Define the current time slice value. If non-zero, a time-slice is active.
|
|
Otherwise, the time_slice is not active. */
|
|
|
|
ULONG _tx_timer_time_slice;
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _tx_timer_initialize PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* William E. Lamie, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function initializes the various control data structures for */
|
|
/* the clock control component. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* None */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* None */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* _tx_thread_create Create the system timer thread */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* _tx_initialize_high_level High level initialization */
|
|
/* */
|
|
/**************************************************************************/
|
|
VOID _tx_timer_initialize(VOID)
|
|
{
|
|
#ifndef TX_NO_TIMER
|
|
#ifndef TX_TIMER_PROCESS_IN_ISR
|
|
UINT status;
|
|
#endif
|
|
|
|
#ifndef TX_DISABLE_REDUNDANT_CLEARING
|
|
|
|
/* Initialize the system clock to 0. */
|
|
_tx_timer_system_clock = ((ULONG) 0);
|
|
|
|
/* Initialize the time-slice value to 0 to make sure it is disabled. */
|
|
_tx_timer_time_slice = ((ULONG) 0);
|
|
|
|
/* Clear the expired flags. */
|
|
_tx_timer_expired_time_slice = TX_FALSE;
|
|
_tx_timer_expired = TX_FALSE;
|
|
|
|
/* Set the currently expired timer being processed pointer to NULL. */
|
|
_tx_timer_expired_timer_ptr = TX_NULL;
|
|
|
|
/* Initialize the thread and application timer management control structures. */
|
|
|
|
/* First, initialize the timer list. */
|
|
TX_MEMSET(&_tx_timer_list[0], 0, (sizeof(_tx_timer_list)));
|
|
#endif
|
|
|
|
/* Initialize all of the list pointers. */
|
|
_tx_timer_list_start = &_tx_timer_list[0];
|
|
_tx_timer_current_ptr = &_tx_timer_list[0];
|
|
|
|
/* Set the timer list end pointer to one past the actual timer list. This is done
|
|
to make the timer interrupt handling in assembly language a little easier. */
|
|
_tx_timer_list_end = &_tx_timer_list[TX_TIMER_ENTRIES-((ULONG) 1)];
|
|
_tx_timer_list_end = TX_TIMER_POINTER_ADD(_tx_timer_list_end, ((ULONG) 1));
|
|
|
|
#ifndef TX_TIMER_PROCESS_IN_ISR
|
|
|
|
/* Setup the variables associated with the system timer thread's stack and
|
|
priority. */
|
|
_tx_timer_stack_start = (VOID *) &_tx_timer_thread_stack_area[0];
|
|
_tx_timer_stack_size = ((ULONG) TX_TIMER_THREAD_STACK_SIZE);
|
|
_tx_timer_priority = ((UINT) TX_TIMER_THREAD_PRIORITY);
|
|
|
|
/* Create the system timer thread. This thread processes all of the timer
|
|
expirations and reschedules. Its stack and priority are defined in the
|
|
low-level initialization component. */
|
|
do
|
|
{
|
|
|
|
|
|
/* Create the system timer thread. */
|
|
status = _tx_thread_create(&_tx_timer_thread,
|
|
TX_CONST_CHAR_TO_CHAR_POINTER_CONVERT("System Timer Thread"),
|
|
_tx_timer_thread_entry,
|
|
((ULONG) TX_TIMER_ID),
|
|
_tx_timer_stack_start, _tx_timer_stack_size,
|
|
_tx_timer_priority, _tx_timer_priority, TX_NO_TIME_SLICE, TX_DONT_START);
|
|
|
|
|
|
#ifdef TX_SAFETY_CRITICAL
|
|
|
|
/* Check return from thread create - if an error is detected throw an exception. */
|
|
if (status != TX_SUCCESS)
|
|
{
|
|
|
|
/* Raise safety critical exception. */
|
|
TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, status);
|
|
}
|
|
#endif
|
|
|
|
/* Define timer initialize extension. */
|
|
TX_TIMER_INITIALIZE_EXTENSION(status)
|
|
|
|
} while (status != TX_SUCCESS);
|
|
|
|
#else
|
|
|
|
/* Clear the timer interrupt processing active flag. */
|
|
_tx_timer_processing_active = TX_FALSE;
|
|
#endif
|
|
|
|
#ifndef TX_DISABLE_REDUNDANT_CLEARING
|
|
|
|
/* Initialize the head pointer of the created application timer list. */
|
|
_tx_timer_created_ptr = TX_NULL;
|
|
|
|
/* Set the created count to zero. */
|
|
_tx_timer_created_count = TX_EMPTY;
|
|
|
|
#ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
|
|
|
|
/* Initialize timer performance counters. */
|
|
_tx_timer_performance_activate_count = ((ULONG) 0);
|
|
_tx_timer_performance_reactivate_count = ((ULONG) 0);
|
|
_tx_timer_performance_deactivate_count = ((ULONG) 0);
|
|
_tx_timer_performance_expiration_count = ((ULONG) 0);
|
|
_tx_timer_performance__expiration_adjust_count = ((ULONG) 0);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
}
|