/* * Back-end function to set an attribute on an MPI object. Assumes * that you already hold the attribute_lock. */ static int set_value(ompi_attribute_type_t type, void *object, opal_hash_table_t **attr_hash, int key, attribute_value_t *new_attr, bool predefined) { ompi_attribute_keyval_t *keyval; int ret; attribute_value_t *old_attr; bool had_old = false; /* Note that this function can be invoked by ompi_attr_copy_all() to set attributes on the new object (in addition to the top-level MPI_* functions that set attributes). */ ret = opal_hash_table_get_value_uint32(keyval_hash, key, (void **) &keyval); /* If key not found */ if ((OMPI_SUCCESS != ret ) || (NULL == keyval) || (keyval->attr_type != type) || ((!predefined) && (keyval->attr_flag & OMPI_KEYVAL_PREDEFINED))) { return OMPI_ERR_BAD_PARAM; } /* Do we need to make a new attr_hash? */ if (NULL == *attr_hash) { ompi_attr_hash_init(attr_hash); } /* Now see if an attribute is already present in the object's hash on the old keyval. If so, delete the old attribute value. */ ret = opal_hash_table_get_value_uint32(*attr_hash, key, (void**) &old_attr); if (OMPI_SUCCESS == ret) { switch (type) { case COMM_ATTR: DELETE_ATTR_CALLBACKS(communicator, old_attr, keyval, object, ret); break; case WIN_ATTR: DELETE_ATTR_CALLBACKS(win, old_attr, keyval, object, ret); break; case TYPE_ATTR: DELETE_ATTR_CALLBACKS(datatype, old_attr, keyval, object, ret); break; default: /* This should not happen */ assert(0); break; } if (MPI_SUCCESS != ret) { return ret; } OBJ_RELEASE(old_attr); had_old = true; } ret = opal_hash_table_get_value_uint32(keyval_hash, key, (void **) &keyval); if ((OMPI_SUCCESS != ret ) || (NULL == keyval)) { /* Keyval has disappeared underneath us -- this shouldn't happen! */ assert(0); return OMPI_ERR_BAD_PARAM; } new_attr->av_key = key; new_attr->av_sequence = attr_sequence++; ret = opal_hash_table_set_value_uint32(*attr_hash, key, new_attr); /* Increase the reference count of the object, only if there was no old atribute/no old entry in the object's key hash */ if (OMPI_SUCCESS == ret && !had_old) { OBJ_RETAIN(keyval); } return ret; }
/* * Initialize comm world/self/null/parent. */ int ompi_comm_init(void) { ompi_group_t *group; size_t size; /* Setup communicator array */ OBJ_CONSTRUCT(&ompi_mpi_communicators, opal_pointer_array_t); if( OPAL_SUCCESS != opal_pointer_array_init(&ompi_mpi_communicators, 0, OMPI_FORTRAN_HANDLE_MAX, 64) ) { return OMPI_ERROR; } /* Setup MPI_COMM_WORLD */ OBJ_CONSTRUCT(&ompi_mpi_comm_world, ompi_communicator_t); group = OBJ_NEW(ompi_group_t); group->grp_proc_pointers = ompi_proc_world(&size); group->grp_proc_count = (int)size; OMPI_GROUP_SET_INTRINSIC (group); OMPI_GROUP_SET_DENSE (group); ompi_set_group_rank(group, ompi_proc_local()); ompi_group_increment_proc_count (group); ompi_mpi_comm_world.comm.c_contextid = 0; ompi_mpi_comm_world.comm.c_id_start_index = 4; ompi_mpi_comm_world.comm.c_id_available = 4; ompi_mpi_comm_world.comm.c_f_to_c_index = 0; ompi_mpi_comm_world.comm.c_my_rank = group->grp_my_rank; ompi_mpi_comm_world.comm.c_local_group = group; ompi_mpi_comm_world.comm.c_remote_group = group; OBJ_RETAIN(ompi_mpi_comm_world.comm.c_remote_group); ompi_mpi_comm_world.comm.c_cube_dim = opal_cube_dim((int)size); ompi_mpi_comm_world.comm.error_handler = &ompi_mpi_errors_are_fatal.eh; OBJ_RETAIN( &ompi_mpi_errors_are_fatal.eh ); OMPI_COMM_SET_PML_ADDED(&ompi_mpi_comm_world.comm); opal_pointer_array_set_item (&ompi_mpi_communicators, 0, &ompi_mpi_comm_world); MEMCHECKER (memset (ompi_mpi_comm_world.comm.c_name, 0, MPI_MAX_OBJECT_NAME)); strncpy (ompi_mpi_comm_world.comm.c_name, "MPI_COMM_WORLD", strlen("MPI_COMM_WORLD")+1 ); ompi_mpi_comm_world.comm.c_flags |= OMPI_COMM_NAMEISSET; ompi_mpi_comm_world.comm.c_flags |= OMPI_COMM_INTRINSIC; /* We have to create a hash (although it is legal to leave this filed NULL -- the attribute accessor functions will intepret this as "there are no attributes cached on this object") because MPI_COMM_WORLD has some predefined attributes. */ ompi_attr_hash_init(&ompi_mpi_comm_world.comm.c_keyhash); /* Setup MPI_COMM_SELF */ OBJ_CONSTRUCT(&ompi_mpi_comm_self, ompi_communicator_t); group = OBJ_NEW(ompi_group_t); group->grp_proc_pointers = ompi_proc_self(&size); group->grp_my_rank = 0; group->grp_proc_count = (int)size; OMPI_GROUP_SET_INTRINSIC (group); OMPI_GROUP_SET_DENSE (group); ompi_mpi_comm_self.comm.c_contextid = 1; ompi_mpi_comm_self.comm.c_f_to_c_index = 1; ompi_mpi_comm_self.comm.c_id_start_index = 20; ompi_mpi_comm_self.comm.c_id_available = 20; ompi_mpi_comm_self.comm.c_my_rank = group->grp_my_rank; ompi_mpi_comm_self.comm.c_local_group = group; ompi_mpi_comm_self.comm.c_remote_group = group; OBJ_RETAIN(ompi_mpi_comm_self.comm.c_remote_group); ompi_mpi_comm_self.comm.error_handler = &ompi_mpi_errors_are_fatal.eh; OBJ_RETAIN( &ompi_mpi_errors_are_fatal.eh ); OMPI_COMM_SET_PML_ADDED(&ompi_mpi_comm_self.comm); opal_pointer_array_set_item (&ompi_mpi_communicators, 1, &ompi_mpi_comm_self); MEMCHECKER (memset (ompi_mpi_comm_self.comm.c_name, 0, MPI_MAX_OBJECT_NAME)); strncpy(ompi_mpi_comm_self.comm.c_name,"MPI_COMM_SELF",strlen("MPI_COMM_SELF")+1); ompi_mpi_comm_self.comm.c_flags |= OMPI_COMM_NAMEISSET; ompi_mpi_comm_self.comm.c_flags |= OMPI_COMM_INTRINSIC; /* We can set MPI_COMM_SELF's keyhash to NULL because it has no predefined attributes. If a user defines an attribute on MPI_COMM_SELF, the keyhash will automatically be created. */ ompi_mpi_comm_self.comm.c_keyhash = NULL; /* Setup MPI_COMM_NULL */ OBJ_CONSTRUCT(&ompi_mpi_comm_null, ompi_communicator_t); ompi_mpi_comm_null.comm.c_local_group = &ompi_mpi_group_null.group; ompi_mpi_comm_null.comm.c_remote_group = &ompi_mpi_group_null.group; OBJ_RETAIN(&ompi_mpi_group_null.group); OBJ_RETAIN(&ompi_mpi_group_null.group); ompi_mpi_comm_null.comm.c_contextid = 2; ompi_mpi_comm_null.comm.c_f_to_c_index = 2; ompi_mpi_comm_null.comm.c_my_rank = MPI_PROC_NULL; ompi_mpi_comm_null.comm.error_handler = &ompi_mpi_errors_are_fatal.eh; OBJ_RETAIN( &ompi_mpi_errors_are_fatal.eh ); opal_pointer_array_set_item (&ompi_mpi_communicators, 2, &ompi_mpi_comm_null); MEMCHECKER (memset (ompi_mpi_comm_null.comm.c_name, 0, MPI_MAX_OBJECT_NAME)); strncpy(ompi_mpi_comm_null.comm.c_name,"MPI_COMM_NULL",strlen("MPI_COMM_NULL")+1); ompi_mpi_comm_null.comm.c_flags |= OMPI_COMM_NAMEISSET; ompi_mpi_comm_null.comm.c_flags |= OMPI_COMM_INTRINSIC; /* Initialize the parent communicator to MPI_COMM_NULL */ ompi_mpi_comm_parent = &ompi_mpi_comm_null.comm; OBJ_RETAIN(&ompi_mpi_comm_null); OBJ_RETAIN(&ompi_mpi_group_null.group); OBJ_RETAIN(&ompi_mpi_errors_are_fatal.eh); /* initialize the comm_reg stuff for multi-threaded comm_cid allocation */ ompi_comm_reg_init(); return OMPI_SUCCESS; }
/* * Back-end function to set an attribute on an MPI object */ static int set_value(ompi_attribute_type_t type, void *object, opal_hash_table_t **attr_hash, int key, attribute_value_t *new_attr, bool predefined) { ompi_attribute_keyval_t *keyval; int ret, err; attribute_value_t *old_attr; bool had_old = false; /* Note that this function can be invoked by ompi_attr_copy_all() to set attributes on the new object (in addition to the top-level MPI_* functions that set attributes). */ OPAL_THREAD_LOCK(&keyval_hash_lock); ret = opal_hash_table_get_value_uint32(keyval_hash, key, (void **) &keyval); OPAL_THREAD_UNLOCK(&keyval_hash_lock); /* If key not found */ if ((OMPI_SUCCESS != ret ) || (NULL == keyval) || (keyval->attr_type != type) || ((!predefined) && (keyval->attr_flag & OMPI_KEYVAL_PREDEFINED))) { return OMPI_ERR_BAD_PARAM; } /* Do we need to make a new attr_hash? */ OPAL_THREAD_LOCK(&attr_hash_lock); if (NULL == *attr_hash) { ompi_attr_hash_init(attr_hash); } /* Now see if an attribute is already present in the object's hash on the old keyval. If so, delete the old attribute value. */ ret = opal_hash_table_get_value_uint32(*attr_hash, key, (void**) &old_attr); OPAL_THREAD_UNLOCK(&attr_hash_lock); if (OMPI_SUCCESS == ret) { switch (type) { case COMM_ATTR: DELETE_ATTR_CALLBACKS(communicator, old_attr, keyval, object); break; case WIN_ATTR: DELETE_ATTR_CALLBACKS(win, old_attr, keyval, object); break; case TYPE_ATTR: DELETE_ATTR_CALLBACKS(datatype, old_attr, keyval, object); break; default: return MPI_ERR_INTERN; } had_old = true; OBJ_RELEASE(old_attr); } OPAL_THREAD_LOCK(&keyval_hash_lock); ret = opal_hash_table_get_value_uint32(keyval_hash, key, (void **) &keyval); if ((OMPI_SUCCESS != ret ) || (NULL == keyval)) { /* Keyval has disappeared underneath us. Someone must have called ompi_attr_free_keyval since we last looked it up in the hash. We'll behave as if we never found it in the first place */ OPAL_THREAD_UNLOCK(&keyval_hash_lock); return OMPI_ERR_BAD_PARAM; } OPAL_THREAD_LOCK(&attr_hash_lock); ret = opal_hash_table_set_value_uint32(*attr_hash, key, new_attr); OPAL_THREAD_UNLOCK(&attr_hash_lock); OPAL_THREAD_UNLOCK(&keyval_hash_lock); /* Increase the reference count of the object, only if there was no old atribute/no old entry in the object's key hash */ if (OMPI_SUCCESS == ret && !had_old) { OBJ_RETAIN(keyval); } if (OMPI_SUCCESS != ret) { return ret; } return MPI_SUCCESS; }