Hello!
Before I send it to wine-patches I'd like developers to look at it because
it's an important issue and I'm not 100% sure that it's the best fix.
I'm trying to compile CVS with without optimization and it fails:
make[1]: Entering directory `/usr/local/src/wine/miscemu'
gcc -o wine -Wl,--section-start,.interp=0x3c000100 main.o -L../dlls
-lntdll.dll -L../libs/wine -lwine -L../libs/unicode -lwine_unicode
-L../libs/port -lwine_port
../dlls/libntdll.dll.so: undefined reference to
`InterlockedCompareExchange'
InterlockedCompareExchange() is defined as extern inline in
include/winbase.h for i386 and PowerPC. It's defined extern for other
architectures.
It's implemented in dlls/kernel/sync.c for all architectures, either in
assembly code or as a call to interlocked_cmpxchg(). The implementation
is linked into kernel32.dll.
interlocked_cmpxchg() is declared in include/wine/port.h and implemented
in libs/port/interlocked.c. It's exported by libwine_port.a.
The unresolved call to InterlockedCompareExchange comes from
wine/win32/device.c, which is linked into ntdll.dll. Actually, device.c
calls InterlockedCompareExchangePointer(), which is a static inline
function that calls InterlockedCompareExchange().
If optimization if off, InterlockedCompareExchangePointer() is used as a
static function in wine/win32/device.c, and it calls external function
InterlockedCompareExchange().
When the wine executable is linked, it's linked against ntdll.dll, but not
against kernel32.dll. Therefore, the reference to
InterlockedCompareExchange() in ntdll.dll is not satisfied.
I see two solutions. One is to link wine executable against kernel32.dll.
Another is to use the low-level function interlocked_cmpxchg_ptr(), which
is what other code linked with "wine" does.
I prefer the second solution for its simplicity and consistency. But I
don't know, maybe dependency of ntdll.dll and wine executable on
kernel32.dll is OK. Then we could eliminate low-level
interlocked_cmpxchg() and use Win32 API functions for interlocking.
Anyway, here's the patch. It works for me (Linux 2.4.23-pre4, gcc 3.2.2
from Red Hat 9, AMD Athlon). Tested with winemine, notepad and Windows
Commander under Wine compiled with CFLAGS=-g
=================================
--- win32/device.c
+++ win32/device.c
@@ -611,7 +611,7 @@ static HKEY create_special_root_hkey( HK
if (NtCreateKey( &hkey, access, &attr, 0, NULL, 0, NULL )) return 0;
}
- if (!(ret = InterlockedCompareExchangePointer( (PVOID) &special_root_keys[idx], hkey, 0 )))
+ if (!(ret = interlocked_cmpxchg_ptr( (PVOID) &special_root_keys[idx], hkey, 0 )))
ret = hkey;
else
NtClose( hkey ); /* somebody beat us to it */
=================================
--
Regards,
Pavel Roskin