liveBook · Manning

Uninterruptible operation

As explained in Modern C

An uninterruptible operation appears indivisible to a signal handler, either not having started or having completed.

An assignment to a double may take several machine operations. If a signal arrives partway through, its handler could see a value made from parts of the old and new values. That combination might not even be a valid double. section 17.6

TAKEAWAY: An operation is uninterruptible when a signal handler can observe it only as not yet started or completed. It need not be physically undivided; the runtime may enforce that appearance. section 17.6

C provides three relevant type classes:

  • sig_atomic_t supports uninterruptible loads and stores. It can hold a signal number, but should not be used as a counter: ++ can involve a load, increment, and store, and the type may be narrow. section 17.6
  • atomic_flag and other lock-free atomic types provide uninterruptible operations. These atomic types were introduced in C11. section 17.6
31   #if ATOMIC_LONG_LOCK_FREE > 1
32   /**
33    ** @brief Keep track of the number of calls into a
34    ** signal handler for each possible signal.
35    **
36    ** Don't use this array directly.
37    **
38    ** @see sh_count to update this information.
39    ** @see SH_PRINT to use that information.
40    **/
41   extern _Atomic(unsigned long) sh_counts[];
42
43   /**
44    ** @brief Use this in your signal handler to keep track of the
45    ** number of calls to the signal @a sig.
46    **
47    ** @see sh_counted to use that information.
48    **/
49   inline
50   void sh_count(int sig) {
51     if (sig < sh_known) ++sh_counts[sig];
52   }
53
54   inline
55   unsigned long sh_counted(int sig){
56     return (sig < sh_known) ? sh_counts[sig] : 0;
57   }


!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":0},{\"line\":0,\"ch\":2}],[{\"line\":0,\"ch\":5},{\"line\":0,\"ch\":8}],[{\"line\":0,\"ch\":9},{\"line\":0,\"ch\":30}],[{\"line\":1,\"ch\":0},{\"line\":1,\"ch\":2}],[{\"line\":2,\"ch\":0},{\"line\":2,\"ch\":2}],[{\"line\":3,\"ch\":0},{\"line\":3,\"ch\":2}],[{\"line\":4,\"ch\":0},{\"line\":4,\"ch\":2}],[{\"line\":5,\"ch\":0},{\"line\":5,\"ch\":2}],[{\"line\":6,\"ch\":0},{\"line\":6,\"ch\":2}],[{\"line\":7,\"ch\":0},{\"line\":7,\"ch\":2}],[{\"line\":8,\"ch\":0},{\"line\":8,\"ch\":2}],[{\"line\":9,\"ch\":0},{\"line\":9,\"ch\":2}],[{\"line\":10,\"ch\":0},{\"line\":10,\"ch\":2}],[{\"line\":10,\"ch\":5},{\"line\":10,\"ch\":33}],[{\"line\":11,\"ch\":0},{\"line\":11,\"ch\":2}],[{\"line\":12,\"ch\":0},{\"line\":12,\"ch\":2}],[{\"line\":13,\"ch\":0},{\"line\":13,\"ch\":2}],[{\"line\":14,\"ch\":0},{\"line\":14,\"ch\":2}],[{\"line\":15,\"ch\":0},{\"line\":15,\"ch\":2}],[{\"line\":16,\"ch\":0},{\"line\":16,\"ch\":2}],[{\"line\":17,\"ch\":0},{\"line\":17,\"ch\":2}],[{\"line\":18,\"ch\":0},{\"line\":18,\"ch\":2}],[{\"line\":18,\"ch\":5},{\"line\":18,\"ch\":11}],[{\"line\":23,\"ch\":5},{\"line\":23,\"ch\":11}],[{\"line\":19,\"ch\":0},{\"line\":19,\"ch\":2}],[{\"line\":19,\"ch\":5},{\"line\":19,\"ch\":9}],[{\"line\":7,\"ch\":14},{\"line\":7,\"ch\":22}],[{\"line\":10,\"ch\":35},{\"line\":10,\"ch\":43}],[{\"line\":16,\"ch\":14},{\"line\":16,\"ch\":22}],[{\"line\":19,\"ch\":10},{\"line\":19,\"ch\":18}],[{\"line\":20,\"ch\":29},{\"line\":20,\"ch\":37}],[{\"line\":24,\"ch\":19},{\"line\":24,\"ch\":27}],[{\"line\":25,\"ch\":33},{\"line\":25,\"ch\":41}],[{\"line\":2,\"ch\":50},{\"line\":2,\"ch\":53}],[{\"line\":19,\"ch\":19},{\"line\":19,\"ch\":22}],[{\"line\":24,\"ch\":30},{\"line\":24,\"ch\":33}],[{\"line\":20,\"ch\":0},{\"line\":20,\"ch\":2}],[{\"line\":0,\"ch\":6},{\"line\":0,\"ch\":8}],[{\"line\":20,\"ch\":7},{\"line\":20,\"ch\":9}],[{\"line\":21,\"ch\":0},{\"line\":21,\"ch\":2}],[{\"line\":22,\"ch\":0},{\"line\":22,\"ch\":2}],[{\"line\":23,\"ch\":0},{\"line\":23,\"ch\":2}],[{\"line\":18,\"ch\":5},{\"line\":18,\"ch\":11}],[{\"line\":23,\"ch\":5},{\"line\":23,\"ch\":11}],[{\"line\":24,\"ch\":0},{\"line\":24,\"ch\":2}],[{\"line\":10,\"ch\":20},{\"line\":10,\"ch\":33}],[{\"line\":24,\"ch\":5},{\"line\":24,\"ch\":18}],[{\"line\":16,\"ch\":14},{\"line\":16,\"ch\":24}],[{\"line\":24,\"ch\":19},{\"line\":24,\"ch\":29}],[{\"line\":2,\"ch\":50},{\"line\":2,\"ch\":53}],[{\"line\":19,\"ch\":19},{\"line\":19,\"ch\":22}],[{\"line\":24,\"ch\":30},{\"line\":24,\"ch\":33}],[{\"line\":25,\"ch\":0},{\"line\":25,\"ch\":2}],[{\"line\":25,\"ch\":7},{\"line\":25,\"ch\":13}],[{\"line\":26,\"ch\":0},{\"line\":26,\"ch\":2}]]"}
!@%STYLE%@!

The signal-counting example enables an atomic counter only when its lock-free test succeeds; the counter update is ++sh_counts[sig]. section 17.6

How Modern C covers it

How deep it goes
Defines apparent indivisibility and distinguishes sig_atomic_t loads and stores from increments, without detailing runtime enforcement.
Examples
Contrasts a split double assignment with signal-number storage and a conditionally enabled atomic signal counter.
What it assumes
Assumes C assignments and signal handlers while explaining why one C statement can comprise several machine operations.
What you can do after
Apply it by using sig_atomic_t for signal-number storage and checking lock-free support before using an atomic counter.
How it connects
Links signal handlers to sig_atomic_t, atomic_flag, lock-free atomic types, and machine operations.

This explainer was generated by Manning's knowledge graph from the text of Modern C. The section links point to the parts of the book it draws on.