msvcp120: Implement _Thrd_create/join.
Signed-off-by: Daniel Lehman <dlehman@esri.com> Signed-off-by: Piotr Caban <piotr@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
498d8861e0
commit
f3a0ac8d53
|
@ -3856,12 +3856,12 @@
|
||||||
@ cdecl _Strcoll(ptr ptr ptr ptr ptr)
|
@ cdecl _Strcoll(ptr ptr ptr ptr ptr)
|
||||||
@ stub _Strxfrm
|
@ stub _Strxfrm
|
||||||
@ stub _Thrd_abort
|
@ stub _Thrd_abort
|
||||||
@ stub _Thrd_create
|
@ cdecl _Thrd_create(ptr ptr ptr)
|
||||||
@ cdecl _Thrd_current()
|
@ cdecl _Thrd_current()
|
||||||
@ stub _Thrd_detach
|
@ stub _Thrd_detach
|
||||||
@ cdecl _Thrd_equal(ptr ptr)
|
@ cdecl _Thrd_equal(ptr ptr)
|
||||||
@ stub _Thrd_exit
|
@ stub _Thrd_exit
|
||||||
@ stub _Thrd_join
|
@ cdecl _Thrd_join(ptr long)
|
||||||
@ cdecl _Thrd_lt(ptr ptr)
|
@ cdecl _Thrd_lt(ptr ptr)
|
||||||
@ cdecl _Thrd_sleep(ptr)
|
@ cdecl _Thrd_sleep(ptr)
|
||||||
@ stub _Thrd_start
|
@ stub _Thrd_start
|
||||||
|
|
|
@ -3803,12 +3803,12 @@
|
||||||
@ cdecl _Strcoll(ptr ptr ptr ptr ptr)
|
@ cdecl _Strcoll(ptr ptr ptr ptr ptr)
|
||||||
@ stub _Strxfrm
|
@ stub _Strxfrm
|
||||||
@ stub _Thrd_abort
|
@ stub _Thrd_abort
|
||||||
@ stub _Thrd_create
|
@ cdecl _Thrd_create(ptr ptr ptr)
|
||||||
@ cdecl _Thrd_current()
|
@ cdecl _Thrd_current()
|
||||||
@ stub _Thrd_detach
|
@ stub _Thrd_detach
|
||||||
@ cdecl _Thrd_equal(ptr ptr)
|
@ cdecl _Thrd_equal(ptr ptr)
|
||||||
@ stub _Thrd_exit
|
@ stub _Thrd_exit
|
||||||
@ stub _Thrd_join
|
@ cdecl _Thrd_join(ptr long)
|
||||||
@ cdecl _Thrd_lt(ptr ptr)
|
@ cdecl _Thrd_lt(ptr ptr)
|
||||||
@ cdecl _Thrd_sleep(ptr)
|
@ cdecl _Thrd_sleep(ptr)
|
||||||
@ stub _Thrd_start
|
@ stub _Thrd_start
|
||||||
|
|
|
@ -139,10 +139,14 @@ typedef struct
|
||||||
|
|
||||||
#define TIMEDELTA 150 /* 150 ms uncertainty allowed */
|
#define TIMEDELTA 150 /* 150 ms uncertainty allowed */
|
||||||
|
|
||||||
|
typedef int (__cdecl *_Thrd_start_t)(void*);
|
||||||
|
|
||||||
static int (__cdecl *p__Thrd_equal)(_Thrd_t, _Thrd_t);
|
static int (__cdecl *p__Thrd_equal)(_Thrd_t, _Thrd_t);
|
||||||
static int (__cdecl *p__Thrd_lt)(_Thrd_t, _Thrd_t);
|
static int (__cdecl *p__Thrd_lt)(_Thrd_t, _Thrd_t);
|
||||||
static void (__cdecl *p__Thrd_sleep)(const xtime*);
|
static void (__cdecl *p__Thrd_sleep)(const xtime*);
|
||||||
static _Thrd_t (__cdecl *p__Thrd_current)(void);
|
static _Thrd_t (__cdecl *p__Thrd_current)(void);
|
||||||
|
static int (__cdecl *p__Thrd_create)(_Thrd_t*, _Thrd_start_t, void*);
|
||||||
|
static int (__cdecl *p__Thrd_join)(_Thrd_t, int*);
|
||||||
|
|
||||||
#ifdef __i386__
|
#ifdef __i386__
|
||||||
static ULONGLONG (__cdecl *p_i386_Thrd_current)(void);
|
static ULONGLONG (__cdecl *p_i386_Thrd_current)(void);
|
||||||
|
@ -296,6 +300,10 @@ static BOOL init(void)
|
||||||
"_Thrd_lt");
|
"_Thrd_lt");
|
||||||
SET(p__Thrd_sleep,
|
SET(p__Thrd_sleep,
|
||||||
"_Thrd_sleep");
|
"_Thrd_sleep");
|
||||||
|
SET(p__Thrd_create,
|
||||||
|
"_Thrd_create");
|
||||||
|
SET(p__Thrd_join,
|
||||||
|
"_Thrd_join");
|
||||||
|
|
||||||
msvcr = GetModuleHandleA("msvcr120.dll");
|
msvcr = GetModuleHandleA("msvcr120.dll");
|
||||||
p_setlocale = (void*)GetProcAddress(msvcr, "setlocale");
|
p_setlocale = (void*)GetProcAddress(msvcr, "setlocale");
|
||||||
|
@ -1163,9 +1171,17 @@ static void test_tr2_sys__Last_write_time(void)
|
||||||
ok(ret == 1, "test_tr2_sys__Remove_dir(): expect 1 got %d\n", ret);
|
ok(ret == 1, "test_tr2_sys__Remove_dir(): expect 1 got %d\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __cdecl thrd_thread(void *arg)
|
||||||
|
{
|
||||||
|
_Thrd_t *thr = arg;
|
||||||
|
|
||||||
|
*thr = p__Thrd_current();
|
||||||
|
return 0x42;
|
||||||
|
}
|
||||||
|
|
||||||
static void test_thrd(void)
|
static void test_thrd(void)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret, i, r;
|
||||||
struct test {
|
struct test {
|
||||||
_Thrd_t a;
|
_Thrd_t a;
|
||||||
_Thrd_t b;
|
_Thrd_t b;
|
||||||
|
@ -1226,6 +1242,22 @@ static void test_thrd(void)
|
||||||
ok(ta.hnd == tb.hnd, "got a %p b %p\n", ta.hnd, tb.hnd);
|
ok(ta.hnd == tb.hnd, "got a %p b %p\n", ta.hnd, tb.hnd);
|
||||||
ok(!CloseHandle(ta.hnd), "handle %p not closed\n", ta.hnd);
|
ok(!CloseHandle(ta.hnd), "handle %p not closed\n", ta.hnd);
|
||||||
ok(!CloseHandle(tb.hnd), "handle %p not closed\n", tb.hnd);
|
ok(!CloseHandle(tb.hnd), "handle %p not closed\n", tb.hnd);
|
||||||
|
|
||||||
|
/* test for create/join */
|
||||||
|
if (0) /* crash on Windows */
|
||||||
|
{
|
||||||
|
p__Thrd_create(NULL, thrd_thread, NULL);
|
||||||
|
p__Thrd_create(&ta, NULL, NULL);
|
||||||
|
}
|
||||||
|
r = -1;
|
||||||
|
ret = p__Thrd_create(&ta, thrd_thread, (void*)&tb);
|
||||||
|
ok(!ret, "failed to create thread, got %d\n", ret);
|
||||||
|
ret = p__Thrd_join(ta, &r);
|
||||||
|
ok(!ret, "failed to join thread, got %d\n", ret);
|
||||||
|
ok(ta.id == tb.id, "expected %d, got %d\n", ta.id, tb.id);
|
||||||
|
ok(ta.hnd != tb.hnd, "same handles, got %p\n", ta.hnd);
|
||||||
|
ok(r == 0x42, "expected 0x42, got %d\n", r);
|
||||||
|
ok(!CloseHandle(ta.hnd), "handle %p not closed\n", ta.hnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(msvcp120)
|
START_TEST(msvcp120)
|
||||||
|
|
|
@ -3803,12 +3803,12 @@
|
||||||
@ cdecl _Strcoll(ptr ptr ptr ptr ptr) msvcp120._Strcoll
|
@ cdecl _Strcoll(ptr ptr ptr ptr ptr) msvcp120._Strcoll
|
||||||
@ stub _Strxfrm
|
@ stub _Strxfrm
|
||||||
@ stub _Thrd_abort
|
@ stub _Thrd_abort
|
||||||
@ stub _Thrd_create
|
@ cdecl _Thrd_create(ptr ptr ptr) msvcp120._Thrd_create
|
||||||
@ cdecl _Thrd_current() msvcp120._Thrd_current
|
@ cdecl _Thrd_current() msvcp120._Thrd_current
|
||||||
@ stub _Thrd_detach
|
@ stub _Thrd_detach
|
||||||
@ cdecl _Thrd_equal(ptr ptr) msvcp120._Thrd_equal
|
@ cdecl _Thrd_equal(ptr ptr) msvcp120._Thrd_equal
|
||||||
@ stub _Thrd_exit
|
@ stub _Thrd_exit
|
||||||
@ stub _Thrd_join
|
@ cdecl _Thrd_join(ptr long) msvcp120._Thrd_join
|
||||||
@ cdecl _Thrd_lt(ptr ptr) msvcp120._Thrd_lt
|
@ cdecl _Thrd_lt(ptr ptr) msvcp120._Thrd_lt
|
||||||
@ cdecl _Thrd_sleep(ptr) msvcp120._Thrd_sleep
|
@ cdecl _Thrd_sleep(ptr) msvcp120._Thrd_sleep
|
||||||
@ stub _Thrd_start
|
@ stub _Thrd_start
|
||||||
|
|
|
@ -691,6 +691,10 @@ typedef struct
|
||||||
DWORD id;
|
DWORD id;
|
||||||
} _Thrd_t;
|
} _Thrd_t;
|
||||||
|
|
||||||
|
typedef int (__cdecl *_Thrd_start_t)(void*);
|
||||||
|
|
||||||
|
#define _THRD_ERROR 4
|
||||||
|
|
||||||
int __cdecl _Thrd_equal(_Thrd_t a, _Thrd_t b)
|
int __cdecl _Thrd_equal(_Thrd_t a, _Thrd_t b)
|
||||||
{
|
{
|
||||||
TRACE("(%p %u %p %u)\n", a.hnd, a.id, b.hnd, b.id);
|
TRACE("(%p %u %p %u)\n", a.hnd, a.id, b.hnd, b.id);
|
||||||
|
@ -750,4 +754,24 @@ ULONGLONG __cdecl _Thrd_current(void)
|
||||||
return ret.ull;
|
return ret.ull;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int __cdecl _Thrd_join(_Thrd_t thr, int *code)
|
||||||
|
{
|
||||||
|
TRACE("(%p %u %p)\n", thr.hnd, thr.id, code);
|
||||||
|
if (WaitForSingleObject(thr.hnd, INFINITE))
|
||||||
|
return _THRD_ERROR;
|
||||||
|
|
||||||
|
if (code)
|
||||||
|
GetExitCodeThread(thr.hnd, (DWORD *)code);
|
||||||
|
|
||||||
|
CloseHandle(thr.hnd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __cdecl _Thrd_create(_Thrd_t *thr, _Thrd_start_t proc, void *arg)
|
||||||
|
{
|
||||||
|
TRACE("(%p %p %p)\n", thr, proc, arg);
|
||||||
|
thr->hnd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)proc, arg, 0, &thr->id);
|
||||||
|
return !thr->hnd;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue