From owner-freebsd-net@FreeBSD.ORG Mon Sep 21 12:43:34 2009 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EFFEB106577E for ; Mon, 21 Sep 2009 12:43:34 +0000 (UTC) (envelope-from brampton@gmail.com) Received: from mail-ew0-f211.google.com (mail-ew0-f211.google.com [209.85.219.211]) by mx1.freebsd.org (Postfix) with ESMTP id 872798FC15 for ; Mon, 21 Sep 2009 12:43:34 +0000 (UTC) Received: by ewy7 with SMTP id 7so2897186ewy.7 for ; Mon, 21 Sep 2009 05:43:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:sender:received:date :x-google-sender-auth:message-id:subject:from:to:content-type; bh=p9O4yJFn4WWjy1A6T/qdTW3NGgBuEa7d7PecdmuvdxQ=; b=uuaTwsB0Y8stIBrICCKHfSHwIb9Q+coZDZKCRoDyXwLxrPEaP01HlbONebt2Fb5apR /gve+V/DKrm+wI4I0D7auNoDdj7KnBYkh2T0gU0r3IWtRnV9382jjdI3JX2UiEWXFgxA gwlUV4UpVx5G6qqRcVM1TF9j1Unl5Z1ei90cI= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:sender:date:x-google-sender-auth:message-id:subject :from:to:content-type; b=NZnozibfEsZsidQmPMyGsaoY+BEPyexgEmtBuH95dc0QdC6ZGXNOHf9ZcyIkpKsQh2 MhjWlaINu9F/AhyH8tJVx7OqjFwVpXAdPCzvIvex8r/Wtl4BV9K7ozVuasRtHktr+b/i bDwxcpTsqXPuqZgnM27smIDE9jA7g11HCceRE= MIME-Version: 1.0 Sender: brampton@gmail.com Received: by 10.216.90.81 with SMTP id d59mr1301606wef.29.1253537013352; Mon, 21 Sep 2009 05:43:33 -0700 (PDT) Date: Mon, 21 Sep 2009 13:43:33 +0100 X-Google-Sender-Auth: ae9463b87fbd5962 Message-ID: From: Andrew Brampton To: freebsd-net@freebsd.org Content-Type: text/plain; charset=UTF-8 Subject: Is this a race in mbuf's refcounting? X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 21 Sep 2009 12:43:35 -0000 I've been reading the FreeBSD source code to understand how mbufs are reference counted. However, there are a few bits of code that I'm wondering if they would fail under the exactly right timing. Take for example in uipc_mbuf.c: 286 static void 287 mb_dupcl(struct mbuf *n, struct mbuf *m) 288 { ... 293 if (*(m->m_ext.ref_cnt) == 1) 294 *(m->m_ext.ref_cnt) += 1; 295 else 296 atomic_add_int(m->m_ext.ref_cnt, 1); ... 305 } Now, the way I understand this code is, if ref_cnt is 1, then it is not shared. In that case non-atomically increment ref_cnt. However, if ref_cnt was something else, then it is shared so update the value in an atomic way. This seems valid, however what happens if two threads call mb_dupcl at the same time with a non-shared m. Could they both evaluate the if on line 293 at the same time, and then both non-atomically increment ref_cnt? If this could happen then we have a lost update and our reference counting is broken. I've also noticed that in other places similar optimisations are made to avoid the atomic operation. So is this a problem? thanks Andrew