Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 Sep 2009 13:43:33 +0100
From:      Andrew Brampton <brampton+freebsd-net@gmail.com>
To:        freebsd-net@freebsd.org
Subject:   Is this a race in mbuf's refcounting?
Message-ID:  <d41814900909210543p46894d83u6d814353ea1ee130@mail.gmail.com>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?d41814900909210543p46894d83u6d814353ea1ee130>