1 /* os_mutex-unix.c -*-C-*-
3 *************************************************************************
6 * Copyright (C) 2009-2013, Intel Corporation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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
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.
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 **************************************************************************/
46 // contains notification macros for VTune.
47 #include "cilk-ittnotify.h"
52 * Not to be confused with the spinlock mutexes implemented in cilk_mutex.c
56 pthread_mutex_t mutex
; ///< On Linux, os_mutex is implemented with a pthreads mutex
59 // Unix implementation of the global OS mutex. This will be created by the
60 // first call to global_os_mutex_lock() and *NEVER* destroyed. On gcc-based
61 // systems there's no way to guarantee the ordering of constructors and
62 // destructors, so we can't be guaranteed that our destructor for a static
63 // object will be called *after* any static destructors that may use Cilk
64 // in the user's application
65 static struct os_mutex
*global_os_mutex
= NULL
;
67 /* Sometimes during shared library load malloc doesn't work.
68 To handle that case, preallocate space for one mutex. */
69 static struct os_mutex static_mutex
;
70 static int static_mutex_used
;
72 struct os_mutex
*__cilkrts_os_mutex_create(void)
75 struct os_mutex
*mutex
= (struct os_mutex
*)malloc(sizeof(struct os_mutex
));
76 pthread_mutexattr_t attr
;
78 ITT_SYNC_CREATE(mutex
, "OS Mutex");
81 if (static_mutex_used
) {
82 __cilkrts_bug("Cilk RTS library initialization failed");
84 static_mutex_used
= 1;
85 mutex
= &static_mutex
;
89 status
= pthread_mutexattr_init(&attr
);
90 CILK_ASSERT (status
== 0);
91 #if defined DEBUG || CILK_LIB_DEBUG
92 #ifdef PTHREAD_MUTEX_ERRORCHECK
93 status
= pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_ERRORCHECK
);
95 status
= pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_ERRORCHECK_NP
);
97 CILK_ASSERT (status
== 0);
99 status
= pthread_mutex_init (&mutex
->mutex
, &attr
);
100 CILK_ASSERT (status
== 0);
101 pthread_mutexattr_destroy(&attr
);
106 void __cilkrts_os_mutex_lock(struct os_mutex
*p
)
109 status
= pthread_mutex_lock (&p
->mutex
);
110 ITT_SYNC_ACQUIRED(p
);
111 if (__builtin_expect(status
, 0) == 0)
113 if (status
== EDEADLK
)
114 __cilkrts_bug("Cilk runtime error: deadlock acquiring mutex %p\n",
117 __cilkrts_bug("Cilk runtime error %d acquiring mutex %p\n",
121 int __cilkrts_os_mutex_trylock(struct os_mutex
*p
)
124 status
= pthread_mutex_trylock (&p
->mutex
);
125 return (status
== 0);
128 void __cilkrts_os_mutex_unlock(struct os_mutex
*p
)
131 ITT_SYNC_RELEASING(p
);
132 status
= pthread_mutex_unlock (&p
->mutex
);
133 CILK_ASSERT(status
== 0);
136 void __cilkrts_os_mutex_destroy(struct os_mutex
*p
)
138 pthread_mutex_destroy (&p
->mutex
);
139 if (p
== &static_mutex
) {
140 static_mutex_used
= 0;
147 * create_global_os_mutex
149 * Function used with pthread_once to initialize the global OS mutex. Since
150 * pthread_once requires a function which takes no parameters and has no
151 * return value, the global OS mutex will be stored in the static (global
152 * to the compilation unit) variable "global_os_mutex."
155 * global_os_mutex will never be destroyed.
157 static void create_global_os_mutex(void)
159 CILK_ASSERT(NULL
== global_os_mutex
);
160 global_os_mutex
= __cilkrts_os_mutex_create();
163 void global_os_mutex_lock(void)
165 // pthread_once_t used with pthread_once to guarantee that
166 // create_global_os_mutex() is only called once
167 static pthread_once_t global_os_mutex_is_initialized
= PTHREAD_ONCE_INIT
;
169 // Execute create_global_os_mutex once in a thread-safe manner
170 // Note that create_global_os_mutex returns the mutex in the static
171 // (global to the module) variable "global_os_mutex"
172 pthread_once(&global_os_mutex_is_initialized
,
173 create_global_os_mutex
);
175 // We'd better have allocated a global_os_mutex
176 CILK_ASSERT(NULL
!= global_os_mutex
);
178 // Acquire the global OS mutex
179 __cilkrts_os_mutex_lock(global_os_mutex
);
182 void global_os_mutex_unlock(void)
184 // We'd better have allocated a global_os_mutex. This means you should
185 // have called global_os_mutex_lock() before calling
186 // global_os_mutex_unlock(), but this is the only check for it.
187 CILK_ASSERT(NULL
!= global_os_mutex
);
189 // Release the global OS mutex
190 __cilkrts_os_mutex_unlock(global_os_mutex
);
193 /* End os_mutex-unix.c */