This fixes https://bugs.winehq.org/show_bug.cgi?id=52094.
For reference, here's how current_modref is being passed around (before this patch):
```mermaid
graph TB
fii["fixup_imports_ilonly<br><em style='color:#ff0'>(directly sets current_modref)</em>"]
fi["fixup_imports<br><em style='color:#ff0'>(directly sets current_modref)</em>"]
pa["process_attach<br><em style='color:#ff0'>(directly sets current_modref)</em>"]
ld[load_dll]
id["import_dll<br><em style='color:#0f0'>(directly uses current_modref)</em>"]
bin["build_import_name<br><em style='color:#0f0'>(directly uses current_modref)</em>"]
foe["find_ordinal_export<br><em style='color:#0f0'>(uses current_modref for relay)</em>"]
ffe["find_forwarded_export<br><em style='color:#0f0'>(directly uses current_modref)</em>"]
fne[find_named_export]
MI[MODULE_InitDLL]
fii --> ld
fi --> id
pa --> MI -.-> DllMain
id --> bin
id --> ld
id --> foe
id --> fne --> foe --> ffe --> foe
ffe --> fne
ffe --> bin
style DllMain color:red;
```
--
v15: ntdll: Remove superflous NULL check for importer.
ntdll: Properly track refcount on dynamic imports of export forwarders.
ntdll: Explicitly ignore dynamic (GetProcAddress) importers as relay/snoop user module.
ntdll: Eagerly call process_attach() on dynamic imports of export forwarders.
ntdll: Properly track refcount on static imports of export forwarders.
ntdll: Register module dependency for export forwarders regardless of whether the dependency is already loaded.
ntdll: Don't re-add a module dependency if it already exists.
ntdll: Sink module dependency registration towards the end of the
https://gitlab.winehq.org/wine/wine/-/merge_requests/7
On Thu Feb 20 21:41:59 2025 +0000, Paul Gofman wrote:
> On Windows sleep / timer resolution is 16ms by default however. That can
> be changed systemwide with NtSetTimerResolution() /
> winmm.timeBeginPeriod and AFAIK (didn't test that myself) 0.5ms is the
> best supported resolution (only available through NtSetTimerResolution).
> So it is interesting what the game does exactly, which sort of delays or
> waits affect the performance and how that works on Windows.
> Just making sleep precision as good as possible might instead negatively
> affact the performance in some other games.
Well, for one, I'd like to see an example of a real game that doesn't call timeBeginPeriod(1), but that's besides the point. We already simulate a 1ms timer period by having the tick count increase every millisecond, and this is absolutely not intended to change that.
What this is addressing is unrelated server calls from other threads pushing the **global** `current_time` and `monotonic_time` (updated each timeout) forward. That causes the timeouts for alertable `SleepEx` (used in those games' frame limiters) to expire for up to 1ms from that last update, as it's ceil'd to the next millisecond to avoid spinning with a 0 timeout. This causes, on average, an additional 0.5ms waited, depending on where we land on the tick boundary.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/7392#note_95431
On Windows sleep / timer resolution is 16ms by default however. That can be changed systemwide with NtSetTimerResolution() / winmm.timeBeginPeriod and AFAIK (didn't test that myself) 0.5ms is the best supported resolution (only available through NtSetTimerResolution). So it is interesting what the game does exactly, which sort of delays or waits affect the performance and how that works on Windows.
Just making sleep precision as good as possible might instead negatively affact the performance in some other games.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/7392#note_95428