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 */ =================================
Pavel Roskin wrote:
Hello!
I see two solutions. One is to link wine executable against kernel32.dll.
I don't think you can do that. As kernel32.dll requires ntdll, you would create a real circular dependancy.
Another is to use the low-level function interlocked_cmpxchg_ptr(), which is what other code linked with "wine" does.
On Thu, 18 Sep 2003, Shachar Shemesh wrote:
I see two solutions. One is to link wine executable against kernel32.dll.
I don't think you can do that. As kernel32.dll requires ntdll, you would create a real circular dependancy.
Thanks for the reply. I see that some other patch has been applied to win32/device.c so it's now possible to compile Wine without optimization.