Module: wine Branch: master Commit: 3fa2bb2dce9b52b24e512580241185888716fc0f URL: http://source.winehq.org/git/wine.git/?a=commit;h=3fa2bb2dce9b52b24e51258024...
Author: Piotr Caban piotr@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@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 */ } }
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;