@@ -65,6 +65,7 @@ static void parsec_data_construct(parsec_data_t* obj )
6565 obj -> preferred_device = -1 ;
6666 obj -> key = 0 ;
6767 obj -> nb_elts = 0 ;
68+ obj -> nb_copies = 0 ;
6869 for ( uint32_t i = 0 ; i < parsec_nb_devices ;
6970 obj -> device_copies [i ] = NULL , i ++ );
7071 obj -> dc = NULL ;
@@ -99,11 +100,12 @@ static void parsec_data_destruct(parsec_data_t* obj )
99100 * GPU copies are normally stored in LRU lists, and must be
100101 * destroyed by the release list to free the memory on the device
101102 */
102- PARSEC_OBJ_RELEASE ( copy );
103+ PARSEC_DATA_COPY_RELEASE ( copy );
103104 }
104105 }
105106 assert (NULL == obj -> device_copies [i ]);
106107 }
108+ assert (0 == obj -> nb_copies );
107109}
108110
109111PARSEC_OBJ_CLASS_INSTANCE (parsec_data_t , parsec_object_t ,
@@ -161,8 +163,8 @@ void parsec_data_delete(parsec_data_t* data)
161163
162164inline int
163165parsec_data_copy_attach (parsec_data_t * data ,
164- parsec_data_copy_t * copy ,
165- uint8_t device )
166+ parsec_data_copy_t * copy ,
167+ uint8_t device )
166168{
167169 assert (NULL == copy -> original );
168170 assert (NULL == copy -> older );
@@ -175,6 +177,7 @@ parsec_data_copy_attach(parsec_data_t* data,
175177 copy -> older = NULL ;
176178 return PARSEC_ERROR ;
177179 }
180+ parsec_atomic_fetch_add_int32 (& data -> nb_copies , 1 );
178181 PARSEC_OBJ_RETAIN (data );
179182 return PARSEC_SUCCESS ;
180183}
@@ -192,6 +195,7 @@ int parsec_data_copy_detach(parsec_data_t* data,
192195 return PARSEC_ERR_NOT_FOUND ;
193196 }
194197 data -> device_copies [device ] = copy -> older ;
198+ parsec_atomic_fetch_add_int32 (& data -> nb_copies , -1 );
195199
196200 copy -> original = NULL ;
197201 copy -> older = NULL ;
@@ -221,7 +225,7 @@ parsec_data_copy_t* parsec_data_copy_new(parsec_data_t* data, uint8_t device,
221225 }
222226 copy -> flags = flags ;
223227 if ( PARSEC_SUCCESS != parsec_data_copy_attach (data , copy , device ) ) {
224- PARSEC_OBJ_RELEASE (copy );
228+ PARSEC_DATA_COPY_RELEASE (copy );
225229 return NULL ;
226230 }
227231 copy -> dtt = dtt ;
@@ -330,6 +334,12 @@ int parsec_data_start_transfer_ownership_to_copy(parsec_data_t* data,
330334 copy = data -> device_copies [device ];
331335 assert ( NULL != copy );
332336
337+ if ( valid_copy == device ) {
338+ PARSEC_DEBUG_VERBOSE (10 , parsec_debug_output ,
339+ "DEV[%d]: already has ownership of data %p to copy %p in mode %d" ,
340+ device , data , copy , access_mode );
341+ goto bookkeeping ;
342+ }
333343 PARSEC_DEBUG_VERBOSE (10 , parsec_debug_output ,
334344 "DEV[%d]: start transfer ownership of data %p to copy %p in mode %d" ,
335345 device , data , copy , access_mode );
@@ -417,6 +427,7 @@ int parsec_data_start_transfer_ownership_to_copy(parsec_data_t* data,
417427 }
418428 }
419429
430+ bookkeeping :
420431 if ( PARSEC_FLOW_ACCESS_READ & access_mode ) {
421432 copy -> readers ++ ;
422433 }
@@ -435,40 +446,52 @@ int parsec_data_start_transfer_ownership_to_copy(parsec_data_t* data,
435446 return valid_copy ;
436447}
437448
438- static char dump_coherency_codex (parsec_data_coherency_t state )
439- {
440- if ( PARSEC_DATA_COHERENCY_INVALID == state ) return 'I' ;
441- if ( PARSEC_DATA_COHERENCY_OWNED == state ) return 'O' ;
442- if ( PARSEC_DATA_COHERENCY_EXCLUSIVE == state ) return 'E' ;
443- if ( PARSEC_DATA_COHERENCY_SHARED == state ) return 'S' ;
444- return 'X' ;
445- }
446-
447- void parsec_dump_data_copy (parsec_data_copy_t * copy )
449+ void parsec_data_copy_dump (parsec_data_copy_t * copy )
448450{
449- parsec_debug_verbose (0 , 0 , "- [%d]: copy %p state %c readers %d version %u\n" ,
450- (int )copy -> device_index , copy , dump_coherency_codex (copy -> coherency_state ), copy -> readers , copy -> version );
451+ char * tranfer = "---" , flags [] = "----" , * coherency = "undef" ;
452+ switch (copy -> data_transfer_status ) {
453+ case PARSEC_DATA_STATUS_NOT_TRANSFER : tranfer = "no" ; break ;
454+ case PARSEC_DATA_STATUS_UNDER_TRANSFER : tranfer = "yes" ; break ;
455+ case PARSEC_DATA_STATUS_COMPLETE_TRANSFER : tranfer = "no" ; break ;
456+ }
457+ if (copy -> flags & PARSEC_DATA_FLAG_ARENA ) flags [0 ] = 'A' ;
458+ if (copy -> flags & PARSEC_DATA_FLAG_TRANSIT ) flags [1 ] = 'T' ;
459+ if (copy -> flags & PARSEC_DATA_FLAG_PARSEC_MANAGED ) flags [2 ] = 'M' ;
460+ if (copy -> flags & PARSEC_DATA_FLAG_PARSEC_OWNED ) flags [3 ] = 'O' ;
461+
462+ if ( PARSEC_DATA_COHERENCY_INVALID == copy -> coherency_state ) coherency = "invalid" ;
463+ if ( PARSEC_DATA_COHERENCY_OWNED == copy -> coherency_state ) coherency = "owned" ;
464+ if ( PARSEC_DATA_COHERENCY_EXCLUSIVE == copy -> coherency_state ) coherency = "exclusive" ;
465+ if ( PARSEC_DATA_COHERENCY_SHARED == copy -> coherency_state ) coherency = "shared" ;
466+
467+ parsec_debug_verbose (0 , 0 , "%s [%d]: copy %p [ref %d] coherency %s readers %d version %u transit %s flags %s\n"
468+ " older %p orig %p arena %p dev_priv %p\n" ,
469+ ((NULL != copy -> original ) && (copy -> original -> owner_device == copy -> device_index )) ? "*" : " " ,
470+ (int )copy -> device_index , copy , copy -> super .super .obj_reference_count , coherency , copy -> readers , copy -> version , tranfer , flags ,
471+ (void * )copy -> older , (void * )copy -> original , (void * )copy -> arena_chunk , copy -> device_private );
451472}
452473
453- void parsec_dump_data (parsec_data_t * data )
474+ void parsec_data_dump (parsec_data_t * data )
454475{
455- parsec_debug_verbose (0 , 0 , "data %p key %lu owner %d\n" , data , data -> key , data -> owner_device );
476+ parsec_debug_verbose (0 , 0 , "data %p [ref %d] key %lu owner dev %d pref dev %d copies %d dc %p [# elems %zu]\n" ,
477+ data , data -> super .obj_reference_count , data -> key , data -> owner_device , data -> preferred_device , data -> nb_copies ,
478+ (void * )data -> dc , data -> nb_elts );
456479
457480 for ( uint32_t i = 0 ; i < parsec_nb_devices ; i ++ ) {
458481 if ( NULL != data -> device_copies [i ])
459- parsec_dump_data_copy (data -> device_copies [i ]);
482+ parsec_data_copy_dump (data -> device_copies [i ]);
460483 }
461484}
462485
463486parsec_data_copy_t *
464487parsec_data_get_copy (parsec_data_t * data , uint32_t device )
465488{
466- return PARSEC_DATA_GET_COPY (data , device );
489+ return PARSEC_DATA_GET_COPY (data , device );
467490}
468491
469492void parsec_data_copy_release (parsec_data_copy_t * copy )
470493{
471- /* TODO: Move the copy back to the CPU before destroying it */
494+ /* TODO: Move the copy back to the CPU before destroying it */
472495 PARSEC_DATA_COPY_RELEASE (copy );
473496}
474497
@@ -509,7 +532,7 @@ parsec_data_create( parsec_data_t **holder,
509532
510533 if ( !parsec_atomic_cas_ptr (holder , NULL , data ) ) {
511534 parsec_data_copy_detach (data , data_copy , 0 );
512- PARSEC_OBJ_RELEASE (data_copy );
535+ PARSEC_DATA_COPY_RELEASE (data_copy );
513536 data = * holder ;
514537 }
515538 } else {
@@ -560,3 +583,38 @@ parsec_data_destroy( parsec_data_t *data )
560583#endif
561584 PARSEC_OBJ_RELEASE (data );
562585}
586+
587+ #include "parsec/utils/debug.h"
588+
589+ int parsec_data_release_self_contained_data (parsec_data_t * data )
590+ {
591+ if (data -> super .obj_reference_count == data -> nb_copies ) return 0 ;
592+ parsec_data_copy_t * copy ;
593+ PARSEC_DEBUG_VERBOSE (1 , parsec_debug_output , "Examine the status of data %p with %d copies and refcounts at %s:%d\n" ,
594+ data , data -> nb_copies , __FILE__ , __LINE__ );
595+ /* this data is only referenced by it's own copies. If these copies are also only referenced by
596+ * data, then we can release them all.
597+ */
598+ for ( uint32_t i = 0 ; i < parsec_nb_devices ; i ++ ) {
599+ if (NULL == (copy = data -> device_copies [i ])) continue ;
600+ if ( copy -> super .super .obj_reference_count > 1 )
601+ return 0 ;
602+ }
603+ PARSEC_DEBUG_VERBOSE (1 , parsec_debug_output , "Force the release of data %p at %s:%d" , (COPY ), __FILE__ , __LINE__ );
604+ for ( uint32_t i = 0 ; i < parsec_nb_devices ; i ++ ) {
605+ if (NULL == (copy = data -> device_copies [i ])) continue ;
606+ assert (1 == copy -> super .super .obj_reference_count );
607+ if ( 0 == copy -> device_index ) {
608+ PARSEC_OBJ_RELEASE (copy );
609+ assert (NULL == copy );
610+ } else {
611+ /* Do not release data copies that do not belong to the CPU or really bad things will happen.
612+ * Only the device manager can release these copies, the best we can do here is to detach them
613+ * from the data and eventually release their memory.
614+ */
615+ parsec_data_copy_detach (data , copy , copy -> device_index );
616+ }
617+ }
618+ return 1 ;
619+ }
620+
0 commit comments