Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 18 Sep 2003 14:43:40 +1000 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Alan Cox <alc@cs.rice.edu>
Cc:        smp@freebsd.org
Subject:   Re: atomicity of unlocked reads
Message-ID:  <20030918134424.N1635@gamplex.bde.org>
In-Reply-To: <20030917182237.GM12711@cs.rice.edu>
References:  <XFMail.20030917114537.jhb@FreeBSD.org> <20030917182237.GM12711@cs.rice.edu>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 17 Sep 2003, Alan Cox wrote:

> On Wed, Sep 17, 2003 at 10:50:58AM -0700, Frank Mayhar wrote:
> > John Baldwin wrote:
> > > I think you can assume that the read will be atomic.  I don't think FreeBSD
> > > would work very well on a machine where aligned pointer reads/writes weren't
> > > atomic.
> >
> > I dunno, I tend to think that making such assumptions may well come back to
> > bite me in the ass when I least expect it.  In such situation, I invariably
> > use some kind of "atomic_xxx_load/store" primitive that does the job safely
> > and in a machine-dependent way while hiding the details from the MI code.
>
> Indeed.  Atomicity of the read is not the only issue.  Unless I
> misunderstood, Bruce is proposing to perform an unsynchronized read of
> a location that is updated by a different processor.  This
> unsynchronized read is to obtain a pointer.  In weaker memory
> consistency models (than that of the x86), there is no guarantee that
> the data that the pointer refers to will be consistent.  In other
> words, updates to the data that the pointer refers to may not have
> completed, even though the update to the memory location containing
> the pointer has completed.

The data is known to be consistent in my application.  I'm just
implementing a circular buffer with essentially 1 writer and 1 reader
(they can be on different CPUs and the writer can be different, but
locking for each gives coherency.  Only the writer writes to the buffer,
so the data is always consistent.  The reader advances the read pointer
(normally without telling the writer), and the writer only needs the
read pointer to determine the space available for writing.  If it sees
an old value then it underestimates the space, but there is no a problem
because the writer will get woken up by the reader when the space goes
below a watermark.  If the writer sees a garbage value then it will
compute a garbage amount of space and may write more than fits.

Reading the read pointer without locking is only a micro-optimization
here, but I believe there are some lengthy list traversals that would
benefit from similar optimizations.  (Don't lock each element or the
whole list, but somehow ensure that the elements or the list pointers
in them are not garbage even if they are stale.)

> This is what an "acquire load" is for.  Roughly speaking, it should
> guarantee that any updates prior to a corresponding "release store"
> (by a different processor) will be seen.

For the optimized circular buffer, stricter locking of the write pointer
is required for essentially this reason.  The situation with the read
and write pointers is not symmetrical like I said when I started this
thread.  Fortunately, stricter locking for the write pointer is more
natural and I already did it without thinking much about it.

Bruce



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