5
5
* reserved.
6
6
* Copyright (c) 2016 Los Alamos National Security, LLC. All rights
7
7
* reserved.
8
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
8
9
* $COPYRIGHT$
9
10
*
10
11
* Additional copyrights may follow
13
14
*/
14
15
#include "opal/sys/atomic.h"
15
16
#include "opal/threads/condition.h"
17
+ #include "opal/constants.h"
18
+ #include "opal/prefetch.h"
16
19
#include <pthread.h>
17
20
18
21
BEGIN_C_DECLS
@@ -33,17 +36,29 @@ typedef struct ompi_wait_sync_t {
33
36
34
37
#define WAIT_SYNC_RELEASE (sync ) \
35
38
if (opal_using_threads()) { \
39
+ pthread_mutex_lock(&(sync)->lock); \
36
40
pthread_cond_destroy(&(sync)->condition); \
41
+ pthread_mutex_unlock(&(sync)->lock); \
37
42
pthread_mutex_destroy(&(sync)->lock); \
38
43
}
39
44
40
- #define WAIT_SYNC_SIGNAL (sync ) \
45
+ #define WAIT_SYNC_LOCK (sync ) \
41
46
if (opal_using_threads()) { \
42
- pthread_mutex_lock(&(sync->lock)); \
43
- pthread_cond_signal(&sync->condition); \
44
- pthread_mutex_unlock(&(sync->lock)); \
47
+ pthread_mutex_lock(&((sync)->lock)); \
45
48
}
46
49
50
+ #define WAIT_SYNC_SIGNAL_UNLOCK (sync ) \
51
+ if (opal_using_threads()) { \
52
+ pthread_cond_signal(&((sync)->condition)); \
53
+ pthread_mutex_unlock(&((sync)->lock)); \
54
+ }
55
+
56
+ #define WAIT_SYNC_UNLOCK (sync ) \
57
+ if (opal_using_threads()) { \
58
+ pthread_mutex_unlock(&((sync)->lock)); \
59
+ }
60
+
61
+
47
62
OPAL_DECLSPEC int sync_wait_mt (ompi_wait_sync_t * sync );
48
63
static inline int sync_wait_st (ompi_wait_sync_t * sync )
49
64
{
@@ -75,16 +90,38 @@ static inline int sync_wait_st (ompi_wait_sync_t *sync)
75
90
*/
76
91
static inline void wait_sync_update (ompi_wait_sync_t * sync , int updates , int status )
77
92
{
93
+ /* Fast path: if we can decrement the sync->count without
94
+ * dropping it to 0 - just return
95
+ * Consider that there might be concurrent decrements
96
+ */
97
+ if ( OPAL_LIKELY (OPAL_SUCCESS == status ) ) {
98
+ /* we know that our contribution is not yet there
99
+ * so we can safely check if the count will still be above 0
100
+ * after the change */
101
+ while ( (sync -> count - updates > 0 ) ){
102
+ if ( OPAL_ATOMIC_CMPSET_32 (& sync -> count , sync -> count , sync -> count - updates ) ){
103
+ /* fastpath succeeds */
104
+ return ;
105
+ }
106
+ }
107
+ }
108
+
109
+ /* Slow path */
110
+ WAIT_SYNC_LOCK (sync );
111
+
78
112
if ( OPAL_LIKELY (OPAL_SUCCESS == status ) ) {
79
113
if ( 0 != (OPAL_THREAD_ADD32 (& sync -> count , - updates )) ) {
80
- return ;
114
+ goto unlock ;
81
115
}
82
116
} else {
83
117
/* this is an error path so just use the atomic */
84
118
opal_atomic_swap_32 (& sync -> count , 0 );
85
119
sync -> status = OPAL_ERROR ;
86
120
}
87
- WAIT_SYNC_SIGNAL (sync );
121
+ WAIT_SYNC_SIGNAL_UNLOCK (sync );
122
+ return ;
123
+ unlock :
124
+ WAIT_SYNC_UNLOCK (sync );
88
125
}
89
126
90
127
END_C_DECLS
0 commit comments