diff options
author | alc <alc@FreeBSD.org> | 2005-03-06 20:09:00 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2005-03-06 20:09:00 +0000 |
commit | 2213f95a5239d5d00ef2065a8f1777b6b2084f8c (patch) | |
tree | abe12aba3c3d16582553b14d5e9632c9ed3f93d4 /sys/kern/uipc_mbuf.c | |
parent | 4afa67d7680cea34fe67c52377dd25add391412c (diff) | |
download | FreeBSD-src-2213f95a5239d5d00ef2065a8f1777b6b2084f8c.zip FreeBSD-src-2213f95a5239d5d00ef2065a8f1777b6b2084f8c.tar.gz |
The m_ext reference counts are potentially shared and modified
asynchronously by different threads. Thus, declare as volatile the
reference count that is accessed through m_ext's pointer, ref_cnt.
Revert the previous change, revision 1.144, that casts as volatile a
single dereference of ref_cnt.
Reviewed by: bmilekic, dwhite
Problem reported by: kris
MFC after: 3 days
Diffstat (limited to 'sys/kern/uipc_mbuf.c')
-rw-r--r-- | sys/kern/uipc_mbuf.c | 10 |
1 files changed, 4 insertions, 6 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index 1f6069e..5e65572 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -199,7 +199,7 @@ m_extadd(struct mbuf *mb, caddr_t buf, u_int size, ref_cnt = (u_int *)uma_find_refcnt(zone_clust, mb->m_ext.ext_buf); else if (type == EXT_EXTREF) - ref_cnt = mb->m_ext.ref_cnt; + ref_cnt = __DEVOLATILE(u_int *, mb->m_ext.ref_cnt); mb->m_ext.ref_cnt = (ref_cnt == NULL) ? malloc(sizeof(u_int), M_MBUF, M_NOWAIT) : (u_int *)ref_cnt; if (mb->m_ext.ref_cnt != NULL) { @@ -234,12 +234,9 @@ mb_free_ext(struct mbuf *m) * This is tricky. We need to make sure to decrement the * refcount in a safe way but to also clean up if we're the * last reference. This method seems to do it without race. - * The volatile cast is required to emit the proper load - * instructions. Otherwise gcc will optimize the read outside - * of the while loop. */ while (dofree == 0) { - cnt = *(volatile u_int *)(m->m_ext.ref_cnt); + cnt = *(m->m_ext.ref_cnt); if (atomic_cmpset_int(m->m_ext.ref_cnt, cnt, cnt - 1)) { if (cnt == 1) dofree = 1; @@ -262,7 +259,8 @@ mb_free_ext(struct mbuf *m) m->m_ext.ext_args); if (m->m_ext.ext_type != EXT_EXTREF) { if (m->m_ext.ref_cnt != NULL) - free(m->m_ext.ref_cnt, M_MBUF); + free(__DEVOLATILE(u_int *, + m->m_ext.ref_cnt), M_MBUF); m->m_ext.ref_cnt = NULL; } m->m_ext.ext_buf = NULL; |