Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InterlockedCompareExchange atomic implementation #19

Open
friendlyanon opened this issue Apr 14, 2024 · 8 comments · May be fixed by #21
Open

InterlockedCompareExchange atomic implementation #19

friendlyanon opened this issue Apr 14, 2024 · 8 comments · May be fixed by #21

Comments

@friendlyanon
Copy link

This reimplementation of the function is obviously not atomic:

dotnet9x/wrappers/kernel32.c

Lines 1777 to 1789 in ee01c8e

// Reimplemented
LONG WINAPI CORKEL32_InterlockedCompareExchange(LONG *dest, LONG xchg, LONG compare)
{
LONG temp = *dest;
Trace(TRACE_FORCE_DONT_PRINT, "InterlockedCompareExchange");
if (compare == *dest) {
*dest = xchg;
}
return temp;
}

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
Copy link

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
Copy link
Author

True, but that would be a correctness compromise.

@friendlyanon friendlyanon linked a pull request Apr 14, 2024 that will close this issue
@whindsaks
Copy link

Otherwise fall-through into the original non-atomic one

Win98 used a driver for this when running on a 386

@andresvettori
Copy link

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
Copy link

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

@whindsaks
Copy link

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
Copy link

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
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants