55 * Copyright (c) 2014 The University of Tennessee and The University
66 * of Tennessee Research Foundation. All rights
77 * reserved.
8+ * Copyright (c) 2020 Google, LLC. All rights reserved.
89 * $COPYRIGHT$
910 *
1011 * Additional copyrights may follow
@@ -44,19 +45,34 @@ static int vader_check_reg (mca_rcache_base_registration_t *reg, void *ctx)
4445{
4546 vader_check_reg_ctx_t * vader_ctx = (vader_check_reg_ctx_t * ) ctx ;
4647
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 ) {
4949 /* ignore this registration */
5050 return OPAL_SUCCESS ;
5151 }
5252
5353 vader_ctx -> reg [0 ] = reg ;
5454
5555 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+ }
5764 return 1 ;
5865 }
5966
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. */
6076 return 2 ;
6177}
6278
@@ -67,8 +83,12 @@ void vader_return_registration (mca_rcache_base_registration_t *reg, struct mca_
6783
6884 ref_count = opal_atomic_add_fetch_32 (& reg -> ref_count , -1 );
6985 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
7292 opal_memchecker_base_mem_noaccess (reg -> rcache_context , (uintptr_t )(reg -> bound - reg -> base ));
7393 (void )xpmem_detach (reg -> rcache_context );
7494 OBJ_RELEASE (reg );
@@ -100,16 +120,9 @@ mca_rcache_base_registration_t *vader_get_registation (struct mca_btl_base_endpo
100120 /* several segments may match the base pointer */
101121 rc = mca_rcache_base_vma_iterate (vma_module , (void * ) base , bound - base , true, vader_check_reg , & check_ctx );
102122 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 );
113126 reg = NULL ;
114127 }
115128
@@ -151,25 +164,39 @@ mca_rcache_base_registration_t *vader_get_registation (struct mca_btl_base_endpo
151164 return reg ;
152165}
153166
167+ struct vader_cleanup_reg_ctx {
168+ mca_btl_vader_endpoint_t * ep ;
169+ opal_list_t * registrations ;
170+ };
171+
154172static int mca_btl_vader_endpoint_xpmem_rcache_cleanup (mca_rcache_base_registration_t * reg , void * ctx )
155173{
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 );
161177 }
162178
163179 return OPAL_SUCCESS ;
164180}
165181
166182void mca_btl_vader_xpmem_cleanup_endpoint (struct mca_btl_base_endpoint_t * ep )
167183{
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+
168190 /* clean out the registration cache */
169191 (void ) mca_rcache_base_vma_iterate (mca_btl_vader_component .vma_module ,
170192 NULL , (size_t ) -1 , true,
171193 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+
173200 if (ep -> segment_base ) {
174201 xpmem_release (ep -> segment_data .xpmem .apid );
175202 ep -> segment_data .xpmem .apid = 0 ;
0 commit comments