2014-07-29 Ed Smith-Rowland <3dw4rd@verizon.net>
[official-gcc.git] / libcilkrts / runtime / os_mutex-unix.c
blobaf398cdd089ff17c9be8c09e1a7da38831e8ecc4
1 /* os_mutex-unix.c -*-C-*-
3 *************************************************************************
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:
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.
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 **************************************************************************/
39 #include "os_mutex.h"
40 #include "bug.h"
42 #include <stdlib.h>
43 #include <errno.h>
44 #include <pthread.h>
46 // contains notification macros for VTune.
47 #include "cilk-ittnotify.h"
50 * OS Mutex functions.
52 * Not to be confused with the spinlock mutexes implemented in cilk_mutex.c
55 struct os_mutex {
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)
74 int status;
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");
80 if (!mutex) {
81 if (static_mutex_used) {
82 __cilkrts_bug("Cilk RTS library initialization failed");
83 } else {
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);
94 #else
95 status = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
96 #endif
97 CILK_ASSERT (status == 0);
98 #endif
99 status = pthread_mutex_init (&mutex->mutex, &attr);
100 CILK_ASSERT (status == 0);
101 pthread_mutexattr_destroy(&attr);
103 return mutex;
106 void __cilkrts_os_mutex_lock(struct os_mutex *p)
108 int status;
109 status = pthread_mutex_lock (&p->mutex);
110 ITT_SYNC_ACQUIRED(p);
111 if (__builtin_expect(status, 0) == 0)
112 return;
113 if (status == EDEADLK)
114 __cilkrts_bug("Cilk runtime error: deadlock acquiring mutex %p\n",
116 else
117 __cilkrts_bug("Cilk runtime error %d acquiring mutex %p\n",
118 status, p);
121 int __cilkrts_os_mutex_trylock(struct os_mutex *p)
123 int status;
124 status = pthread_mutex_trylock (&p->mutex);
125 return (status == 0);
128 void __cilkrts_os_mutex_unlock(struct os_mutex *p)
130 int status;
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;
141 } else {
142 free(p);
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 */