msvcp120: Implement _Cnd_* functions.
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
c2533ecb73
commit
df096e6b60
|
@ -3729,15 +3729,15 @@
|
||||||
@ cdecl -arch=win64 ?xsputn@?$basic_streambuf@_WU?$char_traits@_W@std@@@std@@MEAA_JPEB_W_J@Z(ptr ptr long) basic_streambuf_wchar_xsputn
|
@ cdecl -arch=win64 ?xsputn@?$basic_streambuf@_WU?$char_traits@_W@std@@@std@@MEAA_JPEB_W_J@Z(ptr ptr long) basic_streambuf_wchar_xsputn
|
||||||
@ cdecl _Call_once(ptr ptr)
|
@ cdecl _Call_once(ptr ptr)
|
||||||
@ cdecl _Call_onceEx(ptr ptr ptr)
|
@ cdecl _Call_onceEx(ptr ptr ptr)
|
||||||
@ stub _Cnd_broadcast
|
@ cdecl _Cnd_broadcast(ptr)
|
||||||
@ stub _Cnd_destroy
|
@ cdecl _Cnd_destroy(ptr)
|
||||||
@ stub _Cnd_do_broadcast_at_thread_exit
|
@ stub _Cnd_do_broadcast_at_thread_exit
|
||||||
@ stub _Cnd_init
|
@ cdecl _Cnd_init(ptr)
|
||||||
@ stub _Cnd_register_at_thread_exit
|
@ stub _Cnd_register_at_thread_exit
|
||||||
@ stub _Cnd_signal
|
@ cdecl _Cnd_signal(ptr)
|
||||||
@ stub _Cnd_timedwait
|
@ cdecl _Cnd_timedwait(ptr ptr ptr)
|
||||||
@ stub _Cnd_unregister_at_thread_exit
|
@ stub _Cnd_unregister_at_thread_exit
|
||||||
@ stub _Cnd_wait
|
@ cdecl _Cnd_wait(ptr ptr)
|
||||||
@ stub _Cosh
|
@ stub _Cosh
|
||||||
@ extern _Denorm
|
@ extern _Denorm
|
||||||
@ stub _Dint
|
@ stub _Dint
|
||||||
|
|
|
@ -3670,15 +3670,15 @@
|
||||||
@ cdecl -arch=win64 ?xsputn@?$basic_streambuf@_WU?$char_traits@_W@std@@@std@@MEAA_JPEB_W_J@Z(ptr ptr long) basic_streambuf_wchar_xsputn
|
@ cdecl -arch=win64 ?xsputn@?$basic_streambuf@_WU?$char_traits@_W@std@@@std@@MEAA_JPEB_W_J@Z(ptr ptr long) basic_streambuf_wchar_xsputn
|
||||||
@ cdecl _Call_once(ptr ptr)
|
@ cdecl _Call_once(ptr ptr)
|
||||||
@ cdecl _Call_onceEx(ptr ptr ptr)
|
@ cdecl _Call_onceEx(ptr ptr ptr)
|
||||||
@ stub _Cnd_broadcast
|
@ cdecl _Cnd_broadcast(ptr)
|
||||||
@ stub _Cnd_destroy
|
@ cdecl _Cnd_destroy(ptr)
|
||||||
@ stub _Cnd_do_broadcast_at_thread_exit
|
@ stub _Cnd_do_broadcast_at_thread_exit
|
||||||
@ stub _Cnd_init
|
@ cdecl _Cnd_init(ptr)
|
||||||
@ stub _Cnd_register_at_thread_exit
|
@ stub _Cnd_register_at_thread_exit
|
||||||
@ stub _Cnd_signal
|
@ cdecl _Cnd_signal(ptr)
|
||||||
@ stub _Cnd_timedwait
|
@ cdecl _Cnd_timedwait(ptr ptr ptr)
|
||||||
@ stub _Cnd_unregister_at_thread_exit
|
@ stub _Cnd_unregister_at_thread_exit
|
||||||
@ stub _Cnd_wait
|
@ cdecl _Cnd_wait(ptr ptr)
|
||||||
@ stub _Cosh
|
@ stub _Cosh
|
||||||
@ extern _Denorm
|
@ extern _Denorm
|
||||||
@ stub _Dint
|
@ stub _Dint
|
||||||
|
|
|
@ -137,7 +137,7 @@ typedef struct
|
||||||
DWORD id;
|
DWORD id;
|
||||||
} _Thrd_t;
|
} _Thrd_t;
|
||||||
|
|
||||||
#define TIMEDELTA 150 /* 150 ms uncertainty allowed */
|
#define TIMEDELTA 250 /* 250 ms uncertainty allowed */
|
||||||
|
|
||||||
typedef int (__cdecl *_Thrd_start_t)(void*);
|
typedef int (__cdecl *_Thrd_start_t)(void*);
|
||||||
|
|
||||||
|
@ -161,6 +161,24 @@ _Thrd_t __cdecl i386_Thrd_current(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* mtx */
|
||||||
|
typedef void *_Mtx_t;
|
||||||
|
static int (__cdecl *p__Mtx_init)(_Mtx_t*, int);
|
||||||
|
static void (__cdecl *p__Mtx_destroy)(_Mtx_t*);
|
||||||
|
static int (__cdecl *p__Mtx_lock)(_Mtx_t*);
|
||||||
|
static int (__cdecl *p__Mtx_unlock)(_Mtx_t*);
|
||||||
|
|
||||||
|
/* cnd */
|
||||||
|
typedef void *_Cnd_t;
|
||||||
|
|
||||||
|
static int (__cdecl *p__Cnd_init)(_Cnd_t*);
|
||||||
|
static void (__cdecl *p__Cnd_destroy)(_Cnd_t*);
|
||||||
|
static int (__cdecl *p__Cnd_wait)(_Cnd_t*, _Mtx_t*);
|
||||||
|
static int (__cdecl *p__Cnd_timedwait)(_Cnd_t*, _Mtx_t*, const xtime*);
|
||||||
|
static int (__cdecl *p__Cnd_broadcast)(_Cnd_t*);
|
||||||
|
static int (__cdecl *p__Cnd_signal)(_Cnd_t*);
|
||||||
|
|
||||||
|
|
||||||
static HMODULE msvcp;
|
static HMODULE msvcp;
|
||||||
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y)
|
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y)
|
||||||
#define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
|
#define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
|
||||||
|
@ -305,6 +323,28 @@ static BOOL init(void)
|
||||||
SET(p__Thrd_join,
|
SET(p__Thrd_join,
|
||||||
"_Thrd_join");
|
"_Thrd_join");
|
||||||
|
|
||||||
|
SET(p__Mtx_init,
|
||||||
|
"_Mtx_init");
|
||||||
|
SET(p__Mtx_destroy,
|
||||||
|
"_Mtx_destroy");
|
||||||
|
SET(p__Mtx_lock,
|
||||||
|
"_Mtx_lock");
|
||||||
|
SET(p__Mtx_unlock,
|
||||||
|
"_Mtx_unlock");
|
||||||
|
|
||||||
|
SET(p__Cnd_init,
|
||||||
|
"_Cnd_init");
|
||||||
|
SET(p__Cnd_destroy,
|
||||||
|
"_Cnd_destroy");
|
||||||
|
SET(p__Cnd_wait,
|
||||||
|
"_Cnd_wait");
|
||||||
|
SET(p__Cnd_timedwait,
|
||||||
|
"_Cnd_timedwait");
|
||||||
|
SET(p__Cnd_broadcast,
|
||||||
|
"_Cnd_broadcast");
|
||||||
|
SET(p__Cnd_signal,
|
||||||
|
"_Cnd_signal");
|
||||||
|
|
||||||
msvcr = GetModuleHandleA("msvcr120.dll");
|
msvcr = GetModuleHandleA("msvcr120.dll");
|
||||||
p_setlocale = (void*)GetProcAddress(msvcr, "setlocale");
|
p_setlocale = (void*)GetProcAddress(msvcr, "setlocale");
|
||||||
p__setmbcp = (void*)GetProcAddress(msvcr, "_setmbcp");
|
p__setmbcp = (void*)GetProcAddress(msvcr, "_setmbcp");
|
||||||
|
@ -1260,6 +1300,147 @@ static void test_thrd(void)
|
||||||
ok(!CloseHandle(ta.hnd), "handle %p not closed\n", ta.hnd);
|
ok(!CloseHandle(ta.hnd), "handle %p not closed\n", ta.hnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define NUM_THREADS 10
|
||||||
|
struct cndmtx
|
||||||
|
{
|
||||||
|
HANDLE initialized;
|
||||||
|
int started;
|
||||||
|
int thread_no;
|
||||||
|
|
||||||
|
_Cnd_t cnd;
|
||||||
|
_Mtx_t mtx;
|
||||||
|
BOOL timed_wait;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __cdecl cnd_wait_thread(void *arg)
|
||||||
|
{
|
||||||
|
struct cndmtx *cm = arg;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
p__Mtx_lock(&cm->mtx);
|
||||||
|
|
||||||
|
if(InterlockedIncrement(&cm->started) == cm->thread_no)
|
||||||
|
SetEvent(cm->initialized);
|
||||||
|
|
||||||
|
if(cm->timed_wait) {
|
||||||
|
xtime xt;
|
||||||
|
|
||||||
|
p_xtime_get(&xt, 1);
|
||||||
|
xt.sec += 2;
|
||||||
|
r = p__Cnd_timedwait(&cm->cnd, &cm->mtx, &xt);
|
||||||
|
ok(!r, "timed wait failed\n");
|
||||||
|
} else {
|
||||||
|
r = p__Cnd_wait(&cm->cnd, &cm->mtx);
|
||||||
|
ok(!r, "wait failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
p__Mtx_unlock(&cm->mtx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_cnd(void)
|
||||||
|
{
|
||||||
|
_Thrd_t threads[NUM_THREADS];
|
||||||
|
xtime xt, before, after;
|
||||||
|
MSVCRT_long diff;
|
||||||
|
struct cndmtx cm;
|
||||||
|
_Cnd_t cnd;
|
||||||
|
_Mtx_t mtx;
|
||||||
|
int r, i;
|
||||||
|
|
||||||
|
r = p__Cnd_init(&cnd);
|
||||||
|
ok(!r, "failed to init cnd\n");
|
||||||
|
|
||||||
|
r = p__Mtx_init(&mtx, 0);
|
||||||
|
ok(!r, "failed to init mtx\n");
|
||||||
|
|
||||||
|
if (0) /* crash on Windows */
|
||||||
|
{
|
||||||
|
p__Cnd_init(NULL);
|
||||||
|
p__Cnd_wait(NULL, &mtx);
|
||||||
|
p__Cnd_wait(&cnd, NULL);
|
||||||
|
p__Cnd_timedwait(NULL, &mtx, &xt);
|
||||||
|
p__Cnd_timedwait(&cnd, &mtx, &xt);
|
||||||
|
}
|
||||||
|
p__Cnd_destroy(NULL);
|
||||||
|
|
||||||
|
/* test _Cnd_signal/_Cnd_wait */
|
||||||
|
cm.initialized = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||||
|
cm.started = 0;
|
||||||
|
cm.thread_no = 1;
|
||||||
|
cm.cnd = cnd;
|
||||||
|
cm.mtx = mtx;
|
||||||
|
cm.timed_wait = FALSE;
|
||||||
|
p__Thrd_create(&threads[0], cnd_wait_thread, (void*)&cm);
|
||||||
|
|
||||||
|
WaitForSingleObject(cm.initialized, INFINITE);
|
||||||
|
p__Mtx_lock(&mtx);
|
||||||
|
p__Mtx_unlock(&mtx);
|
||||||
|
|
||||||
|
r = p__Cnd_signal(&cm.cnd);
|
||||||
|
ok(!r, "failed to signal\n");
|
||||||
|
p__Thrd_join(threads[0], NULL);
|
||||||
|
|
||||||
|
/* test _Cnd_timedwait time out */
|
||||||
|
p__Mtx_lock(&mtx);
|
||||||
|
p_xtime_get(&before, 1);
|
||||||
|
xt = before;
|
||||||
|
xt.sec += 1;
|
||||||
|
r = p__Cnd_timedwait(&cnd, &mtx, &xt);
|
||||||
|
p_xtime_get(&after, 1);
|
||||||
|
p__Mtx_unlock(&mtx);
|
||||||
|
|
||||||
|
diff = p__Xtime_diff_to_millis2(&after, &before);
|
||||||
|
ok(r == 2, "should have timed out\n");
|
||||||
|
ok(diff > 1000 - TIMEDELTA, "got %d\n", diff);
|
||||||
|
|
||||||
|
/* test _Cnd_timedwait */
|
||||||
|
cm.started = 0;
|
||||||
|
cm.timed_wait = TRUE;
|
||||||
|
p__Thrd_create(&threads[0], cnd_wait_thread, (void*)&cm);
|
||||||
|
|
||||||
|
WaitForSingleObject(cm.initialized, INFINITE);
|
||||||
|
p__Mtx_lock(&mtx);
|
||||||
|
p__Mtx_unlock(&mtx);
|
||||||
|
|
||||||
|
r = p__Cnd_signal(&cm.cnd);
|
||||||
|
ok(!r, "failed to signal\n");
|
||||||
|
p__Thrd_join(threads[0], NULL);
|
||||||
|
|
||||||
|
/* test _Cnd_broadcast */
|
||||||
|
cm.started = 0;
|
||||||
|
cm.thread_no = NUM_THREADS;
|
||||||
|
cm.timed_wait = FALSE;
|
||||||
|
|
||||||
|
for(i = 0; i < cm.thread_no; i++)
|
||||||
|
p__Thrd_create(&threads[i], cnd_wait_thread, (void*)&cm);
|
||||||
|
|
||||||
|
WaitForSingleObject(cm.initialized, INFINITE);
|
||||||
|
p__Mtx_lock(&mtx);
|
||||||
|
p__Mtx_unlock(&mtx);
|
||||||
|
|
||||||
|
r = p__Cnd_broadcast(&cnd);
|
||||||
|
ok(!r, "failed to broadcast\n");
|
||||||
|
for(i = 0; i < cm.thread_no; i++)
|
||||||
|
p__Thrd_join(threads[i], NULL);
|
||||||
|
|
||||||
|
/* test broadcast with _Cnd_destroy */
|
||||||
|
cm.started = 0;
|
||||||
|
for(i = 0; i < cm.thread_no; i++)
|
||||||
|
p__Thrd_create(&threads[i], cnd_wait_thread, (void*)&cm);
|
||||||
|
|
||||||
|
WaitForSingleObject(cm.initialized, INFINITE);
|
||||||
|
p__Mtx_lock(&mtx);
|
||||||
|
p__Mtx_unlock(&mtx);
|
||||||
|
|
||||||
|
p__Cnd_destroy(&cnd);
|
||||||
|
for(i = 0; i < cm.thread_no; i++)
|
||||||
|
p__Thrd_join(threads[i], NULL);
|
||||||
|
|
||||||
|
p__Mtx_destroy(&mtx);
|
||||||
|
CloseHandle(cm.initialized);
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(msvcp120)
|
START_TEST(msvcp120)
|
||||||
{
|
{
|
||||||
if(!init()) return;
|
if(!init()) return;
|
||||||
|
@ -1285,6 +1466,7 @@ START_TEST(msvcp120)
|
||||||
test_tr2_sys__Last_write_time();
|
test_tr2_sys__Last_write_time();
|
||||||
|
|
||||||
test_thrd();
|
test_thrd();
|
||||||
|
test_cnd();
|
||||||
|
|
||||||
FreeLibrary(msvcp);
|
FreeLibrary(msvcp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3670,15 +3670,15 @@
|
||||||
@ cdecl -arch=win64 ?xsputn@?$basic_streambuf@_WU?$char_traits@_W@std@@@std@@MEAA_JPEB_W_J@Z(ptr ptr long) msvcp120.?xsputn@?$basic_streambuf@_WU?$char_traits@_W@std@@@std@@MEAA_JPEB_W_J@Z
|
@ cdecl -arch=win64 ?xsputn@?$basic_streambuf@_WU?$char_traits@_W@std@@@std@@MEAA_JPEB_W_J@Z(ptr ptr long) msvcp120.?xsputn@?$basic_streambuf@_WU?$char_traits@_W@std@@@std@@MEAA_JPEB_W_J@Z
|
||||||
@ cdecl _Call_once(ptr ptr) msvcp120._Call_once
|
@ cdecl _Call_once(ptr ptr) msvcp120._Call_once
|
||||||
@ cdecl _Call_onceEx(ptr ptr ptr) msvcp120._Call_onceEx
|
@ cdecl _Call_onceEx(ptr ptr ptr) msvcp120._Call_onceEx
|
||||||
@ stub _Cnd_broadcast
|
@ cdecl _Cnd_broadcast(ptr) msvcp120._Cnd_broadcast
|
||||||
@ stub _Cnd_destroy
|
@ cdecl _Cnd_destroy(ptr) msvcp120._Cnd_destroy
|
||||||
@ stub _Cnd_do_broadcast_at_thread_exit
|
@ stub _Cnd_do_broadcast_at_thread_exit
|
||||||
@ stub _Cnd_init
|
@ cdecl _Cnd_init(ptr) msvcp120._Cnd_init
|
||||||
@ stub _Cnd_register_at_thread_exit
|
@ stub _Cnd_register_at_thread_exit
|
||||||
@ stub _Cnd_signal
|
@ cdecl _Cnd_signal(ptr) msvcp120._Cnd_signal
|
||||||
@ stub _Cnd_timedwait
|
@ cdecl _Cnd_timedwait(ptr ptr ptr) msvcp120._Cnd_timedwait
|
||||||
@ stub _Cnd_unregister_at_thread_exit
|
@ stub _Cnd_unregister_at_thread_exit
|
||||||
@ stub _Cnd_wait
|
@ cdecl _Cnd_wait(ptr ptr) msvcp120._Cnd_wait
|
||||||
@ stub _Cosh
|
@ stub _Cosh
|
||||||
@ extern _Denorm msvcp120._Denorm
|
@ extern _Denorm msvcp120._Denorm
|
||||||
@ stub _Dint
|
@ stub _Dint
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
|
#include "winternl.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(msvcp);
|
WINE_DEFAULT_DEBUG_CHANNEL(msvcp);
|
||||||
|
|
||||||
|
@ -527,6 +528,101 @@ critical_section* __cdecl _Mtx_getconcrtcs(_Mtx_t *mtx)
|
||||||
{
|
{
|
||||||
return &(*mtx)->cs;
|
return &(*mtx)->cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline LONG interlocked_dec_if_nonzero( LONG *dest )
|
||||||
|
{
|
||||||
|
LONG val, tmp;
|
||||||
|
for (val = *dest;; val = tmp)
|
||||||
|
{
|
||||||
|
if (!val || (tmp = InterlockedCompareExchange( dest, val - 1, val )) == val)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CND_TIMEDOUT 2
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CONDITION_VARIABLE cv;
|
||||||
|
} *_Cnd_t;
|
||||||
|
|
||||||
|
static HANDLE keyed_event;
|
||||||
|
|
||||||
|
int __cdecl _Cnd_init(_Cnd_t *cnd)
|
||||||
|
{
|
||||||
|
*cnd = MSVCRT_operator_new(sizeof(**cnd));
|
||||||
|
InitializeConditionVariable(&(*cnd)->cv);
|
||||||
|
|
||||||
|
if(!keyed_event) {
|
||||||
|
HANDLE event;
|
||||||
|
|
||||||
|
NtCreateKeyedEvent(&event, GENERIC_READ|GENERIC_WRITE, NULL, 0);
|
||||||
|
if(InterlockedCompareExchangePointer(&keyed_event, event, NULL) != NULL)
|
||||||
|
NtClose(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __cdecl _Cnd_wait(_Cnd_t *cnd, _Mtx_t *mtx)
|
||||||
|
{
|
||||||
|
CONDITION_VARIABLE *cv = &(*cnd)->cv;
|
||||||
|
|
||||||
|
InterlockedExchangeAdd( (LONG *)&cv->Ptr, 1 );
|
||||||
|
_Mtx_unlock(mtx);
|
||||||
|
|
||||||
|
NtWaitForKeyedEvent(keyed_event, &cv->Ptr, FALSE, NULL);
|
||||||
|
|
||||||
|
_Mtx_lock(mtx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __cdecl _Cnd_timedwait(_Cnd_t *cnd, _Mtx_t *mtx, const xtime *xt)
|
||||||
|
{
|
||||||
|
CONDITION_VARIABLE *cv = &(*cnd)->cv;
|
||||||
|
LARGE_INTEGER timeout;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
InterlockedExchangeAdd( (LONG *)&cv->Ptr, 1 );
|
||||||
|
_Mtx_unlock(mtx);
|
||||||
|
|
||||||
|
timeout.QuadPart = (ULONGLONG)_Xtime_diff_to_millis(xt) * -10000;
|
||||||
|
status = NtWaitForKeyedEvent(keyed_event, &cv->Ptr, FALSE, &timeout);
|
||||||
|
if (status)
|
||||||
|
{
|
||||||
|
if (!interlocked_dec_if_nonzero( (LONG *)&cv->Ptr ))
|
||||||
|
status = NtWaitForKeyedEvent( keyed_event, &cv->Ptr, FALSE, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
_Mtx_lock(mtx);
|
||||||
|
return status ? CND_TIMEDOUT : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __cdecl _Cnd_broadcast(_Cnd_t *cnd)
|
||||||
|
{
|
||||||
|
CONDITION_VARIABLE *cv = &(*cnd)->cv;
|
||||||
|
LONG val = InterlockedExchange( (LONG *)&cv->Ptr, 0 );
|
||||||
|
while (val-- > 0)
|
||||||
|
NtReleaseKeyedEvent( keyed_event, &cv->Ptr, FALSE, NULL );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int __cdecl _Cnd_signal(_Cnd_t *cnd)
|
||||||
|
{
|
||||||
|
CONDITION_VARIABLE *cv = &(*cnd)->cv;
|
||||||
|
if (interlocked_dec_if_nonzero( (LONG *)&cv->Ptr ))
|
||||||
|
NtReleaseKeyedEvent( keyed_event, &cv->Ptr, FALSE, NULL );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __cdecl _Cnd_destroy(_Cnd_t *cnd)
|
||||||
|
{
|
||||||
|
if(cnd) {
|
||||||
|
_Cnd_broadcast(cnd);
|
||||||
|
MSVCRT_operator_delete(*cnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if _MSVCP_VER == 100
|
#if _MSVCP_VER == 100
|
||||||
|
@ -684,6 +780,14 @@ void init_misc(void *base)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void free_misc(void)
|
||||||
|
{
|
||||||
|
#if _MSVCP_VER >= 110
|
||||||
|
if(keyed_event)
|
||||||
|
NtClose(keyed_event);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if _MSVCP_VER >= 110
|
#if _MSVCP_VER >= 110
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -629,3 +629,5 @@ static inline int mbstowcs_wrapper( size_t *ret, wchar_t *wcs, size_t size, cons
|
||||||
#define mbstowcs_s( ret, wcs, size, mbs, count ) mbstowcs_wrapper( ret, wcs, size, mbs, count )
|
#define mbstowcs_s( ret, wcs, size, mbs, count ) mbstowcs_wrapper( ret, wcs, size, mbs, count )
|
||||||
#define hypotf( x, y ) ((float)hypot( (double)(x), (double)(y) ))
|
#define hypotf( x, y ) ((float)hypot( (double)(x), (double)(y) ))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void free_misc(void);
|
||||||
|
|
|
@ -134,6 +134,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
free_io();
|
free_io();
|
||||||
free_locale();
|
free_locale();
|
||||||
free_lockit();
|
free_lockit();
|
||||||
|
free_misc();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue