Shared Data Problem

I

Ian Bell

Apologies for the last post; got the topic wrong.

What is the current thinking on the best way to solve the shared data
problem i.e. accesssing a shared variable in a non atomic way can give
erroneous results if an interrupt service routine that also changes it
occurs part way through the access.
 
J

Joona I Palaste

Ian Bell said:
Apologies for the last post; got the topic wrong.
What is the current thinking on the best way to solve the shared data
problem i.e. accesssing a shared variable in a non atomic way can give
erroneous results if an interrupt service routine that also changes it
occurs part way through the access.

The C standard doesn't specify anything about shared data or interrupt
services either. As far as the C standard is concerned, a C program runs
in completer isolation from the rest of the world. Please ask in a
newsgroup about your own implementation.
 
C

Chris Croughton

Apologies for the last post; got the topic wrong.

What is the current thinking on the best way to solve the shared data
problem i.e. accesssing a shared variable in a non atomic way can give
erroneous results if an interrupt service routine that also changes it
occurs part way through the access.

Standard C doesn't know anything about interrupt routines either, but
you're getting closer because it does know anout signals, which may be
asynchronous.

I suspect what you are looking for is the 'volatile' keyword, that says
that the variable must be re-read every time it is accessed in case it
has changed since the last time. However, the only type which is
guaranteed to be truly 'atomic' in C (in the sense that no other code
can access it in the middle of another access) is char, which is defined
as the smallest addressable element. In practice, most platforms will
probably treat int as atomic, but you really need to look at your
specific hardware.

For anything else, use a volatile char as a lock and use volatile for
any other shared area to disable optimisations based on prior values.
That will slow it down, of course, so keep such accesses to a minimum if
that's a concern.

Or, in the extreme, use system-specific constructs to disable interrupts
(the specific interrupt if you can) round the accesses. You may be able
to do that with inline assembler, for instance (but wrap it in macros in
a header file so it can be replaced for porting).

Chris C
 
I

Ian Bell

Joona said:
The C standard doesn't specify anything about shared data or interrupt
services either. As far as the C standard is concerned, a C program runs
in completer isolation from the rest of the world. Please ask in a
newsgroup about your own implementation.

Is this a newsgroup about C or the C standard?? The standard does not
mention applications but they are discussed here all the time.

Ian
 
C

CBFalconer

Ian said:
.... snip ...

Is this a newsgroup about C or the C standard?? The standard does
not mention applications but they are discussed here all the time.

No, we don't need another long discourse on what the subject of the
group really is. Just read the references below.

--
Some useful references:
<http://www.ungerhu.com/jxh/clc.welcome.txt>
<http://www.eskimo.com/~scs/C-faq/top.html>
<http://benpfaff.org/writings/clc/off-topic.html>
<http://anubis.dkuug.dk/jtc1/sc22/wg14/www/docs/n869/> (C99)
<http://www.dinkumware.com/refxc.html> C-library
 
T

Tor Rustad

Ian Bell said:
Apologies for the last post; got the topic wrong.

What is the current thinking on the best way to solve the shared data
problem i.e. accesssing a shared variable in a non atomic way can give
erroneous results if an interrupt service routine that also changes it
occurs part way through the access.

Objects you can access in an atomic way, must have type

sig_atomic_t

Even in case of asynchronous interrupts, the standard guarantee atomic
access, if the object is declared with the volatile qualifier:

volatile .sig_atomic_t shared_data;

Not much else you can safely do in a signal handler...
 
T

Tor Rustad

The C standard doesn't specify anything about shared data or interrupt
services either. As far as the C standard is concerned, a C program
runs in completer isolation from the rest of the world.

The signal() function is there to let us handle interrupts and
exceptions. Interrupts can viewed as as asynchronous events,
while exceptions can be viewed as synchronous events.

Floating-point exceptions (SIGFPE) is an example of synchronous
events. SIGINT is asynchronous event, that can be generated with
an interactive action e.g. by pressing Ctrl-C.

Hence, a C program doesn't run that isolated, SIGTERM may
come from a user or another program...
 
W

Walter Roberson

:The signal() function is there to let us handle interrupts and
:exceptions. Interrupts can viewed as as asynchronous events,
:while exceptions can be viewed as synchronous events.

:Floating-point exceptions (SIGFPE) is an example of synchronous
:events.

Is there an expressible upper-bound on the reception of a SIGFPE?
Same statement? Same block? Same routine?

