Commit 3fa2bb2d authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

msvcp110: Add _Mtx_{destroy,getconcrtcs,init,lock,unlock,trylock} implementation.

parent 333fbba6
......@@ -3819,14 +3819,14 @@
@ cdecl _Mbrtowc(ptr ptr long ptr ptr)
@ stub _Mtx_clear_owner
@ stub _Mtx_current_owns
@ stub _Mtx_destroy
@ stub _Mtx_getconcrtcs
@ stub _Mtx_init
@ stub _Mtx_lock
@ cdecl _Mtx_destroy(ptr)
@ cdecl _Mtx_getconcrtcs(ptr)
@ cdecl _Mtx_init(ptr long)
@ cdecl _Mtx_lock(ptr)
@ stub _Mtx_reset_owner
@ stub _Mtx_timedlock
@ stub _Mtx_trylock
@ stub _Mtx_unlock
@ cdecl _Mtx_trylock(ptr)
@ cdecl _Mtx_unlock(ptr)
@ stub _Mtxdst
@ stub _Mtxinit
@ stub _Mtxlock
......
......@@ -374,3 +374,107 @@ unsigned int __cdecl _Random_device(void)
return ret;
}
#endif
#if _MSVCP_VER >= 110
#if defined(__i386__) && !defined(__arm__)
#define THISCALL(func) __thiscall_ ## func
#define __thiscall __stdcall
#define DEFINE_THISCALL_WRAPPER(func,args) \
extern void THISCALL(func)(void); \
__ASM_GLOBAL_FUNC(__thiscall_ ## func, \
"popl %eax\n\t" \
"pushl %ecx\n\t" \
"pushl %eax\n\t" \
"jmp " __ASM_NAME(#func) __ASM_STDCALL(args) )
extern void *call_thiscall_func;
__ASM_GLOBAL_FUNC(call_thiscall_func,
"popl %eax\n\t"
"popl %edx\n\t"
"popl %ecx\n\t"
"pushl %eax\n\t"
"jmp *%edx\n\t")
#define call_func1(func,this) ((void* (WINAPI*)(void*,void*))&call_thiscall_func)(func,this)
#else /* __i386__ */
#define __thiscall __cdecl
#define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */
#define call_func1(func,this) func(this)
#endif /* __i386__ */
#define MTX_MULTI_LOCK 0x100
#define MTX_LOCKED 3
typedef struct
{
DWORD flags;
critical_section cs;
DWORD thread_id;
DWORD count;
} *_Mtx_t;
int __cdecl _Mtx_init(_Mtx_t *mtx, int flags)
{
if(flags & ~MTX_MULTI_LOCK)
FIXME("unknown flags ignorred: %x\n", flags);
*mtx = MSVCRT_operator_new(sizeof(**mtx));
(*mtx)->flags = flags;
call_func1(critical_section_ctor, &(*mtx)->cs);
(*mtx)->thread_id = -1;
(*mtx)->count = 0;
return 0;
}
void __cdecl _Mtx_destroy(_Mtx_t *mtx)
{
call_func1(critical_section_dtor, &(*mtx)->cs);
MSVCRT_operator_delete(*mtx);
}
int __cdecl _Mtx_lock(_Mtx_t *mtx)
{
if((*mtx)->thread_id != GetCurrentThreadId()) {
call_func1(critical_section_lock, &(*mtx)->cs);
(*mtx)->thread_id = GetCurrentThreadId();
}else if(!((*mtx)->flags & MTX_MULTI_LOCK)) {
return MTX_LOCKED;
}
(*mtx)->count++;
return 0;
}
int __cdecl _Mtx_unlock(_Mtx_t *mtx)
{
if(--(*mtx)->count)
return 0;
(*mtx)->thread_id = -1;
call_func1(critical_section_unlock, &(*mtx)->cs);
return 0;
}
int __cdecl _Mtx_trylock(_Mtx_t *mtx)
{
if((*mtx)->thread_id != GetCurrentThreadId()) {
if(!call_func1(critical_section_trylock, &(*mtx)->cs))
return MTX_LOCKED;
(*mtx)->thread_id = GetCurrentThreadId();
}else if(!((*mtx)->flags & MTX_MULTI_LOCK)) {
return MTX_LOCKED;
}
(*mtx)->count++;
return 0;
}
critical_section* __cdecl _Mtx_getconcrtcs(_Mtx_t *mtx)
{
return &(*mtx)->cs;
}
#endif
......@@ -45,6 +45,31 @@ extern void* (__cdecl *MSVCRT_operator_new)(MSVCP_size_t);
extern void (__cdecl *MSVCRT_operator_delete)(void*);
extern void* (__cdecl *MSVCRT_set_new_handler)(void*);
#if _MSVCP_VER >= 110
/* keep in sync with msvcrt/lock.c */
typedef struct cs_queue
{
struct cs_queue *next;
BOOL free;
int unknown;
} cs_queue;
typedef struct
{
ULONG_PTR unk_thread_id;
cs_queue unk_active;
void *unknown[2];
cs_queue *head;
void *tail;
} critical_section;
extern critical_section* (__thiscall *critical_section_ctor)(critical_section*);
extern void (__thiscall *critical_section_dtor)(critical_section*);
extern void (__thiscall *critical_section_lock)(critical_section*);
extern void (__thiscall *critical_section_unlock)(critical_section*);
extern MSVCP_bool (__thiscall *critical_section_trylock)(critical_section*);
#endif
/* basic_string<char, char_traits<char>, allocator<char>> */
#define BUF_SIZE_CHAR 16
typedef struct
......
......@@ -60,6 +60,14 @@ void* (__cdecl *MSVCRT_operator_new)(MSVCP_size_t);
void (__cdecl *MSVCRT_operator_delete)(void*);
void* (__cdecl *MSVCRT_set_new_handler)(void*);
#if _MSVCP_VER >= 110
critical_section* (__thiscall *critical_section_ctor)(critical_section*);
void (__thiscall *critical_section_dtor)(critical_section*);
void (__thiscall *critical_section_lock)(critical_section*);
void (__thiscall *critical_section_unlock)(critical_section*);
MSVCP_bool (__thiscall *critical_section_trylock)(critical_section*);
#endif
#define VERSION_STRING(ver) #ver
#define MSVCRT_NAME(ver) "msvcr" VERSION_STRING(ver) ".dll"
......@@ -74,12 +82,36 @@ static void init_cxx_funcs(void)
MSVCRT_operator_new = (void*)GetProcAddress(hmod, "??2@YAPEAX_K@Z");
MSVCRT_operator_delete = (void*)GetProcAddress(hmod, "??3@YAXPEAX@Z");
MSVCRT_set_new_handler = (void*)GetProcAddress(hmod, "?_set_new_handler@@YAP6AH_K@ZP6AH0@Z@Z");
#if _MSVCP_VER >= 110
critical_section_ctor = (void*)GetProcAddress(hmod, "??0critical_section@Concurrency@@QEAA@XZ");
critical_section_dtor = (void*)GetProcAddress(hmod, "??1critical_section@Concurrency@@QEAA@XZ");
critical_section_lock = (void*)GetProcAddress(hmod, "?lock@critical_section@Concurrency@@QEAAXXZ");
critical_section_unlock = (void*)GetProcAddress(hmod, "?unlock@critical_section@Concurrency@@QEAAXXZ");
critical_section_trylock = (void*)GetProcAddress(hmod, "?try_lock@critical_section@Concurrency@@QEAA_NXZ");
#endif
}
else
{
MSVCRT_operator_new = (void*)GetProcAddress(hmod, "??2@YAPAXI@Z");
MSVCRT_operator_delete = (void*)GetProcAddress(hmod, "??3@YAXPAX@Z");
MSVCRT_set_new_handler = (void*)GetProcAddress(hmod, "?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z");
#if _MSVCP_VER >= 110
#ifdef __arm__
critical_section_ctor = (void*)GetProcAddress(hmod, "??0critical_section@Concurrency@@QAA@XZ");
critical_section_dtor = (void*)GetProcAddress(hmod, "??1critical_section@Concurrency@@QAA@XZ");
critical_section_lock = (void*)GetProcAddress(hmod, "?lock@critical_section@Concurrency@@QAAXXZ");
critical_section_unlock = (void*)GetProcAddress(hmod, "?unlock@critical_section@Concurrency@@QAAXXZ");
critical_section_trylock = (void*)GetProcAddress(hmod, "?try_lock@critical_section@Concurrency@@QAA_NXZ");
#else
critical_section_ctor = (void*)GetProcAddress(hmod, "??0critical_section@Concurrency@@QAE@XZ");
critical_section_dtor = (void*)GetProcAddress(hmod, "??1critical_section@Concurrency@@QAE@XZ");
critical_section_lock = (void*)GetProcAddress(hmod, "?lock@critical_section@Concurrency@@QAEXXZ");
critical_section_unlock = (void*)GetProcAddress(hmod, "?unlock@critical_section@Concurrency@@QAEXXZ");
critical_section_trylock = (void*)GetProcAddress(hmod, "?try_lock@critical_section@Concurrency@@QAE_NXZ");
#endif
#endif /* _MSVCP_VER >= 110 */
}
}
......
......@@ -287,6 +287,7 @@ MSVCRT_bool __thiscall SpinWait__SpinOnce(SpinWait *this)
static HANDLE keyed_event;
/* keep in sync with msvcp90/msvcp90.h */
typedef struct cs_queue
{
struct cs_queue *next;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment