"Martin Pieuchot" <m...@openbsd.org> writes:

> On 24/01/23(Tue) 04:40, Renato Aguiar wrote:
>> Hi Martin,
>>
>> "David Hill" <dh...@mindcry.org> writes:
>>
>> >
>> > Yes, same result as before.  This patch does not seem to help.
>> >
>>
>> I could also reproduce it with patched 'current' :(
>
> Here's another possible fix I came up with.  The idea is to deliberately
> allow readers to starve writers for the VM map lock.
>
> My previous fix didn't work because a writer could already be waiting on
> the lock before calling vm_map_busy() and there's currently no way to
> tell it to back out and stop preventing readers from making progress.
>
> I don't see any simpler solution without rewriting the vm_map_lock()
> primitive.
>
> Could you confirm this work for you?  If so I'll document the new
> RW_FORCEREAD flag and add a comment to explain why we need it in this
> case.
>
> Thanks,
> Martin
>
> Index: kern/kern_rwlock.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/kern_rwlock.c,v
> retrieving revision 1.48
> diff -u -p -r1.48 kern_rwlock.c
> --- kern/kern_rwlock.c        10 May 2022 16:56:16 -0000      1.48
> +++ kern/kern_rwlock.c        18 Feb 2023 07:48:23 -0000
> @@ -225,7 +225,7 @@ rw_enter(struct rwlock *rwl, int flags)
>  {
>       const struct rwlock_op *op;
>       struct sleep_state sls;
> -     unsigned long inc, o;
> +     unsigned long inc, o, check;
>  #ifdef MULTIPROCESSOR
>       /*
>        * If process holds the kernel lock, then we want to give up on CPU
> @@ -248,10 +248,14 @@ rw_enter(struct rwlock *rwl, int flags)
>  #endif
>
>       op = &rw_ops[(flags & RW_OPMASK) - 1];
> +     check = op->check;
> +
> +     if (flags & RW_FORCEREAD)
> +             check &= ~RWLOCK_WRWANT;
>
>       inc = op->inc + RW_PROC(curproc) * op->proc_mult;
>  retry:
> -     while (__predict_false(((o = rwl->rwl_owner) & op->check) != 0)) {
> +     while (__predict_false(((o = rwl->rwl_owner) & check) != 0)) {
>               unsigned long set = o | op->wait_set;
>               int do_sleep;
>
> Index: sys/rwlock.h
> ===================================================================
> RCS file: /cvs/src/sys/sys/rwlock.h,v
> retrieving revision 1.28
> diff -u -p -r1.28 rwlock.h
> --- sys/rwlock.h      11 Jan 2021 18:49:38 -0000      1.28
> +++ sys/rwlock.h      18 Feb 2023 07:44:13 -0000
> @@ -117,6 +117,7 @@ struct rwlock {
>  #define RW_NOSLEEP           0x0040UL /* don't wait for the lock */
>  #define RW_RECURSEFAIL               0x0080UL /* Fail on recursion for RRW 
> locks. */
>  #define RW_DUPOK             0x0100UL /* Permit duplicate lock */
> +#define RW_FORCEREAD         0x0200UL /* Let a reader preempt writers.  */
>
>  /*
>   * for rw_status() and rrw_status() only: exclusive lock held by
> Index: uvm/uvm_map.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_map.c,v
> retrieving revision 1.312
> diff -u -p -r1.312 uvm_map.c
> --- uvm/uvm_map.c     13 Feb 2023 14:52:55 -0000      1.312
> +++ uvm/uvm_map.c     18 Feb 2023 07:46:23 -0000
> @@ -5406,7 +5406,7 @@ void
>  vm_map_lock_read_ln(struct vm_map *map, char *file, int line)
>  {
>       if ((map->flags & VM_MAP_INTRSAFE) == 0)
> -             rw_enter_read(&map->lock);
> +             rw_enter(&map->lock, RW_READ|RW_FORCEREAD);
>       else
>               mtx_enter(&map->mtx);
>       LPRINTF(("map   lock: %p (at %s %d)\n", map, file, line));


I can't reproduce it anymore with this patch on 7.2-stable :)

--
Renato

Reply via email to