ANDROID: percpu-rwsem: enable percpu_sem destruction in atomic context

Calling percpu_free_rwsem in atomic context results in "scheduling while
atomic" bug being triggered:

BUG: scheduling while atomic: klogd/158/0x00000002
...
  __schedule_bug+0x191/0x290
  schedule_debug+0x97/0x180
  __schedule+0xdc/0xba0
  schedule+0xda/0x250
  schedule_timeout+0x92/0x2d0
  __wait_for_common+0x25b/0x430
  wait_for_completion+0x1f/0x30
  rcu_barrier+0x440/0x4f0
  rcu_sync_dtor+0xaa/0x190
  percpu_free_rwsem+0x41/0x80

Introduce percpu_rwsem_destroy function to perform semaphore destruction
in a worker thread.

Bug: 161210518
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
Change-Id: I74ac65c2a9962492cd5002d7a019d2aa13a21a8c
This commit is contained in:
Suren Baghdasaryan
2021-11-04 13:42:56 -07:00
parent f3f87608d8
commit 2fc2c66b9c
2 changed files with 44 additions and 1 deletions

View File

@@ -13,7 +13,14 @@ struct percpu_rw_semaphore {
struct rcu_sync rss;
unsigned int __percpu *read_count;
struct rcuwait writer;
wait_queue_head_t waiters;
/*
* destroy_list_entry is used during object destruction when waiters
* can't be used, therefore reusing the same space.
*/
union {
wait_queue_head_t waiters;
struct list_head destroy_list_entry;
};
atomic_t block;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
@@ -127,8 +134,12 @@ extern void percpu_up_write(struct percpu_rw_semaphore *);
extern int __percpu_init_rwsem(struct percpu_rw_semaphore *,
const char *, struct lock_class_key *);
/* Can't be called in atomic context. */
extern void percpu_free_rwsem(struct percpu_rw_semaphore *);
/* Invokes percpu_free_rwsem and frees the semaphore from a worker thread. */
extern void percpu_rwsem_async_destroy(struct percpu_rw_semaphore *sem);
#define percpu_init_rwsem(sem) \
({ \
static struct lock_class_key rwsem_key; \