Commit 4a8ea86713 for aom

commit 4a8ea86713ded9624a0632c8644370cef4b6ef21
Author: Ihor Buhaiov <freedbrt@gmail.com>
Date:   Sat Oct 10 19:42:31 2026 +0200

    Remove the per SB exit check in loop filter rows

    In the horizontal pass, av1_thread_loop_filter_rows() locked the shared
    job_mutex for every superblock only to read lf_mt_exit. With row
    multithreading every worker takes that lock thousands of times per frame
    and the workers wait on each other.

    On error, av1_set_vert_loop_filter_done() now writes LF_SYNC_EXIT into
    the column counter of every row, under the row mutex, and wakes the
    waiting workers. sync_read() already holds that mutex, so it reports
    the exit and the horizontal pass stops. sync_write() keeps the larger
    value, so the exit value stays.

    This applies to every multithreaded loop filter run, in the encoder and
    the decoder. The output does not change.

    Encode time saved, screen recordings at RT speed 11 with 64x64
    superblocks, aq mode 0 and the loop filter on every frame, median of
    paired runs. 0.0% is within the noise. With the default 128x128
    superblocks or when cyclic refresh turns the loop filter off, the
    change is much smaller.

                                  2 thr   4 thr   8 thr  12 thr
      Apple M3 Pro, macOS
        2560x1440, active map      0.0%    8.3%   10.7%    7.1%
        2559x1372, active map      3.5%    6.5%    8.1%    6.9%
        2560x1440, no map          0.0%    0.0%    4.1%    8.8%
        2559x1372, no map          0.0%    0.0%    5.4%    8.5%
      Ryzen 9 5900X, Windows
        2560x1440, active map      0.0%    0.0%    4.2%    4.6%
        2559x1372, active map      0.0%    0.0%    3.1%    3.9%
        2560x1440, no map          0.0%    0.0%    3.5%    4.0%
        2559x1372, no map          0.0%    0.0%    2.2%    2.4%

    Change-Id: I7278541d130e13433ed7cdc2c931332fd183df20

diff --git a/av1/common/thread_common.c b/av1/common/thread_common.c
index dee45b44c2..975c0902f8 100644
--- a/av1/common/thread_common.c
+++ b/av1/common/thread_common.c
@@ -10,6 +10,7 @@
  */

 #include <assert.h>
+#include <limits.h>

 #include "aom/aom_image.h"
 #include "config/aom_config.h"
@@ -204,8 +205,16 @@ static inline void cdef_row_mt_sync_write(AV1CdefSync *const cdef_sync,
 #endif  // CONFIG_MULTITHREAD
 }

-static inline void sync_read(AV1LfSync *const lf_sync, int r, int c,
+// Value of cur_sb_col[plane][r] after a worker has encountered an error. It
+// wakes up the workers waiting in sync_read() and tells them to exit.
+#define LF_SYNC_EXIT INT_MAX
+
+// Returns true if the sync read is successful and the caller can continue.
+// Returns false if the caller should exit because a worker has encountered an
+// error.
+static inline bool sync_read(AV1LfSync *const lf_sync, int r, int c,
                              int plane) {
+  bool lf_mt_continue = true;
 #if CONFIG_MULTITHREAD
   const int nsync = lf_sync->sync_range;

@@ -216,6 +225,7 @@ static inline void sync_read(AV1LfSync *const lf_sync, int r, int c,
     while (c > lf_sync->cur_sb_col[plane][r - 1] - nsync) {
       pthread_cond_wait(&lf_sync->cond_[plane][r - 1], mutex);
     }
+    lf_mt_continue = lf_sync->cur_sb_col[plane][r - 1] != LF_SYNC_EXIT;
     pthread_mutex_unlock(mutex);
   }
 #else
@@ -224,6 +234,7 @@ static inline void sync_read(AV1LfSync *const lf_sync, int r, int c,
   (void)c;
   (void)plane;
 #endif  // CONFIG_MULTITHREAD
+  return lf_mt_continue;
 }

 static inline void sync_write(AV1LfSync *const lf_sync, int r, int c,
@@ -244,11 +255,9 @@ static inline void sync_write(AV1LfSync *const lf_sync, int r, int c,
   if (sig) {
     pthread_mutex_lock(&lf_sync->mutex_[plane][r]);

-    // When a thread encounters an error, cur_sb_col[plane][r] is set to maximum
-    // column number. In this case, the AOMMAX operation here ensures that
-    // cur_sb_col[plane][r] is not overwritten with a smaller value thus
-    // preventing the infinite waiting of threads in the relevant sync_read()
-    // function.
+    // After an error cur_sb_col[plane][r] holds LF_SYNC_EXIT. AOMMAX keeps it
+    // from being lowered, so workers waiting in sync_read() still see it and
+    // exit.
     lf_sync->cur_sb_col[plane][r] = AOMMAX(lf_sync->cur_sb_col[plane][r], cur);

     pthread_cond_broadcast(&lf_sync->cond_[plane][r]);
@@ -313,22 +322,12 @@ void av1_thread_loop_filter_rows(

       if (lf_sync != NULL) {
         // Wait for vertical edge filtering of the top-right block to be
-        // completed
-        sync_read(lf_sync, r, c, plane);
+        // completed. Exit in case any worker has encountered an error.
+        if (!sync_read(lf_sync, r, c, plane)) return;

         // Wait for vertical edge filtering of the right block to be completed
-        sync_read(lf_sync, r + 1, c, plane);
-      }
-
-#if CONFIG_MULTITHREAD
-      if (lf_sync && lf_sync->num_workers > 1) {
-        pthread_mutex_lock(lf_sync->job_mutex);
-        const bool lf_mt_exit = lf_sync->lf_mt_exit;
-        pthread_mutex_unlock(lf_sync->job_mutex);
-        // Exit in case any worker has encountered an error.
-        if (lf_mt_exit) return;
+        if (!sync_read(lf_sync, r + 1, c, plane)) return;
       }
-#endif

       av1_setup_dst_planes(planes, cm->seq_params->sb_size, frame_buffer,
                            mi_row, mi_col, plane, plane + num_planes);
@@ -352,20 +351,28 @@ void av1_thread_loop_filter_rows(

 void av1_set_vert_loop_filter_done(AV1_COMMON *cm, AV1LfSync *lf_sync,
                                    int num_mis_in_lpf_unit_height_log2) {
-  int plane, sb_row;
-  const int sb_cols =
-      CEIL_POWER_OF_TWO(cm->mi_params.mi_cols, num_mis_in_lpf_unit_height_log2);
+#if CONFIG_MULTITHREAD
   const int sb_rows =
       CEIL_POWER_OF_TWO(cm->mi_params.mi_rows, num_mis_in_lpf_unit_height_log2);

   // In case of loopfilter row-multithreading, the worker on an SB row waits for
   // the vertical edge filtering of the right and top-right SBs. Hence, in case
-  // a thread (main/worker) encounters an error, update that vertical
-  // loopfiltering of every SB row in the frame is complete in order to avoid
-  // dependent workers waiting indefinitely.
-  for (sb_row = 0; sb_row < sb_rows; ++sb_row)
-    for (plane = 0; plane < MAX_MB_PLANE; ++plane)
-      sync_write(lf_sync, sb_row, sb_cols - 1, sb_cols, plane);
+  // a thread (main/worker) encounters an error, mark every SB row in the frame
+  // with LF_SYNC_EXIT. This avoids dependent workers waiting indefinitely and
+  // makes them exit instead of filtering.
+  for (int sb_row = 0; sb_row < sb_rows; ++sb_row) {
+    for (int plane = 0; plane < MAX_MB_PLANE; ++plane) {
+      pthread_mutex_lock(&lf_sync->mutex_[plane][sb_row]);
+      lf_sync->cur_sb_col[plane][sb_row] = LF_SYNC_EXIT;
+      pthread_cond_broadcast(&lf_sync->cond_[plane][sb_row]);
+      pthread_mutex_unlock(&lf_sync->mutex_[plane][sb_row]);
+    }
+  }
+#else
+  (void)cm;
+  (void)lf_sync;
+  (void)num_mis_in_lpf_unit_height_log2;
+#endif  // CONFIG_MULTITHREAD
 }

 static inline void sync_lf_workers(AVxWorker *const workers,