Skip to content

[Linux, threading] WaitMultiple causing deadlock #1677

Open
@JoelLinn

Description

@JoelLinn

From PR #1317:

// TODO(bwrsandman, Triang3l) This is controversial, see issue #1677
// This will probably cause a deadlock on the next thread doing any waiting
// if the thread is suspended between locking and waiting
std::unique_lock<std::mutex> lock(PosixConditionBase::mutex_);

@Triang3l :

This will probably cause a deadlock on the next thread doing any waiting if the thread is suspended between locking and waiting.

Suspension needs rework to only occur immediately when the thread is in guest code, but deferred until the return to the guest if it happens during a kernel call. Or, for performance reasons, possibly not on every guest–host boundary, but when a special kind of mutex, similar to global_critical_region but not limited to a single instance, is locked/unlocked.

This should be somewhat easy to implement on POSIX because the thread itself will reply to the suspension signal — it can set a flag in its context structure when it enters a kernel function, and the signal handler can check whether to sleep immediately or to defer the suspension.

On Windows, however (while there is a native WaitForMultipleObjects implementation that will work fine, having control over suspension would allow us to have more granular kernel mutexes rather than just a single global_critical_region which is our current way of preventing suspension when kernel state is being modified, with easier usage of condition variables in the kernel — would possibly be useful for GPU readback in the access violation handler), the target thread can't provide its own response to suspension, and there are no signals. A possible solution is making suspension synchronous (which is contrary to the way it actually works on Windows, but possibly should have no noticeable effect on anything), with the source thread, not the target, being partially responsible for checking whether the target is in kernel code: call SuspendThread, then GetThreadContext to synchronize with the suspended thread, and check whether it's sleeping in kernel code currently — if yes, notify it that suspension was requested and unsuspend it on the host, to let it self-suspend on the next kernel to guest return.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions