> On Sunday, April 17, 2011 3:49:48 pm Rick Macklem wrote: > > Hi, > > > > I should know the answer to this, but... When reading a global > > kernel > > variable, where its modifications are protected by a mutex, is it > > necessary to get the mutex lock to just read its value? > > > > For example: > > A if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) > > return (EPERM); > > versus > > B MNT_ILOCK(mp); > > if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) { > > MNT_IUNLOCK(mp); > > return (EPERM); > > } > > MNT_IUNLOCK(mp); > > > > My hunch is that B is necessary if you need an up-to-date value > > for the variable (mp->mnt_kern_flag in this case). > > > > Is that correct? > > You already have good followups from Attilio and Kostik, but one thing > to keep > in mind is that if a simple read is part of a larger "atomic > operation" then > it may still need a lock. In this case Kostik points out that another > lock > prevents updates to mnt_kern_flag so that this is safe. However, if > not for > that you would need to consider the case that another thread sets the > flag on > the next instruction. Even the B case above might still have that > problem > since you drop the lock right after checking it and the rest of the > function > is implicitly assuming the flag is never set perhaps (or it needs to > handle > the case that the flag might become set in the future while > MNT_ILOCK() is > dropped). > > One way you can make that code handle that race is by holding > MNT_ILOCK() > around the entire function, but that approach is often only suitable > for a > simple routine. > All of this makes sense. What I was concerned about was memory cache consistency and whet (if anything) has to be done to make sure a thread doesn't see a stale cached value for the memory location.
Here's a generic example of what I was thinking of: (assume x is a global int and y is a local int on the thread's stack) - time proceeds down the screen thread X on CPU 0 thread Y on CPU 1 x = 0; x = 0; /* 0 for x's location in CPU 1's memory cache */ x = 1; y = x; --> now, is "y" guaranteed to be 1 or can it get the stale cached 0 value? if not, what needs to be done to guarantee it? For the original example, I am fine so long as the bit is seen as set after dounmount() has set it. Also, I see cases of: mtx_lock(&np); np->n_attrstamp = 0; mtx_unlock(&np); in the regular NFS client. Why is the assignment mutex locked? (I had assumed it was related to the above memory caching issue, but now I'm not so sure.) Thanks a lot for all the good responses, rick ps: I guess it comes down to whether or not "atomic" includes ensuring memory cache consistency. I'll admit I assumed "atomic" meant that the memory access or modify couldn't be interleaved with one done to the same location by another CPU, but not memory cache consistency. _______________________________________________ freebsd-hackers@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-hackers To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"