OpenMPI  0.1.1
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 */
static void opal_mutex_lock(opal_mutex_t *mutex)
Acquire a mutex.
OPAL output stream facility.
static int opal_mutex_atomic_trylock(opal_mutex_t *mutex)
Try to acquire a mutex using atomic operations.
static void opal_mutex_atomic_unlock(opal_mutex_t *mutex)
Release a mutex using atomic operations.
Definition: mutex_unix.h:53
static int opal_mutex_trylock(opal_mutex_t *mutex)
Try to acquire a mutex.
Mutual exclusion functions: Unix implementation.
Mutual exclusion functions: Windows implementation.
static void opal_mutex_unlock(opal_mutex_t *mutex)
Release a mutex.
OPAL_DECLSPEC void opal_output(int output_id, const char *format,...) __opal_attribute_format__(__printf__
Main function to send output to a stream.
static bool opal_set_using_threads(bool have)
Set whether the process is using multiple threads or not.
Definition: mutex.h:175
Atomic operations.
static void opal_mutex_atomic_lock(opal_mutex_t *mutex)
Acquire a mutex using atomic operations.