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
PARENTSRC = ../msvcrt
C_SRCS = \
concrt140.c \
concurrency.c \
details.c
details.c \
exception_ptr.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,13 @@ 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);
}
static BOOL init_cxx_funcs(void)
{
msvcp140 = LoadLibraryA("msvcp140.dll");
......@@ -138,7 +146,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
......
......@@ -17,6 +17,7 @@ C_SRCS = \
except_arm64.c \
except_i386.c \
except_x86_64.c \
exception_ptr.c \
exit.c \
file.c \
heap.c \
......
......@@ -18,6 +18,7 @@ C_SRCS = \
except_arm64.c \
except_i386.c \
except_x86_64.c \
exception_ptr.c \
exit.c \
file.c \
heap.c \
......
......@@ -18,6 +18,7 @@ C_SRCS = \
except_arm64.c \
except_i386.c \
except_x86_64.c \
exception_ptr.c \
exit.c \
file.c \
heap.c \
......
......@@ -18,6 +18,7 @@ C_SRCS = \
except_arm64.c \
except_i386.c \
except_x86_64.c \
exception_ptr.c \
exit.c \
file.c \
heap.c \
......
......@@ -18,6 +18,7 @@ C_SRCS = \
except_arm64.c \
except_i386.c \
except_x86_64.c \
exception_ptr.c \
exit.c \
file.c \
heap.c \
......
......@@ -1900,13 +1900,56 @@ 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 (!((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)
......@@ -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@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z */
/* ?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z */
......@@ -2060,6 +2113,7 @@ void __thiscall _StructuredTaskCollection__Schedule(
_StructuredTaskCollection *this, _UnrealizedChore *chore)
{
LONG expected, val;
ULONG_PTR exception;
TRACE("(%p %p)\n", this, chore);
......@@ -2085,6 +2139,17 @@ void __thiscall _StructuredTaskCollection__Schedule(
this->finished = 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;
}
......
......@@ -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*);
......@@ -149,21 +149,6 @@ DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame
/* call a copy constructor */
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 */
extern void DECLSPEC_NORETURN continue_after_catch( cxx_exception_frame* frame, void *addr );
......
......@@ -28,6 +28,37 @@
#include "msvcrt.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
WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
......@@ -89,6 +120,8 @@ void __cdecl __ExceptionPtrDestroy(exception_ptr *ep)
}
}
#ifndef _CONCRT
/*********************************************************************
* ?__ExceptionPtrCopy@@YAXPAXPBX@Z
* ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z
......@@ -120,6 +153,8 @@ void __cdecl __ExceptionPtrAssign(exception_ptr *ep, const exception_ptr *assign
InterlockedIncrement(ep->ref);
}
#endif
/*********************************************************************
* ?__ExceptionPtrRethrow@@YAXPBX@Z
* ?__ExceptionPtrRethrow@@YAXPEBX@Z
......@@ -138,21 +173,8 @@ void __cdecl __ExceptionPtrRethrow(const exception_ptr *ep)
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__
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 +218,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 +264,8 @@ static void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec)
}
#endif
#ifndef _CONCRT
/*********************************************************************
* ?__ExceptionPtrCurrentException@@YAXPAX@Z
* ?__ExceptionPtrCurrentException@@YAXPEAX@Z
......@@ -349,4 +373,6 @@ bool __cdecl __ExceptionPtrCompare(const exception_ptr *ep1, const exception_ptr
return ep1->rec == ep2->rec;
}
#endif
#endif /* _MSVCR_VER >= 100 */
......@@ -19,6 +19,7 @@ C_SRCS = \
except_arm64.c \
except_i386.c \
except_x86_64.c \
exception_ptr.c \
exit.c \
file.c \
heap.c \
......
......@@ -23,6 +23,7 @@ C_SRCS = \
except_arm64.c \
except_i386.c \
except_x86_64.c \
exception_ptr.c \
exit.c \
file.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