os_mutex-unix.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /* os_mutex-unix.c -*-C-*-
  2. *
  3. *************************************************************************
  4. *
  5. * @copyright
  6. * Copyright (C) 2009-2013, Intel Corporation
  7. * All rights reserved.
  8. *
  9. * @copyright
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. *
  14. * * Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. * * Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in
  18. * the documentation and/or other materials provided with the
  19. * distribution.
  20. * * Neither the name of Intel Corporation nor the names of its
  21. * contributors may be used to endorse or promote products derived
  22. * from this software without specific prior written permission.
  23. *
  24. * @copyright
  25. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  26. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  27. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  28. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  29. * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  30. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  31. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  32. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  33. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
  35. * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. **************************************************************************/
  38. #include "os_mutex.h"
  39. #include "bug.h"
  40. #include <stdlib.h>
  41. #include <errno.h>
  42. #include <pthread.h>
  43. // contains notification macros for VTune.
  44. #include "cilk-ittnotify.h"
  45. /*
  46. * OS Mutex functions.
  47. *
  48. * Not to be confused with the spinlock mutexes implemented in cilk_mutex.c
  49. */
  50. struct os_mutex {
  51. pthread_mutex_t mutex; ///< On Linux, os_mutex is implemented with a pthreads mutex
  52. };
  53. // Unix implementation of the global OS mutex. This will be created by the
  54. // first call to global_os_mutex_lock() and *NEVER* destroyed. On gcc-based
  55. // systems there's no way to guarantee the ordering of constructors and
  56. // destructors, so we can't be guaranteed that our destructor for a static
  57. // object will be called *after* any static destructors that may use Cilk
  58. // in the user's application
  59. static struct os_mutex *global_os_mutex = NULL;
  60. /* Sometimes during shared library load malloc doesn't work.
  61. To handle that case, preallocate space for one mutex. */
  62. static struct os_mutex static_mutex;
  63. static int static_mutex_used;
  64. struct os_mutex *__cilkrts_os_mutex_create(void)
  65. {
  66. int status;
  67. struct os_mutex *mutex = (struct os_mutex *)malloc(sizeof(struct os_mutex));
  68. pthread_mutexattr_t attr;
  69. ITT_SYNC_CREATE(mutex, "OS Mutex");
  70. if (!mutex) {
  71. if (static_mutex_used) {
  72. __cilkrts_bug("Cilk RTS library initialization failed");
  73. } else {
  74. static_mutex_used = 1;
  75. mutex = &static_mutex;
  76. }
  77. }
  78. status = pthread_mutexattr_init(&attr);
  79. CILK_ASSERT (status == 0);
  80. #if defined DEBUG || CILK_LIB_DEBUG
  81. #ifdef PTHREAD_MUTEX_ERRORCHECK
  82. status = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
  83. #else
  84. status = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
  85. #endif
  86. CILK_ASSERT (status == 0);
  87. #endif
  88. status = pthread_mutex_init (&mutex->mutex, &attr);
  89. CILK_ASSERT (status == 0);
  90. pthread_mutexattr_destroy(&attr);
  91. return mutex;
  92. }
  93. void __cilkrts_os_mutex_lock(struct os_mutex *p)
  94. {
  95. int status;
  96. status = pthread_mutex_lock (&p->mutex);
  97. ITT_SYNC_ACQUIRED(p);
  98. if (__builtin_expect(status, 0) == 0)
  99. return;
  100. if (status == EDEADLK)
  101. __cilkrts_bug("Cilk runtime error: deadlock acquiring mutex %p\n",
  102. p);
  103. else
  104. __cilkrts_bug("Cilk runtime error %d acquiring mutex %p\n",
  105. status, p);
  106. }
  107. int __cilkrts_os_mutex_trylock(struct os_mutex *p)
  108. {
  109. int status;
  110. status = pthread_mutex_trylock (&p->mutex);
  111. return (status == 0);
  112. }
  113. void __cilkrts_os_mutex_unlock(struct os_mutex *p)
  114. {
  115. int status;
  116. ITT_SYNC_RELEASING(p);
  117. status = pthread_mutex_unlock (&p->mutex);
  118. CILK_ASSERT(status == 0);
  119. }
  120. void __cilkrts_os_mutex_destroy(struct os_mutex *p)
  121. {
  122. pthread_mutex_destroy (&p->mutex);
  123. if (p == &static_mutex) {
  124. static_mutex_used = 0;
  125. } else {
  126. free(p);
  127. }
  128. }
  129. /*
  130. * create_global_os_mutex
  131. *
  132. * Function used with pthread_once to initialize the global OS mutex. Since
  133. * pthread_once requires a function which takes no parameters and has no
  134. * return value, the global OS mutex will be stored in the static (global
  135. * to the compilation unit) variable "global_os_mutex."
  136. *
  137. *
  138. * global_os_mutex will never be destroyed.
  139. */
  140. static void create_global_os_mutex(void)
  141. {
  142. CILK_ASSERT(NULL == global_os_mutex);
  143. global_os_mutex = __cilkrts_os_mutex_create();
  144. }
  145. void global_os_mutex_lock(void)
  146. {
  147. // pthread_once_t used with pthread_once to guarantee that
  148. // create_global_os_mutex() is only called once
  149. static pthread_once_t global_os_mutex_is_initialized = PTHREAD_ONCE_INIT;
  150. // Execute create_global_os_mutex once in a thread-safe manner
  151. // Note that create_global_os_mutex returns the mutex in the static
  152. // (global to the module) variable "global_os_mutex"
  153. pthread_once(&global_os_mutex_is_initialized,
  154. create_global_os_mutex);
  155. // We'd better have allocated a global_os_mutex
  156. CILK_ASSERT(NULL != global_os_mutex);
  157. // Acquire the global OS mutex
  158. __cilkrts_os_mutex_lock(global_os_mutex);
  159. }
  160. void global_os_mutex_unlock(void)
  161. {
  162. // We'd better have allocated a global_os_mutex. This means you should
  163. // have called global_os_mutex_lock() before calling
  164. // global_os_mutex_unlock(), but this is the only check for it.
  165. CILK_ASSERT(NULL != global_os_mutex);
  166. // Release the global OS mutex
  167. __cilkrts_os_mutex_unlock(global_os_mutex);
  168. }
  169. /* End os_mutex-unix.c */