Piotr Caban : msvcp110: Add _Mtx_{destroy, getconcrtcs, init, lock, unlock, trylock} implementation.
Alexandre Julliard
julliard at wine.codeweavers.com
Thu Jun 26 15:04:51 CDT 2014
Module: wine
Branch: master
Commit: 3fa2bb2dce9b52b24e512580241185888716fc0f
URL: http://source.winehq.org/git/wine.git/?a=commit;h=3fa2bb2dce9b52b24e512580241185888716fc0f
Author: Piotr Caban <piotr at codeweavers.com>
Date: Thu Jun 26 13:46:09 2014 +0200
msvcp110: Add _Mtx_{destroy,getconcrtcs,init,lock,unlock,trylock} implementation.
---
dlls/msvcp110/msvcp110.spec | 12 ++---
dlls/msvcp90/misc.c | 104 ++++++++++++++++++++++++++++++++++++++++++++
dlls/msvcp90/msvcp90.h | 25 +++++++++++
dlls/msvcp90/msvcp_main.c | 32 ++++++++++++++
dlls/msvcrt/lock.c | 1 +
5 files changed, 168 insertions(+), 6 deletions(-)
diff --git a/dlls/msvcp110/msvcp110.spec b/dlls/msvcp110/msvcp110.spec
index 331df11..5fc5348 100644
--- a/dlls/msvcp110/msvcp110.spec
+++ b/dlls/msvcp110/msvcp110.spec
@@ -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
diff --git a/dlls/msvcp90/misc.c b/dlls/msvcp90/misc.c
index 1c3bd2f..abd53d7 100644
--- a/dlls/msvcp90/misc.c
+++ b/dlls/msvcp90/misc.c
@@ -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
diff --git a/dlls/msvcp90/msvcp90.h b/dlls/msvcp90/msvcp90.h
index 0d5e124..5062bdc 100644
--- a/dlls/msvcp90/msvcp90.h
+++ b/dlls/msvcp90/msvcp90.h
@@ -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
diff --git a/dlls/msvcp90/msvcp_main.c b/dlls/msvcp90/msvcp_main.c
index 489aacb..edbdd50 100644
--- a/dlls/msvcp90/msvcp_main.c
+++ b/dlls/msvcp90/msvcp_main.c
@@ -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 at YAPEAX_K@Z");
MSVCRT_operator_delete = (void*)GetProcAddress(hmod, "??3 at YAXPEAX@Z");
MSVCRT_set_new_handler = (void*)GetProcAddress(hmod, "?_set_new_handler@@YAP6AH_K at ZP6AH0@Z at Z");
+
+#if _MSVCP_VER >= 110
+ critical_section_ctor = (void*)GetProcAddress(hmod, "??0critical_section at Concurrency@@QEAA at XZ");
+ critical_section_dtor = (void*)GetProcAddress(hmod, "??1critical_section at Concurrency@@QEAA at XZ");
+ critical_section_lock = (void*)GetProcAddress(hmod, "?lock at critical_section@Concurrency@@QEAAXXZ");
+ critical_section_unlock = (void*)GetProcAddress(hmod, "?unlock at critical_section@Concurrency@@QEAAXXZ");
+ critical_section_trylock = (void*)GetProcAddress(hmod, "?try_lock at critical_section@Concurrency@@QEAA_NXZ");
+#endif
}
else
{
MSVCRT_operator_new = (void*)GetProcAddress(hmod, "??2 at YAPAXI@Z");
MSVCRT_operator_delete = (void*)GetProcAddress(hmod, "??3 at YAXPAX@Z");
MSVCRT_set_new_handler = (void*)GetProcAddress(hmod, "?_set_new_handler@@YAP6AHI at ZP6AHI@Z at Z");
+
+#if _MSVCP_VER >= 110
+#ifdef __arm__
+ critical_section_ctor = (void*)GetProcAddress(hmod, "??0critical_section at Concurrency@@QAA at XZ");
+ critical_section_dtor = (void*)GetProcAddress(hmod, "??1critical_section at Concurrency@@QAA at XZ");
+ critical_section_lock = (void*)GetProcAddress(hmod, "?lock at critical_section@Concurrency@@QAAXXZ");
+ critical_section_unlock = (void*)GetProcAddress(hmod, "?unlock at critical_section@Concurrency@@QAAXXZ");
+ critical_section_trylock = (void*)GetProcAddress(hmod, "?try_lock at critical_section@Concurrency@@QAA_NXZ");
+#else
+ critical_section_ctor = (void*)GetProcAddress(hmod, "??0critical_section at Concurrency@@QAE at XZ");
+ critical_section_dtor = (void*)GetProcAddress(hmod, "??1critical_section at Concurrency@@QAE at XZ");
+ critical_section_lock = (void*)GetProcAddress(hmod, "?lock at critical_section@Concurrency@@QAEXXZ");
+ critical_section_unlock = (void*)GetProcAddress(hmod, "?unlock at critical_section@Concurrency@@QAEXXZ");
+ critical_section_trylock = (void*)GetProcAddress(hmod, "?try_lock at critical_section@Concurrency@@QAE_NXZ");
+#endif
+#endif /* _MSVCP_VER >= 110 */
}
}
diff --git a/dlls/msvcrt/lock.c b/dlls/msvcrt/lock.c
index aee8d2b..328b5b5 100644
--- a/dlls/msvcrt/lock.c
+++ b/dlls/msvcrt/lock.c
@@ -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;
More information about the wine-cvs
mailing list