gpsd-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [gpsd-users] gpsd and shared memory


From: Gary E. Miller
Subject: Re: [gpsd-users] gpsd and shared memory
Date: Mon, 5 Oct 2015 11:57:02 -0700

Yo Roger!

On Mon, 5 Oct 2015 08:28:37 +0000
Roger Oberholtzer <address@hidden> wrote:

> I like to go off in places with few others blocking the scenery...

Cool.  You found one of those places.

> > It does not know it is 'new', but it does know it is valid or
> > atomic. When the bookends match the the data was read in a
> > consistent state.
> 
> I guess I am trying to figure out why there is both a barrier and the
> bookends.

Yeah, it is a hard one to grok.

> The barrier, I would imagine, ensures that the shm reader
> has exclusive access so the contents do not change during the copy.

Nope.  That is incorrect.  You are thinking of atomic ops, and they only
work on single primitve types like one integer or one float.

Oversimplyfying just a bit, a barrier just pauses the current CPU
until all pending cache reads and writes have finished.

One main reason to do this is that the C compiler, and the CPU, are
allowed to reorder reads and writes in unexpected ways.

As an example of many things that can go wrong:
        a = 1;  // mark we are doing a write
        b++;
        c++;
        a = 0;  // mark we are done.

The point is that another thread would not read b or c while a is non-zero.

Worst case, the C compiler may never bother to set a to 1 as it knows
that it will soon be set to zero, so saves the 'unneccessary' write.

So maybe you denote a as volatile, then the C compiler is still free
to reorder the writes to something like this:

        a = 1;  // mark we are doing a write
        a = 0;  // mark we are done.
        b++;
        c++;

Legal, but now a no longer marks the time b and c are modified.

So, to force the writes in the order we want them, we add barriers:

        a = 1;  // mark we are doing a write
        barrier();
        b++;
        c++;
        barrier();
        a = 0;  // mark we are done.

Now b and c are only changed in memory while a is a one.  But that
still leaves problems, more below.

> If that is the case, what purpose are the bookends?

Since that is NOT the case, think of the bookends as a handshake.

> There is a
> comment in the code, but it is unclear to me what is really trying to
> be accomplished. Are the bookends some mechanism to determine if the
> contents have changed since a previous copy of the data? Or something
> obtuse?

Yes, the bookends are to verify we have a nice current copy.  To expand
the previous example a bit, yet still wrong:

    while ( true ) {
        do_something();
        a = 1;  // mark we are doing a write
        barrier();
        b++;
        c++;
        barrier();
        a = 0;  // mark we are done.
    }

This sort of looks like the gpsd main loop,  do something, then put
the results in memory.

Imagine another thread reading a, b and c.  It is possible that the read
may wait for a to be zero, then read b, then get an interrupt.  While
in the interrupt, a pulses another time, then the reader reads c.  Note
that c is from a different iterration of the loop than the b that was
read.

So now we get to the final form of the loop:

    tick = 0;
    while ( true ) {
        do_something();
        tick++;
        a = tick;  // mark we are doing a write
        barrier();
        b++;
        c++;
        barrier();
        a1 = tick;
    }

Now the reader reads a, a1, b and c.  If a is the same as a1, then we
know the reader got all four from the same cycle and we know that b and
c are in the same data set.

There is some voodoo in there, and I would rather have used posix
semaphores as they are 'known' correct, but this looks pretty good so
far.

> > Doing shared memory is a twitchy thing, note the comments on
> > barriers, read/write order, etc.  So just use the function, dont
> > try to duplicate it.
> 
> I have used shared memory in other situations to great effect. It is
> all in what you claim to be putting in the segment that decides the
> degree of twitchiness. 

Exactly, SHMMEM give you all the tools you need to shoot yourself in the
foot.  :-)

> Yeah, but that changes the access logic I am hoping to implement. 

Not as much as you would think.  Sockets are pretty easy, and really hard
to mess up.  SHMMEM has many non-obvious ways to fail...

BTW, I tweaked the comment in shmexport.c to mention the role of
memory_barrier() a bit.

RGDS
GARY
---------------------------------------------------------------------------
Gary E. Miller Rellim 109 NW Wilmington Ave., Suite E, Bend, OR 97703
        address@hidden  Tel:+1 541 382 8588

Attachment: pgpd3sWvqFJGa.pgp
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]