[RFC PATCH v2 0/2] binder: split alloc->mutex to improve performance

Bo Zhang posted 2 patches 3 weeks, 5 days ago
There is a newer version of this series
drivers/android/binder_alloc.c | 114 ++++++++++++++++++++++-----------
drivers/android/binder_alloc.h |  11 ++--
2 files changed, 85 insertions(+), 40 deletions(-)
[RFC PATCH v2 0/2] binder: split alloc->mutex to improve performance
Posted by Bo Zhang 3 weeks, 5 days ago
Hi,

This is v2 of the binder alloc lock optimization. Thanks to Alice Ryhl
for the thorough review of v1 [1].

v1 simply converted alloc->mutex to a spinlock, but Alice pointed out
a race between page installation and shrinker's zap_vma_range() [2],
and that busy-wait retry would deadlock with SCHED_FIFO threads [3].

v2 splits the lock into two:

  - spinlock: protects buffer metadata (rb-trees, free_async_space,
    LRU operations) on the hot path (every binder transaction).

  - install_mutex: serializes page installation and shrinker zap on
    the cold path only when pages are installed or reclaimed.

The install_mutex ensures pages[index]=NULL and zap_vma_range() are
atomic to the install side, eliminating the race from v1. Since
install_mutex serializes all installers, binder_page_lookup() (GUP)
is no longer needed.

When binder_lru_freelist_del() finds a page already isolated by the
shrinker (when list_lru_del returns false), it rolls back and returns
-EAGAIN. The caller waits for the shrinker via mutex_lock/unlock on
install_mutex, which is safe for SCHED_FIFO (sleeps instead of spins).

Performance (binderThroughputTest, Qualcomm SM8850, 2 workers, 10 runs):

                      mutex (baseline)    spinlock + install_mutex
  throughput:    27k-59k iter/s       81k-94k iter/s  (~80% improvement)
  average:       0.031-0.068ms        0.020-0.023ms  (~45% reduction)
  P99:           0.088-0.148ms        0.047-0.061ms  (~55% reduction)

Tested under memory pressure (concurrent drop_caches) to exercise the
install_mutex and shrinker paths. No regression compared to the pure
spinlock approach in v1.

Changes since v1:
- Dropped the simple spinlock-only approach that had a race between
  page installation and shrinker zap (Alice)
- Added install_mutex to serialize page install and shrinker zap
- Removed binder_page_lookup() (GUP) since install_mutex serializes
  concurrent installers
- Handle list_lru_del() failure in binder_lru_freelist_del() with
  rollback and -EAGAIN, wait on install_mutex instead of busy-wait
  to avoid SCHED_FIFO deadlock (Alice)

[1] https://lore.kernel.org/all/20260805152752.1924434-1-zhangbo56@xiaomi.com/
[2] https://lore.kernel.org/all/anRNX4sftcuDXRj8@google.com/
[3] https://lore.kernel.org/all/ancz-vd9v5P5kRJq@google.com/

Bo Zhang (2):
  binder: switch alloc->mutex to spinlock for buffer metadata
  binder: add install_mutex to serialize page install and shrinker zap

 drivers/android/binder_alloc.c | 114 ++++++++++++++++++++++-----------
 drivers/android/binder_alloc.h |  11 ++--
 2 files changed, 85 insertions(+), 40 deletions(-)

-- 
2.34.1