Commit a25ac1ed authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

server: Store both contexts in pending context object.

And discard irrelevant parts in select request.
parent 949681d8
......@@ -119,11 +119,10 @@ struct context
{
struct object obj; /* object header */
unsigned int status; /* status of the context */
context_t regs[3]; /* context data */
context_t regs[2]; /* context data */
};
#define CTX_NATIVE 0 /* context for native machine */
#define CTX_WOW 1 /* context if thread is inside WoW */
#define CTX_PENDING 2 /* pending native context when we don't know whether thread is inside WoW */
/* flags for registers that always need to be set from the server side */
static const unsigned int system_flags = SERVER_CTX_DEBUG_REGISTERS;
......@@ -292,7 +291,6 @@ static struct context *create_thread_context( struct thread *thread )
context->status = STATUS_PENDING;
memset( &context->regs, 0, sizeof(context->regs) );
context->regs[CTX_NATIVE].machine = native_machine;
context->regs[CTX_PENDING].machine = native_machine;
return context;
}
......@@ -1591,8 +1589,6 @@ DECL_HANDLER(select)
const context_t *native_context = (const context_t *)((const char *)(result + 1) + req->size);
const context_t *wow_context = (ctx_count > 1) ? native_context + 1 : NULL;
if (current->context && current->context->status != STATUS_PENDING) goto invalid_param;
if (native_context->machine == native_machine)
{
if (wow_context && wow_context->machine != current->process->machine) goto invalid_param;
......@@ -1605,7 +1601,14 @@ DECL_HANDLER(select)
}
else goto invalid_param;
if (!current->context && !(current->context = create_thread_context( current ))) return;
if ((ctx = current->context))
{
if (ctx->status != STATUS_PENDING) goto invalid_param;
/* if context was modified in pending state, discard irrelevant changes */
if (wow_context) ctx->regs[CTX_NATIVE].flags &= ~ctx->regs[CTX_WOW].flags;
else ctx->regs[CTX_WOW].flags = ctx->regs[CTX_WOW].machine = 0;
}
else if (!(current->context = create_thread_context( current ))) return;
ctx = current->context;
if (native_context)
......@@ -1618,13 +1621,6 @@ DECL_HANDLER(select)
ctx->regs[CTX_WOW].machine = current->process->machine;
copy_context( &ctx->regs[CTX_WOW], wow_context, wow_context->flags & ~ctx->regs[CTX_WOW].flags );
}
else if (ctx->regs[CTX_PENDING].flags)
{
unsigned int flags = ctx->regs[CTX_PENDING].flags & ~ctx->regs[CTX_NATIVE].flags;
copy_context( &ctx->regs[CTX_NATIVE], &ctx->regs[CTX_PENDING], flags );
ctx->regs[CTX_NATIVE].flags |= flags;
}
ctx->regs[CTX_PENDING].flags = 0;
ctx->status = STATUS_SUCCESS;
current->suspend_cookie = req->cookie;
wake_up( &ctx->obj, 0 );
......@@ -1931,36 +1927,37 @@ DECL_HANDLER(set_thread_context)
set_error( STATUS_INVALID_PARAMETER );
else if (thread->state != TERMINATED)
{
unsigned int ctx = CTX_NATIVE;
const context_t *context = &contexts[CTX_NATIVE];
unsigned int flags = system_flags & context->flags;
unsigned int native_flags = context->flags & req->native_flags;
unsigned int flags = system_flags & contexts[CTX_NATIVE].flags;
if (thread != current) stop_thread( thread );
else if (flags) set_thread_context( thread, context, flags );
else if (flags) set_thread_context( thread, &contexts[CTX_NATIVE], flags );
if (thread->context && !get_error())
{
if (ctx_count == 2)
/* If context is in a pending state, we don't know if we will use WoW or native
* context, so store both and discard irrevelant one in select request. */
const int is_pending = thread->context->status == STATUS_PENDING;
unsigned int native_flags = contexts[CTX_NATIVE].flags;
if (ctx_count == 2 && (is_pending || thread->context->regs[CTX_WOW].machine))
{
/* If the target thread doesn't have a WoW context, set native instead.
* If we don't know yet whether we have a WoW context, store native context
* in CTX_PENDING and update when the target thread sends its context(s). */
if (thread->context->status != STATUS_PENDING)
{
ctx = thread->context->regs[CTX_WOW].machine ? CTX_WOW : CTX_NATIVE;
context = &contexts[ctx];
}
else ctx = CTX_PENDING;
context_t *ctx = &thread->context->regs[CTX_WOW];
/* some regs are always set from the native context */
flags = contexts[CTX_WOW].flags & ~req->native_flags;
if (is_pending) ctx->machine = contexts[CTX_WOW].machine;
else native_flags &= req->native_flags;
copy_context( ctx, &contexts[CTX_WOW], flags );
ctx->flags |= flags;
}
flags = context->flags;
if (native_flags && ctx != CTX_NATIVE) /* some regs are always set from the native context */
if (native_flags)
{
copy_context( &thread->context->regs[CTX_NATIVE], &contexts[CTX_NATIVE], native_flags );
thread->context->regs[CTX_NATIVE].flags |= native_flags;
flags &= ~native_flags;
context_t *ctx = &thread->context->regs[CTX_NATIVE];
copy_context( ctx, &contexts[CTX_NATIVE], native_flags );
ctx->flags |= native_flags;
}
copy_context( &thread->context->regs[ctx], context, flags );
thread->context->regs[ctx].flags |= flags;
}
}
else set_error( STATUS_UNSUCCESSFUL );
......
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