sig_atomic_t

  • Thread starter Vijay Kumar R Zanvar
  • Start date
J

James Hu

What is the purpose of sig_atomic_t?

It is an integer type that is guaranteed by the standard to not be
partially written or partially read in the presence of asynchronous
interrupts.

-- James
 
D

Dan Pop

In said:
It is an integer type that is guaranteed by the standard to not be
partially written or partially read in the presence of asynchronous
interrupts.

While correct, this is not a direct answer to OP's question.

sig_atomic_t, along with the character types, are the only types that can
be reliably used in a signal handler. External objects of other types
used in a signal handler must be defined as const (or merely be de facto
constant in the program).

Dan
 
J

James Hu

While correct, this is not a direct answer to OP's question.

Thanks for the clarification.
sig_atomic_t, along with the character types, are the only types that can
be reliably used in a signal handler. External objects of other types
used in a signal handler must be defined as const (or merely be de facto
constant in the program).

Your second sentence hints at this, but I'll state it explicitly. The
signal handler can use objects of types other than sig_atomic_t as long
as the objects are not ever accessed by the program outside of the
signal handler's context.

-- James
 
S

Sudheer Reddy Vakati

Your second sentence hints at this, but I'll state it explicitly. The
signal handler can use objects of types other than sig_atomic_t as long
as the objects are not ever accessed by the program outside of the
signal handler's context.
Do you mean that i cant modify a global variable in my signal handler?
Why this particular restriction?


Sudheer
 
I

Irrwahn Grausewitz

Do you mean that i cant modify a global variable in my signal handler?
Why this particular restriction?

You can, but these objects have to be declared as
'volatile sig_atomic_t' to avoid undefined behaviour.

Regards
 
C

Chris Torek

[Someone wrote:]
Do you mean that i cant modify a global variable in my signal handler?

Not exactly, but mostly.
Why this particular restriction?

Consider the following example. Suppose you have a machine with
32-bit "long"s, 32-bit CPU registers, 64-bit "long long"s, and an
implementation that handles something like:

/* long x; */
x = 7;

by generating machine instructions of the form:

move #7, reg
store reg, [memory location for x]

But if "y" is a "long long" (and thus 64 bits wide), it requires
two separate stores to set it to a new value -- for instance:

/* long long y; */
y = 0x1111111122222222LL;

might compile to:

move #0x11111111, reg
store reg, [memory location for y]
move #0x22222222, reg
store reg, [(memory location for y) + 4]

Now, suppose that you wrote C code of the form:

printf("y is %llx\n", y);

and that this compiles to code of the form:

load reg, [y]
--> push reg
load reg, [y+4]
push reg
move #stringaddr("y is 0x%llxLL\n"), reg
push reg
call printf

Suppose further that you manage to invoke your signal handler right
when the processor has finished the first "load" but has not yet
started the second "load", i.e., is about to execute (or has just
executed) the instruction marked with the "-->" arrow. If y used
to hold the value 0x8888888899999999LL, the code will have handled
the first half -- 0x88888888 -- but not the second. Then your
signal handler will change y to 0x1111111122222222LL, and only
when that finishes will the CPU resume and execute the second "load".
The output from printf() will then be:

y is 0x8888888822222222LL

which, as you will see, is an "impossible" value -- y is *supposed*
to be either 0x8888888899999999LL or 0x1111111122222222LL, but not
0x1111111199999999LL nor 0x8888888822222222LL.

Now, you might say "oh, well, in that case I will just avoid using
64-bit variables" -- but what if your CPU has 32-bit "int"s and
16-bit registers, or 16-bit "int"s and 8-bit registers, or any
other number of possibilities? Even if you use a size that happens
to match your CPU hardware -- either by accident, or by knowing
all the details about your CPU -- what if the compiler chooses to
decide: "aha, I know for sure that I only need to modify the low
byte of variable y here"? (Admittedly, the "volatile" keyword is
likely to inhibit such an optimization.)

The one guarantee you get, from the ANSI/ISO C standard, is that
you can assign to a "volatile sig_atomic_t" variable and see *only*
either the old value or the new value, never any weird intermediate
mix. Use any other type and the C-level guarantee is gone. This
does not mean you *cannot* use any other type, only that if you do,
you must look elsewhere for guarantees about it.

(Incidentally, if you study the above assembly too closely, you
will observe that "long long"s are big-endian in RAM but little-endian
when pushed on the stack for printf(). This is partly for exposition,
but also deliberate: there is nothing that says they must be
consistent; the va_arg() macro could assemble "long long"s in
reverse word-endian-ness order.)
 

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

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top