FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavutil/tests/atomic.c
Date: 2026-09-14 12:48:48
Exec Total Coverage
Lines: 82 82 100.0%
Functions: 2 2 100.0%
Branches: 20 40 50.0%

Line Branch Exec Source
1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 /*
20 * Test the stdatomic.h interface as used by FFmpeg, against whichever
21 * implementation configure selected, the native one or the compat fallback.
22 *
23 * The output is architecture independent: integer results are converted to
24 * long long before printing, and no pointer values are printed.
25 */
26
27 #include <limits.h>
28 #include <stdint.h>
29 #include <stdio.h>
30 #include <stdatomic.h>
31
32 static int called;
33
34 1 static void callback(void)
35 {
36 1 called++;
37 1 }
38
39 #define TEST(A, T, name, V1, V2) \
40 do { \
41 A object = 0; \
42 T expected, r; \
43 atomic_store(&object, (T)(V1)); \
44 r = atomic_exchange(&object, (T)(V2)); \
45 printf(name " exchange %lld\n", (long long)r); \
46 r = atomic_fetch_add(&object, (T)1); \
47 printf(name " add %lld\n", (long long)r); \
48 r = atomic_fetch_sub(&object, (T)((uint64_t)(V2) + 1)); \
49 printf(name " sub %lld\n", (long long)r); \
50 r = atomic_fetch_or(&object, (T)0x10); \
51 printf(name " or %lld\n", (long long)r); \
52 r = atomic_fetch_xor(&object, (T)0x10); \
53 printf(name " xor %lld\n", (long long)r); \
54 r = atomic_fetch_and(&object, (T)1); \
55 printf(name " and %lld\n", (long long)r); \
56 atomic_store(&object, (T)0x5a); \
57 expected = (T)(V1); \
58 r = atomic_compare_exchange_strong(&object, &expected, (T)(V2)); \
59 printf(name " cas %lld %lld\n", \
60 (long long)r, (long long)expected); \
61 do { \
62 r = atomic_compare_exchange_weak(&object, &expected, (T)(V1)); \
63 } while (!r); \
64 printf(name " cas weak %lld %lld %lld\n", \
65 (long long)r, (long long)expected, \
66 (long long)atomic_load(&object)); \
67 } while (0)
68
69 1 int main(void)
70 {
71 1 _Bool _Atomic b = 0;
72 _Bool be;
73 1 atomic_uint u32 = 0;
74 1 atomic_ullong u64 = 0;
75 1 atomic_uchar u8 = 0;
76 1 int x = 42;
77 1 int *_Atomic p = NULL;
78 int *pe;
79 1 void (*_Atomic fp)(void) = NULL;
80 1 const int *const arr[2] = { &x, NULL };
81 1 const int *const *_Atomic lst = NULL;
82 1 atomic_flag f = ATOMIC_FLAG_INIT;
83 long long old;
84 int r1, r2, r3;
85 void (*loaded_callback)(void);
86
87
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_char, char, "char", 97, 122);
88
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_schar, signed char, "schar", -5, 42);
89
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_uchar, unsigned char, "uchar", 200, 42);
90
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_short, short, "short", -30000, 42);
91
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_ushort, unsigned short, "ushort", 60000, 42);
92
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_int, int, "int", -2000000000, 2000000000);
93
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_uint, unsigned int, "uint", 4000000000u, 7u);
94
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_long, long, "long", -2000000000L, 2000000000L);
95
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_ulong, unsigned long, "ulong", 4000000000UL, 7UL);
96
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_llong, long long, "llong", -9007199254740993LL, 9007199254740993LL);
97
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_ullong, unsigned long long, "ullong", 18446744073709551615ULL, 3ULL);
98
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_int_least16_t, int_least16_t, "int_least16", -30000, 42);
99
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_uint_least32_t, uint_least32_t, "uint_least32", 4000000000u, 7u);
100
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_int_least64_t, int_least64_t, "int_least64", -9007199254740993LL, 9007199254740993LL);
101
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_uint_least64_t, uint_least64_t, "uint_least64", 18446744073709551615ULL, 3ULL);
102
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_int_fast16_t, int_fast16_t, "int_fast16", -30000, 42);
103
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_uint_fast32_t, uint_fast32_t, "uint_fast32", 4000000000u, 7u);
104
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_intptr_t, intptr_t, "intptr", -123456, 42);
105
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_size_t, size_t, "size", 4000000000u, 7u);
106
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
1 TEST(atomic_intmax_t, intmax_t, "intmax", -9007199254740993LL, 9007199254740993LL);
107
108 /* unsigned wraparound */
109 1 atomic_store(&u32, UINT_MAX);
110 1 old = atomic_fetch_add(&u32, 1u);
111 1 printf("uint wrap %lld %lld\n",
112 1 old, (long long)atomic_load(&u32));
113 1 atomic_store(&u64, ULLONG_MAX);
114 1 old = (long long)atomic_fetch_add(&u64, 1);
115 1 printf("ullong add %lld %lld\n",
116 1 old, (long long)atomic_load(&u64));
117 1 atomic_store(&u64, 5);
118 1 old = (long long)atomic_fetch_sub(&u64, 10);
119 1 printf("ullong sub %lld %lld\n",
120 1 old, (long long)atomic_load(&u64));
121 1 atomic_store(&u8, 200);
122 1 old = atomic_fetch_add(&u8, 100);
123 1 printf("uchar add %lld %lld\n",
124 1 old, (long long)atomic_load(&u8));
125
126 /* bool, including the normalization of the desired value */
127 1 atomic_store(&b, 1);
128 1 be = 0;
129 1 r1 = atomic_load(&b);
130 1 r2 = atomic_exchange(&b, 0);
131 1 r3 = atomic_compare_exchange_strong(&b, &be, 2);
132 1 printf("bool %d %d %d %d %d\n", r1, r2, r3,
133 1 (int)be, (int)atomic_load(&b));
134
135 /* object pointers */
136 1 atomic_store_explicit(&p, &x, memory_order_relaxed);
137 1 pe = NULL;
138 1 r1 = atomic_load_explicit(&p, memory_order_relaxed) == &x;
139 1 r2 = atomic_compare_exchange_strong(&p, &pe, NULL);
140 1 printf("ptr %d %d %d\n", r1, r2, pe == &x);
141 1 printf("ptr exch %d\n", atomic_exchange(&p, NULL) == &x);
142
143 /* function pointers, as in the log callback */
144 1 atomic_store_explicit(&fp, callback, memory_order_relaxed);
145 1 loaded_callback = atomic_load_explicit(&fp, memory_order_relaxed);
146 1 loaded_callback();
147
148 /* pointers to const, as in the device lists */
149 const int *const *l;
150 1 atomic_store_explicit(&lst, arr, memory_order_relaxed);
151 1 l = atomic_load_explicit(&lst, memory_order_relaxed);
152 1 printf("lst %d %d\n", l == arr, **l == x);
153
154 1 r1 = atomic_flag_test_and_set(&f);
155 1 r2 = atomic_flag_test_and_set(&f);
156 1 atomic_flag_clear(&f);
157 1 r3 = atomic_flag_test_and_set(&f);
158 1 printf("flag %d %d %d\n", r1, r2, r3);
159 1 printf("called %d\n", called);
160
161 {
162 1 int _Atomic i = 0;
163 1 atomic_init(&i, 43);
164 1 printf("init %d\n", (int)atomic_load(&i));
165 }
166 1 atomic_thread_fence(memory_order_seq_cst);
167 1 atomic_signal_fence(memory_order_acquire);
168 1 printf("kill_dep %d\n", (int)kill_dependency(1));
169
170 1 return 0;
171 }
172