Blaukovitch / API-MS-WIN_XP

Microsoft API libs Windows 11/10/8/ to Windows XP
https://microsoft.com
69 stars 7 forks source link

API-MS-WIN-CORE-SYNCH-L1-2-0.dll: WaitOnAddress\WakeByAddressAll\WakeByAddressSingle #6

Open devobject opened 3 weeks ago

devobject commented 3 weeks ago

Привет.

Чтобы исправить проблему "May be 100% CPU load or freeze – «API-MS-WIN-CORE-SYNCH-L1-2-0.dll»" - нужно все таки корректно реализовать функции: WaitOnAddress, WakeByAddressAll, WakeByAddressSingle. Если не охота, ковыряться в недрах винды\вайна, то можно поступить проще и взять их аналоги из msvcp140_atomic_wait.dll

Вот рабочий C код:

#include <windows.h>
#pragma comment(lib, "libcpmt.lib") //static

// from xatomic_wait.h
typedef BOOL (__stdcall *_Atomic_wait_indirect_equal_callback_t) (const void* _Storage, void* _Comparand, size_t _Size, void* _Param);
int __stdcall __std_atomic_wait_indirect(const void* _Storage, void* _Comparand, size_t _Size, void* _Param, _Atomic_wait_indirect_equal_callback_t _Are_equal, unsigned long _Remaining_timeout);
void __stdcall __std_atomic_notify_one_indirect(const void* _Storage);
void __stdcall __std_atomic_notify_all_indirect(const void* _Storage);

BOOL __stdcall _Atomic_wait_are_equal_direct_fallback(const void* _Storage, void* _Comparand, size_t _Size, void* _Param) {
    switch (_Size) {
        case 1:
            return (*(const UCHAR *)  _Storage == *(const UCHAR *)_Comparand);
        case 2:
            return (*(const USHORT *) _Storage == *(const USHORT *)_Comparand);
        case 4:
            return (*(const ULONG *)  _Storage == *(const ULONG *)_Comparand);
        case 8:
            return (*(const ULONG64 *)_Storage == *(const ULONG64 *)_Comparand);
        default:
            return FALSE;
    }
}

BOOL WINAPI WaitOnAddress(const void *Address, PVOID CompareAddress, SIZE_T AddressSize, DWORD Milliseconds OPTIONAL) {
    return __std_atomic_wait_indirect(Address, CompareAddress, AddressSize, 0, _Atomic_wait_are_equal_direct_fallback, Milliseconds);
}

void WINAPI WakeByAddressAll(const void *addr) {
    __std_atomic_notify_all_indirect(addr);
}

void WINAPI WakeByAddressSingle(const void *addr) {
    __std_atomic_notify_one_indirect(addr);
}

Есть побочный эффект, с которым не разбрался, линкер зачем-то в пустую линкует функцию __CxxFrameHandler из VCRUNTIME140.dll.

PS: Еще можно сильно упростить себе задачу написания прокси функции. Заменив их forward экспортом: в файле .def пишем:

LIBRARY ...
EXPORTS
SystemFunction036=advapi32.SystemFunction036
SystemFunction040=advapi32.SystemFunction040
SystemFunction041=advapi32.SystemFunction041
... и т.д
Blaukovitch commented 3 weeks ago

О, спасибо!

VCRUNTIME140.dll. SystemFunction036... Прочекаю в следующих выпусках.