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 ...@@ -119,11 +119,10 @@ struct context
{ {
struct object obj; /* object header */ struct object obj; /* object header */
unsigned int status; /* status of the context */ 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_NATIVE 0 /* context for native machine */
#define CTX_WOW 1 /* context if thread is inside WoW */ #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 */ /* flags for registers that always need to be set from the server side */
static const unsigned int system_flags = SERVER_CTX_DEBUG_REGISTERS; static const unsigned int system_flags = SERVER_CTX_DEBUG_REGISTERS;
...@@ -292,7 +291,6 @@ static struct context *create_thread_context( struct thread *thread ) ...@@ -292,7 +291,6 @@ static struct context *create_thread_context( struct thread *thread )
context->status = STATUS_PENDING; context->status = STATUS_PENDING;
memset( &context->regs, 0, sizeof(context->regs) ); memset( &context->regs, 0, sizeof(context->regs) );
context->regs[CTX_NATIVE].machine = native_machine; context->regs[CTX_NATIVE].machine = native_machine;
context->regs[CTX_PENDING].machine = native_machine;
return context; return context;
} }
...@@ -1591,8 +1589,6 @@ DECL_HANDLER(select) ...@@ -1591,8 +1589,6 @@ DECL_HANDLER(select)
const context_t *native_context = (const context_t *)((const char *)(result + 1) + req->size); 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; 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 (native_context->machine == native_machine)
{ {
if (wow_context && wow_context->machine != current->process->machine) goto invalid_param; if (wow_context && wow_context->machine != current->process->machine) goto invalid_param;
...@@ -1605,7 +1601,14 @@ DECL_HANDLER(select) ...@@ -1605,7 +1601,14 @@ DECL_HANDLER(select)
} }
else goto invalid_param; 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; ctx = current->context;
if (native_context) if (native_context)
...@@ -1618,13 +1621,6 @@ DECL_HANDLER(select) ...@@ -1618,13 +1621,6 @@ DECL_HANDLER(select)
ctx->regs[CTX_WOW].machine = current->process->machine; ctx->regs[CTX_WOW].machine = current->process->machine;
copy_context( &ctx->regs[CTX_WOW], wow_context, wow_context->flags & ~ctx->regs[CTX_WOW].flags ); 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; ctx->status = STATUS_SUCCESS;
current->suspend_cookie = req->cookie; current->suspend_cookie = req->cookie;
wake_up( &ctx->obj, 0 ); wake_up( &ctx->obj, 0 );
...@@ -1931,36 +1927,37 @@ DECL_HANDLER(set_thread_context) ...@@ -1931,36 +1927,37 @@ DECL_HANDLER(set_thread_context)
set_error( STATUS_INVALID_PARAMETER ); set_error( STATUS_INVALID_PARAMETER );
else if (thread->state != TERMINATED) else if (thread->state != TERMINATED)
{ {
unsigned int ctx = CTX_NATIVE; unsigned int flags = system_flags & contexts[CTX_NATIVE].flags;
const context_t *context = &contexts[CTX_NATIVE];
unsigned int flags = system_flags & context->flags;
unsigned int native_flags = context->flags & req->native_flags;
if (thread != current) stop_thread( thread ); 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 (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. context_t *ctx = &thread->context->regs[CTX_WOW];
* 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). */ /* some regs are always set from the native context */
if (thread->context->status != STATUS_PENDING) flags = contexts[CTX_WOW].flags & ~req->native_flags;
{ if (is_pending) ctx->machine = contexts[CTX_WOW].machine;
ctx = thread->context->regs[CTX_WOW].machine ? CTX_WOW : CTX_NATIVE; else native_flags &= req->native_flags;
context = &contexts[ctx];
} copy_context( ctx, &contexts[CTX_WOW], flags );
else ctx = CTX_PENDING; 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 ); context_t *ctx = &thread->context->regs[CTX_NATIVE];
thread->context->regs[CTX_NATIVE].flags |= native_flags; copy_context( ctx, &contexts[CTX_NATIVE], native_flags );
flags &= ~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 ); 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