Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

typdef'ing from sig_atomic_t valid?

34 views
Skip to first unread message

Mark Piffer

unread,
Apr 22, 2004, 8:14:05 AM4/22/04
to
Does a typedef like
typedef sig_atomic_t atomic_int;
produce an atomically write/readable type? From what I read in the
standard I would guess yes, as sig_atomic_t itself is produced by a
typedef and typedefs don't really introduce new types. For another
question though, how to define an unsigned atomic type? I can't find
anything in the standard that would justify it, if sig_atomic_t is
signed, not even looking into signal.h and using the unsigned type
from which sig_atomic_t is constructed, as it could well have a
different width/object representation.

Mark

Ian Woods

unread,
Apr 22, 2004, 11:14:38 AM4/22/04
to
sorryon...@yahoo.com (Mark Piffer) wrote in
news:cce99527.0404...@posting.google.com:

sig_atomic_t has a range of SIG_ATOMIC_MIN to SIG_ATOMIC_MAX and may be
either signed or unsigned. Signed, the minimum range is -127 to 127.
Unsigned, the minimum range is 0 to 255. Or, in other words... you know for
definate that sig_atomic_t can hold values from 0 to 127 whether it's
signed or unsigned. (All from C99). Either way, I can't see any way of
making a "signed" or "unsigned" version of sig_atomic_t.

sig_atomic_t is best treated IMO as a completely seperate type from all the
other integer types rather than thinking of it as "typedef"ed from some
other type. The fact that the compiler has to make operations on it atomic
means that the compiler at some level has to know that isn't just a plain
old integer type.

Ian Woods

--
"I'm a paranoid schizophrenic sado-masochist.
My other half's out to get me and I can't wait."
Richard Heathfield

Dan Pop

unread,
Apr 22, 2004, 12:28:18 PM4/22/04
to
In <Xns94D3A4ABCE75...@217.32.252.50> Ian Woods <news...@wuggyNOCAPS.org> writes:

>sig_atomic_t is best treated IMO as a completely seperate type from all the
>other integer types rather than thinking of it as "typedef"ed from some
>other type. The fact that the compiler has to make operations on it atomic
>means that the compiler at some level has to know that isn't just a plain
>old integer type.

If the compiler *naturally* handles integer type T atomically, then
it couldn't care less whether the object was defined as having type
T directly or via sig_atomic_t.

It would take a less than 8-bit processor so that none of the integer
types can be handled atomically, requiring the additional information
you're talking about. But I have yet to hear about standard C
implementations for such processors...

I agree that maximally portable code can only rely on the 0..127 range
for sig_atomic_t, but this range should be more than enough for most
applications. Keep in mind that only *accesses* to sig_atomic_t are
guaranteed to be performed atomically, so the only meaningful operations
on this type are assigning a value and reading the current value.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Dan...@ifh.de

Kevin D. Quitt

unread,
Apr 22, 2004, 3:38:35 PM4/22/04
to
On 22 Apr 2004 16:28:18 GMT, Dan...@cern.ch (Dan Pop) wrote:
>Keep in mind that only *accesses* to sig_atomic_t are
>guaranteed to be performed atomically, so the only meaningful operations
>on this type are assigning a value and reading the current value.

Does this mean that atomic read-modify-write is not supported? If not, of
what use is sig_atomic_t?


--
#include <standard.disclaimer>
_
Kevin D Quitt USA 91387-4454 96.37% of all statistics are made up
Per the FCA, this address may not be added to any commercial mail list

those who know me have no need of my name

unread,
Apr 23, 2004, 5:57:05 AM4/23/04
to
in comp.lang.c i read:

>On 22 Apr 2004 16:28:18 GMT, Dan...@cern.ch (Dan Pop) wrote:

>>Keep in mind that only *accesses* to sig_atomic_t are
>>guaranteed to be performed atomically, so the only meaningful operations
>>on this type are assigning a value and reading the current value.
>
>Does this mean that atomic read-modify-write is not supported? If not, of
>what use is sig_atomic_t?

