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