server: Store both contexts in pending context object.
And discard irrelevant parts in select request.
This commit is contained in:
parent
949681d8c3
commit
a25ac1edb9
1 changed files with 32 additions and 35 deletions
|
@ -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 );
|
||||
|
|
Loading…
Add table
Reference in a new issue