From: Piotr Caban Subject: [PATCH 2/7 v2] msvcrt: Add ExternalContextBase class stub Message-Id: Date: Thu, 23 Mar 2017 11:41:05 +0100 Signed-off-by: Piotr Caban --- dlls/msvcrt/cppexcept.h | 2 +- dlls/msvcrt/cxx.h | 15 ++++ dlls/msvcrt/main.c | 10 +++ dlls/msvcrt/msvcrt.h | 6 ++ dlls/msvcrt/scheduler.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 213 insertions(+), 7 deletions(-) diff --git a/dlls/msvcrt/cppexcept.h b/dlls/msvcrt/cppexcept.h index 16a6e16..6ea5818 100644 --- a/dlls/msvcrt/cppexcept.h +++ b/dlls/msvcrt/cppexcept.h @@ -33,7 +33,7 @@ typedef struct __type_info { const vtable_ptr *vtable; char *name; /* Unmangled name, allocated lazily */ - char mangled[32]; /* Variable length, but we declare it large enough for static RTTI */ + char mangled[64]; /* Variable length, but we declare it large enough for static RTTI */ } type_info; /* exception object */ diff --git a/dlls/msvcrt/cxx.h b/dlls/msvcrt/cxx.h index 8f31f24..baf519f 100644 --- a/dlls/msvcrt/cxx.h +++ b/dlls/msvcrt/cxx.h @@ -259,3 +259,18 @@ typedef struct } rtti_object_locator; #endif + +#ifdef __i386__ + +#define CALL_VTBL_FUNC(this, off, ret, type, args) ((ret (WINAPI*)type)&vtbl_wrapper_##off)args + +extern void *vtbl_wrapper_0; +extern void *vtbl_wrapper_4; +extern void *vtbl_wrapper_8; +extern void *vtbl_wrapper_20; + +#else + +#define CALL_VTBL_FUNC(this, off, ret, type, args) ((ret (__cdecl***)type)this)[0][off/4]args + +#endif diff --git a/dlls/msvcrt/main.c b/dlls/msvcrt/main.c index a930a32..0be8dd3 100644 --- a/dlls/msvcrt/main.c +++ b/dlls/msvcrt/main.c @@ -115,6 +115,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) msvcrt_init_console(); msvcrt_init_args(); msvcrt_init_signals(); +#if _MSVCR_VER >= 100 && _MSVCR_VER <= 120 + msvcrt_init_scheduler(hinstDLL); +#endif #if _MSVCR_VER == 0 /* don't allow unloading msvcrt, we can't setup file handles twice */ LdrAddRefDll( LDR_ADDREF_DLL_PIN, hinstDLL ); @@ -137,11 +140,18 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) if (!msvcrt_free_tls()) return FALSE; MSVCRT__free_locale(MSVCRT_locale); +#if _MSVCR_VER >= 100 && _MSVCR_VER <= 120 + msvcrt_free_scheduler_thread(); + msvcrt_free_scheduler(); +#endif msvcrt_destroy_heap(); TRACE("finished process free\n"); break; case DLL_THREAD_DETACH: msvcrt_free_tls_mem(); +#if _MSVCR_VER >= 100 && _MSVCR_VER <= 120 + msvcrt_free_scheduler_thread(); +#endif TRACE("finished thread free\n"); break; } diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index cee8113..659a3dc 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -329,6 +329,12 @@ extern void msvcrt_free_popen_data(void) DECLSPEC_HIDDEN; extern BOOL msvcrt_init_heap(void) DECLSPEC_HIDDEN; extern void msvcrt_destroy_heap(void) DECLSPEC_HIDDEN; +#if _MSVCR_VER >= 100 +extern void msvcrt_init_scheduler(void*) DECLSPEC_HIDDEN; +extern void msvcrt_free_scheduler(void) DECLSPEC_HIDDEN; +extern void msvcrt_free_scheduler_thread(void) DECLSPEC_HIDDEN; +#endif + extern unsigned msvcrt_create_io_inherit_block(WORD*, BYTE**) DECLSPEC_HIDDEN; extern unsigned int __cdecl _control87(unsigned int, unsigned int); diff --git a/dlls/msvcrt/scheduler.c b/dlls/msvcrt/scheduler.c index f7fd859..c76aa00 100644 --- a/dlls/msvcrt/scheduler.c +++ b/dlls/msvcrt/scheduler.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include "config.h" + #include #include "windef.h" @@ -29,23 +31,89 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); +#ifdef __i386__ + +#define DEFINE_VTBL_WRAPPER(off) \ + __ASM_GLOBAL_FUNC(vtbl_wrapper_ ## off, \ + "popl %eax\n\t" \ + "popl %ecx\n\t" \ + "pushl %eax\n\t" \ + "movl 0(%ecx), %eax\n\t" \ + "jmp *" #off "(%eax)\n\t") + +DEFINE_VTBL_WRAPPER(0); +DEFINE_VTBL_WRAPPER(4); +DEFINE_VTBL_WRAPPER(8); +DEFINE_VTBL_WRAPPER(20); + +#endif + typedef struct { const vtable_ptr *vtable; } Context; +#define call_Context_GetId(this) CALL_VTBL_FUNC(this, 0, \ + unsigned int, (const Context*), (this)) +#define call_Context_GetVirtualProcessorId(this) CALL_VTBL_FUNC(this, 4, \ + unsigned int, (const Context*), (this)) +#define call_Context_GetScheduleGroupId(this) CALL_VTBL_FUNC(this, 8, \ + unsigned int, (const Context*), (this)) +#define call_Context_dtor(this, flags) CALL_VTBL_FUNC(this, 20, \ + Context*, (Context*, unsigned int), (this, flags)) + +typedef struct { + Context context; +} ExternalContextBase; +extern const vtable_ptr MSVCRT_ExternalContextBase_vtable; +static void ExternalContextBase_ctor(ExternalContextBase*); + +static int context_tls_index = TLS_OUT_OF_INDEXES; + +static Context* try_get_current_context(void) +{ + if (context_tls_index == TLS_OUT_OF_INDEXES) + return NULL; + return TlsGetValue(context_tls_index); +} + +static Context* get_current_context(void) +{ + Context *ret; + + if (context_tls_index == TLS_OUT_OF_INDEXES) { + int tls_index = TlsAlloc(); + if (tls_index == TLS_OUT_OF_INDEXES) { + /* throw scheduler_resource_allocation_error */ + return NULL; + } + + if(InterlockedCompareExchange(&context_tls_index, tls_index, TLS_OUT_OF_INDEXES) != TLS_OUT_OF_INDEXES) + TlsFree(tls_index); + } + + ret = TlsGetValue(context_tls_index); + if (!ret) { + ExternalContextBase *context = MSVCRT_operator_new(sizeof(ExternalContextBase)); + ExternalContextBase_ctor(context); + TlsSetValue(context_tls_index, context); + ret = &context->context; + } + return ret; +} /* ?CurrentContext@Context@Concurrency@@SAPAV12@XZ */ /* ?CurrentContext@Context@Concurrency@@SAPEAV12@XZ */ Context* __cdecl Context_CurrentContext(void) { - FIXME("()\n"); - return NULL; + TRACE("()\n"); + return get_current_context(); } /* ?Id@Context@Concurrency@@SAIXZ */ unsigned int __cdecl Context_Id(void) { - FIXME("()\n"); - return -1; + Context *ctx = try_get_current_context(); + TRACE("()\n"); + return ctx ? call_Context_GetId(ctx) : -1; } /* ?Block@Context@Concurrency@@SAXXZ */ @@ -82,13 +150,120 @@ void __cdecl Context_Oversubscribe(MSVCRT_bool begin) /* ?ScheduleGroupId@Context@Concurrency@@SAIXZ */ unsigned int __cdecl Context_ScheduleGroupId(void) { - FIXME("()\n"); - return -1; + Context *ctx = try_get_current_context(); + TRACE("()\n"); + return ctx ? call_Context_GetScheduleGroupId(ctx) : -1; } /* ?VirtualProcessorId@Context@Concurrency@@SAIXZ */ unsigned int __cdecl Context_VirtualProcessorId(void) { + Context *ctx = try_get_current_context(); FIXME("()\n"); + return ctx ? call_Context_GetVirtualProcessorId(ctx) : -1; +} + +DEFINE_THISCALL_WRAPPER(ExternalContextBase_GetId, 4) +unsigned int __thiscall ExternalContextBase_GetId(const ExternalContextBase *this) +{ + FIXME("(%p)->() stub\n", this); return -1; } + +DEFINE_THISCALL_WRAPPER(ExternalContextBase_GetVirtualProcessorId, 4) +unsigned int __thiscall ExternalContextBase_GetVirtualProcessorId(const ExternalContextBase *this) +{ + FIXME("(%p)->() stub\n", this); + return -1; +} + +DEFINE_THISCALL_WRAPPER(ExternalContextBase_GetScheduleGroupId, 4) +unsigned int __thiscall ExternalContextBase_GetScheduleGroupId(const ExternalContextBase *this) +{ + FIXME("(%p)->() stub\n", this); + return -1; +} + +DEFINE_THISCALL_WRAPPER(ExternalContextBase_Unblock, 4) +void __thiscall ExternalContextBase_Unblock(ExternalContextBase *this) +{ + FIXME("(%p)->() stub\n", this); +} + +DEFINE_THISCALL_WRAPPER(ExternalContextBase_IsSynchronouslyBlocked, 4) +MSVCRT_bool __thiscall ExternalContextBase_IsSynchronouslyBlocked(const ExternalContextBase *this) +{ + FIXME("(%p)->() stub\n", this); + return FALSE; +} + +static void ExternalContextBase_dtor(ExternalContextBase *this) +{ +} + +DEFINE_THISCALL_WRAPPER(ExternalContextBase_vector_dtor, 8) +Context* __thiscall ExternalContextBase_vector_dtor(ExternalContextBase *this, unsigned int flags) +{ + TRACE("(%p %x)\n", this, flags); + if(flags & 2) { + /* we have an array, with the number of elements stored before the first object */ + INT_PTR i, *ptr = (INT_PTR *)this-1; + + for(i=*ptr-1; i>=0; i--) + ExternalContextBase_dtor(this+i); + MSVCRT_operator_delete(ptr); + } else { + ExternalContextBase_dtor(this); + if(flags & 1) + MSVCRT_operator_delete(this); + } + + return &this->context; +} + +static void ExternalContextBase_ctor(ExternalContextBase *this) +{ + this->context.vtable = &MSVCRT_ExternalContextBase_vtable; +} + +extern const vtable_ptr MSVCRT_type_info_vtable; +DEFINE_RTTI_DATA0(Context, 0, ".?AVContext@Concurrency@@") +DEFINE_RTTI_DATA1(ContextBase, 0, &Context_rtti_base_descriptor, ".?AVContextBase@details@Concurrency@@") +DEFINE_RTTI_DATA2(ExternalContextBase, 0, &ContextBase_rtti_base_descriptor, + &Context_rtti_base_descriptor, ".?AVExternalContextBase@details@Concurrency@@") + +#ifndef __GNUC__ +void __asm_dummy_vtables(void) { +#endif + __ASM_VTABLE(ExternalContextBase, + VTABLE_ADD_FUNC(ExternalContextBase_GetId) + VTABLE_ADD_FUNC(ExternalContextBase_GetVirtualProcessorId) + VTABLE_ADD_FUNC(ExternalContextBase_GetScheduleGroupId) + VTABLE_ADD_FUNC(ExternalContextBase_Unblock) + VTABLE_ADD_FUNC(ExternalContextBase_IsSynchronouslyBlocked) + VTABLE_ADD_FUNC(ExternalContextBase_vector_dtor)); +#ifndef __GNUC__ +} +#endif + +void msvcrt_init_scheduler(void *base) +{ +#ifdef __x86_64__ + init_Context_rtti(base); + init_ContextBase_rtti(base); + init_ExternalContextBase_rtti(base); +#endif +} + +void msvcrt_free_scheduler(void) +{ + if (context_tls_index != TLS_OUT_OF_INDEXES) + TlsFree(context_tls_index); +} + +void msvcrt_free_scheduler_thread(void) +{ + Context *context = try_get_current_context(); + if (!context) return; + call_Context_dtor(context, 1); +}