From ca116e3cf3d7445dd7cff34ceec553614e511207 Mon Sep 17 00:00:00 2001 From: George Bosilca Date: Fri, 3 Mar 2006 20:51:36 +0000 Subject: [PATCH] Where we create a duplicate data-type for the get_content MPI function we have to attach the args from the old data-type. As this args are only read-only, I don't want to have several copies around, so I add a reference count to them and simply attach them to the new datatype. The args array now get freed only when the last reference dissapear. This commit was SVN r9191. --- ompi/datatype/datatype.h | 2 ++ ompi/datatype/dt_args.c | 33 ++++++++++++++++++++++++++++----- ompi/mpi/c/type_get_contents.c | 1 + 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/ompi/datatype/datatype.h b/ompi/datatype/datatype.h index ed87e0b738..56253a4dfa 100644 --- a/ompi/datatype/datatype.h +++ b/ompi/datatype/datatype.h @@ -217,6 +217,8 @@ OMPI_DECLSPEC int32_t ompi_ddt_set_args( ompi_datatype_t* pData, int32_t ci, int32_t ** i, int32_t ca, long* a, int32_t cd, ompi_datatype_t** d,int32_t type); +OMPI_DECLSPEC int32_t ompi_ddt_copy_args( const ompi_datatype_t* source_data, + ompi_datatype_t* dest_data ); OMPI_DECLSPEC int32_t ompi_ddt_release_args( ompi_datatype_t* pData ); /* diff --git a/ompi/datatype/dt_args.c b/ompi/datatype/dt_args.c index 4ed7022f0a..fe9e069122 100644 --- a/ompi/datatype/dt_args.c +++ b/ompi/datatype/dt_args.c @@ -32,6 +32,7 @@ __ompi_ddt_create_from_args( int32_t* i, MPI_Aint* a, MPI_Datatype* d, int32_t type ); typedef struct __dt_args { + int ref_count; int create_type; size_t total_pack_size; int ci; @@ -64,9 +65,10 @@ typedef struct __dt_args { } \ if( pArgs->cd == 0 ) pArgs->d = NULL; \ else pArgs->d = (MPI_Datatype*)buf; \ - (PDATA)->args = (void*)pArgs; \ + pArgs->ref_count = 1; \ pArgs->total_pack_size = (4 + (IC)) * sizeof(int) + \ (AC) * sizeof(MPI_Aint) + (DC) * sizeof(int); \ + (PDATA)->args = (void*)pArgs; \ (PDATA)->packed_description = NULL; \ } while(0) @@ -288,6 +290,20 @@ int32_t ompi_ddt_get_args( const ompi_datatype_t* pData, int32_t which, return MPI_SUCCESS; } +int32_t ompi_ddt_copy_args( const ompi_datatype_t* source_data, + ompi_datatype_t* dest_data ) +{ + ompi_ddt_args_t* pArgs = source_data->args; + + /* If required then increase the reference count of the arguments. This avoid us + * to make one more copy for a read only piece of memory. + */ + assert( NULL != source_data->args ); + pArgs->ref_count++; + dest_data->args = pArgs; + return MPI_SUCCESS; +} + /* In the dt_add function we increase the reference count for all datatypes * (except for the predefined ones) that get added to another datatype. This * insure that they cannot get released until all the references to them @@ -298,12 +314,19 @@ int32_t ompi_ddt_release_args( ompi_datatype_t* pData ) int i; ompi_ddt_args_t* pArgs = pData->args; - for( i = 0; i < pArgs->cd; i++ ) { - if( !(pArgs->d[i]->flags & DT_FLAG_PREDEFINED) ) { - OBJ_RELEASE( pArgs->d[i] ); + assert( 0 < pArgs->ref_count ); + pArgs->ref_count--; + if( 0 == pArgs->ref_count ) { + /* There are some duplicated datatypes around that have a pointer to this + * args. We will release them only when the last datatype will dissapear. + */ + for( i = 0; i < pArgs->cd; i++ ) { + if( !(pArgs->d[i]->flags & DT_FLAG_PREDEFINED) ) { + OBJ_RELEASE( pArgs->d[i] ); + } } + free( pData->args ); } - free( pData->args ); pData->args = NULL; return OMPI_SUCCESS; diff --git a/ompi/mpi/c/type_get_contents.c b/ompi/mpi/c/type_get_contents.c index ed78a15921..37ffb0884e 100644 --- a/ompi/mpi/c/type_get_contents.c +++ b/ompi/mpi/c/type_get_contents.c @@ -74,6 +74,7 @@ int MPI_Type_get_contents(MPI_Datatype mtype, OMPI_ERRHANDLER_RETURN( MPI_ERR_INTERN, MPI_COMM_WORLD, MPI_ERR_INTERN, FUNC_NAME ); } + ompi_ddt_copy_args( array_of_datatypes[i], newtype ); array_of_datatypes[i] = newtype; } }