easy_lock.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #ifndef HEADER_CURL_EASY_LOCK_H
  2. #define HEADER_CURL_EASY_LOCK_H
  3. /***************************************************************************
  4. * _ _ ____ _
  5. * Project ___| | | | _ \| |
  6. * / __| | | | |_) | |
  7. * | (__| |_| | _ <| |___
  8. * \___|\___/|_| \_\_____|
  9. *
  10. * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
  11. *
  12. * This software is licensed as described in the file COPYING, which
  13. * you should have received as part of this distribution. The terms
  14. * are also available at https://curl.se/docs/copyright.html.
  15. *
  16. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  17. * copies of the Software, and permit persons to whom the Software is
  18. * furnished to do so, under the terms of the COPYING file.
  19. *
  20. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  21. * KIND, either express or implied.
  22. *
  23. * SPDX-License-Identifier: curl
  24. *
  25. ***************************************************************************/
  26. #include "curl_setup.h"
  27. #define GLOBAL_INIT_IS_THREADSAFE
  28. #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
  29. #define curl_simple_lock SRWLOCK
  30. #define CURL_SIMPLE_LOCK_INIT SRWLOCK_INIT
  31. #define curl_simple_lock_lock(m) AcquireSRWLockExclusive(m)
  32. #define curl_simple_lock_unlock(m) ReleaseSRWLockExclusive(m)
  33. #elif defined(HAVE_ATOMIC) && defined(HAVE_STDATOMIC_H)
  34. #include <stdatomic.h>
  35. #ifdef HAVE_SCHED_YIELD
  36. #include <sched.h>
  37. #endif
  38. #define curl_simple_lock atomic_int
  39. #define CURL_SIMPLE_LOCK_INIT 0
  40. #ifndef __INTEL_COMPILER
  41. /* The Intel compiler tries to look like GCC *and* clang *and* lies in its
  42. __has_builtin() function, so override it. */
  43. /* if GCC on i386/x86_64 or if the built-in is present */
  44. #if (defined(__GNUC__) && !defined(__clang__)) && \
  45. (defined(__i386__) || defined(__x86_64__))
  46. #define HAVE_BUILTIN_IA32_PAUSE
  47. #elif defined(__has_builtin) /* Keep this PP check separate from others */
  48. #if __has_builtin(__builtin_ia32_pause)
  49. #define HAVE_BUILTIN_IA32_PAUSE
  50. #endif
  51. #endif
  52. #endif
  53. static CURL_INLINE void curl_simple_lock_lock(curl_simple_lock *lock)
  54. {
  55. for(;;) {
  56. if(!atomic_exchange_explicit(lock, true, memory_order_acquire))
  57. break;
  58. /* Reduce cache coherency traffic */
  59. while(atomic_load_explicit(lock, memory_order_relaxed)) {
  60. /* Reduce load (not mandatory) */
  61. #ifdef HAVE_BUILTIN_IA32_PAUSE
  62. __builtin_ia32_pause();
  63. #elif defined(__aarch64__)
  64. __asm__ volatile("yield" ::: "memory");
  65. #elif defined(_WIN32)
  66. Sleep(1);
  67. #elif defined(HAVE_SCHED_YIELD)
  68. sched_yield();
  69. #endif
  70. }
  71. }
  72. }
  73. static CURL_INLINE void curl_simple_lock_unlock(curl_simple_lock *lock)
  74. {
  75. atomic_store_explicit(lock, false, memory_order_release);
  76. }
  77. #elif defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)
  78. #include <pthread.h>
  79. #define curl_simple_lock pthread_mutex_t
  80. #define CURL_SIMPLE_LOCK_INIT PTHREAD_MUTEX_INITIALIZER
  81. #define curl_simple_lock_lock(m) pthread_mutex_lock(m)
  82. #define curl_simple_lock_unlock(m) pthread_mutex_unlock(m)
  83. #else
  84. #undef GLOBAL_INIT_IS_THREADSAFE
  85. #endif
  86. #endif /* HEADER_CURL_EASY_LOCK_H */