/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 | 422 | void CRYPTO_refcount_inc(CRYPTO_refcount_t *in_count) { |
32 | 422 | CRYPTO_atomic_u32 *count = (CRYPTO_atomic_u32 *)in_count; |
33 | 422 | uint32_t expected = CRYPTO_atomic_load_u32(count); |
34 | | |
35 | 422 | while (expected != CRYPTO_REFCOUNT_MAX) { |
36 | 422 | uint32_t new_value = expected + 1; |
37 | 422 | if (CRYPTO_atomic_compare_exchange_weak_u32(count, &expected, new_value)) { |
38 | 422 | break; |
39 | 422 | } |
40 | 422 | } |
41 | 422 | } |
42 | | |
43 | 44.3k | int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *in_count) { |
44 | 44.3k | CRYPTO_atomic_u32 *count = (CRYPTO_atomic_u32 *)in_count; |
45 | 44.3k | uint32_t expected = CRYPTO_atomic_load_u32(count); |
46 | | |
47 | 44.3k | for (;;) { |
48 | 44.3k | if (expected == 0) { |
49 | 0 | abort(); |
50 | 44.3k | } else if (expected == CRYPTO_REFCOUNT_MAX) { |
51 | 0 | return 0; |
52 | 44.3k | } else { |
53 | 44.3k | const uint32_t new_value = expected - 1; |
54 | 44.3k | if (CRYPTO_atomic_compare_exchange_weak_u32(count, &expected, |
55 | 44.3k | new_value)) { |
56 | 44.3k | return new_value == 0; |
57 | 44.3k | } |
58 | 44.3k | } |
59 | 44.3k | } |
60 | 44.3k | } |