Otherwise we may execute the callback before the value is actually
returned from RegisterWaitForSingleObject.
Gears Tactics shares a pointer to the returned handle with its callbacks
and calls UnregisterWait from there. This creates a race condition that
sometimes causes a double free.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47843
Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This adds several internal flags to TP_WAIT object to support the
implementation:
* WT_EXECUTEONLYONCE: waits are re-queued unless it is set.
* WT_EXECUTEINWAITTHREAD: call the callback in the wait thread when set.
* WT_EXECUTEINIOTHREAD: call alertable NtWaitForMultipleObjects in wait
thread when set, as well the callback in the wait thread, as for
WT_EXECUTEINWAITTHREAD. The worker threads use non-alertable waits
otherwise.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47843
Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
It'll be submitted eventually, no need to force it and it makes support
for WT_EXECUTEINWAITTHREAD flag harder.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47843
Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
Otherwise two consequative submits may have the same
num_busy_workers value if threadpool_worker_proc did not
have a chance to pick the work in between. A new thread is
not created in tp_submit() for the second submit and if the
first submit queues an (infinitely long) wait
the next submitted callback is not called for indefinite
time period.
Fixes hang on exit in Detroit Become Human.
Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
af35aada9b left some issues unfixed.
Instead of running the callback and returning a retval that indicates
the callback is not running, we sometimes wait for it when we are not
supposed to.
Signed-off-by: Stefan Dösinger <stefan@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
Chromium signals the wait semaphore and calls DeregisterWaitEx with
CompletionHandle = INVALID_HANDLE_VALUE in close succession. Sometimes
the worker thread decides to run the callback, but before it sets
CallbackInProgress RtlDeregisterWaitEx decides that the callback is not
running and returns STATUS_SUCCESS. Chromium then releases resources
that the callback needs to run, resulting in random crashes.
Signed-off-by: Stefan Dösinger <stefan@codeweavers.com>
Signed-off-by: Sebastian Lackner <sebastian@fds-team.de>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
Signed-off-by: Bruno Jesus <00cpxxx@gmail.com>
Signed-off-by: Sebastian Lackner <sebastian@fds-team.de>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
When the number of elements per bucket is too small, then try to reduce
the number of threads by merging buckets. This is to ensure that the
number of running wait queue threads doesn't get too big.
To implement waiting for an arbitrary number of handles, we group them
in buckets up to (MAXIMUM_WAIT_OBJECTS - 1) objects, and then assign a
dedicated wait queue thread. The last handle is used to notify about
changes.