From: Torge Matthies tmatthies@codeweavers.com
Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- dlls/concrt140/Makefile.in | 4 ++- dlls/concrt140/concrt140.c | 27 +++++++++++++- dlls/msvcrt/concurrency.c | 71 +++++++++++++++++++++++++++++++++++-- dlls/msvcrt/cxx.h | 5 +++ dlls/msvcrt/exception_ptr.c | 12 +++++-- 5 files changed, 113 insertions(+), 6 deletions(-)
diff --git a/dlls/concrt140/Makefile.in b/dlls/concrt140/Makefile.in index aac1ed7b34a..05258adf7ee 100644 --- a/dlls/concrt140/Makefile.in +++ b/dlls/concrt140/Makefile.in @@ -1,7 +1,9 @@ +EXTRADEFS = -D_CONCRT= MODULE = concrt140.dll PARENTSRC = ../msvcrt
C_SRCS = \ concrt140.c \ concurrency.c \ - details.c + details.c \ + exception_ptr.c diff --git a/dlls/concrt140/concrt140.c b/dlls/concrt140/concrt140.c index 0a770c9dae6..21973103e9f 100644 --- a/dlls/concrt140/concrt140.c +++ b/dlls/concrt140/concrt140.c @@ -91,6 +91,7 @@ __ASM_VTABLE(range_error, VTABLE_ADD_FUNC(exception_what)); __ASM_BLOCK_END
+DEFINE_CXX_EXCEPTION0( exception, exception_dtor ) DEFINE_RTTI_DATA1(runtime_error, 0, &exception_rtti_base_descriptor, ".?AVruntime_error@std@@") DEFINE_CXX_TYPE_INFO(runtime_error) DEFINE_RTTI_DATA2(range_error, 0, &runtime_error_rtti_base_descriptor, @@ -105,6 +106,30 @@ void DECLSPEC_NORETURN throw_range_error(const char *str) _CxxThrowException(&e, &range_error_exception_type); }
+void DECLSPEC_NORETURN throw_exception(const char* msg) +{ + exception e; + __exception_ctor(&e, msg, &exception_vtable); + _CxxThrowException(&e, &exception_exception_type); +} + +#ifdef __i386__ +__ASM_GLOBAL_FUNC( call_copy_ctor, + "pushl %ebp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") + __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") + "movl %esp, %ebp\n\t" + __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") + "pushl $1\n\t" + "movl 12(%ebp), %ecx\n\t" + "pushl 16(%ebp)\n\t" + "call *8(%ebp)\n\t" + "leave\n" + __ASM_CFI(".cfi_def_cfa %esp,4\n\t") + __ASM_CFI(".cfi_same_value %ebp\n\t") + "ret" ); +#endif + static BOOL init_cxx_funcs(void) { msvcp140 = LoadLibraryA("msvcp140.dll"); @@ -138,7 +163,7 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) init_runtime_error_rtti((char*)inst); init_type_info_rtti((char*)inst);
- init_exception_cxx_type_info((char*)inst); + init_exception_cxx((char*)inst); init_runtime_error_cxx_type_info((char*)inst); init_range_error_cxx((char*)inst); #endif diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index 9b066230a54..6d98010dd28 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -1900,13 +1900,57 @@ static ThreadScheduler *get_thread_scheduler_from_context(Context *context) return NULL; }
+struct execute_chore_data { + _UnrealizedChore *chore; + _StructuredTaskCollection *task_collection; +}; + +static LONG CALLBACK execute_chore_except(EXCEPTION_POINTERS *pexc, + void *_data) +{ + struct execute_chore_data *data = _data; + void *prev_exception, *new_exception; + exception_ptr *ptr; + + if (pexc->ExceptionRecord->ExceptionCode != CXX_EXCEPTION) + return EXCEPTION_CONTINUE_SEARCH; + + ptr = operator_new(sizeof(*ptr)); + __ExceptionPtrCreate(ptr); + exception_ptr_from_record(ptr, pexc->ExceptionRecord); + + new_exception = data->task_collection->exception; + do { + if ((ULONG_PTR)new_exception & ~0x7) { + __ExceptionPtrDestroy(ptr); + operator_delete(ptr); + break; + } + prev_exception = new_exception; + new_exception = (void*)((ULONG_PTR)new_exception | (ULONG_PTR)ptr); + } while ((new_exception = InterlockedCompareExchangePointer( + &data->task_collection->exception, new_exception, + prev_exception)) != prev_exception); + data->task_collection->event = 0; + return EXCEPTION_EXECUTE_HANDLER; +} + static void execute_chore(_UnrealizedChore *chore, _StructuredTaskCollection *task_collection) { + struct execute_chore_data data = { chore, task_collection }; + TRACE("(%p %p)\n", chore, task_collection);
- if (chore->chore_proc) - chore->chore_proc(chore); + __TRY + { + if (chore->chore_proc) + chore->chore_proc(chore); + } + __EXCEPT_CTX(execute_chore_except, &data) + { + } + __ENDTRY }
static void CALLBACK chore_wrapper_finally(BOOL normal, void *data) @@ -2052,6 +2096,16 @@ void __thiscall _StructuredTaskCollection__Schedule( } }
+static void CALLBACK exception_ptr_rethrow_finally(BOOL normal, void *data) +{ + exception_ptr *ep = data; + + TRACE("(%u %p)\n", normal, data); + + __ExceptionPtrDestroy(ep); + operator_delete(ep); +} + /* ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAA?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z */ /* ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z */ /* ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z */ @@ -2060,6 +2114,7 @@ _StructuredTaskCollection__RunAndWait( _StructuredTaskCollection *this, _UnrealizedChore *chore) { LONG expected, val; + ULONG_PTR exception;
TRACE("(%p %p)\n", this, chore);
@@ -2085,6 +2140,18 @@ _StructuredTaskCollection__RunAndWait(
this->finished = 0; this->count = 0; + + exception = (ULONG_PTR)this->exception; + if (exception & ~0x7) + this->exception = 0; + if (exception & ~0x7) { + exception_ptr *ep = (exception_ptr*)(exception & ~0x7); + __TRY + { + __ExceptionPtrRethrow(ep); + } + __FINALLY_CTX(exception_ptr_rethrow_finally, ep) + } return 1; }
diff --git a/dlls/msvcrt/cxx.h b/dlls/msvcrt/cxx.h index 4051229c626..c2558974b73 100644 --- a/dlls/msvcrt/cxx.h +++ b/dlls/msvcrt/cxx.h @@ -316,3 +316,8 @@ typedef struct } exception_ptr;
void throw_exception(const char*) DECLSPEC_HIDDEN; +void exception_ptr_from_record(exception_ptr*,EXCEPTION_RECORD*) DECLSPEC_HIDDEN; + +void __cdecl __ExceptionPtrCreate(exception_ptr*); +void __cdecl __ExceptionPtrDestroy(exception_ptr*); +void __cdecl __ExceptionPtrRethrow(const exception_ptr*); diff --git a/dlls/msvcrt/exception_ptr.c b/dlls/msvcrt/exception_ptr.c index 8238baec548..82ab4acff43 100644 --- a/dlls/msvcrt/exception_ptr.c +++ b/dlls/msvcrt/exception_ptr.c @@ -89,6 +89,8 @@ void __cdecl __ExceptionPtrDestroy(exception_ptr *ep) } }
+#ifndef _CONCRT + /********************************************************************* * ?__ExceptionPtrCopy@@YAXPAXPBX@Z * ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z @@ -120,6 +122,8 @@ void __cdecl __ExceptionPtrAssign(exception_ptr *ep, const exception_ptr *assign InterlockedIncrement(ep->ref); }
+#endif + /********************************************************************* * ?__ExceptionPtrRethrow@@YAXPBX@Z * ?__ExceptionPtrRethrow@@YAXPEBX@Z @@ -152,7 +156,7 @@ static inline void call_copy_ctor( void *func, void *this, void *src, int has_vb #endif
#ifndef __x86_64__ -static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) +void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) { TRACE("(%p)\n", ep);
@@ -196,7 +200,7 @@ static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) return; } #else -static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) +void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) { TRACE("(%p)\n", ep);
@@ -242,6 +246,8 @@ static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) } #endif
+#ifndef _CONCRT + /********************************************************************* * ?__ExceptionPtrCurrentException@@YAXPAX@Z * ?__ExceptionPtrCurrentException@@YAXPEAX@Z @@ -349,4 +355,6 @@ bool __cdecl __ExceptionPtrCompare(const exception_ptr *ep1, const exception_ptr return ep1->rec == ep2->rec; }
+#endif + #endif /* _MSVCR_VER >= 100 */