Merge pull request #91725 from RandomShaper/cmd_queue_avoid_skip

`CommandQueueMT`: Fix sync command awaiters missing the chance
This commit is contained in:
Rémi Verschelde 2024-05-09 02:06:34 +02:00 committed by GitHub
commit c4279fe3e0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -327,7 +327,6 @@ class CommandQueueMT {
enum { enum {
DEFAULT_COMMAND_MEM_SIZE_KB = 256, DEFAULT_COMMAND_MEM_SIZE_KB = 256,
SYNC_SEMAPHORES = 8
}; };
BinaryMutex mutex; BinaryMutex mutex;
@ -335,6 +334,7 @@ class CommandQueueMT {
ConditionVariable sync_cond_var; ConditionVariable sync_cond_var;
uint32_t sync_head = 0; uint32_t sync_head = 0;
uint32_t sync_tail = 0; uint32_t sync_tail = 0;
uint32_t sync_awaiters = 0;
WorkerThreadPool::TaskID pump_task_id = WorkerThreadPool::INVALID_TASK_ID; WorkerThreadPool::TaskID pump_task_id = WorkerThreadPool::INVALID_TASK_ID;
uint64_t flush_read_ptr = 0; uint64_t flush_read_ptr = 0;
@ -349,6 +349,15 @@ class CommandQueueMT {
return cmd; return cmd;
} }
_FORCE_INLINE_ void _prevent_sync_wraparound() {
bool safe_to_reset = !sync_awaiters;
bool already_sync_to_latest = sync_head == sync_tail;
if (safe_to_reset && already_sync_to_latest) {
sync_head = 0;
sync_tail = 0;
}
}
void _flush() { void _flush() {
if (unlikely(flush_read_ptr)) { if (unlikely(flush_read_ptr)) {
// Re-entrant call. // Re-entrant call.
@ -365,7 +374,9 @@ class CommandQueueMT {
cmd->call(); cmd->call();
if (unlikely(cmd->sync)) { if (unlikely(cmd->sync)) {
sync_head++; sync_head++;
unlock(); // Give an opportunity to awaiters right away.
sync_cond_var.notify_all(); sync_cond_var.notify_all();
lock();
} }
// If the command involved reallocating the buffer, the address may have changed. // If the command involved reallocating the buffer, the address may have changed.
@ -378,14 +389,20 @@ class CommandQueueMT {
command_mem.clear(); command_mem.clear();
flush_read_ptr = 0; flush_read_ptr = 0;
_prevent_sync_wraparound();
unlock(); unlock();
} }
_FORCE_INLINE_ void _wait_for_sync(MutexLock<BinaryMutex> &p_lock) { _FORCE_INLINE_ void _wait_for_sync(MutexLock<BinaryMutex> &p_lock) {
sync_awaiters++;
uint32_t sync_head_goal = sync_tail; uint32_t sync_head_goal = sync_tail;
do { do {
sync_cond_var.wait(p_lock); sync_cond_var.wait(p_lock);
} while (sync_head != sync_head_goal); // Can't use lower-than because of wraparound. } while (sync_head < sync_head_goal);
sync_awaiters--;
_prevent_sync_wraparound();
} }
void _no_op() {} void _no_op() {}