refcount.h 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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. /* Used to checking reference counts, most while doing perl5 stuff :-) */
  12. # if defined(OPENSSL_NO_STDIO)
  13. # if defined(REF_PRINT)
  14. # error "REF_PRINT requires stdio"
  15. # endif
  16. # endif
  17. # if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
  18. && !defined(__STDC_NO_ATOMICS__)
  19. # include <stdatomic.h>
  20. # define HAVE_C11_ATOMICS
  21. # endif
  22. # if defined(HAVE_C11_ATOMICS) && defined(ATOMIC_INT_LOCK_FREE) \
  23. && ATOMIC_INT_LOCK_FREE > 0
  24. # define HAVE_ATOMICS 1
  25. typedef _Atomic int CRYPTO_REF_COUNT;
  26. static ossl_inline int CRYPTO_UP_REF(_Atomic int *val, int *ret, void *lock)
  27. {
  28. *ret = atomic_fetch_add_explicit(val, 1, memory_order_relaxed) + 1;
  29. return 1;
  30. }
  31. static ossl_inline int CRYPTO_DOWN_REF(_Atomic int *val, int *ret, void *lock)
  32. {
  33. *ret = atomic_fetch_sub_explicit(val, 1, memory_order_release) - 1;
  34. if (*ret == 0)
  35. atomic_thread_fence(memory_order_acquire);
  36. return 1;
  37. }
  38. # elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) && __GCC_ATOMIC_INT_LOCK_FREE > 0
  39. # define HAVE_ATOMICS 1
  40. typedef int CRYPTO_REF_COUNT;
  41. static ossl_inline int CRYPTO_UP_REF(int *val, int *ret, void *lock)
  42. {
  43. *ret = __atomic_fetch_add(val, 1, __ATOMIC_RELAXED) + 1;
  44. return 1;
  45. }
  46. static ossl_inline int CRYPTO_DOWN_REF(int *val, int *ret, void *lock)
  47. {
  48. *ret = __atomic_fetch_sub(val, 1, __ATOMIC_RELEASE) - 1;
  49. if (*ret == 0)
  50. __atomic_thread_fence(__ATOMIC_ACQUIRE);
  51. return 1;
  52. }
  53. # else
  54. typedef int CRYPTO_REF_COUNT;
  55. # define CRYPTO_UP_REF(val, ret, lock) CRYPTO_atomic_add(val, 1, ret, lock)
  56. # define CRYPTO_DOWN_REF(val, ret, lock) CRYPTO_atomic_add(val, -1, ret, lock)
  57. # endif
  58. # if !defined(NDEBUG) && !defined(OPENSSL_NO_STDIO)
  59. # define REF_ASSERT_ISNT(test) \
  60. (void)((test) ? (OPENSSL_die("refcount error", __FILE__, __LINE__), 1) : 0)
  61. # else
  62. # define REF_ASSERT_ISNT(i)
  63. # endif
  64. # ifdef REF_PRINT
  65. # define REF_PRINT_COUNT(a, b) \
  66. fprintf(stderr, "%p:%4d:%s\n", b, b->references, a)
  67. # else
  68. # define REF_PRINT_COUNT(a, b)
  69. # endif
  70. #endif