1+ /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
12/*
23 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
34 * University Research and Technology
1415 * reserved.
1516 * Copyright (c) 2017 Research Organization for Information Science
1617 * and Technology (RIST). All rights reserved.
18+ * Copyright (c) 2018-2021 Triad National Security, LLC. All rights
19+ * reserved.
1720 * $COPYRIGHT$
1821 *
1922 * Additional copyrights may follow
240243#include "ompi/datatype/ompi_datatype.h"
241244#include "ompi/communicator/communicator.h" /* ompi_communicator_t generated in [COPY|DELETE]_ATTR_CALLBACKS */
242245#include "ompi/win/win.h" /* ompi_win_t generated in [COPY|DELETE]_ATTR_CALLBACKS */
246+ #include "ompi/instance/instance.h"
243247#include "ompi/mpi/fortran/base/fint_2_int.h"
244248
249+
245250/*
246251 * Macros
247252 */
256261#define attr_datatype_f d_f_to_c_index
257262#define attr_win_f w_f_to_c_index
258263
259- #define CREATE_KEY (key ) opal_bitmap_find_and_set_first_unset_bit(key_bitmap, (key))
264+ #define CREATE_KEY (key ) opal_bitmap_find_and_set_first_unset_bit(attr_subsys-> key_bitmap, (key))
260265
261- #define FREE_KEY (key ) opal_bitmap_clear_bit(key_bitmap, (key))
266+ #define FREE_KEY (key ) opal_bitmap_clear_bit(attr_subsys-> key_bitmap, (key))
262267
263268
264269/* Not checking for NULL_DELETE_FN here, since according to the
@@ -406,13 +411,24 @@ typedef struct attribute_value_t {
406411 int av_sequence ;
407412} attribute_value_t ;
408413
414+ /*
415+ * struct to hold state of attr subsys
416+ */
417+
418+ typedef struct attr_subsys_t {
419+ opal_object_t super ;
420+ opal_hash_table_t * keyval_hash ;
421+ opal_bitmap_t * key_bitmap ;
422+ } attr_subsys_t ;
409423
410424/*
411425 * Local functions
412426 */
413427static void attribute_value_construct (attribute_value_t * item );
414428static void ompi_attribute_keyval_construct (ompi_attribute_keyval_t * keyval );
415429static void ompi_attribute_keyval_destruct (ompi_attribute_keyval_t * keyval );
430+ static void attr_subsys_construct (attr_subsys_t * subsys );
431+ static void attr_subsys_destruct (attr_subsys_t * subsys );
416432static int set_value (ompi_attribute_type_t type , void * object ,
417433 opal_hash_table_t * * attr_hash , int key ,
418434 attribute_value_t * new_attr ,
@@ -425,6 +441,13 @@ static MPI_Aint translate_to_aint(attribute_value_t *val);
425441
426442static int compare_attr_sequence (const void * attr1 , const void * attr2 );
427443
444+ /*
445+ * attribute_subsys_t class
446+ */
447+ static OBJ_CLASS_INSTANCE (attr_subsys_t ,
448+ opal_object_t ,
449+ attr_subsys_construct ,
450+ attr_subsys_destruct ) ;
428451
429452/*
430453 * attribute_value_t class
@@ -448,19 +471,17 @@ static OBJ_CLASS_INSTANCE(ompi_attribute_keyval_t,
448471 * Static variables
449472 */
450473
451- static opal_hash_table_t * keyval_hash ;
452- static opal_bitmap_t * key_bitmap ;
453- static int attr_sequence ;
474+ static attr_subsys_t * attr_subsys = NULL ;
454475static unsigned int int_pos = 12345 ;
455476static unsigned int integer_pos = 12345 ;
477+ static int attr_sequence ;
456478
457479/*
458480 * MPI attributes are *not* high performance, so just use a One Big Lock
459481 * approach. However, this lock is released before a user provided callback is
460482 * triggered and acquired right after, allowing for recursive behaviors.
461483 */
462- static opal_mutex_t attribute_lock ;
463-
484+ static opal_mutex_t attribute_lock = OPAL_MUTEX_STATIC_INIT ;
464485
465486/*
466487 * attribute_value_t constructor function
@@ -507,33 +528,68 @@ ompi_attribute_keyval_destruct(ompi_attribute_keyval_t *keyval)
507528 free (keyval -> bindings_extra_state );
508529 }
509530
510- opal_hash_table_remove_value_uint32 (keyval_hash , keyval -> key );
531+ opal_hash_table_remove_value_uint32 (attr_subsys -> keyval_hash , keyval -> key );
511532 FREE_KEY (keyval -> key );
512533 }
513534}
514535
515536
516- /*
517- * This will initialize the main list to store key- attribute
518- * items. This will be called one time, during MPI_INIT().
519- */
520- int ompi_attr_init (void )
537+ int ompi_attr_get_ref (void )
538+ {
539+ int ret = OMPI_SUCCESS ;
540+
541+ OPAL_THREAD_LOCK (& attribute_lock );
542+
543+ if (NULL == attr_subsys ) {
544+ attr_subsys = OBJ_NEW (attr_subsys_t );
545+ if (NULL == attr_subsys ) {
546+ ret = OMPI_ERR_OUT_OF_RESOURCE ;
547+ goto fn_exit ;
548+ }
549+ if ((NULL == attr_subsys -> keyval_hash ) || (NULL == attr_subsys -> key_bitmap )) {
550+ OBJ_RELEASE (attr_subsys );
551+ attr_subsys = NULL ;
552+ ret = OMPI_ERR_OUT_OF_RESOURCE ;
553+ goto fn_exit ;
554+ }
555+ } else {
556+ OBJ_RETAIN (attr_subsys );
557+ }
558+
559+ fn_exit :
560+ OPAL_THREAD_UNLOCK (& attribute_lock );
561+
562+ return ret ;
563+ }
564+
565+ int ompi_attr_put_ref (void )
566+ {
567+ if (NULL != attr_subsys ) {
568+ OBJ_RELEASE (attr_subsys );
569+ }
570+ return OMPI_SUCCESS ;
571+ }
572+
573+ static void attr_subsys_construct (attr_subsys_t * subsys )
521574{
522575 int ret ;
523576 void * bogus = (void * ) 1 ;
524577 int * p = (int * ) & bogus ;
525578
526- keyval_hash = OBJ_NEW (opal_hash_table_t );
527- if (NULL == keyval_hash ) {
528- return OMPI_ERR_OUT_OF_RESOURCE ;
529- }
530- key_bitmap = OBJ_NEW (opal_bitmap_t );
579+ subsys -> keyval_hash = OBJ_NEW (opal_hash_table_t );
580+
581+ subsys -> key_bitmap = OBJ_NEW (opal_bitmap_t );
582+
531583 /*
532584 * Set the max size to OMPI_FORTRAN_HANDLE_MAX to enforce bound
533585 */
534- opal_bitmap_set_max_size (key_bitmap , OMPI_FORTRAN_HANDLE_MAX );
535- if (0 != opal_bitmap_init (key_bitmap , 32 )) {
536- return OMPI_ERR_OUT_OF_RESOURCE ;
586+ opal_bitmap_set_max_size (subsys -> key_bitmap ,
587+ OMPI_FORTRAN_HANDLE_MAX );
588+ ret = opal_bitmap_init (subsys -> key_bitmap , 32 );
589+ assert (OPAL_SUCCESS == ret );
590+
591+ for (int i = 0 ; i < MPI_ATTR_KEY_LAST ; i ++ ) {
592+ opal_bitmap_set_bit (subsys -> key_bitmap , i );
537593 }
538594
539595 for (int_pos = 0 ; int_pos < (sizeof (void * ) / sizeof (int ));
@@ -550,31 +606,21 @@ int ompi_attr_init(void)
550606 }
551607 }
552608
553- OBJ_CONSTRUCT (& attribute_lock , opal_mutex_t );
554-
555- if (OMPI_SUCCESS != (ret = opal_hash_table_init (keyval_hash ,
556- ATTR_TABLE_SIZE ))) {
557- return ret ;
558- }
559- if (OMPI_SUCCESS != (ret = ompi_attr_create_predefined ())) {
560- return ret ;
561- }
609+ ret = opal_hash_table_init (subsys -> keyval_hash , ATTR_TABLE_SIZE );
610+ assert (OPAL_SUCCESS == ret );
562611
563- return OMPI_SUCCESS ;
612+ attr_sequence = 0 ;
564613}
565614
566615
567616/*
568- * Cleanup everything during MPI_Finalize().
617+ * Cleanup everything when no more refs to the attr subsys
569618 */
570- int ompi_attr_finalize ( void )
619+ static void attr_subsys_destruct ( attr_subsys_t * subsys )
571620{
572621 ompi_attr_free_predefined ();
573- OBJ_DESTRUCT (& attribute_lock );
574- OBJ_RELEASE (keyval_hash );
575- OBJ_RELEASE (key_bitmap );
576-
577- return OMPI_SUCCESS ;
622+ OBJ_RELEASE (subsys -> keyval_hash );
623+ OBJ_RELEASE (subsys -> key_bitmap );
578624}
579625
580626/*****************************************************************************/
@@ -609,10 +655,15 @@ static int ompi_attr_create_keyval_impl(ompi_attribute_type_t type,
609655
610656 /* Create a new unique key and fill the hash */
611657 OPAL_THREAD_LOCK (& attribute_lock );
612- ret = CREATE_KEY (key );
658+ ret = MPI_SUCCESS ;
659+ if (!(flags & OMPI_KEYVAL_PREDEFINED )) {
660+ ret = CREATE_KEY (key );
661+ }
662+
613663 if (OMPI_SUCCESS == ret ) {
614664 keyval -> key = * key ;
615- ret = opal_hash_table_set_value_uint32 (keyval_hash , * key , keyval );
665+ ret = opal_hash_table_set_value_uint32 (attr_subsys -> keyval_hash ,
666+ * key , keyval );
616667 }
617668
618669 if (OMPI_SUCCESS != ret ) {
@@ -635,11 +686,22 @@ int ompi_attr_create_keyval(ompi_attribute_type_t type,
635686 void * bindings_extra_state )
636687{
637688 ompi_attribute_fortran_ptr_t es_tmp ;
689+ int rc ;
690+
691+ rc = ompi_mpi_instance_retain ();
692+ if (OPAL_UNLIKELY (OMPI_SUCCESS != rc )) {
693+ return rc ;
694+ }
638695
639696 es_tmp .c_ptr = extra_state ;
640- return ompi_attr_create_keyval_impl (type , copy_attr_fn , delete_attr_fn ,
641- key , & es_tmp , flags ,
642- bindings_extra_state );
697+ rc = ompi_attr_create_keyval_impl (type , copy_attr_fn , delete_attr_fn ,
698+ key , & es_tmp , flags ,
699+ bindings_extra_state );
700+ if (OPAL_UNLIKELY (OMPI_SUCCESS != rc )) {
701+ ompi_mpi_instance_release ();
702+ }
703+
704+ return rc ;
643705}
644706
645707int ompi_attr_create_keyval_fint (ompi_attribute_type_t type ,
@@ -651,6 +713,12 @@ int ompi_attr_create_keyval_fint(ompi_attribute_type_t type,
651713 void * bindings_extra_state )
652714{
653715 ompi_attribute_fortran_ptr_t es_tmp ;
716+ int rc ;
717+
718+ rc = ompi_mpi_instance_retain ();
719+ if (OPAL_UNLIKELY (OMPI_SUCCESS != rc )) {
720+ return rc ;
721+ }
654722
655723 es_tmp .f_integer = extra_state ;
656724#if SIZEOF_INT == OMPI_SIZEOF_FORTRAN_INTEGER
@@ -670,6 +738,12 @@ int ompi_attr_create_keyval_aint(ompi_attribute_type_t type,
670738 void * bindings_extra_state )
671739{
672740 ompi_attribute_fortran_ptr_t es_tmp ;
741+ int rc ;
742+
743+ rc = ompi_mpi_instance_retain ();
744+ if (OPAL_UNLIKELY (OMPI_SUCCESS != rc )) {
745+ return rc ;
746+ }
673747
674748 es_tmp .f_address = extra_state ;
675749 return ompi_attr_create_keyval_impl (type , copy_attr_fn , delete_attr_fn ,
@@ -687,7 +761,7 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
687761
688762 /* Find the key-value pair */
689763 OPAL_THREAD_LOCK (& attribute_lock );
690- ret = opal_hash_table_get_value_uint32 (keyval_hash , * key ,
764+ ret = opal_hash_table_get_value_uint32 (attr_subsys -> keyval_hash , * key ,
691765 (void * * ) & keyval );
692766 if ((OMPI_SUCCESS != ret ) || (NULL == keyval ) ||
693767 (keyval -> attr_type != type ) ||
@@ -707,6 +781,9 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
707781 opal_atomic_wmb ();
708782 OPAL_THREAD_UNLOCK (& attribute_lock );
709783
784+ /* balance out retain in keyval_create */
785+ ompi_mpi_instance_release ();
786+
710787 return MPI_SUCCESS ;
711788}
712789
@@ -720,7 +797,7 @@ int ompi_attr_set_c(ompi_attribute_type_t type, void *object,
720797 opal_hash_table_t * * attr_hash ,
721798 int key , void * attribute , bool predefined )
722799{
723- int ret ;
800+ int ret = MPI_SUCCESS ;
724801 attribute_value_t * new_attr = OBJ_NEW (attribute_value_t );
725802 if (NULL == new_attr ) {
726803 return OMPI_ERR_OUT_OF_RESOURCE ;
@@ -942,7 +1019,7 @@ int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
9421019
9431020 /* Get the keyval in the main keyval hash - so that we know
9441021 what the copy_attr_fn is */
945- err = opal_hash_table_get_value_uint32 (keyval_hash , key ,
1022+ err = opal_hash_table_get_value_uint32 (attr_subsys -> keyval_hash , key ,
9461023 (void * * ) & hash_value );
9471024 if (OMPI_SUCCESS != err ) {
9481025 /* This should not happen! */
@@ -1037,7 +1114,7 @@ static int ompi_attr_delete_impl(ompi_attribute_type_t type, void *object,
10371114 attribute_value_t * attr ;
10381115
10391116 /* Check if the key is valid in the master keyval hash */
1040- ret = opal_hash_table_get_value_uint32 (keyval_hash , key ,
1117+ ret = opal_hash_table_get_value_uint32 (attr_subsys -> keyval_hash , key ,
10411118 (void * * ) & keyval );
10421119
10431120 if ((OMPI_SUCCESS != ret ) || (NULL == keyval ) ||
@@ -1053,7 +1130,7 @@ static int ompi_attr_delete_impl(ompi_attribute_type_t type, void *object,
10531130 goto exit ;
10541131 }
10551132
1056- /* Check if the key is valid for the communicator/window/dtype. If
1133+ /* Check if the key is valid for the communicator/window/dtype/instance . If
10571134 yes, then delete the attribute and key entry from the object's
10581135 hash */
10591136 ret = opal_hash_table_get_value_uint32 (attr_hash , key , (void * * ) & attr );
@@ -1198,7 +1275,7 @@ static int set_value(ompi_attribute_type_t type, void *object,
11981275 /* Note that this function can be invoked by ompi_attr_copy_all()
11991276 to set attributes on the new object (in addition to the
12001277 top-level MPI_* functions that set attributes). */
1201- ret = opal_hash_table_get_value_uint32 (keyval_hash , key ,
1278+ ret = opal_hash_table_get_value_uint32 (attr_subsys -> keyval_hash , key ,
12021279 (void * * ) & keyval );
12031280
12041281 /* If key not found */
@@ -1242,7 +1319,7 @@ static int set_value(ompi_attribute_type_t type, void *object,
12421319 had_old = true;
12431320 }
12441321
1245- ret = opal_hash_table_get_value_uint32 (keyval_hash , key ,
1322+ ret = opal_hash_table_get_value_uint32 (attr_subsys -> keyval_hash , key ,
12461323 (void * * ) & keyval );
12471324 if ((OMPI_SUCCESS != ret ) || (NULL == keyval )) {
12481325 /* Keyval has disappeared underneath us -- this shouldn't
@@ -1288,7 +1365,7 @@ static int get_value(opal_hash_table_t *attr_hash, int key,
12881365 with the key, then the call is valid and returns FALSE in the
12891366 flag argument */
12901367 * flag = 0 ;
1291- ret = opal_hash_table_get_value_uint32 (keyval_hash , key ,
1368+ ret = opal_hash_table_get_value_uint32 (attr_subsys -> keyval_hash , key ,
12921369 (void * * ) & keyval );
12931370 if (OMPI_ERR_NOT_FOUND == ret ) {
12941371 return MPI_KEYVAL_INVALID ;
0 commit comments