From owner-freebsd-hackers@FreeBSD.ORG Mon Apr 18 16:56:29 2011 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 43545106566B for ; Mon, 18 Apr 2011 16:56:29 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from cyrus.watson.org (cyrus.watson.org [65.122.17.42]) by mx1.freebsd.org (Postfix) with ESMTP id 18C738FC17 for ; Mon, 18 Apr 2011 16:56:29 +0000 (UTC) Received: from bigwig.baldwin.cx (66.111.2.69.static.nyinternet.net [66.111.2.69]) by cyrus.watson.org (Postfix) with ESMTPSA id BECF046B58; Mon, 18 Apr 2011 12:56:28 -0400 (EDT) Received: from jhbbsd.localnet (unknown [209.249.190.124]) by bigwig.baldwin.cx (Postfix) with ESMTPSA id 563A08A02A; Mon, 18 Apr 2011 12:56:28 -0400 (EDT) From: John Baldwin To: freebsd-hackers@freebsd.org Date: Mon, 18 Apr 2011 08:31:33 -0400 User-Agent: KMail/1.13.5 (FreeBSD/8.2-CBSD-20110325; KDE/4.5.5; amd64; ; ) References: <397135152.167477.1303069788579.JavaMail.root@erie.cs.uoguelph.ca> In-Reply-To: <397135152.167477.1303069788579.JavaMail.root@erie.cs.uoguelph.ca> MIME-Version: 1.0 Content-Type: Text/Plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <201104180831.33796.jhb@freebsd.org> X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.2.6 (bigwig.baldwin.cx); Mon, 18 Apr 2011 12:56:28 -0400 (EDT) Cc: Rick Macklem Subject: Re: SMP question w.r.t. reading kernel variables X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 18 Apr 2011 16:56:29 -0000 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. -- John Baldwin