]>
Commit | Line | Data |
---|---|---|
2f545ae4 KR |
1 | /* |
2 | * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
4 | * Licensed under the OpenSSL license (the "License"). You may not use | |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | #ifndef HEADER_INTERNAL_REFCOUNT_H | |
10 | # define HEADER_INTERNAL_REFCOUNT_H | |
11 | ||
cd420b0b P |
12 | /* Used to checking reference counts, most while doing perl5 stuff :-) */ |
13 | # if defined(OPENSSL_NO_STDIO) | |
14 | # if defined(REF_PRINT) | |
15 | # error "REF_PRINT requires stdio" | |
16 | # endif | |
17 | # endif | |
18 | ||
01b76c2c BE |
19 | # if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \ |
20 | && !defined(__STDC_NO_ATOMICS__) | |
2f545ae4 KR |
21 | # include <stdatomic.h> |
22 | # define HAVE_C11_ATOMICS | |
23 | # endif | |
24 | ||
01b76c2c BE |
25 | # if defined(HAVE_C11_ATOMICS) && defined(ATOMIC_INT_LOCK_FREE) \ |
26 | && ATOMIC_INT_LOCK_FREE > 0 | |
2f545ae4 KR |
27 | |
28 | # define HAVE_ATOMICS 1 | |
29 | ||
30 | typedef _Atomic int CRYPTO_REF_COUNT; | |
31 | ||
32 | static ossl_inline int CRYPTO_UP_REF(_Atomic int *val, int *ret, void *lock) | |
33 | { | |
34 | *ret = atomic_fetch_add_explicit(val, 1, memory_order_relaxed) + 1; | |
35 | return 1; | |
36 | } | |
37 | ||
38 | static ossl_inline int CRYPTO_DOWN_REF(_Atomic int *val, int *ret, void *lock) | |
39 | { | |
40 | *ret = atomic_fetch_sub_explicit(val, 1, memory_order_release) - 1; | |
41 | if (*ret == 0) | |
42 | atomic_thread_fence(memory_order_acquire); | |
43 | return 1; | |
44 | } | |
45 | ||
46 | # elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) && __GCC_ATOMIC_INT_LOCK_FREE > 0 | |
47 | ||
48 | # define HAVE_ATOMICS 1 | |
49 | ||
50 | typedef int CRYPTO_REF_COUNT; | |
51 | ||
52 | static ossl_inline int CRYPTO_UP_REF(int *val, int *ret, void *lock) | |
53 | { | |
54 | *ret = __atomic_fetch_add(val, 1, __ATOMIC_RELAXED) + 1; | |
55 | return 1; | |
56 | } | |
57 | ||
58 | static ossl_inline int CRYPTO_DOWN_REF(int *val, int *ret, void *lock) | |
59 | { | |
60 | *ret = __atomic_fetch_sub(val, 1, __ATOMIC_RELEASE) - 1; | |
61 | if (*ret == 0) | |
62 | __atomic_thread_fence(__ATOMIC_ACQUIRE); | |
63 | return 1; | |
64 | } | |
65 | ||
66 | # else | |
67 | ||
68 | typedef int CRYPTO_REF_COUNT; | |
69 | ||
70 | # define CRYPTO_UP_REF(val, ret, lock) CRYPTO_atomic_add(val, 1, ret, lock) | |
71 | # define CRYPTO_DOWN_REF(val, ret, lock) CRYPTO_atomic_add(val, -1, ret, lock) | |
72 | ||
73 | # endif | |
cd420b0b P |
74 | |
75 | # if !defined(NDEBUG) && !defined(OPENSSL_NO_STDIO) | |
76 | # define REF_ASSERT_ISNT(test) \ | |
77 | (void)((test) ? (OPENSSL_die("refcount error", __FILE__, __LINE__), 1) : 0) | |
78 | # else | |
79 | # define REF_ASSERT_ISNT(i) | |
80 | # endif | |
81 | ||
82 | # ifdef REF_PRINT | |
83 | # define REF_PRINT_COUNT(a, b) \ | |
84 | fprintf(stderr, "%p:%4d:%s\n", b, b->references, a) | |
85 | # else | |
86 | # define REF_PRINT_COUNT(a, b) | |
87 | # endif | |
88 | ||
2f545ae4 | 89 | #endif |