itsmattkc / dotnet9x

Backport of .NET 2.0 - 3.5 to Windows 9x
2.24k stars 146 forks source link

InterlockedCompareExchange atomic implementation #19

Open friendlyanon opened 5 months ago

friendlyanon commented 5 months ago

This reimplementation of the function is obviously not atomic:

https://github.com/itsmattkc/dotnet9x/blob/ee01c8e767d406ec002b0903e716dede98d39ee1/wrappers/kernel32.c#L1777-L1789

However, this could be properly implemented in assembly via CMPXCHG if you require at least a 486 processor. Windows 95 requires at least a 386, so this would mean excluding only the oldest supported processor family for a correct implementation.

Detecting if the system is at least a 486 is also trivial, due to being able to set the AC bit in EFLAGS from user mode (https://en.wikipedia.org/wiki/FLAGS_register).

cargoudel commented 5 months ago

You could add the check for 486 and then do the atomic operation if you have support. Otherwise fall-through into the original non-atomic one as a known/current limitation to 386 support.

friendlyanon commented 5 months ago

True, but that would be a correctness compromise.

whindsaks commented 5 months ago

Otherwise fall-through into the original non-atomic one

Win98 used a driver for this when running on a 386

andresvettori commented 5 months ago

According to Copilot, on a 386 processor, which does not support the CMPXCHG instruction, you could use the XCHG instruction in combination with a LOCK prefix to achieve similar functionality. The XCHG instruction exchanges the values of two operands, and the LOCK prefix ensures that the operation is atomic, preventing other processors from accessing the memory location during the operation

An example implementation using XCHG:

mov eax, [Comparand] ; Load Comparand into EAX register mov ebx, [Destination] ; Load Destination into EBX register mov ecx, [Exchange] ; Load Exchange into ECX register

cmp [ebx], eax ; Compare value at EBX with EAX jne done ; If not equal, jump to done lock xchg [ebx], ecx ; If equal, exchange values atomically

done:

See: https://www.felixcloutier.com/x86/xchg

What do you think?

iProgramMC commented 5 months ago

That isn't really atomic. Something could still end up changing the value of [ebx] before the lock xchg is performed.

whindsaks commented 4 months ago

While the minimum requirements of Windows 95 is a 386 with 4MB RAM, it is not really a useful system and will start swapping as soon as you do anything. Even a 486 cannot play a mp3 in WinAmp v1 without skipping.

What I'm asking is, does anyone really care about pre-Pentium hardware as their .Net host? As a box to run DOS games in real mode on, sure. Running anything made after 1997? Not really?

easyaspi314 commented 1 month ago

While the minimum requirements of Windows 95 is a 386 with 4MB RAM, it is not really a useful system and will start swapping as soon as you do anything. Even a 486 cannot play a mp3 in WinAmp v1 without skipping.

What I'm asking is, does anyone really care about pre-Pentium hardware as their .Net host? As a box to run DOS games in real mode on, sure. Running anything made after 1997? Not really?

Counterpoint: Does anyone really care about Windows 95 as their .Net host?

this project isn't about being practical, it's about pushing the limits.

whindsaks commented 1 month ago

this project isn't about being practical, it's about pushing the limits.

The problem is, supporting the 386 will make everyone slower because the code has to branch or do an indirect call.