compat_mutex_pthreads.c 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /* Copyright (c) 2003-2004, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. #include "lib/lock/compat_mutex.h"
  6. #include "lib/cc/compat_compiler.h"
  7. #include "lib/err/torerr.h"
  8. /** A mutex attribute that we're going to use to tell pthreads that we want
  9. * "recursive" mutexes (i.e., once we can re-lock if we're already holding
  10. * them.) */
  11. static pthread_mutexattr_t attr_recursive;
  12. static int attr_initialized = 0;
  13. void
  14. tor_locking_init(void)
  15. {
  16. if (!attr_initialized) {
  17. pthread_mutexattr_init(&attr_recursive);
  18. pthread_mutexattr_settype(&attr_recursive, PTHREAD_MUTEX_RECURSIVE);
  19. attr_initialized = 1;
  20. }
  21. }
  22. /** Initialize <b>mutex</b> so it can be locked. Every mutex must be set
  23. * up with tor_mutex_init() or tor_mutex_new(); not both. */
  24. void
  25. tor_mutex_init(tor_mutex_t *mutex)
  26. {
  27. if (PREDICT_UNLIKELY(!attr_initialized))
  28. tor_locking_init(); // LCOV_EXCL_LINE
  29. const int err = pthread_mutex_init(&mutex->mutex, &attr_recursive);
  30. if (PREDICT_UNLIKELY(err)) {
  31. // LCOV_EXCL_START
  32. raw_assert_unreached_msg("Error creating a mutex.");
  33. // LCOV_EXCL_STOP
  34. }
  35. }
  36. /** As tor_mutex_init, but initialize a mutex suitable that may be
  37. * non-recursive, if the OS supports that. */
  38. void
  39. tor_mutex_init_nonrecursive(tor_mutex_t *mutex)
  40. {
  41. int err;
  42. if (!attr_initialized)
  43. tor_locking_init(); // LCOV_EXCL_LINE
  44. err = pthread_mutex_init(&mutex->mutex, NULL);
  45. if (PREDICT_UNLIKELY(err)) {
  46. // LCOV_EXCL_START
  47. raw_assert_unreached_msg("Error creating a mutex.");
  48. // LCOV_EXCL_STOP
  49. }
  50. }
  51. /** Wait until <b>m</b> is free, then acquire it. */
  52. void
  53. tor_mutex_acquire(tor_mutex_t *m)
  54. {
  55. int err;
  56. raw_assert(m);
  57. err = pthread_mutex_lock(&m->mutex);
  58. if (PREDICT_UNLIKELY(err)) {
  59. // LCOV_EXCL_START
  60. raw_assert_unreached_msg("Error locking a mutex.");
  61. // LCOV_EXCL_STOP
  62. }
  63. }
  64. /** Release the lock <b>m</b> so another thread can have it. */
  65. void
  66. tor_mutex_release(tor_mutex_t *m)
  67. {
  68. int err;
  69. raw_assert(m);
  70. err = pthread_mutex_unlock(&m->mutex);
  71. if (PREDICT_UNLIKELY(err)) {
  72. // LCOV_EXCL_START
  73. raw_assert_unreached_msg("Error unlocking a mutex.");
  74. // LCOV_EXCL_STOP
  75. }
  76. }
  77. /** Clean up the mutex <b>m</b> so that it no longer uses any system
  78. * resources. Does not free <b>m</b>. This function must only be called on
  79. * mutexes from tor_mutex_init(). */
  80. void
  81. tor_mutex_uninit(tor_mutex_t *m)
  82. {
  83. int err;
  84. raw_assert(m);
  85. err = pthread_mutex_destroy(&m->mutex);
  86. if (PREDICT_UNLIKELY(err)) {
  87. // LCOV_EXCL_START
  88. raw_assert_unreached_msg("Error destroying a mutex.");
  89. // LCOV_EXCL_STOP
  90. }
  91. }