/src/boringssl/crypto/refcount.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (c) 2015, Google Inc. |
2 | | * |
3 | | * Permission to use, copy, modify, and/or distribute this software for any |
4 | | * purpose with or without fee is hereby granted, provided that the above |
5 | | * copyright notice and this permission notice appear in all copies. |
6 | | * |
7 | | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
8 | | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
9 | | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
10 | | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
11 | | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
12 | | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
13 | | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ |
14 | | |
15 | | #include "internal.h" |
16 | | |
17 | | #include <assert.h> |
18 | | #include <stdalign.h> |
19 | | #include <stdlib.h> |
20 | | |
21 | | |
22 | | // See comment above the typedef of CRYPTO_refcount_t about these tests. |
23 | | static_assert(alignof(CRYPTO_refcount_t) == alignof(CRYPTO_atomic_u32), |
24 | | "CRYPTO_refcount_t does not match CRYPTO_atomic_u32 alignment"); |
25 | | static_assert(sizeof(CRYPTO_refcount_t) == sizeof(CRYPTO_atomic_u32), |
26 | | "CRYPTO_refcount_t does not match CRYPTO_atomic_u32 size"); |
27 | | |
28 | | static_assert((CRYPTO_refcount_t)-1 == CRYPTO_REFCOUNT_MAX, |
29 | | "CRYPTO_REFCOUNT_MAX is incorrect"); |
30 | | |
31 | 677k | void CRYPTO_refcount_inc(CRYPTO_refcount_t *in_count) { |
32 | 677k | CRYPTO_atomic_u32 *count = (CRYPTO_atomic_u32 *)in_count; |
33 | 677k | uint32_t expected = CRYPTO_atomic_load_u32(count); |
34 | | |
35 | 677k | while (expected != CRYPTO_REFCOUNT_MAX) { |
36 | 677k | uint32_t new_value = expected + 1; |
37 | 677k | if (CRYPTO_atomic_compare_exchange_weak_u32(count, &expected, new_value)) { |
38 | 677k | break; |
39 | 677k | } |
40 | 677k | } |
41 | 677k | } |
42 | | |
43 | 1.18M | int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *in_count) { |
44 | 1.18M | CRYPTO_atomic_u32 *count = (CRYPTO_atomic_u32 *)in_count; |
45 | 1.18M | uint32_t expected = CRYPTO_atomic_load_u32(count); |
46 | | |
47 | 1.18M | for (;;) { |
48 | 1.18M | if (expected == 0) { |
49 | 0 | abort(); |
50 | 1.18M | } else if (expected == CRYPTO_REFCOUNT_MAX) { |
51 | 0 | return 0; |
52 | 1.18M | } else { |
53 | 1.18M | const uint32_t new_value = expected - 1; |
54 | 1.18M | if (CRYPTO_atomic_compare_exchange_weak_u32(count, &expected, |
55 | 1.18M | new_value)) { |
56 | 1.18M | return new_value == 0; |
57 | 1.18M | } |
58 | 1.18M | } |
59 | 1.18M | } |
60 | 1.18M | } |