xref: /netbsd-src/share/man/man9/atomic_loadstore.9 (revision ef7795e83ef8d54cff3594358ea81c1cd03424f3)
1.\"	$NetBSD: atomic_loadstore.9,v 1.8 2024/06/18 19:10:50 riastradh Exp $
2.\"
3.\" Copyright (c) 2019 The NetBSD Foundation
4.\" All rights reserved.
5.\"
6.\" This code is derived from software contributed to The NetBSD Foundation
7.\" by Taylor R. Campbell.
8.\"
9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions
11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright
13.\"    notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\"    notice, this list of conditions and the following disclaimer in the
16.\"    documentation and/or other materials provided with the distribution.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28.\" POSSIBILITY OF SUCH DAMAGE.
29.\"
30.Dd February 11, 2022
31.Dt ATOMIC_LOADSTORE 9
32.Os
33.Sh NAME
34.Nm atomic_load_relaxed ,
35.Nm atomic_load_acquire ,
36.Nm atomic_load_consume ,
37.Nm atomic_store_relaxed ,
38.Nm atomic_store_release
39.Nd atomic and ordered memory operations
40.Sh SYNOPSIS
41.In sys/atomic.h
42.Ft T
43.Fn atomic_load_relaxed "const volatile T *p"
44.Ft T
45.Fn atomic_load_acquire "const volatile T *p"
46.Ft T
47.Fn atomic_load_consume "const volatile T *p"
48.Ft void
49.Fn atomic_store_relaxed "volatile T *p" "T v"
50.Ft void
51.Fn atomic_store_release "volatile T *p" "T v"
52.Sh DESCRIPTION
53These type-generic macros implement memory operations that are
54.Em atomic
55and that have
56.Em memory ordering constraints .
57Aside from atomicity and ordering, the load operations are equivalent
58to
59.Li * Ns Fa p
60and the store operations are equivalent to
61.Li * Ns Fa p Li "=" Fa v .
62The pointer
63.Fa p
64must be aligned, even on architectures like x86 which generally lack
65strict alignment requirements; see
66.Sx SIZE AND ALIGNMENT
67for details.
68.Pp
69.Em Atomic
70means that the memory operations cannot be
71.Em fused
72or
73.Em torn :
74.Bl -bullet
75.It
76.Em Fusing
77is combining multiple memory operations on a single object into one
78memory operation, such as replacing
79.Bd -literal -compact
80	*p = v;
81	x = *p;
82.Ed
83by
84.Bd -literal -compact
85	*p = v;
86	x = v;
87.Ed
88since the compiler can prove that
89.Li \&*p
90will yield
91.Li v
92after
93.Li \&*p\ =\ v .
94For
95.Em atomic
96memory operations, the implementation
97.Em will not
98assume that
99.Bl -dash -compact
100.It
101consecutive loads of the same object will return the same value, or
102.It
103a store followed by a load of the same object will return the value
104stored, or
105.It
106consecutive stores of the same object are redundant.
107.El
108Thus, the implementation will not replace two consecutive atomic loads
109by one, will not elide an atomic load following a store, and will not
110combine two consecutive atomic stores into one.
111.Pp
112For example,
113.Bd -literal
114	atomic_store_relaxed(&flag, 1);
115	while (atomic_load_relaxed(&flag))
116		continue;
117.Ed
118.Pp
119may be used to set a flag and then busy-wait until another thread
120clears it, whereas
121.Bd -literal
122	flag = 1;
123	while (flag)
124		continue;
125.Ed
126.Pp
127may be transformed into the infinite loop
128.Bd -literal
129	flag = 1;
130	while (1)
131		continue;
132.Ed
133.It
134.Em Tearing
135is implementing a memory operation on a large data unit such as a
13632-bit word by issuing multiple memory operations on smaller data units
137such as 8-bit bytes.
138The implementation will not tear
139.Em atomic
140loads or stores into smaller ones.
141Thus, as far as any interrupt, other thread, or other CPU can tell, an
142atomic memory operation is issued either all at once or not at all.
143.Pp
144For example, if a 32-bit word
145.Va w
146is written with
147.Pp
148.Dl atomic_store_relaxed(&w,\ 0x00010002);
149.Pp
150then an interrupt, other thread, or other CPU reading it with
151.Li atomic_load_relaxed(&w)
152will never witness it partially written, whereas
153.Pp
154.Dl w\ =\ 0x00010002;
155.Pp
156might be compiled into a pair of separate 16-bit store instructions
157instead of one single word-sized store instruction, in which case other
158threads may see the intermediate state with only one of the halves
159written.
160.El
161.Pp
162Atomic operations on any single object occur in a total order shared by
163all interrupts, threads, and CPUs, which is consistent with the program
164order in every interrupt, thread, and CPU.
165A single program without interruption or other threads or CPUs will
166always observe its own loads and stores in program order, but another
167program in an interrupt handler, in another thread, or on another CPU
168may issue loads that return values as if the first program's stores
169occurred out of program order, and vice versa.
170Two different threads might each observe a third thread's memory
171operations in different orders.
172.Pp
173The
174.Em memory ordering constraints
175make limited guarantees of ordering relative to memory operations on
176.Em other
177objects as witnessed by interrupts, other threads, or other CPUs, and
178have the following meanings:
179.Bl -tag -width relaxed
180.It relaxed
181No ordering relative to memory operations on any other objects is
182guaranteed.
183Relaxed ordering is the default for ordinary non-atomic memory
184operations like
185.Li "*p"
186and
187.Li "*p = v" .
188.Pp
189Atomic operations with relaxed ordering are cheap: they are not
190read/modify/write atomic operations, and they do not involve any kind
191of inter-CPU ordering barriers.
192.It acquire
193This memory operation happens before all subsequent memory operations
194in program order.
195However, prior memory operations in program order may be reordered to
196happen after this one.
197For example, assuming no aliasing between the pointers, the
198implementation is allowed to treat
199.Bd -literal
200	int x = *p;
201	if (atomic_load_acquire(q)) {
202		int y = *r;
203		*s = x + y;
204		return 1;
205	}
206.Ed
207.Pp
208as if it were
209.Bd -literal
210	if (atomic_load_acquire(q)) {
211		int x = *p;
212		int y = *r;
213		*s = x + y;
214		return 1;
215	}
216.Ed
217.Pp
218but
219.Em not
220as if it were
221.Bd -literal
222	int x = *p;
223	int y = *r;
224	*s = x + y;
225	if (atomic_load_acquire(q)) {
226		return 1;
227	}
228.Ed
229.It consume
230This memory operation happens before all memory operations on objects
231at addresses that are computed from the value returned by this one.
232Otherwise, no ordering relative to memory operations on other objects
233is implied.
234.Pp
235For example, the implementation is allowed to treat
236.Bd -literal
237	struct foo *foo0, *foo1;
238
239	struct foo *f0 = atomic_load_consume(&foo0);
240	struct foo *f1 = atomic_load_consume(&foo1);
241	int x = f0->x;
242	int y = f1->y;
243.Ed
244.Pp
245as if it were
246.Bd -literal
247	struct foo *foo0, *foo1;
248
249	struct foo *f1 = atomic_load_consume(&foo1);
250	struct foo *f0 = atomic_load_consume(&foo0);
251	int y = f1->y;
252	int x = f0->x;
253.Ed
254.Pp
255but loading
256.Li f0->x
257is guaranteed to happen after loading
258.Li foo0
259even if the CPU had a cached value for the address that
260.Li f0->x
261happened to be at, and likewise for
262.Li f1->y
263and
264.Li foo1 .
265.Pp
266.Fn atomic_load_consume
267functions like
268.Fn atomic_load_acquire
269as long as the memory operations that must happen after it are limited
270to addresses that depend on the value returned by it, but it is almost
271always as cheap as
272.Fn atomic_load_relaxed .
273See
274.Sx ACQUIRE OR CONSUME?
275below for more details.
276.It release
277All prior memory operations in program order happen before this one.
278However, subsequent memory operations in program order may be reordered
279to happen before this one too.
280For example, assuming no aliasing between the pointers, the
281implementation is allowed to treat
282.Bd -literal
283	int x = *p;
284	*q = x;
285	atomic_store_release(r, 0);
286	int y = *s;
287	return x + y;
288.Ed
289.Pp
290as if it were
291.Bd -literal
292	int y = *s;
293	int x = *p;
294	*q = x;
295	atomic_store_release(r, 0);
296	return x + y;
297.Ed
298.Pp
299but
300.Em not
301as if it were
302.Bd -literal
303	atomic_store_release(r, 0);
304	int x = *p;
305	int y = *s;
306	*q = x;
307	return x + y;
308.Ed
309.El
310.Ss PAIRING ORDERED MEMORY OPERATIONS
311In general, each
312.Fn atomic_store_release
313.Em must
314be paired with either
315.Fn atomic_load_acquire
316or
317.Fn atomic_load_consume
318in order to have an effect \(em it is only when a release operation
319synchronizes with an acquire or consume operation that any ordering
320guaranteed between memory operations
321.Em before
322the release operation and memory operations
323.Em after
324the acquire/consume operation.
325.Pp
326For example, to set up an entry in a table and then mark the entry
327ready, you should:
328.Bl -enum
329.It
330Perform memory operations to initialize the data.
331.Bd -literal
332	tab[i].x = ...;
333	tab[i].y = ...;
334.Ed
335.It
336Issue
337.Fn atomic_store_release
338to mark it ready.
339.Bd -literal
340	atomic_store_release(&tab[i].ready, 1);
341.Ed
342.It
343Possibly in another thread, issue
344.Fn atomic_load_acquire
345to ascertain whether it is ready.
346.Bd -literal
347	if (atomic_load_acquire(&tab[i].ready) == 0)
348		return EWOULDBLOCK;
349.Ed
350.It
351Perform memory operations to use the data.
352.Bd -literal
353	do_stuff(tab[i].x, tab[i].y);
354.Ed
355.El
356.Pp
357Similarly, if you want to create an object, initialize it, and then
358publish it to be used by another thread, then you should:
359.Bl -enum
360.It
361Perform memory operations to initialize the object.
362.Bd -literal
363	struct mumble *m = kmem_alloc(sizeof(*m), KM_SLEEP);
364	m->x = x;
365	m->y = y;
366	m->z = m->x + m->y;
367.Ed
368.It
369Issue
370.Fn atomic_store_release
371to publish it.
372.Bd -literal
373	atomic_store_release(&the_mumble, m);
374.Ed
375.It
376Possibly in another thread, issue
377.Fn atomic_load_consume
378to get it.
379.Bd -literal
380	struct mumble *m = atomic_load_consume(&the_mumble);
381.Ed
382.It
383Perform memory operations to use the object's members.
384.Bd -literal
385	m->y &= m->x;
386	do_things(m->x, m->y, m->z);
387.Ed
388.El
389.Pp
390In both examples, assuming that the value written by
391.Fn atomic_store_release
392in step\~2
393is read by
394.Fn atomic_load_acquire
395or
396.Fn atomic_load_consume
397in step\~3, this guarantees that all of the memory operations in
398step\~1 complete before any of the memory operations in step\~4 \(em
399even if they happen on different CPUs.
400.Pp
401Without
402.Em both
403the release operation in step\~2
404.Em and
405the acquire or consume operation in step\~3, no ordering is guaranteed
406between the memory operations in steps\~1 and\~4.
407In fact, without
408.Em both
409release and acquire/consume, even the assignment
410.Li m->z\ =\ m->x\ +\ m->y
411in step\~1 might read values of
412.Li m->x
413and
414.Li m->y
415that were written in step\~4.
416.Ss ACQUIRE OR CONSUME?
417You must use
418.Fn atomic_load_acquire
419when subsequent memory operations in program order that must happen
420after the load are on objects at
421.Em addresses that might not depend arithmetically on the resulting value .
422This applies particularly when the choice of whether to do the
423subsequent memory operation depends on a
424.Em control-flow decision based on the resulting value :
425.Bd -literal
426	struct gadget {
427		int ready, x;
428	} the_gadget;
429
430	/* Producer */
431	the_gadget.x = 42;
432	atomic_store_release(&the_gadget.ready, 1);
433
434	/* Consumer */
435	if (atomic_load_acquire(&the_gadget.ready) == 0)
436		return EWOULDBLOCK;
437	int x = the_gadget.x;
438.Ed
439.Pp
440Here the
441.Em decision of whether to load
442.Li the_gadget.x
443depends on a control-flow decision depending on value loaded from
444.Li the_gadget.ready ,
445and loading
446.Li the_gadget.x
447must happen after loading
448.Li the_gadget.ready .
449Using
450.Fn atomic_load_acquire
451guarantees that the compiler and CPU do not conspire to load
452.Li the_gadget.x
453before we have ascertained that it is ready.
454.Pp
455You may use
456.Fn atomic_load_consume
457if all subsequent memory operations in program order that must happen
458after the load are performed on objects at
459.Em addresses computed arithmetically from the resulting value ,
460such as loading a pointer to a structure object and then dereferencing
461it:
462.Bd -literal
463	struct gizmo {
464		int x, y, z;
465	};
466	struct gizmo null_gizmo;
467	struct gizmo *the_gizmo = &null_gizmo;
468
469	/* Producer */
470	struct gizmo *g = kmem_alloc(sizeof(*g), KM_SLEEP);
471	g->x = 12;
472	g->y = 34;
473	g->z = 56;
474	atomic_store_release(&the_gizmo, g);
475
476	/* Consumer */
477	struct gizmo *g = atomic_load_consume(&the_gizmo);
478	int y = g->y;
479.Ed
480.Pp
481Here the
482.Em address
483of
484.Li g->y
485depends on the value of the pointer loaded from
486.Li the_gizmo .
487Using
488.Fn atomic_load_consume
489guarantees that we do not witness a stale cache for that address.
490.Pp
491In some cases it may be unclear.
492For example:
493.Bd -literal
494	int x[2];
495	bool b;
496
497	/* Producer */
498	x[0] = 42;
499	atomic_store_release(&b, 0);
500
501	/* Consumer 1 */
502	int y = atomic_load_???(&b) ? x[0] : x[1];
503
504	/* Consumer 2 */
505	int y = x[atomic_load_???(&b) ? 0 : 1];
506
507	/* Consumer 3 */
508	int y = x[atomic_load_???(&b) ^ 1];
509.Ed
510.Pp
511Although the three consumers seem to be equivalent, by the letter of
512C11 consumers\~1 and\~2 require
513.Fn atomic_load_acquire
514because the value determines the address of a subsequent load only via
515control-flow decisions in the
516.Li ?:
517operator, whereas consumer\~3 can use
518.Fn atomic_load_consume .
519However, if you're not sure, you should err on the side of
520.Fn atomic_load_acquire
521until C11 implementations have ironed out the kinks in the semantics.
522.Pp
523On all CPUs other than DEC Alpha,
524.Fn atomic_load_consume
525is cheap \(em it is identical to
526.Fn atomic_load_relaxed .
527In contrast,
528.Fn atomic_load_acquire
529usually implies an expensive memory barrier.
530.Ss SIZE AND ALIGNMENT
531The pointer
532.Fa p
533must be aligned \(em that is, if the object it points to is
534.\"
5352\c
536.ie t \s-2\v'-0.4m'n\v'+0.4m'\s+2
537.el ^n
538.\"
539bytes long, then the low-order
540.Ar n
541bits of
542.Fa p
543must be zero.
544.Pp
545All
546.Nx
547ports support cheap atomic loads and stores on units of data up to 32
548bits.
549Some ports additionally support cheap atomic loads and stores on
55064-bit quantities if
551.Dv __HAVE_ATOMIC64_LOADSTORE
552is defined.
553The macros are not allowed on larger quantities of data than the port
554supports atomically; attempts to use them for such quantities should
555result in a compile-time assertion failure.
556.Pp
557For example, as long as you use
558.Fn atomic_store_*
559to write a 32-bit quantity, you can safely use
560.Fn atomic_load_relaxed
561to optimistically read it outside a lock, but for a 64-bit quantity it
562must be conditional on
563.Dv __HAVE_ATOMIC64_LOADSTORE
564\(em otherwise it will lead to compile-time errors on platforms without
56564-bit atomic loads and stores:
566.Bd -literal
567	struct foo {
568		kmutex_t	f_lock;
569		uint32_t	f_refcnt;
570		uint64_t	f_ticket;
571	};
572
573	if (atomic_load_relaxed(&foo->f_refcnt) == 0)
574		return 123;
575#ifdef __HAVE_ATOMIC64_LOADSTORE
576	if (atomic_load_relaxed(&foo->f_ticket) == ticket)
577		return 123;
578#endif
579	mutex_enter(&foo->f_lock);
580	if (foo->f_refcnt == 0 || foo->f_ticket == ticket)
581		ret = 123;
582	...
583#ifdef __HAVE_ATOMIC64_LOADSTORE
584	atomic_store_relaxed(&foo->f_ticket, foo->f_ticket + 1);
585#else
586	foo->f_ticket++;
587#endif
588	...
589	mutex_exit(&foo->f_lock);
590.Ed
591.Pp
592Some ports support expensive 64-bit atomic read/modify/write
593operations, but not cheap 64-bit atomic loads and stores.
594For example, the armv7 instruction set includes 64-bit
595.Li ldrexd
596and
597.Li strexd
598loops (load-exclusive, store-conditional) which are atomic on 64-bit
599quantities.
600But the cheap 64-bit
601.Li ldrd / strd
602instructions are only atomic on 32-bit accesses at a time.
603These ports define
604.Dv __HAVE_ATOMIC64_OPS
605but not
606.Dv __HAVE_ATOMIC64_LOADSTORE ,
607since they do not have cheaper 64-bit atomic load/store operations than
608the full atomic read/modify/write operations.
609.Sh C11 COMPATIBILITY
610These macros are meant to follow
611.Tn C11
612semantics, in terms of
613.Li atomic_load_explicit()
614and
615.Li atomic_store_explicit()
616with the appropriate memory order specifiers, and are meant to make
617future adoption of the
618.Tn C11
619atomic API easier.
620Eventually it may be mandatory to use the
621.Tn C11
622.Vt _Atomic
623type qualifier or equivalent for the operands.
624.Sh LINUX ANALOGUES
625The Linux kernel provides two macros
626.Li READ_ONCE(x)
627and
628.Li WRITE_ONCE(x,\ v)
629which are similar to
630.Li atomic_load_consume(&x)
631and
632.Li atomic_store_relaxed(&x,\ v) ,
633respectively.
634However, while Linux's
635.Li READ_ONCE
636and
637.Li WRITE_ONCE
638prevent fusing, they may in some cases be torn \(em and therefore fail
639to guarantee atomicity \(em because:
640.Bl -bullet
641.It
642They do not require the address
643.Li "&x"
644to be aligned.
645.It
646They do not require
647.Li sizeof(x)
648to be at most the largest size of available atomic loads and stores on
649the host architecture.
650.El
651.Sh MEMORY BARRIERS AND ATOMIC READ/MODIFY/WRITE
652The atomic read/modify/write operations in
653.Xr atomic_ops 3
654have relaxed ordering by default, but can be combined with the memory
655barriers in
656.Xr membar_ops 3
657for the same effect as an acquire operation and a release operation for
658the purposes of pairing with
659.Fn atomic_store_release
660and
661.Fn atomic_load_acquire
662or
663.Fn atomic_load_consume .
664If
665.Li atomic_r/m/w()
666is an atomic read/modify/write operation in
667.Xr atomic_ops 3 ,
668then
669.Bd -literal
670	membar_release();
671	atomic_r/m/w(obj, ...);
672.Ed
673.Pp
674functions like a release operation on
675.Va obj ,
676and
677.Bd -literal
678	atomic_r/m/w(obj, ...);
679	membar_acquire();
680.Ed
681.Pp
682functions like a acquire operation on
683.Va obj .
684.Pp
685On architectures where
686.Dv __HAVE_ATOMIC_AS_MEMBAR
687is defined, all the
688.Xr atomic_ops 3
689imply release and acquire operations, so the
690.Xr membar_acquire 3
691and
692.Xr membar_release 3
693are redundant.
694.Pp
695The combination of
696.Fn atomic_load_relaxed
697and
698.Xr membar_acquire 3
699in that order is equivalent to
700.Fn atomic_load_acquire ,
701and the combination of
702.Xr membar_release 3
703and
704.Fn atomic_store_relaxed
705in that order is equivalent to
706.Fn atomic_store_release .
707.Sh EXAMPLES
708Maintaining lossy counters.
709These may lose some counts, because the read/modify/write cycle as a
710whole is not atomic.
711But this guarantees that the count will increase by at most one each
712time.
713In contrast, without atomic operations, in principle a write to a
71432-bit counter might be torn into multiple smaller stores, which could
715appear to happen out of order from another CPU's perspective, leading
716to nonsensical counter readouts.
717(For frequent events, consider using per-CPU counters instead in
718practice.)
719.Bd -literal
720	unsigned count;
721
722	void
723	record_event(void)
724	{
725		atomic_store_relaxed(&count,
726		    1 + atomic_load_relaxed(&count));
727	}
728
729	unsigned
730	read_event_count(void)
731	{
732		return atomic_load_relaxed(&count);
733	}
734.Ed
735.Pp
736Initialization barrier.
737.Bd -literal
738	int ready;
739	struct data d;
740
741	void
742	setup_and_notify(void)
743	{
744		setup_data(&d.things);
745		atomic_store_release(&ready, 1);
746	}
747
748	void
749	try_if_ready(void)
750	{
751		if (atomic_load_acquire(&ready))
752			do_stuff(d.things);
753	}
754.Ed
755.Pp
756Publishing a pointer to the current snapshot of data.
757(Caller must arrange that only one call to
758.Li take_snapshot()
759happens at any
760given time; generally this should be done in coordination with
761.Xr pserialize 9
762or similar to enable resource reclamation.)
763.Bd -literal
764	struct data *current_d;
765
766	void
767	take_snapshot(void)
768        {
769		struct data *d = kmem_alloc(sizeof(*d));
770
771		d->things = ...;
772
773		atomic_store_release(&current_d, d);
774	}
775
776	struct data *
777	get_snapshot(void)
778	{
779		return atomic_load_consume(&current_d);
780	}
781.Ed
782.Sh CODE REFERENCES
783.Pa sys/sys/atomic.h
784.Sh SEE ALSO
785.Xr atomic_ops 3 ,
786.Xr membar_ops 3 ,
787.Xr pserialize 9
788.Sh HISTORY
789These atomic operations first appeared in
790.Nx 9.0 .
791.Sh CAVEATS
792C11 formally specifies that all subexpressions, except the left
793operands of the
794.Ql && ,
795.Ql || ,
796.Ql ?: ,
797and
798.Ql \&,
799operators and the
800.Li kill_dependency()
801macro, carry dependencies for which
802.Dv memory_order_consume
803guarantees ordering, but most or all implementations to date simply
804treat
805.Dv memory_order_consume
806as
807.Dv memory_order_acquire
808and do not take advantage of data dependencies to elide costly memory
809barriers or load-acquire CPU instructions.
810.Pp
811Instead, we implement
812.Fn atomic_load_consume
813as
814.Fn atomic_load_relaxed
815followed by
816.Xr membar_datadep_consumer 3 ,
817which is equivalent to
818.Xr membar_consumer 3
819on DEC Alpha and
820.Xr __insn_barrier 3
821elsewhere.
822.Sh BUGS
823Some idiot decided to call it
824.Em tearing ,
825depriving us of the opportunity to say that atomic operations prevent
826fusion and
827.Em fission .
828