diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2020-12-03 23:11:13 +0300 |
---|---|---|
committer | Peter Zijlstra <peterz@infradead.org> | 2020-12-09 19:08:42 +0300 |
commit | 31784cff7ee073b34d6eddabb95e3be2880a425c (patch) | |
tree | d1954eccd5b14129437e00b3d03e094a5dae7758 /kernel/locking/rwsem.c | |
parent | 0f9368b5bf6db0c04afc5454b1be79022a681615 (diff) | |
download | linux-31784cff7ee073b34d6eddabb95e3be2880a425c.tar.xz |
rwsem: Implement down_read_interruptible
In preparation for converting exec_update_mutex to a rwsem so that
multiple readers can execute in parallel and not deadlock, add
down_read_interruptible. This is needed for perf_event_open to be
converted (with no semantic changes) from working on a mutex to
wroking on a rwsem.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/87k0tybqfy.fsf@x220.int.ebiederm.org
Diffstat (limited to 'kernel/locking/rwsem.c')
-rw-r--r-- | kernel/locking/rwsem.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c index 54d11cb97551..a163542d178e 100644 --- a/kernel/locking/rwsem.c +++ b/kernel/locking/rwsem.c @@ -1345,6 +1345,18 @@ static inline void __down_read(struct rw_semaphore *sem) } } +static inline int __down_read_interruptible(struct rw_semaphore *sem) +{ + if (!rwsem_read_trylock(sem)) { + if (IS_ERR(rwsem_down_read_slowpath(sem, TASK_INTERRUPTIBLE))) + return -EINTR; + DEBUG_RWSEMS_WARN_ON(!is_rwsem_reader_owned(sem), sem); + } else { + rwsem_set_reader_owned(sem); + } + return 0; +} + static inline int __down_read_killable(struct rw_semaphore *sem) { if (!rwsem_read_trylock(sem)) { @@ -1495,6 +1507,20 @@ void __sched down_read(struct rw_semaphore *sem) } EXPORT_SYMBOL(down_read); +int __sched down_read_interruptible(struct rw_semaphore *sem) +{ + might_sleep(); + rwsem_acquire_read(&sem->dep_map, 0, 0, _RET_IP_); + + if (LOCK_CONTENDED_RETURN(sem, __down_read_trylock, __down_read_interruptible)) { + rwsem_release(&sem->dep_map, _RET_IP_); + return -EINTR; + } + + return 0; +} +EXPORT_SYMBOL(down_read_interruptible); + int __sched down_read_killable(struct rw_semaphore *sem) { might_sleep(); |