correct, read-modify-write is not required to be atomic. it's typical use
is as a flag, not as a counter, e.g.,

#include <stdio.h>
#include <signal.h>

volatile sig_atomic_t attention;

void attention_handler(int sig)
{
attention = 1;
if (SIG_ERR == signal(sig, SIG_DFL)) abort();
}

int main(void)
{
if (SIG_ERR == signal(SIGINT, attention_handler)) abort();
for (long i=0; i<LONG_MAX; i++)
{
/* ... */
if (attention)
{
fprintf(stderr, "interrupted at %ld\n", i);
break;
}
/* ... */
}
}

signal handling and atomic types and operations in standard c are very
limited, else it would be too hard to have hosted implementations on a
significant number of diverse platforms. typically there are other
standards or extensions which enhance an environment so much more can be
done, but you lose some portability (perhaps quite a lot) in the bargain.

--
a signature

Kevin D. Quitt

unread,
Apr 23, 2004, 10:59:37 AM4/23/04
to
On 23 Apr 2004 09:57:05 GMT, those who know me have no need of my name
<not-a-rea...@usa.net> wrote:

>correct, read-modify-write is not required to be atomic. it's typical use
>is as a flag, not as a counter, e.g.,

Clearly this is a meaning of atomic with which I'm not familiar (i.e.,
bus-atomic). There is insufficient information in the Standard to define
what it means by atomic. 7.14 p2 says:

The type defined is
sig_atomic_t
which is the (possibly volatile-qualified) integer type of an object that
can be accessed as an atomic entity, even in the presence of asynchronous
interrupts.

At first that sounds interesting, since that would be very useful for
structs, especially linked lists. But that's clearly not the case; 7.18.3
says:

If sig_atomic_t (see 7.14) is defined as a signed integer type, the value
of SIG_ATOMIC_MIN shall be no greater than -127 and the value of
SIG_ATOMIC_MAX shall be no less than 127; otherwise, sig_atomic_t is
defined as an unsigned integer type, and the value of SIG_ATOMIC_MIN shall
be 0 and the value of SIG_ATOMIC_MAX shall be no less than 255.

So it isn't necessarily more than a byte. How can access to a byte not be
atomic? With an 8-bit processor and bus, it's conceivable that 16- or
32-bit fetches might not be atomic, but 8-bit must be.

And if it must also be declared as volatile, I can't see *any* use for
sig_atomic_t. Please help me cure my ignorance. Point me at the detailed
definition of 'atomic' according to C, or show me code where an object of
type volatile sig_atomic_t acts differently that an object of type
volatile.

Eric Sosman

unread,
Apr 23, 2004, 11:40:09 AM4/23/04
to
"Kevin D. Quitt" wrote:
> [...]

> So it isn't necessarily more than a byte. How can access to a byte not be
> atomic? With an 8-bit processor and bus, it's conceivable that 16- or
> 32-bit fetches might not be atomic, but 8-bit must be.

On the original Alpha processors, the memory subsystem
supported only 64- and 32-bit accesses. If you wanted to
store a byte, you had to fetch the entire containing region,
do some shifting and masking, and store the whole thing
back again. So much for the atomicity of bytes.

--
Eric....@sun.com

Ben Pfaff

unread,
Apr 23, 2004, 2:17:37 PM4/23/04
to
Kevin D. Quitt <KQuitt...@IEEIncUNMUNG.com> writes:

> So it isn't necessarily more than a byte. How can access to a byte not be
> atomic? With an 8-bit processor and bus, it's conceivable that 16- or
> 32-bit fetches might not be atomic, but 8-bit must be.

What about using a 1-bit bus? Or a 32-bit bus? Access to a byte
can easily be non-atomic.
--
"To get the best out of this book, I strongly recommend that you read it."
--Richard Heathfield

Dan Pop

