From c0ea1ad37d3343c403d80ee18bf0d90c2699148b Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Tue, 30 Nov 2021 19:19:06 +0100 Subject: [PATCH] msvcr100: Add _Timer class implementation. Signed-off-by: Piotr Caban Signed-off-by: Alexandre Julliard --- dlls/concrt140/concrt140.spec | 24 ++--- dlls/concrt140/tests/concrt140.c | 145 ++++++++++++++++++++++++++++ dlls/msvcr100/msvcr100.spec | 16 +-- dlls/msvcr110/msvcr110.spec | 24 ++--- dlls/msvcr120/msvcr120.spec | 24 ++--- dlls/msvcr120_app/msvcr120_app.spec | 24 ++--- dlls/msvcrt/concurrency.c | 102 +++++++++++++++++++ 7 files changed, 303 insertions(+), 56 deletions(-) diff --git a/dlls/concrt140/concrt140.spec b/dlls/concrt140/concrt140.spec index aff1fb54f38..364a1ad8d84 100644 --- a/dlls/concrt140/concrt140.spec +++ b/dlls/concrt140/concrt140.spec @@ -72,9 +72,9 @@ @ stub -arch=arm ??0_TaskCollection@details@Concurrency@@QAA@XZ @ stub -arch=i386 ??0_TaskCollection@details@Concurrency@@QAE@XZ @ stub -arch=win64 ??0_TaskCollection@details@Concurrency@@QEAA@XZ -@ stub -arch=arm ??0_Timer@details@Concurrency@@IAA@I_N@Z -@ stub -arch=i386 ??0_Timer@details@Concurrency@@IAE@I_N@Z -@ stub -arch=win64 ??0_Timer@details@Concurrency@@IEAA@I_N@Z +@ cdecl -arch=arm ??0_Timer@details@Concurrency@@IAA@I_N@Z(ptr long long) _Timer_ctor +@ thiscall -arch=i386 ??0_Timer@details@Concurrency@@IAE@I_N@Z(ptr long long) _Timer_ctor +@ cdecl -arch=win64 ??0_Timer@details@Concurrency@@IEAA@I_N@Z(ptr long long) _Timer_ctor @ stub -arch=arm ??0agent@Concurrency@@QAA@AAVScheduleGroup@1@@Z @ stub -arch=i386 ??0agent@Concurrency@@QAE@AAVScheduleGroup@1@@Z @ stub -arch=win64 ??0agent@Concurrency@@QEAA@AEAVScheduleGroup@1@@Z @@ -273,9 +273,9 @@ @ stub -arch=arm ??1_TaskCollection@details@Concurrency@@QAA@XZ @ stub -arch=i386 ??1_TaskCollection@details@Concurrency@@QAE@XZ @ stub -arch=win64 ??1_TaskCollection@details@Concurrency@@QEAA@XZ -@ stub -arch=arm ??1_Timer@details@Concurrency@@MAA@XZ -@ stub -arch=i386 ??1_Timer@details@Concurrency@@MAE@XZ -@ stub -arch=win64 ??1_Timer@details@Concurrency@@MEAA@XZ +@ cdecl -arch=arm ??1_Timer@details@Concurrency@@MAA@XZ(ptr) _Timer_dtor +@ thiscall -arch=i386 ??1_Timer@details@Concurrency@@MAE@XZ(ptr) _Timer_dtor +@ cdecl -arch=win64 ??1_Timer@details@Concurrency@@MEAA@XZ(ptr) _Timer_dtor @ stub -arch=arm ??1agent@Concurrency@@UAA@XZ @ stub -arch=i386 ??1agent@Concurrency@@UAE@XZ @ stub -arch=win64 ??1agent@Concurrency@@UEAA@XZ @@ -629,12 +629,12 @@ @ thiscall -arch=i386 ?_SpinOnce@?$_SpinWait@$0A@@details@Concurrency@@QAE_NXZ(ptr) SpinWait__SpinOnce @ cdecl -arch=win64 ?_SpinOnce@?$_SpinWait@$0A@@details@Concurrency@@QEAA_NXZ(ptr) SpinWait__SpinOnce @ cdecl ?_SpinYield@Context@Concurrency@@SAXXZ() Context__SpinYield -@ stub -arch=arm ?_Start@_Timer@details@Concurrency@@IAAXXZ -@ stub -arch=i386 ?_Start@_Timer@details@Concurrency@@IAEXXZ -@ stub -arch=win64 ?_Start@_Timer@details@Concurrency@@IEAAXXZ -@ stub -arch=arm ?_Stop@_Timer@details@Concurrency@@IAAXXZ -@ stub -arch=i386 ?_Stop@_Timer@details@Concurrency@@IAEXXZ -@ stub -arch=win64 ?_Stop@_Timer@details@Concurrency@@IEAAXXZ +@ cdecl -arch=arm ?_Start@_Timer@details@Concurrency@@IAAXXZ(ptr) _Timer__Start +@ thiscall -arch=i386 ?_Start@_Timer@details@Concurrency@@IAEXXZ(ptr) _Timer__Start +@ cdecl -arch=win64 ?_Start@_Timer@details@Concurrency@@IEAAXXZ(ptr) _Timer__Start +@ cdecl -arch=arm ?_Stop@_Timer@details@Concurrency@@IAAXXZ(ptr) _Timer__Stop +@ thiscall -arch=i386 ?_Stop@_Timer@details@Concurrency@@IAEXXZ(ptr) _Timer__Stop +@ cdecl -arch=win64 ?_Stop@_Timer@details@Concurrency@@IEAAXXZ(ptr) _Timer__Stop @ varargs ?_Trace_agents@Concurrency@@YAXW4Agents_EventType@1@_JZZ(long int64) _Trace_agents @ cdecl -arch=win32 ?_Trace_ppl_function@Concurrency@@YAXABU_GUID@@EW4ConcRT_EventType@1@@Z(ptr long long) _Trace_ppl_function @ cdecl -arch=win64 ?_Trace_ppl_function@Concurrency@@YAXAEBU_GUID@@EW4ConcRT_EventType@1@@Z(ptr long long) _Trace_ppl_function diff --git a/dlls/concrt140/tests/concrt140.c b/dlls/concrt140/tests/concrt140.c index 03e0b2850f2..a6cfe4a809a 100644 --- a/dlls/concrt140/tests/concrt140.c +++ b/dlls/concrt140/tests/concrt140.c @@ -18,6 +18,53 @@ #include "wine/test.h" +#ifdef __i386__ +#include "pshpack1.h" +struct thiscall_thunk +{ + BYTE pop_eax; /* popl %eax (ret addr) */ + BYTE pop_edx; /* popl %edx (func) */ + BYTE pop_ecx; /* popl %ecx (this) */ + BYTE push_eax; /* pushl %eax */ + WORD jmp_edx; /* jmp *%edx */ +}; +#include "poppack.h" + +static ULONG_PTR (WINAPI *call_thiscall_func1)( void *func, void *this ); +static ULONG_PTR (WINAPI *call_thiscall_func3)( void *func, + void *this, const void *a, const void *b ); + +static void init_thiscall_thunk(void) +{ + struct thiscall_thunk *thunk = VirtualAlloc( NULL, sizeof(*thunk), + MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + thunk->pop_eax = 0x58; /* popl %eax */ + thunk->pop_edx = 0x5a; /* popl %edx */ + thunk->pop_ecx = 0x59; /* popl %ecx */ + thunk->push_eax = 0x50; /* pushl %eax */ + thunk->jmp_edx = 0xe2ff; /* jmp *%edx */ + call_thiscall_func1 = (void *)thunk; + call_thiscall_func3 = (void *)thunk; +} + +#define call_func1(func,_this) call_thiscall_func1(func,_this) +#define call_func3(func,_this,a,b) call_thiscall_func3(func,_this,(const void*)(a),(const void*)(b)) + +#else + +#define init_thiscall_thunk() +#define call_func1(func,_this) func(_this) +#define call_func3(func,_this,a,b) func(_this,a,b) + +#endif /* __i386__ */ + +#undef __thiscall +#ifdef __i386__ +#define __thiscall __stdcall +#else +#define __thiscall __cdecl +#endif + typedef void (*vtable_ptr)(void); typedef struct { @@ -28,9 +75,21 @@ typedef struct { Context *ctx; } _Context; +typedef struct { + const vtable_ptr *vtable; + void *timer; + unsigned int elapse; + unsigned char repeat; +} _Timer; + static Context* (__cdecl *p_Context_CurrentContext)(void); static _Context* (__cdecl *p__Context__CurrentContext)(_Context*); +static _Timer* (__thiscall *p__Timer_ctor)(_Timer*,unsigned int,unsigned char); +static void (__thiscall *p__Timer_dtor)(_Timer*); +static void (__thiscall *p__Timer__Start)(_Timer*); +static void (__thiscall *p__Timer__Stop)(_Timer*); + #define SETNOFAIL(x,y) x = (void*)GetProcAddress(module,y) #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0) @@ -50,11 +109,39 @@ static BOOL init(void) if(sizeof(void*) == 8) { /* 64-bit initialization */ SET(p_Context_CurrentContext, "?CurrentContext@Context@Concurrency@@SAPEAV12@XZ"); + SET(p__Timer_ctor, + "??0_Timer@details@Concurrency@@IEAA@I_N@Z"); + SET(p__Timer_dtor, + "??1_Timer@details@Concurrency@@MEAA@XZ"); + SET(p__Timer__Start, + "?_Start@_Timer@details@Concurrency@@IEAAXXZ"); + SET(p__Timer__Stop, + "?_Stop@_Timer@details@Concurrency@@IEAAXXZ"); } else { SET(p_Context_CurrentContext, "?CurrentContext@Context@Concurrency@@SAPAV12@XZ"); +#ifdef __arm__ + SET(p__Timer_ctor, + "??0_Timer@details@Concurrency@@IAA@I_N@Z"); + SET(p__Timer_dtor, + "??1_Timer@details@Concurrency@@MAA@XZ"); + SET(p__Timer__Start, + "?_Start@_Timer@details@Concurrency@@IAAXXZ"); + SET(p__Timer__Stop, + "?_Stop@_Timer@details@Concurrency@@IAAXXZ"); +#else + SET(p__Timer_ctor, + "??0_Timer@details@Concurrency@@IAE@I_N@Z"); + SET(p__Timer_dtor, + "??1_Timer@details@Concurrency@@MAE@XZ"); + SET(p__Timer__Start, + "?_Start@_Timer@details@Concurrency@@IAEXXZ"); + SET(p__Timer__Stop, + "?_Stop@_Timer@details@Concurrency@@IAEXXZ"); +#endif } + init_thiscall_thunk(); return TRUE; } @@ -72,8 +159,66 @@ static void test_CurrentContext(void) ok(ret == &_ctx, "expected %p, got %p\n", &_ctx, ret); } +static HANDLE callback_called; +static void __cdecl timer_callback(_Timer *this) +{ + SetEvent(callback_called); +} + +static void test_Timer(void) +{ + vtable_ptr vtable[2]; + _Timer timer; + DWORD ret; + + callback_called = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(callback_called != NULL, "CreateEvent failed\n"); + + call_func3(p__Timer_ctor, &timer, 1, TRUE); + ok(!timer.timer, "timer already set to %p\n", timer.timer); + ok(timer.elapse == 1, "elapse = %u, expected 0\n", timer.elapse); + ok(timer.repeat, "timer.repeat = FALSE\n"); + vtable[0] = timer.vtable[0]; + vtable[1] = (vtable_ptr)timer_callback; + timer.vtable = vtable; + call_func1(p__Timer__Start, &timer); + ok(timer.timer != NULL, "timer = NULL\n"); + ret = WaitForSingleObject(callback_called, 1000); + ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", ret); + ret = WaitForSingleObject(callback_called, 1000); + ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", ret); + call_func1(p__Timer__Stop, &timer); + ok(!timer.timer, "timer != NULL\n"); + call_func1(p__Timer_dtor, &timer); + + call_func3(p__Timer_ctor, &timer, 1, FALSE); + timer.vtable = vtable; + call_func1(p__Timer__Start, &timer); + ok(timer.timer != NULL, "timer = NULL\n"); + ret = WaitForSingleObject(callback_called, 1000); + ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", ret); + ret = WaitForSingleObject(callback_called, 100); + ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %d\n", ret); + call_func1(p__Timer_dtor, &timer); + + call_func3(p__Timer_ctor, &timer, 0, TRUE); + timer.vtable = vtable; + call_func1(p__Timer__Start, &timer); + ok(timer.timer != NULL, "timer = NULL\n"); + ret = WaitForSingleObject(callback_called, 1000); + ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", ret); + ret = WaitForSingleObject(callback_called, 100); + ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %d\n", ret); + call_func1(p__Timer__Stop, &timer); + ok(!timer.timer, "timer != NULL\n"); + call_func1(p__Timer_dtor, &timer); + + CloseHandle(callback_called); +} + START_TEST(concrt140) { if (!init()) return; test_CurrentContext(); + test_Timer(); } diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec index 339aca6c3ca..19b4cbe96d7 100644 --- a/dlls/msvcr100/msvcr100.spec +++ b/dlls/msvcr100/msvcr100.spec @@ -30,8 +30,8 @@ @ stub -arch=win64 ??0_SpinLock@details@Concurrency@@QEAA@AECJ@Z @ stub -arch=win32 ??0_TaskCollection@details@Concurrency@@QAE@XZ @ stub -arch=win64 ??0_TaskCollection@details@Concurrency@@QEAA@XZ -@ stub -arch=win32 ??0_Timer@details@Concurrency@@IAE@I_N@Z -@ stub -arch=win64 ??0_Timer@details@Concurrency@@IEAA@I_N@Z +@ thiscall -arch=win32 ??0_Timer@details@Concurrency@@IAE@I_N@Z(ptr long long) _Timer_ctor +@ cdecl -arch=win64 ??0_Timer@details@Concurrency@@IEAA@I_N@Z(ptr long long) _Timer_ctor @ thiscall -arch=i386 ??0__non_rtti_object@std@@QAE@ABV01@@Z(ptr ptr) __non_rtti_object_copy_ctor @ cdecl -arch=win64 ??0__non_rtti_object@std@@QEAA@AEBV01@@Z(ptr ptr) __non_rtti_object_copy_ctor @ thiscall -arch=i386 ??0__non_rtti_object@std@@QAE@PBD@Z(ptr ptr) __non_rtti_object_ctor @@ -172,8 +172,8 @@ @ stub -arch=win64 ??1_SpinLock@details@Concurrency@@QEAA@XZ @ stub -arch=win32 ??1_TaskCollection@details@Concurrency@@QAE@XZ @ stub -arch=win64 ??1_TaskCollection@details@Concurrency@@QEAA@XZ -@ stub -arch=win32 ??1_Timer@details@Concurrency@@IAE@XZ -@ stub -arch=win64 ??1_Timer@details@Concurrency@@IEAA@XZ +@ thiscall -arch=win32 ??1_Timer@details@Concurrency@@IAE@XZ(ptr) _Timer_dtor +@ cdecl -arch=win64 ??1_Timer@details@Concurrency@@IEAA@XZ(ptr) _Timer_dtor @ thiscall -arch=i386 ??1__non_rtti_object@std@@UAE@XZ(ptr) __non_rtti_object_dtor @ cdecl -arch=win64 ??1__non_rtti_object@std@@UEAA@XZ(ptr) __non_rtti_object_dtor @ thiscall -arch=i386 ??1bad_cast@std@@UAE@XZ(ptr) bad_cast_dtor @@ -380,10 +380,10 @@ @ thiscall -arch=win32 ?_SpinOnce@?$_SpinWait@$0A@@details@Concurrency@@QAE_NXZ(ptr) SpinWait__SpinOnce @ cdecl -arch=win64 ?_SpinOnce@?$_SpinWait@$0A@@details@Concurrency@@QEAA_NXZ(ptr) SpinWait__SpinOnce @ cdecl ?_SpinYield@Context@Concurrency@@SAXXZ() Context__SpinYield -@ stub -arch=win32 ?_Start@_Timer@details@Concurrency@@IAEXXZ -@ stub -arch=win64 ?_Start@_Timer@details@Concurrency@@IEAAXXZ -@ stub -arch=win32 ?_Stop@_Timer@details@Concurrency@@IAEXXZ -@ stub -arch=win64 ?_Stop@_Timer@details@Concurrency@@IEAAXXZ +@ thiscall -arch=win32 ?_Start@_Timer@details@Concurrency@@IAEXXZ(ptr) _Timer__Start +@ cdecl -arch=win64 ?_Start@_Timer@details@Concurrency@@IEAAXXZ(ptr) _Timer__Start +@ thiscall -arch=win32 ?_Stop@_Timer@details@Concurrency@@IAEXXZ(ptr) _Timer__Stop +@ cdecl -arch=win64 ?_Stop@_Timer@details@Concurrency@@IEAAXXZ(ptr) _Timer__Stop @ stub -arch=win32 ?_Tidy@exception@std@@AAEXXZ @ stub -arch=win64 ?_Tidy@exception@std@@AEAAXXZ @ cdecl -arch=win32 ?_Trace_ppl_function@Concurrency@@YAXABU_GUID@@EW4ConcRT_EventType@1@@Z(ptr long long) _Trace_ppl_function diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec index c32758dcd63..23840f85eda 100644 --- a/dlls/msvcr110/msvcr110.spec +++ b/dlls/msvcr110/msvcr110.spec @@ -71,9 +71,9 @@ @ stub -arch=arm ??0_TaskCollection@details@Concurrency@@QAA@XZ @ stub -arch=i386 ??0_TaskCollection@details@Concurrency@@QAE@XZ @ stub -arch=win64 ??0_TaskCollection@details@Concurrency@@QEAA@XZ -@ stub -arch=arm ??0_Timer@details@Concurrency@@IAA@I_N@Z -@ stub -arch=i386 ??0_Timer@details@Concurrency@@IAE@I_N@Z -@ stub -arch=win64 ??0_Timer@details@Concurrency@@IEAA@I_N@Z +@ cdecl -arch=arm ??0_Timer@details@Concurrency@@IAA@I_N@Z(ptr long long) _Timer_ctor +@ thiscall -arch=i386 ??0_Timer@details@Concurrency@@IAE@I_N@Z(ptr long long) _Timer_ctor +@ cdecl -arch=win64 ??0_Timer@details@Concurrency@@IEAA@I_N@Z(ptr long long) _Timer_ctor @ cdecl -arch=arm ??0__non_rtti_object@std@@QAA@ABV01@@Z(ptr ptr) __non_rtti_object_copy_ctor @ thiscall -arch=i386 ??0__non_rtti_object@std@@QAE@ABV01@@Z(ptr ptr) __non_rtti_object_copy_ctor @ cdecl -arch=win64 ??0__non_rtti_object@std@@QEAA@AEBV01@@Z(ptr ptr) __non_rtti_object_copy_ctor @@ -299,9 +299,9 @@ @ stub -arch=arm ??1_TaskCollection@details@Concurrency@@QAA@XZ @ stub -arch=i386 ??1_TaskCollection@details@Concurrency@@QAE@XZ @ stub -arch=win64 ??1_TaskCollection@details@Concurrency@@QEAA@XZ -@ stub -arch=arm ??1_Timer@details@Concurrency@@MAA@XZ -@ stub -arch=i386 ??1_Timer@details@Concurrency@@MAE@XZ -@ stub -arch=win64 ??1_Timer@details@Concurrency@@MEAA@XZ +@ cdecl -arch=arm ??1_Timer@details@Concurrency@@MAA@XZ(ptr) _Timer_dtor +@ thiscall -arch=i386 ??1_Timer@details@Concurrency@@MAE@XZ(ptr) _Timer_dtor +@ cdecl -arch=win64 ??1_Timer@details@Concurrency@@MEAA@XZ(ptr) _Timer_dtor @ cdecl -arch=arm ??1__non_rtti_object@std@@UAA@XZ(ptr) __non_rtti_object_dtor @ thiscall -arch=i386 ??1__non_rtti_object@std@@UAE@XZ(ptr) __non_rtti_object_dtor @ cdecl -arch=win64 ??1__non_rtti_object@std@@UEAA@XZ(ptr) __non_rtti_object_dtor @@ -648,12 +648,12 @@ @ thiscall -arch=i386 ?_SpinOnce@?$_SpinWait@$0A@@details@Concurrency@@QAE_NXZ(ptr) SpinWait__SpinOnce @ cdecl -arch=win64 ?_SpinOnce@?$_SpinWait@$0A@@details@Concurrency@@QEAA_NXZ(ptr) SpinWait__SpinOnce @ cdecl ?_SpinYield@Context@Concurrency@@SAXXZ() Context__SpinYield -@ stub -arch=arm ?_Start@_Timer@details@Concurrency@@IAAXXZ -@ stub -arch=i386 ?_Start@_Timer@details@Concurrency@@IAEXXZ -@ stub -arch=win64 ?_Start@_Timer@details@Concurrency@@IEAAXXZ -@ stub -arch=arm ?_Stop@_Timer@details@Concurrency@@IAAXXZ -@ stub -arch=i386 ?_Stop@_Timer@details@Concurrency@@IAEXXZ -@ stub -arch=win64 ?_Stop@_Timer@details@Concurrency@@IEAAXXZ +@ cdecl -arch=arm ?_Start@_Timer@details@Concurrency@@IAAXXZ(ptr) _Timer__Start +@ thiscall -arch=i386 ?_Start@_Timer@details@Concurrency@@IAEXXZ(ptr) _Timer__Start +@ cdecl -arch=win64 ?_Start@_Timer@details@Concurrency@@IEAAXXZ(ptr) _Timer__Start +@ cdecl -arch=arm ?_Stop@_Timer@details@Concurrency@@IAAXXZ(ptr) _Timer__Stop +@ thiscall -arch=i386 ?_Stop@_Timer@details@Concurrency@@IAEXXZ(ptr) _Timer__Stop +@ cdecl -arch=win64 ?_Stop@_Timer@details@Concurrency@@IEAAXXZ(ptr) _Timer__Stop @ stub -arch=arm ?_Tidy@exception@std@@AAAXXZ @ stub -arch=i386 ?_Tidy@exception@std@@AAEXXZ @ stub -arch=win64 ?_Tidy@exception@std@@AEAAXXZ diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 49da95587f9..64ddeed42f4 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -68,9 +68,9 @@ @ stub -arch=arm ??0_TaskCollection@details@Concurrency@@QAA@XZ @ stub -arch=i386 ??0_TaskCollection@details@Concurrency@@QAE@XZ @ stub -arch=win64 ??0_TaskCollection@details@Concurrency@@QEAA@XZ -@ stub -arch=arm ??0_Timer@details@Concurrency@@IAA@I_N@Z -@ stub -arch=i386 ??0_Timer@details@Concurrency@@IAE@I_N@Z -@ stub -arch=win64 ??0_Timer@details@Concurrency@@IEAA@I_N@Z +@ cdecl -arch=arm ??0_Timer@details@Concurrency@@IAA@I_N@Z(ptr long long) _Timer_ctor +@ thiscall -arch=i386 ??0_Timer@details@Concurrency@@IAE@I_N@Z(ptr long long) _Timer_ctor +@ cdecl -arch=win64 ??0_Timer@details@Concurrency@@IEAA@I_N@Z(ptr long long) _Timer_ctor @ cdecl -arch=arm ??0__non_rtti_object@std@@QAA@ABV01@@Z(ptr ptr) __non_rtti_object_copy_ctor @ thiscall -arch=i386 ??0__non_rtti_object@std@@QAE@ABV01@@Z(ptr ptr) __non_rtti_object_copy_ctor @ cdecl -arch=win64 ??0__non_rtti_object@std@@QEAA@AEBV01@@Z(ptr ptr) __non_rtti_object_copy_ctor @@ -295,9 +295,9 @@ @ stub -arch=arm ??1_TaskCollection@details@Concurrency@@QAA@XZ @ stub -arch=i386 ??1_TaskCollection@details@Concurrency@@QAE@XZ @ stub -arch=win64 ??1_TaskCollection@details@Concurrency@@QEAA@XZ -@ stub -arch=arm ??1_Timer@details@Concurrency@@MAA@XZ -@ stub -arch=i386 ??1_Timer@details@Concurrency@@MAE@XZ -@ stub -arch=win64 ??1_Timer@details@Concurrency@@MEAA@XZ +@ cdecl -arch=arm ??1_Timer@details@Concurrency@@MAA@XZ(ptr) _Timer_dtor +@ thiscall -arch=i386 ??1_Timer@details@Concurrency@@MAE@XZ(ptr) _Timer_dtor +@ cdecl -arch=win64 ??1_Timer@details@Concurrency@@MEAA@XZ(ptr) _Timer_dtor @ cdecl -arch=arm ??1__non_rtti_object@std@@UAA@XZ(ptr) __non_rtti_object_dtor @ thiscall -arch=i386 ??1__non_rtti_object@std@@UAE@XZ(ptr) __non_rtti_object_dtor @ cdecl -arch=win64 ??1__non_rtti_object@std@@UEAA@XZ(ptr) __non_rtti_object_dtor @@ -630,12 +630,12 @@ @ thiscall -arch=i386 ?_SpinOnce@?$_SpinWait@$0A@@details@Concurrency@@QAE_NXZ(ptr) SpinWait__SpinOnce @ cdecl -arch=win64 ?_SpinOnce@?$_SpinWait@$0A@@details@Concurrency@@QEAA_NXZ(ptr) SpinWait__SpinOnce @ cdecl ?_SpinYield@Context@Concurrency@@SAXXZ() Context__SpinYield -@ stub -arch=arm ?_Start@_Timer@details@Concurrency@@IAAXXZ -@ stub -arch=i386 ?_Start@_Timer@details@Concurrency@@IAEXXZ -@ stub -arch=win64 ?_Start@_Timer@details@Concurrency@@IEAAXXZ -@ stub -arch=arm ?_Stop@_Timer@details@Concurrency@@IAAXXZ -@ stub -arch=i386 ?_Stop@_Timer@details@Concurrency@@IAEXXZ -@ stub -arch=win64 ?_Stop@_Timer@details@Concurrency@@IEAAXXZ +@ cdecl -arch=arm ?_Start@_Timer@details@Concurrency@@IAAXXZ(ptr) _Timer__Start +@ thiscall -arch=i386 ?_Start@_Timer@details@Concurrency@@IAEXXZ(ptr) _Timer__Start +@ cdecl -arch=win64 ?_Start@_Timer@details@Concurrency@@IEAAXXZ(ptr) _Timer__Start +@ cdecl -arch=arm ?_Stop@_Timer@details@Concurrency@@IAAXXZ(ptr) _Timer__Stop +@ thiscall -arch=i386 ?_Stop@_Timer@details@Concurrency@@IAEXXZ(ptr) _Timer__Stop +@ cdecl -arch=win64 ?_Stop@_Timer@details@Concurrency@@IEAAXXZ(ptr) _Timer__Stop @ stub -arch=arm ?_Tidy@exception@std@@AAAXXZ @ stub -arch=i386 ?_Tidy@exception@std@@AAEXXZ @ stub -arch=win64 ?_Tidy@exception@std@@AEAAXXZ diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index 8434c875107..05f408d6884 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -66,9 +66,9 @@ @ stub -arch=arm ??0_TaskCollection@details@Concurrency@@QAA@XZ @ stub -arch=i386 ??0_TaskCollection@details@Concurrency@@QAE@XZ @ stub -arch=win64 ??0_TaskCollection@details@Concurrency@@QEAA@XZ -@ stub -arch=arm ??0_Timer@details@Concurrency@@IAA@I_N@Z -@ stub -arch=i386 ??0_Timer@details@Concurrency@@IAE@I_N@Z -@ stub -arch=win64 ??0_Timer@details@Concurrency@@IEAA@I_N@Z +@ cdecl -arch=arm ??0_Timer@details@Concurrency@@IAA@I_N@Z(ptr long long) msvcr120.??0_Timer@details@Concurrency@@IAA@I_N@Z +@ thiscall -arch=i386 ??0_Timer@details@Concurrency@@IAE@I_N@Z(ptr long long) msvcr120.??0_Timer@details@Concurrency@@IAE@I_N@Z +@ cdecl -arch=win64 ??0_Timer@details@Concurrency@@IEAA@I_N@Z(ptr long long) msvcr120.??0_Timer@details@Concurrency@@IEAA@I_N@Z @ cdecl -arch=arm ??0__non_rtti_object@std@@QAA@ABV01@@Z(ptr ptr) msvcr120.??0__non_rtti_object@std@@QAA@ABV01@@Z @ thiscall -arch=i386 ??0__non_rtti_object@std@@QAE@ABV01@@Z(ptr ptr) msvcr120.??0__non_rtti_object@std@@QAE@ABV01@@Z @ cdecl -arch=win64 ??0__non_rtti_object@std@@QEAA@AEBV01@@Z(ptr ptr) msvcr120.??0__non_rtti_object@std@@QEAA@AEBV01@@Z @@ -292,9 +292,9 @@ @ stub -arch=arm ??1_TaskCollection@details@Concurrency@@QAA@XZ @ stub -arch=i386 ??1_TaskCollection@details@Concurrency@@QAE@XZ @ stub -arch=win64 ??1_TaskCollection@details@Concurrency@@QEAA@XZ -@ stub -arch=arm ??1_Timer@details@Concurrency@@MAA@XZ -@ stub -arch=i386 ??1_Timer@details@Concurrency@@MAE@XZ -@ stub -arch=win64 ??1_Timer@details@Concurrency@@MEAA@XZ +@ cdecl -arch=arm ??1_Timer@details@Concurrency@@MAA@XZ(ptr) msvcr120.??1_Timer@details@Concurrency@@MAA@XZ +@ thiscall -arch=i386 ??1_Timer@details@Concurrency@@MAE@XZ(ptr) msvcr120.??1_Timer@details@Concurrency@@MAE@XZ +@ cdecl -arch=win64 ??1_Timer@details@Concurrency@@MEAA@XZ(ptr) msvcr120.??1_Timer@details@Concurrency@@MEAA@XZ @ cdecl -arch=arm ??1__non_rtti_object@std@@UAA@XZ(ptr) msvcr120.??1__non_rtti_object@std@@UAA@XZ @ thiscall -arch=i386 ??1__non_rtti_object@std@@UAE@XZ(ptr) msvcr120.??1__non_rtti_object@std@@UAE@XZ @ cdecl -arch=win64 ??1__non_rtti_object@std@@UEAA@XZ(ptr) msvcr120.??1__non_rtti_object@std@@UEAA@XZ @@ -626,12 +626,12 @@ @ thiscall -arch=i386 ?_SpinOnce@?$_SpinWait@$0A@@details@Concurrency@@QAE_NXZ(ptr) msvcr120.?_SpinOnce@?$_SpinWait@$0A@@details@Concurrency@@QAE_NXZ @ cdecl -arch=win64 ?_SpinOnce@?$_SpinWait@$0A@@details@Concurrency@@QEAA_NXZ(ptr) msvcr120.?_SpinOnce@?$_SpinWait@$0A@@details@Concurrency@@QEAA_NXZ @ cdecl ?_SpinYield@Context@Concurrency@@SAXXZ() msvcr120.?_SpinYield@Context@Concurrency@@SAXXZ -@ stub -arch=arm ?_Start@_Timer@details@Concurrency@@IAAXXZ -@ stub -arch=i386 ?_Start@_Timer@details@Concurrency@@IAEXXZ -@ stub -arch=win64 ?_Start@_Timer@details@Concurrency@@IEAAXXZ -@ stub -arch=arm ?_Stop@_Timer@details@Concurrency@@IAAXXZ -@ stub -arch=i386 ?_Stop@_Timer@details@Concurrency@@IAEXXZ -@ stub -arch=win64 ?_Stop@_Timer@details@Concurrency@@IEAAXXZ +@ cdecl -arch=arm ?_Start@_Timer@details@Concurrency@@IAAXXZ(ptr) msvcr120.?_Start@_Timer@details@Concurrency@@IAAXXZ +@ thiscall -arch=i386 ?_Start@_Timer@details@Concurrency@@IAEXXZ(ptr) msvcr120.?_Start@_Timer@details@Concurrency@@IAEXXZ +@ cdecl -arch=win64 ?_Start@_Timer@details@Concurrency@@IEAAXXZ(ptr) msvcr120.?_Start@_Timer@details@Concurrency@@IEAAXXZ +@ cdecl -arch=arm ?_Stop@_Timer@details@Concurrency@@IAAXXZ(ptr) msvcr120.?_Stop@_Timer@details@Concurrency@@IAAXXZ +@ thiscall -arch=i386 ?_Stop@_Timer@details@Concurrency@@IAEXXZ(ptr) msvcr120.?_Stop@_Timer@details@Concurrency@@IAEXXZ +@ cdecl -arch=win64 ?_Stop@_Timer@details@Concurrency@@IEAAXXZ(ptr) msvcr120.?_Stop@_Timer@details@Concurrency@@IEAAXXZ @ stub -arch=arm ?_Tidy@exception@std@@AAAXXZ @ stub -arch=i386 ?_Tidy@exception@std@@AAEXXZ @ stub -arch=win64 ?_Tidy@exception@std@@AEAAXXZ diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index 39c4005e582..e9047ab41b9 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -299,6 +299,16 @@ typedef struct { CRITICAL_SECTION cs; } _ReentrantBlockingLock; +#define TICKSPERMSEC 10000 +typedef struct { + const vtable_ptr *vtable; + TP_TIMER *timer; + unsigned int elapse; + bool repeat; +} _Timer; +extern const vtable_ptr _Timer_vtable; +#define call__Timer_callback(this) CALL_VTBL_FUNC(this, 4, void, (_Timer*), (this)) + typedef exception improper_lock; extern const vtable_ptr improper_lock_vtable; @@ -2730,6 +2740,94 @@ void __cdecl _Trace_ppl_function(const GUID *guid, unsigned char level, enum Con FIXME("(%s %u %i) stub\n", debugstr_guid(guid), level, type); } +/* ??0_Timer@details@Concurrency@@IAE@I_N@Z */ +/* ??0_Timer@details@Concurrency@@IEAA@I_N@Z */ +DEFINE_THISCALL_WRAPPER(_Timer_ctor, 12) +_Timer* __thiscall _Timer_ctor(_Timer *this, unsigned int elapse, bool repeat) +{ + TRACE("(%p %u %x)\n", this, elapse, repeat); + + this->vtable = &_Timer_vtable; + this->timer = NULL; + this->elapse = elapse; + this->repeat = repeat; + return this; +} + +static void WINAPI timer_callback(TP_CALLBACK_INSTANCE *instance, void *ctx, TP_TIMER *timer) +{ + _Timer *this = ctx; + TRACE("calling _Timer(%p) callback\n", this); + call__Timer_callback(this); +} + +/* ?_Start@_Timer@details@Concurrency@@IAEXXZ */ +/* ?_Start@_Timer@details@Concurrency@@IEAAXXZ */ +DEFINE_THISCALL_WRAPPER(_Timer__Start, 4) +void __thiscall _Timer__Start(_Timer *this) +{ + LONGLONG ll; + FILETIME ft; + + TRACE("(%p)\n", this); + + this->timer = CreateThreadpoolTimer(timer_callback, this, NULL); + if (!this->timer) + { + FIXME("throw exception?\n"); + return; + } + + ll = -(LONGLONG)this->elapse * TICKSPERMSEC; + ft.dwLowDateTime = ll & 0xffffffff; + ft.dwHighDateTime = ll >> 32; + SetThreadpoolTimer(this->timer, &ft, this->repeat ? this->elapse : 0, 0); +} + +/* ?_Stop@_Timer@details@Concurrency@@IAEXXZ */ +/* ?_Stop@_Timer@details@Concurrency@@IEAAXXZ */ +DEFINE_THISCALL_WRAPPER(_Timer__Stop, 4) +void __thiscall _Timer__Stop(_Timer *this) +{ + TRACE("(%p)\n", this); + + SetThreadpoolTimer(this->timer, NULL, 0, 0); + WaitForThreadpoolTimerCallbacks(this->timer, TRUE); + CloseThreadpoolTimer(this->timer); + this->timer = NULL; +} + +/* ??1_Timer@details@Concurrency@@MAE@XZ */ +/* ??1_Timer@details@Concurrency@@MEAA@XZ */ +DEFINE_THISCALL_WRAPPER(_Timer_dtor, 4) +void __thiscall _Timer_dtor(_Timer *this) +{ + TRACE("(%p)\n", this); + + if (this->timer) + _Timer__Stop(this); +} + +DEFINE_THISCALL_WRAPPER(_Timer_vector_dtor, 8) +_Timer* __thiscall _Timer_vector_dtor(_Timer *this, unsigned int flags) +{ + TRACE("(%p %x)\n", this, flags); + if (flags & 2) { + /* we have an array, with the number of elements stored before the first object */ + INT_PTR i, *ptr = (INT_PTR *)this-1; + + for (i=*ptr-1; i>=0; i--) + _Timer_dtor(this+i); + operator_delete(ptr); + } else { + _Timer_dtor(this); + if (flags & 1) + operator_delete(this); + } + + return this; +} + #ifdef __ASM_USE_THISCALL_WRAPPER #define DEFINE_VTBL_WRAPPER(off) \ @@ -2764,6 +2862,7 @@ DEFINE_RTTI_DATA0(Scheduler, 0, ".?AVScheduler@Concurrency@@") DEFINE_RTTI_DATA1(SchedulerBase, 0, &Scheduler_rtti_base_descriptor, ".?AVSchedulerBase@details@Concurrency@@") DEFINE_RTTI_DATA2(ThreadScheduler, 0, &SchedulerBase_rtti_base_descriptor, &Scheduler_rtti_base_descriptor, ".?AVThreadScheduler@details@Concurrency@@") +DEFINE_RTTI_DATA0(_Timer, 0, ".?AV_Timer@details@Concurrency@@"); __ASM_BLOCK_BEGIN(concurrency_vtables) __ASM_VTABLE(ExternalContextBase, @@ -2794,6 +2893,8 @@ __ASM_BLOCK_BEGIN(concurrency_vtables) VTABLE_ADD_FUNC(ThreadScheduler_IsAvailableLocation) #endif ); + __ASM_VTABLE(_Timer, + VTABLE_ADD_FUNC(_Timer_vector_dtor)); __ASM_BLOCK_END void msvcrt_init_concurrency(void *base) @@ -2813,6 +2914,7 @@ void msvcrt_init_concurrency(void *base) init_Scheduler_rtti(base); init_SchedulerBase_rtti(base); init_ThreadScheduler_rtti(base); + init__Timer_rtti(base); init_cexception_cxx_type_info(base); init_improper_lock_cxx(base);