msvcrt: Add ThreadScheduler::Attach implementation.

Signed-off-by: Piotr Caban <piotr@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Piotr Caban 2017-03-30 22:47:23 +02:00 committed by Alexandre Julliard
parent 1e58032098
commit dbb4e8553f
1 changed files with 39 additions and 3 deletions

View File

@ -96,17 +96,24 @@ union allocator_cache_entry {
} alloc; } alloc;
}; };
struct scheduler_list {
struct Scheduler *scheduler;
struct scheduler_list *next;
};
typedef struct { typedef struct {
Context context; Context context;
struct scheduler_list scheduler;
unsigned int id; unsigned int id;
union allocator_cache_entry *allocator_cache[8]; union allocator_cache_entry *allocator_cache[8];
} ExternalContextBase; } ExternalContextBase;
extern const vtable_ptr MSVCRT_ExternalContextBase_vtable; extern const vtable_ptr MSVCRT_ExternalContextBase_vtable;
static void ExternalContextBase_ctor(ExternalContextBase*); static void ExternalContextBase_ctor(ExternalContextBase*);
typedef struct { typedef struct Scheduler {
const vtable_ptr *vtable; const vtable_ptr *vtable;
} Scheduler; } Scheduler;
#define call_Scheduler_Release(this) CALL_VTBL_FUNC(this, 20, unsigned int, (Scheduler*), (this))
typedef struct { typedef struct {
Scheduler scheduler; Scheduler scheduler;
@ -255,6 +262,7 @@ MSVCRT_bool __thiscall ExternalContextBase_IsSynchronouslyBlocked(const External
static void ExternalContextBase_dtor(ExternalContextBase *this) static void ExternalContextBase_dtor(ExternalContextBase *this)
{ {
struct scheduler_list *scheduler_cur, *scheduler_next;
union allocator_cache_entry *next, *cur; union allocator_cache_entry *next, *cur;
int i; int i;
@ -265,6 +273,16 @@ static void ExternalContextBase_dtor(ExternalContextBase *this)
MSVCRT_operator_delete(cur); MSVCRT_operator_delete(cur);
} }
} }
if (this->scheduler.scheduler) {
call_Scheduler_Release(this->scheduler.scheduler);
for(scheduler_cur=this->scheduler.next; scheduler_cur; scheduler_cur=scheduler_next) {
scheduler_next = scheduler_cur->next;
call_Scheduler_Release(scheduler_cur->scheduler);
MSVCRT_operator_delete(scheduler_cur);
}
}
} }
DEFINE_THISCALL_WRAPPER(ExternalContextBase_vector_dtor, 8) DEFINE_THISCALL_WRAPPER(ExternalContextBase_vector_dtor, 8)
@ -291,9 +309,9 @@ static void ExternalContextBase_ctor(ExternalContextBase *this)
{ {
TRACE("(%p)->()\n", this); TRACE("(%p)->()\n", this);
memset(this, 0, sizeof(*this));
this->context.vtable = &MSVCRT_ExternalContextBase_vtable; this->context.vtable = &MSVCRT_ExternalContextBase_vtable;
this->id = InterlockedIncrement(&context_id); this->id = InterlockedIncrement(&context_id);
memset(this->allocator_cache, 0, sizeof(this->allocator_cache));
} }
/* ?Alloc@Concurrency@@YAPAXI@Z */ /* ?Alloc@Concurrency@@YAPAXI@Z */
@ -607,7 +625,25 @@ void __thiscall ThreadScheduler_RegisterShutdownEvent(ThreadScheduler *this, HAN
DEFINE_THISCALL_WRAPPER(ThreadScheduler_Attach, 4) DEFINE_THISCALL_WRAPPER(ThreadScheduler_Attach, 4)
void __thiscall ThreadScheduler_Attach(ThreadScheduler *this) void __thiscall ThreadScheduler_Attach(ThreadScheduler *this)
{ {
FIXME("(%p) stub\n", this); ExternalContextBase *context = (ExternalContextBase*)get_current_context();
TRACE("(%p)\n", this);
if(context->context.vtable != &MSVCRT_ExternalContextBase_vtable) {
ERR("unknown context set\n");
return;
}
if(context->scheduler.scheduler == &this->scheduler)
throw_exception(EXCEPTION_IMPROPER_SCHEDULER_ATTACH, 0, NULL);
if(context->scheduler.scheduler) {
struct scheduler_list *l = MSVCRT_operator_new(sizeof(*l));
*l = context->scheduler;
context->scheduler.next = l;
}
context->scheduler.scheduler = &this->scheduler;
ThreadScheduler_Reference(this);
} }
DEFINE_THISCALL_WRAPPER(ThreadScheduler_CreateScheduleGroup_loc, 8) DEFINE_THISCALL_WRAPPER(ThreadScheduler_CreateScheduleGroup_loc, 8)