On Tue, May 18, 2021 at 01:24:42PM +0200, Martin Pieuchot wrote: > On 18/05/21(Tue) 12:07, Mark Kettenis wrote: > > > Date: Tue, 18 May 2021 12:02:19 +0200 > > > From: Martin Pieuchot <m...@openbsd.org> > > > > > > This allows us to not rely on the KERNEL_LOCK() to check reference > > > counts. > > > > > > Also reduces differences with NetBSD and shrink my upcoming `vmobjlock' > > > diff. > > > > > > ok? > > > > Shouldn't we make ref_count volatile in that case? > > I don't know, I couldn't find any evidence about where to use "volatile" > in the kernel. > > My understanding is that using "volatile" tells the compiler to not > "cache" the value of such field in a register because it can change at > any time. Is it so? > > If that's correct, we should look at any piece of code reading such field > multiple times without using atomic operation, right? > > In this case `ref_count' is used once for sanity checks in UVM_MAP_REQ_WRITE() > and after calling atomic_dec_int_nv() in uvm_map_deallocate(). So, I don't > see "volatile" necessary here. Did I miss anything? > > There's only a couple of 'volatile' usages in sys/sys. These annotations > do not explicitly indicate which piece of code requires it. Maybe it would > be clearer to use a cast or a macro where necessary. This might help us > understand why and where "volatile" is needed. >
Also "volatile" tells compiler to not drop or reorder expression due to optimisation. But this is not such case. This diff is ok by me. > > > Index: uvm/uvm_map.c > > > =================================================================== > > > RCS file: /cvs/src/sys/uvm/uvm_map.c,v > > > retrieving revision 1.274 > > > diff -u -p -r1.274 uvm_map.c > > > --- uvm/uvm_map.c 26 Mar 2021 13:40:05 -0000 1.274 > > > +++ uvm/uvm_map.c 18 May 2021 09:36:55 -0000 > > > @@ -491,12 +491,13 @@ uvm_mapent_addr_remove(struct vm_map *ma > > > /* > > > * uvm_map_reference: add reference to a map > > > * > > > - * XXX check map reference counter lock > > > + * => map need not be locked > > > */ > > > -#define uvm_map_reference(_map) > > > \ > > > - do { \ > > > - map->ref_count++; \ > > > - } while (0) > > > +void > > > +uvm_map_reference(struct vm_map *map) > > > +{ > > > + atomic_inc_int(&map->ref_count); > > > +} > > > > > > /* > > > * Calculate the dused delta. > > > @@ -4292,7 +4293,7 @@ uvm_map_deallocate(vm_map_t map) > > > int c; > > > struct uvm_map_deadq dead; > > > > > > - c = --map->ref_count; > > > + c = atomic_dec_int_nv(&map->ref_count); > > > if (c > 0) { > > > return; > > > } > > > Index: uvm/uvm_map.h > > > =================================================================== > > > RCS file: /cvs/src/sys/uvm/uvm_map.h,v > > > retrieving revision 1.69 > > > diff -u -p -r1.69 uvm_map.h > > > --- uvm/uvm_map.h 12 Mar 2021 14:15:49 -0000 1.69 > > > +++ uvm/uvm_map.h 18 May 2021 09:36:36 -0000 > > > @@ -259,6 +259,7 @@ RBT_PROTOTYPE(uvm_map_addr, vm_map_entry > > > * read_locks and write_locks are used in lock debugging code. > > > * > > > * Locks used to protect struct members in this file: > > > + * a atomic operations > > > * I immutable after creation or exec(2) > > > * v `vm_map_lock' (this map `lock' or `mtx') > > > */ > > > @@ -272,7 +273,7 @@ struct vm_map { > > > struct uvm_map_addr addr; /* [v] Entry tree, by addr */ > > > > > > vsize_t size; /* virtual size */ > > > - int ref_count; /* Reference count */ > > > + int ref_count; /* [a] Reference count */ > > > int flags; /* flags */ > > > struct mutex flags_lock; /* flags lock */ > > > unsigned int timestamp; /* Version number */ > > > > > > >