C, signal, variable STOR and reentrancy

C

charles_gero

All:

Quick question regarding reentrancy and C99 signals. If we have a C
statement such as:

variable = 123456;

And the resulting compiled machine code for a particular fake platform
is to load the constant into a register, and then use **TWO** STORE
machine instructions to store the variable back to memory, so that it
looks like:

LOAD 123456, REG
STOR REG_UPPERHALF, ADDR1
STOR REG_LOWERHALF, ADDR2

Is it possible for a signal to be delivered between the STOR's? If so,
what prevents general lvalue modifications from being (for lack of a
better word) non reentrant (ie... the signal handler can modify
REG_LOWERHALF, and when it returns, the lower half of the STOR will be
incorrect)? Are lvalue modifications under C considered atomic?
Please provide a reference into the standard. Thanks so much!
 
C

charles_gero

Please excuse this question. I answered it myself. C99 7.14.2. -
sig_atomic_t. Many thanks for this wonderful group.

-Charlie
 
R

Richard Heathfield

(e-mail address removed) said:
All:

Quick question regarding reentrancy and C99 signals. If we have a C
statement such as:

variable = 123456;

And the resulting compiled machine code for a particular fake platform
is to load the constant into a register, and then use **TWO** STORE
machine instructions to store the variable back to memory, so that it
looks like:

LOAD 123456, REG
STOR REG_UPPERHALF, ADDR1
STOR REG_LOWERHALF, ADDR2

Is it possible for a signal to be delivered between the STOR's?
Yes.

If so,
what prevents general lvalue modifications from being (for lack of a
better word) non reentrant (ie... the signal handler can modify
REG_LOWERHALF, and when it returns, the lower half of the STOR will be
incorrect)?

Nothing, unless variable is of type sig_atomic_t.
Are lvalue modifications under C considered atomic?

For objects of type sig_atomic_t, yes. Otherwise, no.
Please provide a reference into the standard. Thanks so much!

Just search the Standard for sig_atomic_t - in my C89 draft, it's section
4.7, and in C99 it's 7.14.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: normal service will be restored as soon as possible. Please do not
adjust your email clients.
 
C

charles_gero

Thanks so much Richard. I actually stumbled across that at the last
moment, my deepest apologies. I have a followup as well. Is there any
guarentee that when an lvalue is accessed for a read, that the
resultant machine code will be loads and no stores. I ask as I am
trying to verify the validity of statements regarding threads
(specifically pthreads, and I understand outside the scope of this
newsgroup) that they can access global shared memory without mutex or
locks as long as the accesses are only reads, since the threads
maintain thread local stacks and registers. However, if in some
strange implementation, everytime you read a variables value, the
resultant machine code also contained some STOR to shared memory (I
don't know why that'd ever be the case, but regardless), this would not
necessarilly be true. I know that sounds very far fetched, but I'm
more or less trying to wrap my head around the theory of it all, and
see what truly is *guarenteed* in the standards. Thanks so much to
everyone in the group and thanks again Richard!
 
R

Richard Heathfield

(e-mail address removed) said:
Thanks so much Richard. I actually stumbled across that at the last
moment, my deepest apologies. I have a followup as well. Is there any
guarentee that when an lvalue is accessed for a read, that the
resultant machine code will be loads and no stores.

I am not aware of any such guarantee.

<snip>

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: normal service will be restored as soon as possible. Please do not
adjust your email clients.
 
F

Flash Gordon

Richard said:
(e-mail address removed) said:


I am not aware of any such guarantee.

Adding the volatile qualify is likely to help although it does depend on
how the implementation chooses to define an access. In my experience,
when using type sig_atomic_t you normally also want volatile.
 
C

Chris Torek

... I have a followup as well. Is there any
guarentee that when an lvalue is accessed for a read, that the
resultant machine code will be loads and no stores.

Not in general, no.

In general, the "volatile" qualifier is necessary but not sufficient
to obtain such a guarantee. It is up to each implementation to
define an "access" for a volatile-qualified type, so -- at least
in theory -- you simply read your implementation document(s) to
see what it/they say, and use that information to select whatever
it is that is both necessary *and* sufficient. This may include
restricting the base type(s) of the volatile-qualified types:
e.g., perhaps "volatile int" is atomic while "volatile long long"
and/or "volatile double" is not.
I ask as I am trying to verify the validity of statements
regarding threads (specifically pthreads, and I understand
outside the scope of this newsgroup) that they can access global
shared memory without mutex or locks as long as the accesses are
only reads, since the threads maintain thread local stacks and
registers.

C does not make such a guarantee, but some other, more restrictive
standard could. Suppose (for instance) that the Zorblatt 25 computer
has a problem with *all* memory-read operations, such that every
load is followed by a store in the generated code (because "load"
means "load and clear", because the Zorblatt has actual "core"
memory with its destructive-read system, and no auto-rewrite).
This machine can support ISO C, but not the other, more-restrictive
standard: any valid, strictly conforming C program runs fine on
the Zorblatt 25, but code that uses thread extensions does not.

In general, the more constraints some programming language or
standard makes, the fewer machines it can run on, but the easier
it is to use. If C had less "undefined behavior", we might be
able to say what "i++ * i++" means, but we might not be able
to implement C on every new machine that comes along (or at least,
not efficiently) -- consider VLIW machines, for instance, with
their multiple functional units. (See the Wikipedia entry at
However, if in some
strange implementation, everytime you read a variables value, the
resultant machine code also contained some STOR to shared memory (I
don't know why that'd ever be the case, but regardless) ...

The above example (magnetic core memory) suggests a possible reason.
Reads are performed by writing a value (normally 0) to the location
whose value is to be read. If writing a zero requires *changing*
the state, the magnetic field flips. This flip is tested-for. If
nothing is sensed, the previous value must have been 0; if something
is sensed, the previous value must have been 1. (For more detail,
see <http://en.wikipedia.org/wiki/Magnetic_core_memory>.)

Interestingly, conventional DRAM actually has the same problem as
old-style magnetic core memory: reads are destructive, because they
discharge the capacitor at the heart of each DRAM cell. In this
case, however, it is necessary for the chip itself to rewrite the
cell contents, as an entire row (or column, in CAS-before-RAS) is
dumped into the row-wide sense amplifiers. This internal rewrite
is harnessed for DRAM refresh. (I am deliberately skipping over
all kinds of detail; again, there is more in Wikipedia at
<http://en.wikipedia.org/wiki/DRAM>.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,772
Messages
2,569,593
Members
45,108
Latest member
AlbertEste
Top