From: novickivan on
On Dec 22, 4:19 pm, David Schwartz <dav...(a)webmaster.com> wrote:
> On Dec 22, 4:09 pm, "novicki...(a)gmail.com" <novicki...(a)gmail.com>

> > The subtle question here is, are reads and writes of a variable
> > atomic?  Do i have to worry that i am reading the variable while it is
> > being updated and might get total garbage such as 9 million as the
> > value when i read it.  Or is the worst case that i missed some
> > increments because the increment on 1 thread was done without taking
> > into account the updates from another thread?
>
> It depends what the documentation for the threading standard you are
> using says. If POSIX, you are not guaranteed anything at all, it could
> even crash.
>
Ok, I understand it is not guaranteed to be safe by POSIX ( yes i am
assuming posix threads).

However, I am still curious if due to the design of modern hardware in
general, it is possible to read a value for the variable that was
never actually set. The code is trying to set values between 1 and 1
million. But could you read a value of 8 million if 8 million is
never set. The reason would be because you read an incompletely
written value at some point. Or is the computer such that you can
only read complete values and never a partially written value.

The use case would be if you did not care about missing some updates
to a variable, that was not locked, but still you don't want to read a
value that was never set in the variable at all. If this could be
"guaranteed" by the bus size or something like that, you might be able
to save doing locks.

Thanks for all the info so far guys.

Cheers, and merry Christmas,
Ivan Novick
From: David Schwartz on
On Dec 23, 8:34 pm, "novicki...(a)gmail.com" <novicki...(a)gmail.com>
wrote:

> However, I am still curious if due to the design of modern hardware in
> general, it is possible to read a value for the variable that was
> never actually set.  The code is trying to set values between 1 and 1
> million.  But could you read a value of 8 million if 8 million is
> never set.  The reason would be because you read an incompletely
> written value at some point.  Or is the computer such that you can
> only read complete values and never a partially written value.

Most likely, word tearing would be the only way. I don't know of any
POSIX platform where integers are subject to word tearing. The problem
is that you would be producing software that might break when a new
CPU, operating system, compiler, or something else comes out. On the
bright side, at least on x86, a lot of software makes the assumption
that read and writes to and from aligned integers are atomic (I think
it may even be guaranteed by Intel in the x86 specification) so you
certainly wouldn't be the only thing that would break.

> The use case would be if you did not care about missing some updates
> to a variable, that was not locked, but still you don't want to read a
> value that was never set in the variable at all.  If this could be
> "guaranteed" by the bus size or something like that, you might be able
> to save doing locks.

It's almost definitely not worth it. You would lose the other benefits
of locks, such as congestion avoidance.

DS
From: Golden California Girls on
novickivan(a)gmail.com wrote:
> lets say I have
>
> unsigned int x = 0;
>
> And the code
>
> x++;
>
> Is run a total of 1 million times but the million times is divided
> across many threads.
>
> If i try to read the value of x am i guaranteed to get a value between
> 0 and 1 million.
>
> The subtle question here is, are reads and writes of a variable
> atomic? Do i have to worry that i am reading the variable while it is
> being updated and might get total garbage such as 9 million as the
> value when i read it. Or is the worst case that i missed some
> increments because the increment on 1 thread was done without taking
> into account the updates from another thread?
>
> I hope i have made the question clear.

There has to be an assumption made, that int is large enough to store 1 million.
That isn't stated in your code. Rather obviously if it isn't large enough and
as it is unsigned then no matter what happens your answer will be yes.



If your question was is there hardware that allows an interrupt in the middle of
a machine cycle of a read or write, I'm not aware of any, but that may not be
true of an emulator machine.
From: David Schwartz on
On Dec 23, 8:59 pm, Golden California Girls <gldncag...(a)aol.com.mil>
wrote:

> If your question was is there hardware that allows an interrupt in the middle of
> a machine cycle of a read or write, I'm not aware of any, but that may not be
> true of an emulator machine.

Well, the more likely problems would be either that a single machine
instruction would be used to accomplish the read or the write or that
one CPU would read at the same time another is writing. An interrupt
in the middle of an instruction is just one possible way it could
fail.

In theory, on x86 you could use two machine instructions to write a 32-
bit value if you wanted to. It's hard to imagine any reason a compiler
would do that. And, on x86, 32-bit aligned values are not subject to
word tearing.

There are other ways it can go wrong, but they're also very unlikely.
For example, the compiler could 'optimize':

a++;

to:

a+=10000;
j=a;
j-=9999;
a=j;

As far as the compiler knows, this will have precisely the same
effect. However, if another thread read the value at the same time as
the 'j=a;' step, and then incremented it and wrote it back after the
'a=j;' step, you could get a totally bogus value.

Now, I know what you're thinking -- there's no way the compiler would
ever make an 'optimization' like this because it actually makes the
code worse. But the scary truth is that there are optimizations like
this that compilers do make.

One example is if the compiler is just one register short. Faced with
'i++;' on a RISC platform the most optimal implementation might be to
swap the memory location with a register, increment the register, and
swap back.

Sadly, there are similar known cases on x86. If I had the time, I'd
track down the GCC bug report.

DS
From: novickivan on
On Dec 23, 10:49 pm, David Schwartz <dav...(a)webmaster.com> wrote:
> On Dec 23, 8:59 pm, Golden California Girls <gldncag...(a)aol.com.mil>
> wrote:
>
> > If your question was is there hardware that allows an interrupt in the middle of
> > a machine cycle of a read or write, I'm not aware of any, but that may not be
> > true of an emulator machine.
>
> Well, the more likely problems would be either that a single machine
> instruction would be used to accomplish the read or the write or that
> one CPU would read at the same time another is writing. An interrupt
> in the middle of an instruction is just one possible way it could
> fail.
>
> In theory, on x86 you could use two machine instructions to write a 32-
> bit value if you wanted to. It's hard to imagine any reason a compiler
> would do that. And, on x86, 32-bit aligned values are not subject to
> word tearing.
>
> There are other ways it can go wrong, but they're also very unlikely.
> For example, the compiler could 'optimize':
>
> a++;
>
> to:
>
> a+=10000;
> j=a;
> j-=9999;
> a=j;
>
> As far as the compiler knows, this will have precisely the same
> effect. However, if another thread read the value at the same time as
> the 'j=a;' step, and then incremented it and wrote it back after the
> 'a=j;' step, you could get a totally bogus value.
>
> Now, I know what you're thinking -- there's no way the compiler would
> ever make an 'optimization' like this because it actually makes the
> code worse. But the scary truth is that there are optimizations like
> this that compilers do make.
>
> One example is if the compiler is just one register short. Faced with
> 'i++;' on a RISC platform the most optimal implementation might be to
> swap the memory location with a register, increment the register, and
> swap back.
>
> Sadly, there are similar known cases on x86. If I had the time, I'd
> track down the GCC bug report.
>
> DS

Ok, I feel convinced, that it is NOT safe to read and write to a
variable from multiple threads without locks even if you are not
concerned with missing the latest updates to the values. At the risk
of starting a whole new thread, I guess the best performance would be
to use atomic memory access functions like these:
http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html or
the equivalent.

Cheers,
Ivan Novick