unread,
Apr 23, 2004, 2:19:04 PM4/23/04
to
In <qn7g80lkh0p3erhn0...@4ax.com> Kevin D. Quitt <KQuitt...@IEEIncUNMUNG.com> writes:

>On 22 Apr 2004 16:28:18 GMT, Dan...@cern.ch (Dan Pop) wrote:
>>Keep in mind that only *accesses* to sig_atomic_t are
>>guaranteed to be performed atomically, so the only meaningful operations
>>on this type are assigning a value and reading the current value.
>
>Does this mean that atomic read-modify-write is not supported?

The type defined is

sig_atomic_t

which is the integral type of an object that can be accessed as an


atomic entity, even in the presence of asynchronous interrupts.

...
If the signal occurs other than as the result of calling the abort
or raise function, the behavior is undefined if the signal handler
^^^^^^^^^^^^^^^^^^^^^^^^^
calls any function in the standard library other than the signal
function itself or refers to any object with static storage duration
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
other than by assigning a value to a static storage duration variable
^^^^^^^^^^^====================^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
of type volatile sig_atomic_t.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

>If not, of what use is sig_atomic_t?

A volatile sig_atomic_t object can be used as a flag that the signal
handler has been executed.

Typical example:

#include <stdio.h>
#include <signal.h>

volatile sig_atomic_t gotsig = 0;

void handler(int signo)
{
gotsig = signo;
}

int main()
{
signal(SIGINT, handler);
puts("Press the interrupt key to exit.");
while (gotsig == 0) ;
printf ("The program received signal %d.\n", (int)gotsig);
return 0;
}

Some people object to the fact that the signal number cannot be
represented by a sig_atomic_t object. I ignore them.

Kevin D. Quitt

