compat_mutex_pthreads.c 2.7 KB

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