diff options
Diffstat (limited to 'ports/win64/vs_2022/src/tx_thread_schedule.c')
| -rw-r--r-- | ports/win64/vs_2022/src/tx_thread_schedule.c | 85 |
1 files changed, 36 insertions, 49 deletions
diff --git a/ports/win64/vs_2022/src/tx_thread_schedule.c b/ports/win64/vs_2022/src/tx_thread_schedule.c index d08305ee..204a1e90 100644 --- a/ports/win64/vs_2022/src/tx_thread_schedule.c +++ b/ports/win64/vs_2022/src/tx_thread_schedule.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -111,8 +111,27 @@ DWORD wait_status; /* Leave the critical section. */ _tx_win32_critical_section_release(&_tx_win32_critical_section); - /* Wait for the next scheduling state change. */ - WaitForSingleObject(_tx_win32_scheduler_wake_event, INFINITE); +#ifdef TX_WIN32_NO_IDLE_ENABLE + + /* No thread is ready to run: advance the simulated clock now + instead of waiting for the wall-clock periodic timer. Kick + the timer thread so it fires the next tick(s) immediately, + then wait for it to signal progress via the wake event. A + short bounded timeout guards against a missed wake. This + makes idle periods CPU-bound rather than wall-clock-bound, + mirroring the Linux port's TX_LINUX_NO_IDLE_ENABLE path. */ + SetEvent(_tx_win32_timer_kick_event); + WaitForSingleObject(_tx_win32_scheduler_wake_event, 2); +#else + + /* Yield to other threads (timer, application threads) instead of + blocking indefinitely. This spin-poll eliminates the ~0.5 ms + kernel-wake latency of WaitForSingleObject(INFINITE) and reduces + context-switch overhead by >10x at the cost of higher CPU usage + during test runs. Drain any pending wake event to keep it clean. */ + WaitForSingleObject(_tx_win32_scheduler_wake_event, 0); + SwitchToThread(); +#endif } } @@ -185,12 +204,16 @@ DWORD wait_status; /* Exit Win32 critical section. */ _tx_win32_critical_section_release(&_tx_win32_critical_section); - /* Now suspend the main thread so the application thread can run. */ - WaitForSingleObject(_tx_win32_scheduler_semaphore, INFINITE); + /* Spin-poll for the application thread to return control. Using + SwitchToThread() between polls yields the CPU without blocking, + matching the low-latency approach used in the idle loop above. */ + while (WaitForSingleObject(_tx_win32_scheduler_semaphore, 0) != WAIT_OBJECT_0) + SwitchToThread(); } } + static VOID _tx_win32_semaphore_reset(HANDLE semaphore_handle) { @@ -216,17 +239,9 @@ void _tx_win32_critical_section_obtain(TX_WIN32_CRITICAL_SECTION *critical_se { /* Get the Win32 critical section. */ - if (WaitForSingleObject(critical_section -> tx_win32_critical_section_mutex_handle, INFINITE) != WAIT_OBJECT_0) - { - - /* Increment the system error counter and stop when the mutex cannot be acquired. */ - _tx_win32_system_error++; - while(1) - { - } - } + EnterCriticalSection(&critical_section -> tx_win32_critical_section_lock); - /* At this point we have the mutex. */ + /* At this point we have the critical section. */ /* Increment the nesting counter. */ critical_section -> tx_win32_critical_section_nested_count = 1; @@ -241,7 +256,7 @@ void _tx_win32_critical_section_release(TX_WIN32_CRITICAL_SECTION *critical_s { - /* Ensure the caller is the mutex owner. */ + /* Ensure the caller is the critical section owner. */ if (critical_section -> tx_win32_critical_section_owner == GetCurrentThreadId()) { @@ -259,21 +274,8 @@ void _tx_win32_critical_section_release(TX_WIN32_CRITICAL_SECTION *critical_s /* Yes, it is being released clear the owner. */ critical_section -> tx_win32_critical_section_owner = 0; - /* Finally, release the mutex. */ - if (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) != TX_TRUE) - { - - /* Increment the system error counter. */ - _tx_win32_system_error++; - } - - /* Just in case, make sure there the mutex is not owned. */ - while (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) == TX_TRUE) - { - - /* Increment the system error counter. */ - _tx_win32_system_error++; - } + /* Finally, release the critical section. */ + LeaveCriticalSection(&critical_section -> tx_win32_critical_section_lock); } } } @@ -289,7 +291,7 @@ void _tx_win32_critical_section_release(TX_WIN32_CRITICAL_SECTION *critical_s void _tx_win32_critical_section_release_all(TX_WIN32_CRITICAL_SECTION *critical_section) { - /* Ensure the caller is the mutex owner. */ + /* Ensure the caller is the critical section owner. */ if (critical_section -> tx_win32_critical_section_owner == GetCurrentThreadId()) { @@ -303,21 +305,8 @@ void _tx_win32_critical_section_release_all(TX_WIN32_CRITICAL_SECTION *cri /* Yes, it is being release clear the owner. */ critical_section -> tx_win32_critical_section_owner = 0; - /* Finally, release the mutex. */ - if (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) != TX_TRUE) - { - - /* Increment the system error counter. */ - _tx_win32_system_error++; - } - - /* Just in case, make sure there the mutex is not owned. */ - while (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) == TX_TRUE) - { - - /* Increment the system error counter. */ - _tx_win32_system_error++; - } + /* Finally, release the critical section. */ + LeaveCriticalSection(&critical_section -> tx_win32_critical_section_lock); } } else @@ -327,5 +316,3 @@ void _tx_win32_critical_section_release_all(TX_WIN32_CRITICAL_SECTION *cri _tx_win32_system_error++; } } - - |
