/* * Copy all the attributes from one MPI object to another. Called * when MPI objects are copied (e.g., back-end actions to * MPI_COMM_DUP). */ int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object, void *new_object, opal_hash_table_t *oldattr_hash, opal_hash_table_t *newattr_hash) { int ret; int err; uint32_t key; int flag; void *node, *in_node; attribute_value_t *old_attr, *new_attr; ompi_attribute_keyval_t *hash_value; /* If there's nothing to do, just return */ if (NULL == oldattr_hash) { return MPI_SUCCESS; } OPAL_THREAD_LOCK(&attribute_lock); /* Get the first attribute in the object's hash */ ret = opal_hash_table_get_first_key_uint32(oldattr_hash, &key, (void **) &old_attr, &node); /* While we still have some attribute in the object's key hash */ while (OMPI_SUCCESS == ret) { in_node = node; /* Get the keyval in the main keyval hash - so that we know what the copy_attr_fn is */ err = opal_hash_table_get_value_uint32(keyval_hash, key, (void **) &hash_value); if (OMPI_SUCCESS != err) { /* This should not happen! */ ret = MPI_ERR_INTERN; goto out; } err = 0; new_attr = OBJ_NEW(attribute_value_t); switch (type) { case COMM_ATTR: /* Now call the copy_attr_fn */ COPY_ATTR_CALLBACKS(communicator, old_object, hash_value, old_attr, new_object, new_attr, err); break; case TYPE_ATTR: /* Now call the copy_attr_fn */ COPY_ATTR_CALLBACKS(datatype, old_object, hash_value, old_attr, new_object, new_attr, err); break; case WIN_ATTR: /* Now call the copy_attr_fn */ COPY_ATTR_CALLBACKS(win, old_object, hash_value, old_attr, new_object, new_attr, err); break; default: /* This should not happen */ assert(0); break; } /* Did the callback return non-MPI_SUCCESS? */ if (0 != err) { ret = err; goto out; } /* Hang this off the object's hash */ /* The COPY_ATTR_CALLBACKS macro will have converted the _flag_ callback output value from Fortran's .TRUE. value to 0/1 (if necessary). So we only need to check for 0/1 here -- not .TRUE. */ if (1 == flag) { if (0 != (hash_value->attr_flag & OMPI_KEYVAL_F77)) { if (0 != (hash_value->attr_flag & OMPI_KEYVAL_F77_INT)) { new_attr->av_set_from = OMPI_ATTRIBUTE_FINT; } else { new_attr->av_set_from = OMPI_ATTRIBUTE_AINT; } } else { new_attr->av_set_from = OMPI_ATTRIBUTE_C; } ret = set_value(type, new_object, &newattr_hash, key, new_attr, true); if (MPI_SUCCESS != ret) { goto out; } } else { OBJ_RELEASE(new_attr); } ret = opal_hash_table_get_next_key_uint32(oldattr_hash, &key, (void **) &old_attr, in_node, &node); } ret = MPI_SUCCESS; out: /* All done */ opal_atomic_wmb(); OPAL_THREAD_UNLOCK(&attribute_lock); return ret; }
/* * Copy all the attributes from one MPI object to another */ int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object, void *new_object, opal_hash_table_t *oldattr_hash, opal_hash_table_t *newattr_hash) { int ret; int err; uint32_t key; int flag; void *node, *in_node; attribute_value_t *old_attr, *new_attr; ompi_attribute_keyval_t *hash_value; /* If there's nothing to do, just return */ if (NULL == oldattr_hash) { return MPI_SUCCESS; } /* Lock this whole sequence of events -- don't let any other thread modify the structure of the attrbitue hash or bitmap while we're traversing it */ OPAL_THREAD_LOCK(&attr_hash_lock); /* Get the first attribute in the object's hash */ ret = opal_hash_table_get_first_key_uint32(oldattr_hash, &key, (void **) &old_attr, &node); OPAL_THREAD_UNLOCK(&attr_hash_lock); /* While we still have some attribute in the object's key hash */ while (OMPI_SUCCESS == ret) { in_node = node; /* Get the keyval in the main keyval hash - so that we know what the copy_attr_fn is */ OPAL_THREAD_LOCK(&keyval_hash_lock); err = opal_hash_table_get_value_uint32(keyval_hash, key, (void **) &hash_value); OPAL_THREAD_UNLOCK(&keyval_hash_lock); new_attr = OBJ_NEW(attribute_value_t); switch (type) { case UNUSED_ATTR: /* keep the compiler happy */ assert(0); break; case COMM_ATTR: /* Now call the copy_attr_fn */ COPY_ATTR_CALLBACKS(communicator, old_object, hash_value, old_attr, new_object, new_attr); break; case TYPE_ATTR: /* Now call the copy_attr_fn */ COPY_ATTR_CALLBACKS(datatype, old_object, hash_value, old_attr, new_object, new_attr); break; case WIN_ATTR: /* Now call the copy_attr_fn */ COPY_ATTR_CALLBACKS(win, old_object, hash_value, old_attr, new_object, new_attr); break; } /* Hang this off the object's hash */ /* The "predefined" parameter to ompi_attr_set() is set to 1, so that no comparison is done for prdefined at all and it just falls off the error checking loop in attr_set */ if (1 == flag) { if (0 != (hash_value->attr_flag & OMPI_KEYVAL_F77)) { if (0 != (hash_value->attr_flag & OMPI_KEYVAL_F77_MPI1)) { new_attr->av_set_from = OMPI_ATTRIBUTE_FORTRAN_MPI1; } else { new_attr->av_set_from = OMPI_ATTRIBUTE_FORTRAN_MPI2; } } else { new_attr->av_set_from = OMPI_ATTRIBUTE_C; } set_value(type, new_object, &newattr_hash, key, new_attr, true); } else { OBJ_RELEASE(new_attr); } OPAL_THREAD_LOCK(&attr_hash_lock); ret = opal_hash_table_get_next_key_uint32(oldattr_hash, &key, (void **) &old_attr, in_node, &node); OPAL_THREAD_UNLOCK(&attr_hash_lock); } /* All done */ return MPI_SUCCESS; }