OpenMPI 0.1.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

mutex.h
Go to the documentation of this file.
1 /*
2 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
3 * University Research and Technology
4 * Corporation. All rights reserved.
5 * Copyright (c) 2004-2006 The University of Tennessee and The University
6 * of Tennessee Research Foundation. All rights
7 * reserved.
8 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
9 * University of Stuttgart. All rights reserved.
10 * Copyright (c) 2004-2005 The Regents of the University of California.
11 * All rights reserved.
12 * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
13 * Copyright (c) 2007 Los Alamos National Security, LLC. All rights
14 * reserved.
15 * Copyright (c) 2007 Voltaire. All rights reserved.
16 * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
17 *
18 * $COPYRIGHT$
19 *
20 * Additional copyrights may follow
21 *
22 * $HEADER$
23 */
24
25 #ifndef OPAL_MUTEX_H
26 #define OPAL_MUTEX_H 1
27
28 #include "opal_config.h"
29
30 #if OPAL_ENABLE_MULTI_THREADS
31 #include "opal/sys/atomic.h"
32 #endif /* OPAL_ENABLE_MULTI_THREADS */
33 #if OPAL_ENABLE_DEBUG
34 #include "opal/util/output.h"
35 #endif
36
37 BEGIN_C_DECLS
38
39 /**
40 * @file:
41 *
42 * Mutual exclusion functions.
43 *
44 * Functions for locking of critical sections.
45 */
46
47 /*
48 * declaring this here so that CL does not complain
49 */
50 OPAL_DECLSPEC extern bool opal_uses_threads;
51
52 #if OPAL_ENABLE_DEBUG
53 OPAL_DECLSPEC extern bool opal_mutex_check_locks;
54 #endif
55
56 /**
57 * Opaque mutex object
58 */
59 typedef struct opal_mutex_t opal_mutex_t;
60
61
62 /**
63 * Try to acquire a mutex.
64 *
65 * @param mutex Address of the mutex.
66 * @return 0 if the mutex was acquired, 1 otherwise.
67 */
68 static inline int opal_mutex_trylock(opal_mutex_t *mutex);
69
70
71 /**
72 * Acquire a mutex.
73 *
74 * @param mutex Address of the mutex.
75 */
76 static inline void opal_mutex_lock(opal_mutex_t *mutex);
77
78
79 /**
80 * Release a mutex.
81 *
82 * @param mutex Address of the mutex.
83 */
84 static inline void opal_mutex_unlock(opal_mutex_t *mutex);
85
86
87 /**
88 * Try to acquire a mutex using atomic operations.
89 *
90 * @param mutex Address of the mutex.
91 * @return 0 if the mutex was acquired, 1 otherwise.
92 */
93 static inline int opal_mutex_atomic_trylock(opal_mutex_t *mutex);
94
95
96 /**
97 * Acquire a mutex using atomic operations.
98 *
99 * @param mutex Address of the mutex.
100 */
101 static inline void opal_mutex_atomic_lock(opal_mutex_t *mutex);
102
103
104 /**
105 * Release a mutex using atomic operations.
106 *
107 * @param mutex Address of the mutex.
108 */
109 static inline void opal_mutex_atomic_unlock(opal_mutex_t *mutex);
110
111 END_C_DECLS
112
113 #ifdef __WINDOWS__
114 #include "mutex_windows.h"
115 #else
116 #include "mutex_unix.h"
117 #endif
118
119 BEGIN_C_DECLS
120
121 /**
122 * Check and see if the process is using multiple threads.
123 *
124 * @retval true If the process may have more than one thread.
125 * @retval false If the process only has a single thread.
126 *
127 * The value that this function returns is influenced by:
128 *
129 * - how MPI_INIT or MPI_INIT_THREAD was invoked,
130 * - what the final MPI thread level was determined to be,
131 * - whether the OMPI or MPI libraries are multi-threaded (Jan 2003:
132 * they're not),
133 * - whether configure determined if we have thread support or not
134 *
135 * MPI_INIT and MPI_INIT_THREAD (specifically, back-end OMPI startup
136 * functions) invoke opal_set_using_threads() to influence the value of
137 * this function, depending on their situation. Some examples:
138 *
139 * - if configure determined that we do not have threads, then this
140 * value will always be false.
141 *
142 * - if MPI_INIT is invoked, and the ompi libraries are [still]
143 * single-threaded, this value will be false.
144 *
145 * - if MPI_INIT_THREAD is invoked with MPI_THREAD_MULTIPLE, we have
146 * thread support, and the final thread level is determined to be
147 * MPI_THREAD_MULTIPLE, this value will be true.
148 *
149 * - if the process is a single-threaded OMPI executable (e.g., mpicc),
150 * this value will be false.
151 *
152 * Hence, this function will return false if there is guaranteed to
153 * only be one thread in the process. If there is even the
154 * possibility that we may have multiple threads, true will be
155 * returned.
156 */
157 #define opal_using_threads() opal_uses_threads
158
159 /**
160 * Set whether the process is using multiple threads or not.
161 *
162 * @param have Boolean indicating whether the process is using
163 * multiple threads or not.
164 *
165 * @retval opal_using_threads The new return value from
166 * opal_using_threads().
167 *
168 * This function is used to influence the return value of
169 * opal_using_threads(). If configure detected that we have thread
170 * support, the return value of future invocations of
171 * opal_using_threads() will be the parameter's value. If configure
172 * detected that we have no thread support, then the retuen from
173 * opal_using_threads() will always be false.
174 */
175 static inline bool opal_set_using_threads(bool have)
176 {
177 #if OPAL_ENABLE_MULTI_THREADS
178 opal_uses_threads = have;
179 #else
180 (void)have; /* just shut up the compiler */
181 opal_uses_threads = false;
182 #endif
183 return opal_uses_threads;
184 }
185
186
187 /**
188 * Lock a mutex if opal_using_threads() says that multiple threads may
189 * be active in the process.
190 *
191 * @param mutex Pointer to a opal_mutex_t to lock.
192 *
193 * If there is a possibility that multiple threads are running in the
194 * process (as determined by opal_using_threads()), this function will
195 * block waiting to lock the mutex.
196 *
197 * If there is no possibility that multiple threads are running in the
198 * process, return immediately.
199 */
200
201 #if OPAL_ENABLE_MULTI_THREADS
202 #define OPAL_THREAD_LOCK(mutex) \
203 do { \
204 if (opal_using_threads()) { \
205 opal_mutex_lock(mutex); \
206 } \
207 } while (0)
208 #elif OPAL_ENABLE_DEBUG
209 #define OPAL_THREAD_LOCK(mutex) \
210 do { \
211 (mutex)->m_lock_debug++; \
212 if (opal_mutex_check_locks && 1 != (mutex)->m_lock_debug) { \
213 opal_output(0, "Warning -- mutex already locked at %s:%d," \
214 " now at %s:%d", \
215 (mutex)->m_lock_file, \
216 (mutex)->m_lock_line, \
217 __FILE__, __LINE__); \
218 } \
219 (mutex)->m_lock_file = __FILE__; \
220 (mutex)->m_lock_line = __LINE__; \
221 } while (0)
222 #else
223 #define OPAL_THREAD_LOCK(mutex)
224 #endif
225
226
227 /**
228 * Try to lock a mutex if opal_using_threads() says that multiple
229 * threads may be active in the process.
230 *
231 * @param mutex Pointer to a opal_mutex_t to trylock
232 *
233 * If there is a possibility that multiple threads are running in the
234 * process (as determined by opal_using_threads()), this function will
235 * trylock the mutex.
236 *
237 * If there is no possibility that multiple threads are running in the
238 * process, return immediately without modifying the mutex.
239 *
240 * Returns 0 if mutex was locked, non-zero otherwise.
241 */
242 #if OPAL_ENABLE_MULTI_THREADS
243 #define OPAL_THREAD_TRYLOCK(mutex) (opal_using_threads() ? opal_mutex_trylock(mutex) : 0)
244 #elif OPAL_ENABLE_DEBUG
245 static inline int
246 opal_thread_debug_trylock(opal_mutex_t *mutex, const char *file, int line)
247 {
248 int ret = -1;
249
250 if (0 == (mutex)->m_lock_debug) {
251 (mutex)->m_lock_debug++;
252 (mutex)->m_lock_file = file;
253 (mutex)->m_lock_line = line;
254 ret = 0;
255 } else {
256 if (opal_mutex_check_locks) {
257 opal_output(0, "Warning -- during trylock, mutex already locked at %s:%d "
258 "now at %s:%d",
259 file, line,
260 (mutex)->m_lock_file,
261 (mutex)->m_lock_line);
262 }
263 }
264
265 return ret;
266 }
267 #define OPAL_THREAD_TRYLOCK(mutex) opal_thread_debug_trylock(mutex, __FILE__, __LINE__)
268 #else
269 #define OPAL_THREAD_TRYLOCK(mutex) 0
270 #endif
271
272
273 /**
274 * Unlock a mutex if opal_using_threads() says that multiple threads
275 * may be active in the process.
276 *
277 * @param mutex Pointer to a opal_mutex_t to unlock.
278 *
279 * If there is a possibility that multiple threads are running in the
280 * process (as determined by opal_using_threads()), this function will
281 * unlock the mutex.
282 *
283 * If there is no possibility that multiple threads are running in the
284 * process, return immediately without modifying the mutex.
285 */
286 #if OPAL_ENABLE_MULTI_THREADS
287 #define OPAL_THREAD_UNLOCK(mutex) \
288 do { \
289 if (opal_using_threads()) { \
290 opal_mutex_unlock(mutex); \
291 } \
292 } while (0)
293 #elif OPAL_ENABLE_DEBUG
294 #define OPAL_THREAD_UNLOCK(mutex) \
295 do { \
296 (mutex)->m_lock_debug--; \
297 if (opal_mutex_check_locks && 0 > (mutex)->m_lock_debug) { \
298 opal_output(0, "Warning -- mutex was double locked from %s:%d", \
299 __FILE__, __LINE__); \
300 } else if (opal_mutex_check_locks && 0 > (mutex)->m_lock_debug) { \
301 opal_output(0, "Warning -- mutex not locked from %s:%d", \
302 __FILE__, __LINE__); \
303 } else { \
304 (mutex)->m_lock_file = NULL; \
305 (mutex)->m_lock_line = 0; \
306 } \
307 } while (0)
308 #else
309 #define OPAL_THREAD_UNLOCK(mutex)
310 #endif
311
312
313 /**
314 * Lock a mutex if opal_using_threads() says that multiple threads may
315 * be active in the process for the duration of the specified action.
316 *
317 * @param mutex Pointer to a opal_mutex_t to lock.
318 * @param action A scope over which the lock is held.
319 *
320 * If there is a possibility that multiple threads are running in the
321 * process (as determined by opal_using_threads()), this function will
322 * acquire the lock before invoking the specified action and release
323 * it on return.
324 *
325 * If there is no possibility that multiple threads are running in the
326 * process, invoke the action without acquiring the lock.
327 */
328
329 #if OPAL_ENABLE_MULTI_THREADS
330 #define OPAL_THREAD_SCOPED_LOCK(mutex, action) \
331 do { \
332 if(opal_using_threads()) { \
333 opal_mutex_lock(mutex); \
334 (action); \
335 opal_mutex_unlock(mutex); \
336 } else { \
337 (action); \
338 } \
339 } while (0)
340 #elif OPAL_ENABLE_DEBUG
341 #define OPAL_THREAD_SCOPED_LOCK(mutex, action) \
342 do { \
343 if (0 != (mutex)->m_lock_debug) { \
344 opal_output(0, "scoped_lock: Warning -- mutex already " \
345 "locked at %s:%d, now at %s:%d", \
346 __FILE__, __LINE__, \
347 (mutex)->m_lock_file, \
348 (mutex)->m_lock_line); \
349 } \
350 (mutex)->m_lock_debug--; \
351 (action); \
352 (mutex)->m_lock_debug++; \
353 } while (0)
354 #else
355 #define OPAL_THREAD_SCOPED_LOCK(mutex, action) (action)
356 #endif
357
358 /**
359 * Use an atomic operation for increment/decrement if opal_using_threads()
360 * indicates that threads are in use by the application or library.
361 */
362
363 #if OPAL_ENABLE_MULTI_THREADS
364 #define OPAL_THREAD_ADD32(x,y) \
365 (opal_using_threads() ? opal_atomic_add_32(x,y) : (*x += y))
366 #else
367 #define OPAL_THREAD_ADD32(x,y) (*x += y)
368 #endif
369
370 #if OPAL_ENABLE_MULTI_THREADS
371 #define OPAL_THREAD_ADD64(x,y) \
372 (opal_using_threads() ? opal_atomic_add_64(x,y) : (*x += y))
373 #else
374 #define OPAL_THREAD_ADD64(x,y) (*x += y)
375 #endif
376
377 #if OPAL_ENABLE_MULTI_THREADS
378 #define OPAL_THREAD_ADD_SIZE_T(x,y) \
379 (opal_using_threads() ? opal_atomic_add_size_t(x,y) : (*x += y))
380 #else
381 #define OPAL_THREAD_ADD_SIZE_T(x,y) (*x += y)
382 #endif
383
384 #define OPAL_CMPSET(x, y, z) ((*(x) == (y)) ? ((*(x) = (z)), 1) : 0)
385
386 #if OPAL_ENABLE_MULTI_THREADS
387 # if OPAL_HAVE_ATOMIC_CMPSET_32
388 # define OPAL_ATOMIC_CMPSET_32(x, y, z) \
389 (opal_using_threads() ? opal_atomic_cmpset_32(x, y, z) : OPAL_CMPSET(x, y, z))
390 # endif
391 # if OPAL_HAVE_ATOMIC_CMPSET_64
392 # define OPAL_ATOMIC_CMPSET_64(x, y, z) \
393 (opal_using_threads() ? opal_atomic_cmpset_64(x, y, z) : OPAL_CMPSET(x, y, z))
394 # endif
395 # if OPAL_HAVE_ATOMIC_CMPSET_32 || OPAL_HAVE_ATOMIC_CMPSET_64
396 # define OPAL_ATOMIC_CMPSET(x, y, z) \
397 (opal_using_threads() ? opal_atomic_cmpset(x, y, z) : OPAL_CMPSET(x, y, z))
398 # endif
399 #else
400 # if OPAL_HAVE_ATOMIC_CMPSET_32
401 # define OPAL_ATOMIC_CMPSET_32(x, y, z) OPAL_CMPSET(x, y, z)
402 # endif
403 # if OPAL_HAVE_ATOMIC_CMPSET_64
404 # define OPAL_ATOMIC_CMPSET_64(x, y, z) OPAL_CMPSET(x, y, z)
405 # endif
406 # if OPAL_HAVE_ATOMIC_CMPSET_32 || OPAL_HAVE_ATOMIC_CMPSET_64
407 # define OPAL_ATOMIC_CMPSET(x, y, z) OPAL_CMPSET(x, y, z)
408 # endif
409 #endif
410
411 END_C_DECLS
412
413 #endif /* OPAL_MUTEX_H */
opal_mutex_lock
static void opal_mutex_lock(opal_mutex_t *mutex)
Acquire a mutex.
output.h
OPAL output stream facility.
opal_mutex_atomic_trylock
static int opal_mutex_atomic_trylock(opal_mutex_t *mutex)
Try to acquire a mutex using atomic operations.
opal_mutex_atomic_unlock
static void opal_mutex_atomic_unlock(opal_mutex_t *mutex)
Release a mutex using atomic operations.
opal_mutex_t
Definition: mutex_unix.h:53
opal_mutex_trylock
static int opal_mutex_trylock(opal_mutex_t *mutex)
Try to acquire a mutex.
mutex_unix.h
Mutual exclusion functions: Unix implementation.
mutex_windows.h
Mutual exclusion functions: Windows implementation.
opal_mutex_unlock
static void opal_mutex_unlock(opal_mutex_t *mutex)
Release a mutex.
opal_output
OPAL_DECLSPEC void opal_output(int output_id, const char *format,...) __opal_attribute_format__(__printf__
Main function to send output to a stream.
opal_set_using_threads
static bool opal_set_using_threads(bool have)
Set whether the process is using multiple threads or not.
Definition: mutex.h:175
atomic.h
Atomic operations.
opal_mutex_atomic_lock
static void opal_mutex_atomic_lock(opal_mutex_t *mutex)
Acquire a mutex using atomic operations.