msvcr120: Add _Condition_variable tests.

Signed-off-by: Piotr Caban <piotr@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Piotr Caban 2016-11-17 09:56:21 -06:00 committed by Alexandre Julliard
parent 5e981f8512
commit ccda9bbba4
1 changed files with 125 additions and 0 deletions

View File

@ -46,6 +46,8 @@ struct thiscall_thunk
static ULONG_PTR (WINAPI *call_thiscall_func1)( void *func, void *this );
static ULONG_PTR (WINAPI *call_thiscall_func2)( void *func, void *this, const void *a );
static ULONG_PTR (WINAPI *call_thiscall_func3)( void *func,
void *this, const void *a, const void *b );
static void init_thiscall_thunk(void)
{
@ -58,16 +60,19 @@ static void init_thiscall_thunk(void)
thunk->jmp_edx = 0xe2ff; /* jmp *%edx */
call_thiscall_func1 = (void *)thunk;
call_thiscall_func2 = (void *)thunk;
call_thiscall_func3 = (void *)thunk;
}
#define call_func1(func,_this) call_thiscall_func1(func,_this)
#define call_func2(func,_this,a) call_thiscall_func2(func,_this,(const void*)(a))
#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_func2(func,_this,a) func(_this,a)
#define call_func3(func,_this,a,b) func(_this,a,b)
#endif /* __i386__ */
@ -103,6 +108,11 @@ typedef struct
int unknown2[2];
} critical_section_scoped_lock;
typedef struct {
void *chain;
critical_section lock;
} _Condition_variable;
static inline float __port_infinity(void)
{
static const unsigned __inf_bytes = 0x7f800000;
@ -188,6 +198,13 @@ static critical_section_scoped_lock* (__thiscall *p_critical_section_scoped_lock
(critical_section_scoped_lock*, critical_section *);
static void (__thiscall *p_critical_section_scoped_lock_dtor)(critical_section_scoped_lock*);
static _Condition_variable* (__thiscall *p__Condition_variable_ctor)(_Condition_variable*);
static void (__thiscall *p__Condition_variable_dtor)(_Condition_variable*);
static void (__thiscall *p__Condition_variable_wait)(_Condition_variable*, critical_section*);
static MSVCRT_bool (__thiscall *p__Condition_variable_wait_for)(_Condition_variable*, critical_section*, unsigned int);
static void (__thiscall *p__Condition_variable_notify_one)(_Condition_variable*);
static void (__thiscall *p__Condition_variable_notify_all)(_Condition_variable*);
#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)
@ -240,6 +257,18 @@ static BOOL init(void)
"??0scoped_lock@critical_section@Concurrency@@QEAA@AEAV12@@Z");
SET(p_critical_section_scoped_lock_dtor,
"??1scoped_lock@critical_section@Concurrency@@QEAA@XZ");
SET(p__Condition_variable_ctor,
"??0_Condition_variable@details@Concurrency@@QEAA@XZ");
SET(p__Condition_variable_dtor,
"??1_Condition_variable@details@Concurrency@@QEAA@XZ");
SET(p__Condition_variable_wait,
"?wait@_Condition_variable@details@Concurrency@@QEAAXAEAVcritical_section@3@@Z");
SET(p__Condition_variable_wait_for,
"?wait_for@_Condition_variable@details@Concurrency@@QEAA_NAEAVcritical_section@3@I@Z");
SET(p__Condition_variable_notify_one,
"?notify_one@_Condition_variable@details@Concurrency@@QEAAXXZ");
SET(p__Condition_variable_notify_all,
"?notify_all@_Condition_variable@details@Concurrency@@QEAAXXZ");
} else {
#ifdef __arm__
SET(p_critical_section_ctor,
@ -260,6 +289,18 @@ static BOOL init(void)
"??0scoped_lock@critical_section@Concurrency@@QAA@AAV12@@Z");
SET(p_critical_section_scoped_lock_dtor,
"??1scoped_lock@critical_section@Concurrency@@QAA@XZ");
SET(p__Condition_variable_ctor,
"??0_Condition_variable@details@Concurrency@@QAA@XZ");
SET(p__Condition_variable_dtor,
"??1_Condition_variable@details@Concurrency@@QAA@XZ");
SET(p__Condition_variable_wait,
"?wait@_Condition_variable@details@Concurrency@@QAAXAAVcritical_section@3@@Z");
SET(p__Condition_variable_wait_for,
"?wait_for@_Condition_variable@details@Concurrency@@QAA_NAAVcritical_section@3@I@Z");
SET(p__Condition_variable_notify_one,
"?notify_one@_Condition_variable@details@Concurrency@@QAAXXZ");
SET(p__Condition_variable_notify_all,
"?notify_all@_Condition_variable@details@Concurrency@@QAAXXZ");
#else
SET(p_critical_section_ctor,
"??0critical_section@Concurrency@@QAE@XZ");
@ -279,6 +320,18 @@ static BOOL init(void)
"??0scoped_lock@critical_section@Concurrency@@QAE@AAV12@@Z");
SET(p_critical_section_scoped_lock_dtor,
"??1scoped_lock@critical_section@Concurrency@@QAE@XZ");
SET(p__Condition_variable_ctor,
"??0_Condition_variable@details@Concurrency@@QAE@XZ");
SET(p__Condition_variable_dtor,
"??1_Condition_variable@details@Concurrency@@QAE@XZ");
SET(p__Condition_variable_wait,
"?wait@_Condition_variable@details@Concurrency@@QAEXAAVcritical_section@3@@Z");
SET(p__Condition_variable_wait_for,
"?wait_for@_Condition_variable@details@Concurrency@@QAE_NAAVcritical_section@3@I@Z");
SET(p__Condition_variable_notify_one,
"?notify_one@_Condition_variable@details@Concurrency@@QAEXXZ");
SET(p__Condition_variable_notify_all,
"?notify_all@_Condition_variable@details@Concurrency@@QAEXXZ");
#endif
}
@ -758,6 +811,77 @@ static void test__wcreate_locale(void)
ok(errno == -1, "expected errno -1, but got %i\n", e);
}
struct wait_thread_arg
{
critical_section *cs;
_Condition_variable *cv;
HANDLE thread_initialized;
};
static DWORD WINAPI condition_variable_wait_thread(void *varg)
{
struct wait_thread_arg *arg = varg;
call_func1(p_critical_section_lock, arg->cs);
SetEvent(arg->thread_initialized);
call_func2(p__Condition_variable_wait, arg->cv, arg->cs);
call_func1(p_critical_section_unlock, arg->cs);
return 0;
}
static void test__Condition_variable(void)
{
critical_section cs;
_Condition_variable cv;
HANDLE thread_initialized = CreateEventW(NULL, FALSE, FALSE, NULL);
struct wait_thread_arg wait_thread_arg = { &cs, &cv, thread_initialized };
HANDLE threads[2];
DWORD ret;
MSVCRT_bool b;
ok(thread_initialized != NULL, "CreateEvent failed\n");
call_func1(p_critical_section_ctor, &cs);
call_func1(p__Condition_variable_ctor, &cv);
call_func1(p__Condition_variable_notify_one, &cv);
call_func1(p__Condition_variable_notify_all, &cv);
threads[0] = CreateThread(0, 0, condition_variable_wait_thread,
&wait_thread_arg, 0, 0);
ok(threads[0] != NULL, "CreateThread failed\n");
WaitForSingleObject(thread_initialized, INFINITE);
call_func1(p_critical_section_lock, &cs);
call_func1(p_critical_section_unlock, &cs);
threads[1] = CreateThread(0, 0, condition_variable_wait_thread,
&wait_thread_arg, 0, 0);
ok(threads[1] != NULL, "CreateThread failed\n");
WaitForSingleObject(thread_initialized, INFINITE);
call_func1(p_critical_section_lock, &cs);
call_func1(p_critical_section_unlock, &cs);
call_func1(p__Condition_variable_notify_one, &cv);
ret = WaitForSingleObject(threads[1], 500);
ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", ret);
call_func1(p__Condition_variable_notify_one, &cv);
ret = WaitForSingleObject(threads[0], 500);
ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", ret);
CloseHandle(threads[0]);
CloseHandle(threads[1]);
call_func1(p_critical_section_lock, &cs);
b = call_func3(p__Condition_variable_wait_for, &cv, &cs, 1);
ok(!b, "_Condition_variable_wait_for returned TRUE\n");
call_func1(p_critical_section_unlock, &cs);
call_func1(p_critical_section_dtor, &cs);
call_func1(p__Condition_variable_dtor, &cv);
CloseHandle(thread_initialized);
}
START_TEST(msvcr120)
{
if (!init()) return;
@ -773,4 +897,5 @@ START_TEST(msvcr120)
test_critical_section();
test_fegetenv();
test__wcreate_locale();
test__Condition_variable();
}