lkml.org 
[lkml]   [1999]   [Nov]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: Shared memory not SMP safe to user-mode code.
On Wed, 1 Dec 1999, Jamie Lokier wrote:

> Richard B. Johnson wrote a spinlock:
> > pars->spin += key;
> > if(pars->spin != key)
> > {
> > pars->spin -= key;
>
> Wrong. This is not safe on UP /or/ SMP because "+=" and "-=" are not
> atomic operations in C. `volatile' does not help either.
>
[SNIPPED]

It is not necessary for the operations to be atomic! It is only essential
that they can be undone. Both the child and the parent have private
copies of their key value. The resulting arithmetic on the shared variable
will be wrong if any of the read/modify/write operations are interrupted
by another task, however, the resulting "mess" will be completely undone
when both of the tasks subtract their key values (in any order). This is
the important point of locking with a private key value, taught when I
was a kid in CS-101.

Note that to resolve deadlocks, both tasks as forced to sleep for a
different amount of time so they don't "attack" the variable again at the
same instant. This will not work with a long-long where addition
and subtraction occur as separate steps over two variables. Only
one variable can be modified. Also, the only reason why it won't
work with such aggregate types is that the propagation from one
variable to another via the carry-flag requires the same order of
subtraction as addition. With a single register or memory operand,
we don't care about the order of operations.

Now, another thing. If any task "thinks" only for an instant, that
their copy of the key is exactly the same as the shared variable, then
it is guaranteed that the other task will never, even for an instant
"think" that the shared variable is the same. This is enforced by
the CPU which guarantees that, regardless of what it "speculates",
code will never be executed out-of-order.

Again, we don't need atomic operations for this.

The task that, for an instant, sees its key equal to the shared variable
owns the lock. It is as simple as that.

That said, the code executes perfectly, but only if you use the
version that has the flush() macro. The flush() macro loads a segment
register (cs) in the "far" return. This flushes the offending cache.

Cheers,
Dick Johnson

Penguin : Linux version 2.3.13 on an i686 machine (400.59 BogoMips).
Warning : It's hard to remain at the trailing edge of technology.


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:55    [W:0.041 / U:0.716 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site