| 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 |