Re: Shared memory not SMP safe to user-mode code.

Andrea Arcangeli (andrea@suse.de)
Wed, 1 Dec 1999 00:34:23 +0100 (CET)


On Tue, 30 Nov 1999, Richard B. Johnson wrote:

>If, at the point, one task discovered that a lock was not obtained and
>subtracted its key, user-code could execute "invlpg", forcing what

invlpg can be run only on pagetables and not over user memory. So you
can't need to run invlpg unless there is a major security branch in the
kernel.

The only thing you may need is to synchronize the tasks sharing the memory
if you risk to race. Just choose your preferred way. You can use a
spinlock allocated in the shm segment, you can use ipc semaphores or ipc
messages too I think. Or if your operations on shm can scale in SMP just
use mb() to enforce ordering and write SMP aware algorithms without
spinlocks at all.

>use that instruction. I will experiment with a "far" jump to see if
>I can do the same thing.

On x86 the only thing you may need is a lock on the bus to avoid
speculative reads.

>In the kernel, everything is easy. Just use a spin-lock, but that's
>not the point. What I need to do is let user-mode code access a

If it's simple for you to use a spinlock in the kernel you are fine as you
can/must use it also in userspace.

>shared-memory board that has NVRAM values that 'eventually' take effect.
>Currently, the maximum rate at which I can write a word is the HZ
>rate (100 Hz) because the CPU dosn't seem to "know" it's been written
>until a context-switch occurs, invalidating the cache.

A context-switch doesn't invalidate the cache, it only flushes the TLB and
it can't be your problem. I guess the 100Hz is just a delay long enough to
trigger some cache timeout.

>Currently, if you were to do the trivial:
>
> *ptr = shared_memory;
>
> while (!*ptr)
> ;
>
>This will loop forever, even when hardware writes non-zero to shared

Are you sure it's not gcc that optimized away the reads from memory? GCC
always think the program is single threaded and if ptr was zero it will
remains zero because nobody other than you is sharing the var and you are
not touching it, so you should make sure to declare it volatile if the
GCC default assumntion are not correct (as in your case).

>memory. This is because the CPU "knows" that it didn't write something
>there since the last time it read, so the data from the last read remains
>in its cache, never updated. Once a task-switch occurs, the loop
>will be broken. However, this limits the maximum data-change-rate
>to 100 Hz (the task-switch time).

This sound very suspect to me. Of course I don't know the details about
the hardware you are using.

Anyway to invalidate the cache what you need is a wbinvd. I don't remeber
if it can be run from userspace (I guess no at least without iopl). Check
the specs for that.

Andrea

-
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/