5
5
* Copyright (c) 2014 The University of Tennessee and The University
6
6
* of Tennessee Research Foundation. All rights
7
7
* reserved.
8
+ * Copyright (c) 2020 Google, LLC. All rights reserved.
8
9
* $COPYRIGHT$
9
10
*
10
11
* Additional copyrights may follow
@@ -44,19 +45,34 @@ static int vader_check_reg (mca_rcache_base_registration_t *reg, void *ctx)
44
45
{
45
46
vader_check_reg_ctx_t * vader_ctx = (vader_check_reg_ctx_t * ) ctx ;
46
47
47
- if ((intptr_t ) reg -> alloc_base != vader_ctx -> ep -> peer_smp_rank ||
48
- (reg -> flags & MCA_RCACHE_FLAGS_PERSIST )) {
48
+ if ((intptr_t ) reg -> alloc_base != vader_ctx -> ep -> peer_smp_rank ) {
49
49
/* ignore this registration */
50
50
return OPAL_SUCCESS ;
51
51
}
52
52
53
53
vader_ctx -> reg [0 ] = reg ;
54
54
55
55
if (vader_ctx -> bound <= (uintptr_t ) reg -> bound && vader_ctx -> base >= (uintptr_t ) reg -> base ) {
56
- opal_atomic_add (& reg -> ref_count , 1 );
56
+ if (0 == opal_atomic_fetch_add_32 (& reg -> ref_count , 1 )) {
57
+ /* registration is being deleted by a thread in vader_return_registration. the
58
+ * VMA tree implementation will block in mca_rcache_delete until we finish
59
+ * iterating over the VMA tree so it is safe to just ignore this registration
60
+ * and continue. */
61
+ vader_ctx -> reg [0 ] = NULL ;
62
+ return OPAL_SUCCESS ;
63
+ }
57
64
return 1 ;
58
65
}
59
66
67
+ if (MCA_RCACHE_FLAGS_INVALID & opal_atomic_fetch_or_32 (& reg -> flags , MCA_RCACHE_FLAGS_INVALID )) {
68
+ /* another thread has already marked this registration as invalid. ignore and continue. */
69
+ vader_ctx -> reg [0 ] = NULL ;
70
+ return OPAL_SUCCESS ;
71
+ }
72
+
73
+ /* let the caller know we found an overlapping registration that can be coalesced into
74
+ * the requested interval. the caller will remove the last reference and delete the
75
+ * registration. */
60
76
return 2 ;
61
77
}
62
78
@@ -67,8 +83,12 @@ void vader_return_registration (mca_rcache_base_registration_t *reg, struct mca_
67
83
68
84
ref_count = opal_atomic_add_fetch_32 (& reg -> ref_count , -1 );
69
85
if (OPAL_UNLIKELY (0 == ref_count && !(reg -> flags & MCA_RCACHE_FLAGS_PERSIST ))) {
70
- mca_rcache_base_vma_delete (vma_module , reg );
71
-
86
+ #if OPAL_DEBUG
87
+ int ret = mca_rcache_base_vma_delete (vma_module , reg );
88
+ assert (OPAL_SUCCESS == ret );
89
+ #else
90
+ (void ) mca_rcache_base_vma_delete (vma_module , reg );
91
+ #endif
72
92
opal_memchecker_base_mem_noaccess (reg -> rcache_context , (uintptr_t )(reg -> bound - reg -> base ));
73
93
(void )xpmem_detach (reg -> rcache_context );
74
94
OBJ_RELEASE (reg );
@@ -100,16 +120,9 @@ mca_rcache_base_registration_t *vader_get_registation (struct mca_btl_base_endpo
100
120
/* several segments may match the base pointer */
101
121
rc = mca_rcache_base_vma_iterate (vma_module , (void * ) base , bound - base , true, vader_check_reg , & check_ctx );
102
122
if (2 == rc ) {
103
- /* remove this pointer from the rcache and decrement its reference count
104
- (so it is detached later) */
105
- mca_rcache_base_vma_delete (vma_module , reg );
106
-
107
- /* start the new segment from the lower of the two bases */
108
- base = (uintptr_t ) reg -> base < base ? (uintptr_t ) reg -> base : base ;
109
-
110
- /* remove the last reference to this registration */
111
- vader_return_registration (reg , ep );
112
-
123
+ bound = bound < (uintptr_t ) reg -> bound ? (uintptr_t ) reg -> bound : bound ;
124
+ base = base > (uintptr_t ) reg -> base ? (uintptr_t ) reg -> base : base ;
125
+ vader_return_registration (reg , ep );
113
126
reg = NULL ;
114
127
}
115
128
@@ -151,25 +164,39 @@ mca_rcache_base_registration_t *vader_get_registation (struct mca_btl_base_endpo
151
164
return reg ;
152
165
}
153
166
167
+ struct vader_cleanup_reg_ctx {
168
+ mca_btl_vader_endpoint_t * ep ;
169
+ opal_list_t * registrations ;
170
+ };
171
+
154
172
static int mca_btl_vader_endpoint_xpmem_rcache_cleanup (mca_rcache_base_registration_t * reg , void * ctx )
155
173
{
156
- mca_btl_vader_endpoint_t * ep = (mca_btl_vader_endpoint_t * ) ctx ;
157
- if ((intptr_t ) reg -> alloc_base == ep -> peer_smp_rank ) {
158
- /* otherwise dereg will fail on assert */
159
- reg -> ref_count = 0 ;
160
- OBJ_RELEASE (reg );
174
+ struct vader_cleanup_reg_ctx * cleanup_ctx = (struct vader_cleanup_reg_ctx * ) ctx ;
175
+ if ((intptr_t ) reg -> alloc_base == cleanup_ctx -> ep -> peer_smp_rank ) {
176
+ opal_list_append (cleanup_ctx -> registrations , & reg -> super .super );
161
177
}
162
178
163
179
return OPAL_SUCCESS ;
164
180
}
165
181
166
182
void mca_btl_vader_xpmem_cleanup_endpoint (struct mca_btl_base_endpoint_t * ep )
167
183
{
184
+ mca_rcache_base_registration_t * reg ;
185
+ opal_list_t registrations ;
186
+ struct vader_cleanup_reg_ctx cleanup_ctx = {.ep = ep , .registrations = & registrations };
187
+
188
+ OBJ_CONSTRUCT (& registrations , opal_list_t );
189
+
168
190
/* clean out the registration cache */
169
191
(void ) mca_rcache_base_vma_iterate (mca_btl_vader_component .vma_module ,
170
192
NULL , (size_t ) -1 , true,
171
193
mca_btl_vader_endpoint_xpmem_rcache_cleanup ,
172
- (void * ) ep );
194
+ (void * ) & cleanup_ctx );
195
+ while (NULL != (reg = (mca_rcache_base_registration_t * ) opal_list_remove_first (& registrations ))) {
196
+ vader_return_registration (reg , ep );
197
+ }
198
+ OBJ_DESTRUCT (& registrations );
199
+
173
200
if (ep -> segment_base ) {
174
201
xpmem_release (ep -> segment_data .xpmem .apid );
175
202
ep -> segment_data .xpmem .apid = 0 ;
0 commit comments