Commit f26985af authored by Torge Matthies's avatar Torge Matthies Committed by Alexandre Julliard

msvcr100: Implement exception passing from chore threads to _RunAndWait.

parent 96e2a766
EXTRADEFS = -D_CONCRT=
MODULE = concrt140.dll MODULE = concrt140.dll
PARENTSRC = ../msvcrt PARENTSRC = ../msvcrt
C_SRCS = \ C_SRCS = \
concrt140.c \ concrt140.c \
concurrency.c \ concurrency.c \
details.c details.c \
exception_ptr.c
...@@ -91,6 +91,7 @@ __ASM_VTABLE(range_error, ...@@ -91,6 +91,7 @@ __ASM_VTABLE(range_error,
VTABLE_ADD_FUNC(exception_what)); VTABLE_ADD_FUNC(exception_what));
__ASM_BLOCK_END __ASM_BLOCK_END
DEFINE_CXX_EXCEPTION0( exception, exception_dtor )
DEFINE_RTTI_DATA1(runtime_error, 0, &exception_rtti_base_descriptor, ".?AVruntime_error@std@@") DEFINE_RTTI_DATA1(runtime_error, 0, &exception_rtti_base_descriptor, ".?AVruntime_error@std@@")
DEFINE_CXX_TYPE_INFO(runtime_error) DEFINE_CXX_TYPE_INFO(runtime_error)
DEFINE_RTTI_DATA2(range_error, 0, &runtime_error_rtti_base_descriptor, DEFINE_RTTI_DATA2(range_error, 0, &runtime_error_rtti_base_descriptor,
...@@ -105,6 +106,13 @@ void DECLSPEC_NORETURN throw_range_error(const char *str) ...@@ -105,6 +106,13 @@ void DECLSPEC_NORETURN throw_range_error(const char *str)
_CxxThrowException(&e, &range_error_exception_type); _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);
}
static BOOL init_cxx_funcs(void) static BOOL init_cxx_funcs(void)
{ {
msvcp140 = LoadLibraryA("msvcp140.dll"); msvcp140 = LoadLibraryA("msvcp140.dll");
...@@ -138,7 +146,7 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) ...@@ -138,7 +146,7 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
init_runtime_error_rtti((char*)inst); init_runtime_error_rtti((char*)inst);
init_type_info_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_runtime_error_cxx_type_info((char*)inst);
init_range_error_cxx((char*)inst); init_range_error_cxx((char*)inst);
#endif #endif
......
...@@ -17,6 +17,7 @@ C_SRCS = \ ...@@ -17,6 +17,7 @@ C_SRCS = \
except_arm64.c \ except_arm64.c \
except_i386.c \ except_i386.c \
except_x86_64.c \ except_x86_64.c \
exception_ptr.c \
exit.c \ exit.c \
file.c \ file.c \
heap.c \ heap.c \
......
...@@ -18,6 +18,7 @@ C_SRCS = \ ...@@ -18,6 +18,7 @@ C_SRCS = \
except_arm64.c \ except_arm64.c \
except_i386.c \ except_i386.c \
except_x86_64.c \ except_x86_64.c \
exception_ptr.c \
exit.c \ exit.c \
file.c \ file.c \
heap.c \ heap.c \
......
...@@ -18,6 +18,7 @@ C_SRCS = \ ...@@ -18,6 +18,7 @@ C_SRCS = \
except_arm64.c \ except_arm64.c \
except_i386.c \ except_i386.c \
except_x86_64.c \ except_x86_64.c \
exception_ptr.c \
exit.c \ exit.c \
file.c \ file.c \
heap.c \ heap.c \
......
...@@ -18,6 +18,7 @@ C_SRCS = \ ...@@ -18,6 +18,7 @@ C_SRCS = \
except_arm64.c \ except_arm64.c \
except_i386.c \ except_i386.c \
except_x86_64.c \ except_x86_64.c \
exception_ptr.c \
exit.c \ exit.c \
file.c \ file.c \
heap.c \ heap.c \
......
...@@ -18,6 +18,7 @@ C_SRCS = \ ...@@ -18,6 +18,7 @@ C_SRCS = \
except_arm64.c \ except_arm64.c \
except_i386.c \ except_i386.c \
except_x86_64.c \ except_x86_64.c \
exception_ptr.c \
exit.c \ exit.c \
file.c \ file.c \
heap.c \ heap.c \
......
...@@ -1900,13 +1900,56 @@ static ThreadScheduler *get_thread_scheduler_from_context(Context *context) ...@@ -1900,13 +1900,56 @@ static ThreadScheduler *get_thread_scheduler_from_context(Context *context)
return NULL; 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, static void execute_chore(_UnrealizedChore *chore,
_StructuredTaskCollection *task_collection) _StructuredTaskCollection *task_collection)
{ {
struct execute_chore_data data = { chore, task_collection };
TRACE("(%p %p)\n", chore, task_collection); TRACE("(%p %p)\n", chore, task_collection);
if (chore->chore_proc) __TRY
chore->chore_proc(chore); {
if (!((ULONG_PTR)task_collection->exception & ~0x7) && chore->chore_proc)
chore->chore_proc(chore);
}
__EXCEPT_CTX(execute_chore_except, &data)
{
}
__ENDTRY
} }
static void CALLBACK chore_wrapper_finally(BOOL normal, void *data) static void CALLBACK chore_wrapper_finally(BOOL normal, void *data)
...@@ -2053,6 +2096,16 @@ void __thiscall _StructuredTaskCollection__Schedule( ...@@ -2053,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@@QAA?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z */
/* ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAG?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 */ /* ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z */
...@@ -2060,6 +2113,7 @@ void __thiscall _StructuredTaskCollection__Schedule( ...@@ -2060,6 +2113,7 @@ void __thiscall _StructuredTaskCollection__Schedule(
_StructuredTaskCollection *this, _UnrealizedChore *chore) _StructuredTaskCollection *this, _UnrealizedChore *chore)
{ {
LONG expected, val; LONG expected, val;
ULONG_PTR exception;
TRACE("(%p %p)\n", this, chore); TRACE("(%p %p)\n", this, chore);
...@@ -2085,6 +2139,17 @@ void __thiscall _StructuredTaskCollection__Schedule( ...@@ -2085,6 +2139,17 @@ void __thiscall _StructuredTaskCollection__Schedule(
this->finished = 0; this->finished = 0;
this->count = 0; this->count = 0;
exception = (ULONG_PTR)this->exception;
if (exception & ~0x7) {
exception_ptr *ep = (exception_ptr*)(exception & ~0x7);
this->exception = 0;
__TRY
{
__ExceptionPtrRethrow(ep);
}
__FINALLY_CTX(exception_ptr_rethrow_finally, ep)
}
return 1; return 1;
} }
......
...@@ -316,3 +316,8 @@ typedef struct ...@@ -316,3 +316,8 @@ typedef struct
} exception_ptr; } exception_ptr;
void throw_exception(const char*) DECLSPEC_HIDDEN; 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*);
...@@ -149,21 +149,6 @@ DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame ...@@ -149,21 +149,6 @@ DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame
/* call a copy constructor */ /* call a copy constructor */
extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase ); extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase );
__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" );
/* continue execution to the specified address after exception is caught */ /* continue execution to the specified address after exception is caught */
extern void DECLSPEC_NORETURN continue_after_catch( cxx_exception_frame* frame, void *addr ); extern void DECLSPEC_NORETURN continue_after_catch( cxx_exception_frame* frame, void *addr );
......
...@@ -28,6 +28,37 @@ ...@@ -28,6 +28,37 @@
#include "msvcrt.h" #include "msvcrt.h"
#include "cxx.h" #include "cxx.h"
#ifdef __i386__
extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase );
__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" );
#elif _MSVCR_VER >= 100
static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase )
{
if (has_vbase)
((void (__cdecl*)(void*, void*, BOOL))func)(this, src, 1);
else
((void (__cdecl*)(void*, void*))func)(this, src);
}
#endif
#if _MSVCR_VER >= 100 #if _MSVCR_VER >= 100
WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
...@@ -89,6 +120,8 @@ void __cdecl __ExceptionPtrDestroy(exception_ptr *ep) ...@@ -89,6 +120,8 @@ void __cdecl __ExceptionPtrDestroy(exception_ptr *ep)
} }
} }
#ifndef _CONCRT
/********************************************************************* /*********************************************************************
* ?__ExceptionPtrCopy@@YAXPAXPBX@Z * ?__ExceptionPtrCopy@@YAXPAXPBX@Z
* ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z * ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z
...@@ -120,6 +153,8 @@ void __cdecl __ExceptionPtrAssign(exception_ptr *ep, const exception_ptr *assign ...@@ -120,6 +153,8 @@ void __cdecl __ExceptionPtrAssign(exception_ptr *ep, const exception_ptr *assign
InterlockedIncrement(ep->ref); InterlockedIncrement(ep->ref);
} }
#endif
/********************************************************************* /*********************************************************************
* ?__ExceptionPtrRethrow@@YAXPBX@Z * ?__ExceptionPtrRethrow@@YAXPBX@Z
* ?__ExceptionPtrRethrow@@YAXPEBX@Z * ?__ExceptionPtrRethrow@@YAXPEBX@Z
...@@ -138,21 +173,8 @@ void __cdecl __ExceptionPtrRethrow(const exception_ptr *ep) ...@@ -138,21 +173,8 @@ void __cdecl __ExceptionPtrRethrow(const exception_ptr *ep)
ep->rec->NumberParameters, ep->rec->ExceptionInformation); ep->rec->NumberParameters, ep->rec->ExceptionInformation);
} }
#ifdef __i386__
extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase );
#else
static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase )
{
TRACE( "calling copy ctor %p object %p src %p\n", func, this, src );
if (has_vbase)
((void (__cdecl*)(void*, void*, BOOL))func)(this, src, 1);
else
((void (__cdecl*)(void*, void*))func)(this, src);
}
#endif
#ifndef __x86_64__ #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); TRACE("(%p)\n", ep);
...@@ -196,7 +218,7 @@ static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) ...@@ -196,7 +218,7 @@ static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec)
return; return;
} }
#else #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); TRACE("(%p)\n", ep);
...@@ -242,6 +264,8 @@ static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec) ...@@ -242,6 +264,8 @@ static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec)
} }
#endif #endif
#ifndef _CONCRT
/********************************************************************* /*********************************************************************
* ?__ExceptionPtrCurrentException@@YAXPAX@Z * ?__ExceptionPtrCurrentException@@YAXPAX@Z
* ?__ExceptionPtrCurrentException@@YAXPEAX@Z * ?__ExceptionPtrCurrentException@@YAXPEAX@Z
...@@ -349,4 +373,6 @@ bool __cdecl __ExceptionPtrCompare(const exception_ptr *ep1, const exception_ptr ...@@ -349,4 +373,6 @@ bool __cdecl __ExceptionPtrCompare(const exception_ptr *ep1, const exception_ptr
return ep1->rec == ep2->rec; return ep1->rec == ep2->rec;
} }
#endif
#endif /* _MSVCR_VER >= 100 */ #endif /* _MSVCR_VER >= 100 */
...@@ -19,6 +19,7 @@ C_SRCS = \ ...@@ -19,6 +19,7 @@ C_SRCS = \
except_arm64.c \ except_arm64.c \
except_i386.c \ except_i386.c \
except_x86_64.c \ except_x86_64.c \
exception_ptr.c \
exit.c \ exit.c \
file.c \ file.c \
heap.c \ heap.c \
......
...@@ -23,6 +23,7 @@ C_SRCS = \ ...@@ -23,6 +23,7 @@ C_SRCS = \
except_arm64.c \ except_arm64.c \
except_i386.c \ except_i386.c \
except_x86_64.c \ except_x86_64.c \
exception_ptr.c \
exit.c \ exit.c \
file.c \ file.c \
heap.c \ heap.c \
......
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