Is there a way of expressing that "This section of code might
generate a SIGFPE signal, and if it does then use this signal
handler, but if the signal hasn't been generated by the time
the last instruction of the code has had its results 'fully
graduated', then ignore that handler" ?

Is there a way of expressing 'fully graduated' in C?
There are "sequence points", but the "as if" qualifiers
with respect to sequence points deliberately leave a lot
of leeway so that optimization can be use -- is there a way
to be -sure- that a particular computation has fully finished
in all math co-processors and internal CPU conditional computation
registers... or is assigning to a volatile variable the closest
such mechanism?

I'm just not sure that C has any provision for "synchronous events"
in any meaningful way.
 
C

Chris Torek

... Is there a way of expressing that "This section of code might
generate a SIGFPE signal, and if it does then use this signal
handler, but if the signal hasn't been generated by the time
the last instruction of the code has had its results 'fully
graduated', then ignore that handler" ?
No.

Is there a way of expressing 'fully graduated' in C?
There are "sequence points", but the "as if" qualifiers
with respect to sequence points deliberately leave a lot
of leeway so that optimization can be use -- is there a way
to be -sure- that a particular computation has fully finished
in all math co-processors and internal CPU conditional computation
registers... or is assigning to a volatile variable the closest
such mechanism?

Volatile is all you get, and it is not sufficient (as you observe).

In general, when attacking this problem, people just invent quickie
ad-hoc solutions, such as using inline assembly or a call to a short
assembly-language routine. Obviously these are machine- and even
compiler-dependent.
I'm just not sure that C has any provision for "synchronous events"
in any meaningful way.

Indeed. The situation is even worse when working with real shared
memory on real systems that share memory. In particular, one has
to choose a memory model, and on CPUs with instruction reordering,
synchronization primitives. In general, systems that offer
thread-handling routines (such as POSIX threads) will take care of
all the synchronization required at thread-mutex points, so that
the threads will work on multi-CPU boxes. I imagine there are
plenty of exceptions to this rule.

(There is a whole newsgroup, comp.programming.threads, for
thread-related discussion. POSIX particulars belong in
comp.unix.programmer -- a newsgroup whose "improper" hierarchical
name is a historical artifact, something like the way "comp.lang.c"
really means "comp.lang.iso-standard-c". :) )
 
C

Chris Torek

I suspect what you are looking for is the 'volatile' keyword, that says
that the variable must be re-read every time it is accessed in case it
has changed since the last time. However, the only type which is
guaranteed to be truly 'atomic' in C (in the sense that no other code
can access it in the middle of another access) is char, which is defined
as the smallest addressable element. ...

Actually, you need "volatile sig_atomic_t" in signal handlers. It
is so restricted as to be worthless for most "real work" though.
(You *can* use it, and a "real" solution to a real problem might
well incorporate "volatile sig_atomic_t", but that solution will
probably depend on things not guaranteed by the ISO C standards.)
For anything else, use a volatile char as a lock and use volatile for
any other shared area to disable optimisations based on prior values.

Do not do this: it will fail on some machines (e.g., SPARC, some
MIPS, some Alpha).

(One can only get atomic byte-wide access on SPARCs using the ldstub
instruction, which C compilers do not generally generate, not even
for "volatile char". Mutexes will generally be implemented with
the the V9-specific "cas" -- compare-and-swap -- instruction, which
operates on a 32-bit word.)
 
T

Tor Rustad

Walter Roberson said:
:The signal() function is there to let us handle interrupts and
:exceptions. Interrupts can viewed as as asynchronous events,
:while exceptions can be viewed as synchronous events.

:Floating-point exceptions (SIGFPE) is an example of synchronous
:events.

Is there an expressible upper-bound on the reception of a SIGFPE?
Same statement? Same block? Same routine?

No, from the C standard point of view, a program where a
computation raises a signal, has fallen into undefined behavior:

[#6.5]

"If an /exception/ occurs during the evaluation of an expression (that
is, if the result is not mathematically defined or not in the range of
representable values for its type), the behavior is undefined."


However, IF the abstract C machine is running on a CPU with
HW floating-point support, then I expect that the CPU
automatically suspend executing the current task (in the case
of a floating-point exception), until the exception handler
has finished...
 
T

Tor Rustad

Ian Bell said:
Is this a newsgroup about C or the C standard?? The standard
does not mention applications but they are discussed here all
the time.

C code can easily be written in a non-portable way, but
c.l.c. on-topic discussions, are about portable C code.

However, given an _interesting_ question, many regulars
will respond anyway... the trick is to start with an on-topic
question and afterwards pull in the off-topic stuff! ;-)
 

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,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top