unread,
Apr 23, 2004, 8:14:11 PM4/23/04
to
OK, thanks to the both of your for removing one set of my (many, I'm sure)
blinders.

(Except, of course, you invoked a read-modify-write, which would have been
a really useful thing to have been in the standard. But never mind.)

Kevin D. Quitt

unread,
Apr 23, 2004, 8:29:43 PM4/23/04
to
On 23 Apr 2004 18:19:04 GMT, Dan...@cern.ch (Dan Pop) wrote:
> function itself or refers to any object with static storage duration
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> other than by assigning a value to a static storage duration variable
> ^^^^^^^^^^^====================^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> of type volatile sig_atomic_t.
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

OK, so by definition, the only thing a signal handler can write to that's
available to the rest of the world is a sig_atomic_t. And it has to be
volatile to the rest of the world to make access correct. So the only
thing that makes sig_atomic_t useful is the fact that it's defined to be
useful.


>>If not, of what use is sig_atomic_t?
>
>A volatile sig_atomic_t object can be used as a flag that the signal
>handler has been executed.

Simply declaring that byte volatile would have the same effect under any
set of circumstances I can imagine. Clearly I'm having trouble with my
imagination.


>Some people object to the fact that the signal number cannot be
>represented by a sig_atomic_t object. I ignore them.

Me, too. It's meaningless in light of the definition of sig_atomic_t.

those who know me have no need of my name

unread,
Apr 23, 2004, 8:55:27 PM4/23/04
to
in comp.lang.c i read:

>On 23 Apr 2004 18:19:04 GMT, Dan...@cern.ch (Dan Pop) wrote:

>>Some people object to the fact that the signal number cannot be
>>represented by a sig_atomic_t object. I ignore them.
>
>Me, too. It's meaningless in light of the definition of sig_atomic_t.

i think the point is that it is possible for SIGINT to have a value outside
the range of sig_atomic_t. i've never seen it in the wild, but if one is
usually pedantic about the standard, especially having just quoted it, it's
not entirely misplaced to expect mention of the possibility -- even a left-
handed mention.

--
a signature

Kevin D. Quitt

unread,
Apr 23, 2004, 9:06:33 PM4/23/04
to
On 24 Apr 2004 00:55:27 GMT, those who know me have no need of my name

<not-a-rea...@usa.net> wrote:
>i think the point is that it is possible for SIGINT to have a value outside
>the range of sig_atomic_t.

I was only saying that *that* problem is a small one compared to the
problematic utility of sig_atomic_t as defined.


> i've never seen it in the wild, but if one is
>usually pedantic about the standard, especially having just quoted it, it's
>not entirely misplaced to expect mention of the possibility -- even a left-
>handed mention.

Completely fair of course. I'm really just trying to cure my ignorance,
but I'm beginning to think that I do understand C's idea of "atomic" - and
that it isn't what "atomic" means to most everybody else.

Michael Wojcik

unread,
Apr 26, 2004, 1:55:23 PM4/26/04
to

In article <66fj80lmoep6ou2ll...@4ax.com>, Kevin D. Quitt <KQuitt...@IEEIncUNMUNG.com> writes:
>
> ... I'm beginning to think that I do understand C's idea of "atomic" - and

> that it isn't what "atomic" means to most everybody else.

I can't speak for "most everybody else", but I've never thought
"atomic" implied "atomic read-and-update" in the context of the C
standard. Obviously "atomic" in computer science usually means that
some operation will either be performed completely or not at all, but
what that operation is can vary widely depending on context.

In the case of sig_atomic_t ISTM that the intent of the standard is
clear: assigning to a sig_atomic_t variable, or referencing one,
will be an atomic operation. The assignment, or reference, will
occur completely or not at all.

Consider a hypothetical conforming implementation on a processor with
an 8-bit bus, where a 16-bit store requires two instructions. An
asynchronous signal could interrupt that sequence between the two
instructions and leave a 16-bit value partially updated. On such an
implementation, sig_atomic_t would have to be an 8-bit integer
(signed or unsigned char, where CHAR_BIT was 8) so that no
sig_atomic_t variable could ever have a partially-updated value.

That said, sig_atomic_t as defined in the standard adds relatively
little value, because there are few cases where strictly-conforming
code could read a partially-updated value from any object. In
particular, a signal handler for an asynchronous signal cannot read
such a value, since it cannot refer to any object with static storage
duration except to assign to a volatile sig_atomic_t.

Footnote 109 (C90) states that another signal while in a handler for
an asynchronous signal causes undefined behavior. Footnotes aren't
normative, but clearly the standard doesn't intend to cover this case
(where a handler's assignment to a variable is interrupted by another
signal) with sig_atomic_t either.

The only other case I can think of is one where:

- Function A establishes a jmp_buf with setjmp.
- Function B assigns a value to a file-scope object X.
- Signal handler H longjmps back to A.
- A, when returning from setjmp via longjmp, refers to X.
- An asynchronous signal occurs while B is assigning to X.

However, it appears to me that this is not guaranteed to work by
the standard (I'm looking at C90), because while it says that a
signal handler may exit by calling longjmp, it also says it's not
allowed to "refer[] to any object with static storage duration"
except for the aforementioned assignment to a volatile sig_atomic_t.
Does calling longjmp constitute referring to the jmp_buf? Also,
in the case of asynchronous signals (ie ones not caused by abort or
raise), handlers are prohibited from calling any library function
other than signal. So as far as I can tell, there are no circum-
stances where a partial assignment could be detected (by strictly-
conforming code) anyway.

I suspect sig_atomic_t is one of those things which has semantics
that are not actually useful for strictly-conforming code, but are
plausibly useful in a variety of implementations as a common
extension. Specifically, I suspect that in most implementations
an asynchronous handler can safely refer to the value of a volatile
sig_atomic_t (as well as assigning to it), and in this case its
atomicity is important (as it guarantees that the handler will not
see a partial value).


--
Michael Wojcik michael...@microfocus.com

How can I sing with love in my bosom?
Unclean, immature and unseasonable salmon. -- Basil Bunting

Dan Pop

unread,
Apr 26, 2004, 2:14:03 PM4/26/04
to
In <obcj80hk6jqu1rnj8...@4ax.com> Kevin D. Quitt <KQuitt...@IEEIncUNMUNG.com> writes:

>On 23 Apr 2004 18:19:04 GMT, Dan...@cern.ch (Dan Pop) wrote:
>>
>>A volatile sig_atomic_t object can be used as a flag that the signal
>>handler has been executed.
>
>Simply declaring that byte volatile would have the same effect under any
>set of circumstances I can imagine. Clearly I'm having trouble with my
>imagination.

Clearly. Imagine a traditional Cray processor, that can only access
64-bit words, but whose C implementation uses 8-bit bytes. How do you
write something to one *byte* atomically?

At the other range of the spectre, imagine a 4-bit processor.
This is a pathological case, where sig_atomic_t is different
from normal C types: the compiler has to disable interrupts (errr,
delivery of asynchronous signals) while writing or reading all the 8+
bits composing the sig_atomic_t type, while such precautions are not
necessary for ordinary byte accesses.

Dan Pop

unread,
Apr 27, 2004, 9:02:15 AM4/27/04
to
In <c6jie...@news3.newsguy.com> mwo...@newsguy.com (Michael Wojcik) writes:


>That said, sig_atomic_t as defined in the standard adds relatively
>little value, because there are few cases where strictly-conforming
>code could read a partially-updated value from any object. In
>particular, a signal handler for an asynchronous signal cannot read
>such a value, since it cannot refer to any object with static storage
>duration except to assign to a volatile sig_atomic_t.

It's the ordinary code that is exposed to this problem, not the signal
handler. Imagine that this code has read half of the flag, the signal
handler has been executed, than the interrupted code resumed its
execution by reading the other half of the flag, that has been updated
in the meantine, ending up with half of the old value and half of the
new value. It is precisely this problem that sig_atomic_t solves.

Kevin D. Quitt

unread,
Apr 27, 2004, 11:11:00 AM4/27/04
to
On 26 Apr 2004 18:14:03 GMT, Dan...@cern.ch (Dan Pop) wrote:


>In <obcj80hk6jqu1rnj8...@4ax.com> Kevin D. Quitt <KQuitt...@IEEIncUNMUNG.com> writes:
>>Clearly I'm having trouble with my
>>imagination.
>
>Clearly. Imagine a traditional Cray processor, that can only access
>64-bit words, but whose C implementation uses 8-bit bytes. How do you
>write something to one *byte* atomically?

Trivially. One either uses a single instruction that is read-modify-write
bus atomic, or three instructions to do the same. No danger of a
partial-read by anybody.

On any machine that can write (at least) a byte in a single
uninterruptable instruction, there is no meaning to, or protection
provided by sig_atomic_t. sig_atomic_t specifically does *not* provide
protection against the following sequence:

Client task reads sig_atomic_t flag and starts to clear that flag.

Signal handler activates and writes new (different) value to sig_atomic_t
flag.

Client task completes clearing the flag.

Information has now been lost. There is no more protection using volatile
sig_atomic_t than there is just using a volatile. In this case,
sig_atomic_t is meaningless.

Compare this to the operation of a truly bus-atomic test-and-set
instruction, coupled with a bus-atomic test-and-clear, where one can be
guaranteed that information can never be lost. Even more powerful are
instructions like those on the 68K family that can link and unlink
doubly-linked list entries atomically.


>At the other range of the spectre, imagine a 4-bit processor.

This is another case completely, but only because the size of sig_atomic_t
is defined so as to force the loss of information by requiring a data size
that requires multiple instructions for access. On the C compiler I wrote
for the 6502, all accesses to volatile variables of any size were
protected by blocking int^W asynchronous signals; again, sig_atomic_t
would have made no difference.


It seems to me that this is one of those *very( rare cases where somebody
had an idea and an agenda, and forced it through the committee, without
anybody really thinking about it overly much.

Truly, I'm very surprised it got through - I have a great deal of respect
for the members. People around me consider me to be a C guru; I consider
myself (just barely) an expert and certainly not in the league of those on
the committee (those with whom I am familiar).

So basically, it boils down to: sig_atomic_t is useful because the use on
anything else is forbidden.

Dan Pop

unread,
Apr 27, 2004, 1:44:31 PM4/27/04
to
You seem to be MUCH denser than usual.

In <6lss809igso44brc3...@4ax.com> Kevin D. Quitt <KQuitt...@IEEIncUNMUNG.com> writes:

>On 26 Apr 2004 18:14:03 GMT, Dan...@cern.ch (Dan Pop) wrote:
>
>
>>In <obcj80hk6jqu1rnj8...@4ax.com> Kevin D. Quitt <KQuitt...@IEEIncUNMUNG.com> writes:
>>>Clearly I'm having trouble with my
>>>imagination.
>>
>>Clearly. Imagine a traditional Cray processor, that can only access
>>64-bit words, but whose C implementation uses 8-bit bytes. How do you
>>write something to one *byte* atomically?
>
>Trivially. One either uses a single instruction that is read-modify-write
>bus atomic,

It's not enough, even if such an instruction actually exist. Think about
the complete sequence of operations needed for the job:

read word
AND operation to clear old byte
OR operation to insert new byte
write word

>or three instructions to do the same. No danger of a
>partial-read by anybody.

Huh?!? What is preventing an interrupt from occurring in the middle of
the sequence?

>On any machine that can write (at least) a byte in a single
>uninterruptable instruction, there is no meaning to, or protection
>provided by sig_atomic_t.

The point is that you don't know what is the type that can be atomically
written to, even if it exists. On the Cray it is int, on an 8-bit micro
it is char. Hence the need for sig_atomic_t.

>sig_atomic_t specifically does *not* provide
>protection against the following sequence:
>
>Client task reads sig_atomic_t flag and starts to clear that flag.
>
>Signal handler activates and writes new (different) value to sig_atomic_t
>flag.
>
>Client task completes clearing the flag.

You're forgetting that clearing the sig_atomic_t flag is an atomic
operation *by definition*, therefore your scenario cannot happen.

2 The type defined is

sig_atomic_t

which is the (possibly volatile-qualified) integer type of an


object that can be accessed as an atomic entity, even in the

presence of asynchronous interrupts. ^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

>Information has now been lost.

No information has been lost.

>There is no more protection using volatile
>sig_atomic_t than there is just using a volatile. In this case,
>sig_atomic_t is meaningless.

Bullshit!

>Compare this to the operation of a truly bus-atomic test-and-set
>instruction, coupled with a bus-atomic test-and-clear, where one can be
>guaranteed that information can never be lost. Even more powerful are
>instructions like those on the 68K family that can link and unlink
>doubly-linked list entries atomically.

They are entirely irrelevant in the context of sig_atomic_t and
signal handlers, as specified by the C standard.

>It seems to me that this is one of those *very( rare cases where somebody
>had an idea and an agenda, and forced it through the committee, without
>anybody really thinking about it overly much.

You're the only who failed to really engage his brain on this issue,
despite the detailed explanations you have already gotten.

>Truly, I'm very surprised it got through - I have a great deal of respect
>for the members. People around me consider me to be a C guru; I consider
>myself (just barely) an expert and certainly not in the league of those on
>the committee (those with whom I am familiar).

You're behaving like an idiot in this thread.

>So basically, it boils down to: sig_atomic_t is useful because the use on
>anything else is forbidden.

And there is a *good* reason for forbidding the use of anything else,
as already explained: char doesn't work on the Cray (and the 21064 Alpha),
anything wider than a char doesn't work on the 8-bit micro. No standard
integer type at all works on the less than 8-bit micro.

those who know me have no need of my name

unread,
Apr 27, 2004, 3:45:55 PM4/27/04
to
in comp.lang.c i read:

>On 26 Apr 2004 18:14:03 GMT, Dan...@cern.ch (Dan Pop) wrote:

>>Clearly. Imagine a traditional Cray processor, that can only access
>>64-bit words, but whose C implementation uses 8-bit bytes. How do you
>>write something to one *byte* atomically?
>
>Trivially. One either uses a single instruction that is read-modify-write
>bus atomic, or three instructions to do the same. No danger of a
>partial-read by anybody.

volatile sig_atomic_t is the clue to the compiler that this effort is
needed. a vast speed improvement is typically available when a `bus
atomic' transaction is avoided.

>On any machine that can write (at least) a byte in a single
>uninterruptable instruction, there is no meaning to, or protection
>provided by sig_atomic_t.

portability. one cannot know that any particular system will have this
property.

>Client task reads sig_atomic_t flag and starts to clear that flag.
>
>Signal handler activates and writes new (different) value to sig_atomic_t
>flag.
>
>Client task completes clearing the flag.

indeed, which is why it must also be qualified volatile as well. the
combination (causes the compiler to emit code which) prevents this from
occurring.

>Information has now been lost. There is no more protection using volatile
>sig_atomic_t than there is just using a volatile.

only on specific platforms -- hence non-portable code.

--
a signature

Mark Piffer

unread,
Apr 28, 2004, 8:14:08 AM4/28/04
to
Kevin D. Quitt <KQuitt...@IEEIncUNMUNG.com> wrote in message news:<6lss809igso44brc3...@4ax.com>...

> On 26 Apr 2004 18:14:03 GMT, Dan...@cern.ch (Dan Pop) wrote:
> >Clearly. Imagine a traditional Cray processor, that can only access
> >64-bit words, but whose C implementation uses 8-bit bytes. How do you
> >write something to one *byte* atomically?
>
> Trivially. One either uses a single instruction that is read-modify-write
> bus atomic, or three instructions to do the same. No danger of a
> partial-read by anybody.

But there is no such thing as a read-modify-write access in the
semantics of C. Not in the Standard and I highly doubt in any real
implementation either. Read-modify-write is what happens to come out
of an optimizing stage.


> On any machine that can write (at least) a byte in a single
> uninterruptable instruction, there is no meaning to, or protection
> provided by sig_atomic_t.

Exactly. Thats just restating the standard's definiton of sig_atomic_t
in another way: it is a typedef from an existing type, so the compiler
gains _no_ information whatsoever about integers of that type - it
just can be assumed to always generate atomic writes or reads to them.
You could use the implementation defined underlying type and produce
equivalent code (on one platform), with the same semantics of atomic
access, this time just hidden in the compiler handbooks.


> This is another case completely, but only because the size of sig_atomic_t
> is defined so as to force the loss of information by requiring a data size
> that requires multiple instructions for access. On the C compiler I wrote
> for the 6502, all accesses to volatile variables of any size were
> protected by blocking int^W asynchronous signals; again, sig_atomic_t
> would have made no difference.

IOW you implemented your special flavour of C, which in the case of
volatiles takes another (safer, I admit) approach than standard C.
Unluckily I don't expect to become a user of the 6502 or your compiler
any time soon, so my question was directed towards the standard atomic
types. Keep in mind also, that with this policy you prohibit certain
optimizations which contradicts the C design principles.

> Truly, I'm very surprised it got through - I have a great deal of respect
> for the members. People around me consider me to be a C guru; I consider
> myself (just barely) an expert and certainly not in the league of those on
> the committee (those with whom I am familiar).
>
> So basically, it boils down to: sig_atomic_t is useful because the use on
> anything else is forbidden.

Yes, also IMHO sig_atomic_t is one of the dirty corners where your
only lucky escape is to leave the paths of portability to do anything
real-world-ish, with the risk of adapting to this bad practice and
being beaten up on c.l.c ;)

Mark

Kevin D. Quitt

unread,
Apr 28, 2004, 5:22:15 PM4/28/04
to
On 27 Apr 2004 17:44:31 GMT, Dan...@cern.ch (Dan Pop) wrote:
>The point is that you don't know what is the type that can be atomically
>written to, even if it exists. On the Cray it is int, on an 8-bit micro
>it is char. Hence the need for sig_atomic_t.

OK. It's strictly for portability. I have to revise my view of it, then;
it does have a real (meta) use.


>>Client task reads sig_atomic_t flag and starts to clear that flag.
>>Signal handler activates and writes new (different) value to sig_atomic_t
>>flag.
>>Client task completes clearing the flag.
>
>You're forgetting that clearing the sig_atomic_t flag is an atomic
>operation *by definition*, therefore your scenario cannot happen.

Nah - the client read the value into another variable, or uses the
variable in a switch or if. It's another line of code before it can get
around to setting it to zero. The interrupt can happen in between, so you
can still lose the information.


>>There is no more protection using volatile
>>sig_atomic_t than there is just using a volatile. In this case,
>>sig_atomic_t is meaningless.
>
>Bullshit!

Except for portability, I stand by the comment. If you use a volatile
variable that's the right size for the hardware in question, adding
sig_atomic_t to it gets you no more protection.


>You're the only who failed to really engage his brain on this issue,
>despite the detailed explanations you have already gotten.

Apparently so. Your immediately previous post is the only one that
specifically said it was to guarantee portability. I guess I was still
thinking down in the hardware details and not an abstract enough.


>You're behaving like an idiot in this thread.

I was behaving ignorantly in this thread, trying to cure my ignorance.
With your (and others') help, I've cured it. I thank you.

Dan Pop

unread,
Apr 29, 2004, 8:10:51 AM4/29/04
to
In <58rt80der4mfuc3n4...@4ax.com> Kevin D. Quitt <KQuitt...@IEEIncUNMUNG.com> writes:

>On 27 Apr 2004 17:44:31 GMT, Dan...@cern.ch (Dan Pop) wrote:
>>The point is that you don't know what is the type that can be atomically
>>written to, even if it exists. On the Cray it is int, on an 8-bit micro
>>it is char. Hence the need for sig_atomic_t.
>
>OK. It's strictly for portability. I have to revise my view of it, then;
>it does have a real (meta) use.

Try to write a portable signal handler, according to the standard
specification, and you'll see that there is no place for "meta"
in your statement above.

>>>Client task reads sig_atomic_t flag and starts to clear that flag.
>>>Signal handler activates and writes new (different) value to sig_atomic_t
>>>flag.
>>>Client task completes clearing the flag.
>>
>>You're forgetting that clearing the sig_atomic_t flag is an atomic
>>operation *by definition*, therefore your scenario cannot happen.
>
>Nah - the client read the value into another variable, or uses the
>variable in a switch or if. It's another line of code before it can get
>around to setting it to zero. The interrupt can happen in between, so you
>can still lose the information.

If you want to shoot yourself in the foot, C is not going to prevent you
from doing it. The point is that sig_atomic_t *can* be safely used in
portable C code. Look again at the demo code I've posted. There is no
danger to lose any information there.

There is one genuine problem with signal handling in standard C and it
was recently discussed in comp.std.c, so I'm not going to rehash it here
(the standard specification allows race conditions).

>>>There is no more protection using volatile
>>>sig_atomic_t than there is just using a volatile. In this case,
>>>sig_atomic_t is meaningless.
>>
>>Bullshit!
>
>Except for portability, I stand by the comment.

The only reason to pay any attention to the C standard is portability.
Otherwise, the documentation of your compiler is much better and provides
lots of extra functionality. So, I miss your point: *everything* in the
C standard is about portability and sig_atomic_t is no exception.

0 new messages