Fixes trac:2767: Recursive locking when ROMIO used with THREAD_MULITPLE
This commit was SVN r24681. The following Trac tickets were found above: Ticket 2767 --> https://svn.open-mpi.org/trac/ompi/ticket/2767
Этот коммит содержится в:
родитель
34abbce82c
Коммит
bab59bda76
@ -255,9 +255,7 @@
|
||||
(&(((ompi_##type##_t *)object)->attr_##type##_f), \
|
||||
&f_key, &attr_val, &keyval_obj->extra_state.f_integer, &f_err); \
|
||||
if (MPI_SUCCESS != OMPI_FINT_2_INT(f_err)) { \
|
||||
if (need_lock) { \
|
||||
OPAL_THREAD_UNLOCK(&alock); \
|
||||
} \
|
||||
OPAL_THREAD_UNLOCK(&attr_hash_lock); \
|
||||
return OMPI_FINT_2_INT(f_err); \
|
||||
} \
|
||||
} \
|
||||
@ -268,9 +266,7 @@
|
||||
(&(((ompi_##type##_t *)object)->attr_##type##_f), \
|
||||
&f_key, (int*)&attr_val, &keyval_obj->extra_state.f_address, &f_err); \
|
||||
if (MPI_SUCCESS != OMPI_FINT_2_INT(f_err)) { \
|
||||
if (need_lock) { \
|
||||
OPAL_THREAD_UNLOCK(&alock); \
|
||||
} \
|
||||
OPAL_THREAD_UNLOCK(&attr_hash_lock); \
|
||||
return OMPI_FINT_2_INT(f_err); \
|
||||
} \
|
||||
} \
|
||||
@ -282,9 +278,7 @@
|
||||
((ompi_##type##_t *)object, \
|
||||
key, attr_val, \
|
||||
keyval_obj->extra_state.c_ptr)) != MPI_SUCCESS) {\
|
||||
if (need_lock) { \
|
||||
OPAL_THREAD_UNLOCK(&alock); \
|
||||
} \
|
||||
OPAL_THREAD_UNLOCK(&attr_hash_lock); \
|
||||
return err;\
|
||||
} \
|
||||
}
|
||||
@ -306,7 +300,7 @@
|
||||
&f_key, &keyval_obj->extra_state.f_integer, \
|
||||
&in, &out, &f_flag, &f_err); \
|
||||
if (MPI_SUCCESS != OMPI_FINT_2_INT(f_err)) { \
|
||||
OPAL_THREAD_UNLOCK(&alock); \
|
||||
OPAL_THREAD_UNLOCK(&attr_hash_lock); \
|
||||
return OMPI_FINT_2_INT(f_err); \
|
||||
} \
|
||||
out_attr->av_value = (void*) 0; \
|
||||
@ -322,7 +316,7 @@
|
||||
&f_key, &keyval_obj->extra_state.f_address, &in, &out, \
|
||||
&f_flag, &f_err); \
|
||||
if (MPI_SUCCESS != OMPI_FINT_2_INT(f_err)) { \
|
||||
OPAL_THREAD_UNLOCK(&alock); \
|
||||
OPAL_THREAD_UNLOCK(&attr_hash_lock); \
|
||||
return OMPI_FINT_2_INT(f_err); \
|
||||
} \
|
||||
out_attr->av_value = (void *) out; \
|
||||
@ -336,7 +330,7 @@
|
||||
if ((err = (*((keyval_obj->copy_attr_fn).attr_##type##_copy_fn)) \
|
||||
((ompi_##type##_t *)old_object, key, keyval_obj->extra_state.c_ptr, \
|
||||
in, &out, &flag, (ompi_##type##_t *)(new_object))) != MPI_SUCCESS) { \
|
||||
OPAL_THREAD_UNLOCK(&alock); \
|
||||
OPAL_THREAD_UNLOCK(&attr_hash_lock); \
|
||||
return err; \
|
||||
} \
|
||||
out_attr->av_value = out; \
|
||||
@ -374,7 +368,7 @@ static void ompi_attribute_keyval_destruct(ompi_attribute_keyval_t *keyval);
|
||||
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, bool need_lock);
|
||||
bool predefined);
|
||||
static int get_value(opal_hash_table_t *attr_hash, int key,
|
||||
attribute_value_t **attribute, int *flag);
|
||||
static void *translate_to_c(attribute_value_t *val);
|
||||
@ -409,14 +403,22 @@ static opal_bitmap_t *key_bitmap;
|
||||
static unsigned int int_pos = 12345;
|
||||
|
||||
/*
|
||||
* Have one lock protect all access to any attribute stuff (keyval
|
||||
* hash, key bitmap, attribute hashes on MPI objects, etc.).
|
||||
* Arguably, we would have a finer-grained scheme (e.g., 2 locks) that
|
||||
* would allow at least *some* concurrency, but these are attributes
|
||||
* -- they're not in the performance-critical portions of the code.
|
||||
* So why bother?
|
||||
* Have one lock protect all access to any attribute hashes on MPI
|
||||
* objects and one to protect access to any other attribute stuff
|
||||
* (keyval hash, key bitmap,). We could eventually go for finer
|
||||
* grained locking, but this will do for now. Originally had only
|
||||
* one lock, but this can lead to a deadlock if the delete callback
|
||||
* for an attribute attempts to free a keyval
|
||||
*
|
||||
* Notes:
|
||||
* 1. If you need both locks simultaneously, ALWAYS take
|
||||
* the keyval_hash_lock lock first.
|
||||
* 2. You *must* always drop both locks before calling any user defined
|
||||
* callbacks (ie copy/delete callbacks)
|
||||
*
|
||||
*/
|
||||
static opal_mutex_t alock;
|
||||
static opal_mutex_t keyval_hash_lock;
|
||||
static opal_mutex_t attr_hash_lock;
|
||||
|
||||
|
||||
/*
|
||||
@ -456,7 +458,7 @@ static void
|
||||
ompi_attribute_keyval_destruct(ompi_attribute_keyval_t *keyval)
|
||||
{
|
||||
/* THIS FUNCTION ASSUMES THAT THE CALLER ALREADY HAS OBTAINED THE
|
||||
alock MUTEX! Remove the keyval entry from the hash and free
|
||||
keyval_hash_lock MUTEX! Remove the keyval entry from the hash and free
|
||||
the key. */
|
||||
|
||||
if (-1 != keyval->key) {
|
||||
@ -502,7 +504,8 @@ int ompi_attr_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
OBJ_CONSTRUCT(&alock, opal_mutex_t);
|
||||
OBJ_CONSTRUCT(&keyval_hash_lock, opal_mutex_t);
|
||||
OBJ_CONSTRUCT(&attr_hash_lock, opal_mutex_t);
|
||||
|
||||
if (OMPI_SUCCESS != (ret = opal_hash_table_init(keyval_hash,
|
||||
ATTR_TABLE_SIZE))) {
|
||||
@ -543,12 +546,6 @@ static int ompi_attr_create_keyval_impl(ompi_attribute_type_t type,
|
||||
ompi_attribute_keyval_t *keyval;
|
||||
int ret;
|
||||
|
||||
/* Protect against the user calling ompi_attr_destroy and then
|
||||
calling any of the functions which use it */
|
||||
if (NULL == keyval_hash) {
|
||||
return MPI_ERR_INTERN;
|
||||
}
|
||||
|
||||
/* Allocate space for the list item */
|
||||
|
||||
keyval = OBJ_NEW(ompi_attribute_keyval_t);
|
||||
@ -570,7 +567,7 @@ static int ompi_attr_create_keyval_impl(ompi_attribute_type_t type,
|
||||
|
||||
/* Create a new unique key and fill the hash */
|
||||
|
||||
OPAL_THREAD_LOCK(&alock);
|
||||
OPAL_THREAD_LOCK(&keyval_hash_lock);
|
||||
ret = CREATE_KEY(key);
|
||||
if (OMPI_SUCCESS == ret) {
|
||||
keyval->key = *key;
|
||||
@ -578,11 +575,11 @@ static int ompi_attr_create_keyval_impl(ompi_attribute_type_t type,
|
||||
}
|
||||
if (OMPI_SUCCESS != ret) {
|
||||
OBJ_RELEASE(keyval);
|
||||
OPAL_THREAD_UNLOCK(&alock);
|
||||
return ret;
|
||||
} else {
|
||||
ret = MPI_SUCCESS;
|
||||
}
|
||||
|
||||
OPAL_THREAD_UNLOCK(&alock);
|
||||
OPAL_THREAD_UNLOCK(&keyval_hash_lock);
|
||||
return MPI_SUCCESS;
|
||||
}
|
||||
|
||||
@ -640,22 +637,16 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
|
||||
int ret;
|
||||
ompi_attribute_keyval_t *keyval;
|
||||
|
||||
/* Protect against the user calling ompi_attr_destroy and then
|
||||
calling any of the functions which use it */
|
||||
if (NULL == keyval_hash) {
|
||||
return MPI_ERR_INTERN;
|
||||
}
|
||||
|
||||
/* Find the key-value pair */
|
||||
|
||||
OPAL_THREAD_LOCK(&alock);
|
||||
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->attr_type != type) ||
|
||||
((!predefined) && (keyval->attr_flag & OMPI_KEYVAL_PREDEFINED))) {
|
||||
OPAL_THREAD_UNLOCK(&alock);
|
||||
OPAL_THREAD_UNLOCK(&keyval_hash_lock);
|
||||
return OMPI_ERR_BAD_PARAM;
|
||||
}
|
||||
|
||||
@ -668,7 +659,7 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
|
||||
the last attribute is deleted, this object gets deleted too */
|
||||
|
||||
OBJ_RELEASE(keyval);
|
||||
OPAL_THREAD_UNLOCK(&alock);
|
||||
OPAL_THREAD_UNLOCK(&keyval_hash_lock);
|
||||
|
||||
return MPI_SUCCESS;
|
||||
}
|
||||
@ -676,52 +667,44 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
|
||||
|
||||
int ompi_attr_delete(ompi_attribute_type_t type, void *object,
|
||||
opal_hash_table_t *attr_hash, int key,
|
||||
bool predefined, bool need_lock)
|
||||
bool predefined)
|
||||
{
|
||||
ompi_attribute_keyval_t *keyval;
|
||||
int ret = OMPI_SUCCESS, err;
|
||||
attribute_value_t *attr;
|
||||
|
||||
/* Protect against the user calling ompi_attr_destroy and then
|
||||
calling any of the functions which use it */
|
||||
if (NULL == keyval_hash) {
|
||||
return MPI_ERR_INTERN;
|
||||
}
|
||||
|
||||
/* Note that this function can be invoked by
|
||||
ompi_attr_delete_all() to set attributes on the new object (in
|
||||
addition to the top-level MPI_* functions that set attributes).
|
||||
In these cases, ompi_attr_delete_all() has already locked the
|
||||
keyval_lock, so we should not try to lock it again. */
|
||||
|
||||
if (need_lock) {
|
||||
OPAL_THREAD_LOCK(&alock);
|
||||
}
|
||||
|
||||
/* Check if the key is valid in the master keyval hash */
|
||||
|
||||
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 ((OMPI_SUCCESS != ret) || (NULL == keyval) ||
|
||||
(keyval->attr_type!= type) ||
|
||||
((!predefined) && (keyval->attr_flag & OMPI_KEYVAL_PREDEFINED))) {
|
||||
ret = OMPI_ERR_BAD_PARAM;
|
||||
goto exit;
|
||||
return ret;
|
||||
}
|
||||
|
||||
OPAL_THREAD_LOCK(&attr_hash_lock);
|
||||
/* Ensure that we don't have an empty attr_hash */
|
||||
|
||||
if (NULL == attr_hash) {
|
||||
ret = OMPI_ERR_BAD_PARAM;
|
||||
goto exit;
|
||||
OPAL_THREAD_UNLOCK(&attr_hash_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check if the key is valid for the communicator/window/dtype. If
|
||||
yes, then delete the attribute and key entry from the object's
|
||||
hash */
|
||||
|
||||
/* Note that this function can be invoked by
|
||||
ompi_attr_delete_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(attr_hash, key, (void**) &attr);
|
||||
OPAL_THREAD_UNLOCK(&attr_hash_lock);
|
||||
|
||||
if (OMPI_SUCCESS == ret) {
|
||||
switch (type) {
|
||||
case COMM_ATTR:
|
||||
@ -742,7 +725,10 @@ int ompi_attr_delete(ompi_attribute_type_t type, void *object,
|
||||
}
|
||||
OBJ_RELEASE(attr);
|
||||
|
||||
OPAL_THREAD_LOCK(&attr_hash_lock);
|
||||
ret = opal_hash_table_remove_value_uint32(attr_hash, key);
|
||||
OPAL_THREAD_UNLOCK(&attr_hash_lock);
|
||||
|
||||
if (OMPI_SUCCESS != ret) {
|
||||
goto exit;
|
||||
}
|
||||
@ -757,13 +743,11 @@ int ompi_attr_delete(ompi_attribute_type_t type, void *object,
|
||||
freed the last attribute that was using the keyval. */
|
||||
|
||||
if (OMPI_SUCCESS == ret) {
|
||||
OPAL_THREAD_LOCK(&keyval_hash_lock);
|
||||
OBJ_RELEASE(keyval);
|
||||
OPAL_THREAD_UNLOCK(&keyval_hash_lock);
|
||||
}
|
||||
|
||||
if (need_lock) {
|
||||
OPAL_THREAD_UNLOCK(&alock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -774,7 +758,7 @@ int ompi_attr_delete(ompi_attribute_type_t type, void *object,
|
||||
*/
|
||||
int ompi_attr_set_c(ompi_attribute_type_t type, void *object,
|
||||
opal_hash_table_t **attr_hash,
|
||||
int key, void *attribute, bool predefined, bool need_lock)
|
||||
int key, void *attribute, bool predefined)
|
||||
{
|
||||
attribute_value_t *new_attr = OBJ_NEW(attribute_value_t);
|
||||
if (NULL == new_attr) {
|
||||
@ -784,7 +768,7 @@ int ompi_attr_set_c(ompi_attribute_type_t type, void *object,
|
||||
new_attr->av_value = attribute;
|
||||
new_attr->av_set_from = OMPI_ATTRIBUTE_C;
|
||||
return set_value(type, object, attr_hash, key, new_attr,
|
||||
predefined, need_lock);
|
||||
predefined);
|
||||
}
|
||||
|
||||
|
||||
@ -795,7 +779,7 @@ int ompi_attr_set_c(ompi_attribute_type_t type, void *object,
|
||||
int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *object,
|
||||
opal_hash_table_t **attr_hash,
|
||||
int key, MPI_Fint attribute,
|
||||
bool predefined, bool need_lock)
|
||||
bool predefined)
|
||||
{
|
||||
attribute_value_t *new_attr = OBJ_NEW(attribute_value_t);
|
||||
if (NULL == new_attr) {
|
||||
@ -806,7 +790,7 @@ int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *object,
|
||||
*new_attr->av_integer_pointer = attribute;
|
||||
new_attr->av_set_from = OMPI_ATTRIBUTE_FORTRAN_MPI1;
|
||||
return set_value(type, object, attr_hash, key, new_attr,
|
||||
predefined, need_lock);
|
||||
predefined);
|
||||
}
|
||||
|
||||
|
||||
@ -817,7 +801,7 @@ int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *object,
|
||||
int ompi_attr_set_fortran_mpi2(ompi_attribute_type_t type, void *object,
|
||||
opal_hash_table_t **attr_hash,
|
||||
int key, MPI_Aint attribute,
|
||||
bool predefined, bool need_lock)
|
||||
bool predefined)
|
||||
{
|
||||
attribute_value_t *new_attr = OBJ_NEW(attribute_value_t);
|
||||
if (NULL == new_attr) {
|
||||
@ -827,7 +811,7 @@ int ompi_attr_set_fortran_mpi2(ompi_attribute_type_t type, void *object,
|
||||
new_attr->av_value = (void *) attribute;
|
||||
new_attr->av_set_from = OMPI_ATTRIBUTE_FORTRAN_MPI2;
|
||||
return set_value(type, object, attr_hash, key, new_attr,
|
||||
predefined, need_lock);
|
||||
predefined);
|
||||
}
|
||||
|
||||
|
||||
@ -903,12 +887,6 @@ int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
|
||||
attribute_value_t *old_attr, *new_attr;
|
||||
ompi_attribute_keyval_t *hash_value;
|
||||
|
||||
/* Protect against the user calling ompi_attr_destroy and then
|
||||
calling any of the functions which use it */
|
||||
if (NULL == keyval_hash) {
|
||||
return MPI_ERR_INTERN;
|
||||
}
|
||||
|
||||
/* If there's nothing to do, just return */
|
||||
|
||||
if (NULL == oldattr_hash) {
|
||||
@ -916,15 +894,15 @@ int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
|
||||
}
|
||||
|
||||
/* Lock this whole sequence of events -- don't let any other
|
||||
thread modify the structure of the keyval hash or bitmap while
|
||||
we're traversing it */
|
||||
|
||||
OPAL_THREAD_LOCK(&alock);
|
||||
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) {
|
||||
@ -933,8 +911,10 @@ int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
|
||||
/* 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) {
|
||||
@ -977,19 +957,21 @@ int ompi_attr_copy_all(ompi_attribute_type_t type, void *old_object,
|
||||
new_attr->av_set_from = OMPI_ATTRIBUTE_C;
|
||||
}
|
||||
set_value(type, new_object, &newattr_hash, key,
|
||||
new_attr, true, false);
|
||||
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 */
|
||||
|
||||
OPAL_THREAD_UNLOCK(&alock);
|
||||
return MPI_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1004,12 +986,6 @@ int ompi_attr_delete_all(ompi_attribute_type_t type, void *object,
|
||||
uint32_t key, oldkey;
|
||||
void *node, *in_node, *old_attr;
|
||||
|
||||
/* Protect against the user calling ompi_attr_destroy and then
|
||||
calling any of the functions which use it */
|
||||
if (NULL == keyval_hash) {
|
||||
return MPI_ERR_INTERN;
|
||||
}
|
||||
|
||||
/* Ensure that the table is not empty */
|
||||
|
||||
if (NULL == attr_hash) {
|
||||
@ -1017,15 +993,16 @@ int ompi_attr_delete_all(ompi_attribute_type_t type, void *object,
|
||||
}
|
||||
|
||||
/* Lock this whole sequence of events -- don't let any other
|
||||
thread modify the structure of the keyval hash or bitmap while
|
||||
we're traversing it */
|
||||
|
||||
OPAL_THREAD_LOCK(&alock);
|
||||
thread modify the structure of the attribute hash or bitmap
|
||||
while we're traversing it */
|
||||
|
||||
OPAL_THREAD_LOCK(&attr_hash_lock);
|
||||
/* Get the first key in local object's hash */
|
||||
key_ret = opal_hash_table_get_first_key_uint32(attr_hash,
|
||||
&key, &old_attr,
|
||||
&node);
|
||||
OPAL_THREAD_UNLOCK(&attr_hash_lock);
|
||||
|
||||
del_ret = OMPI_SUCCESS;
|
||||
while (OMPI_SUCCESS == key_ret && OMPI_SUCCESS == del_ret) {
|
||||
|
||||
@ -1037,17 +1014,19 @@ int ompi_attr_delete_all(ompi_attribute_type_t type, void *object,
|
||||
|
||||
/* Move to the next node */
|
||||
|
||||
OPAL_THREAD_LOCK(&attr_hash_lock);
|
||||
key_ret = opal_hash_table_get_next_key_uint32(attr_hash,
|
||||
&key, &old_attr,
|
||||
in_node, &node);
|
||||
OPAL_THREAD_UNLOCK(&attr_hash_lock);
|
||||
|
||||
/* Now delete this attribute */
|
||||
|
||||
del_ret = ompi_attr_delete(type, object, attr_hash, oldkey, true, false);
|
||||
del_ret = ompi_attr_delete(type, object, attr_hash, oldkey, true);
|
||||
}
|
||||
|
||||
/* All done */
|
||||
|
||||
OPAL_THREAD_UNLOCK(&alock);
|
||||
return del_ret;
|
||||
}
|
||||
|
||||
@ -1059,47 +1038,32 @@ int ompi_attr_delete_all(ompi_attribute_type_t type, void *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, bool need_lock)
|
||||
bool predefined)
|
||||
{
|
||||
ompi_attribute_keyval_t *keyval;
|
||||
int ret, err;
|
||||
attribute_value_t *old_attr;
|
||||
bool had_old = false;
|
||||
|
||||
/* Protect against the user calling ompi_attr_destroy and then
|
||||
calling any of the functions which use it */
|
||||
if (NULL == keyval_hash) {
|
||||
return MPI_ERR_INTERN;
|
||||
}
|
||||
if (NULL == attr_hash) {
|
||||
return MPI_ERR_INTERN;
|
||||
}
|
||||
|
||||
/* 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). In these
|
||||
cases, ompi_attr_copy_all() has already locked the keyval_lock,
|
||||
so we should not try to lock it again. */
|
||||
top-level MPI_* functions that set attributes). */
|
||||
|
||||
if (need_lock) {
|
||||
OPAL_THREAD_LOCK(&alock);
|
||||
}
|
||||
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))) {
|
||||
if (need_lock) {
|
||||
OPAL_THREAD_UNLOCK(&alock);
|
||||
}
|
||||
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);
|
||||
}
|
||||
@ -1108,6 +1072,8 @@ static int set_value(ompi_attribute_type_t type, void *object,
|
||||
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:
|
||||
@ -1123,16 +1089,28 @@ static int set_value(ompi_attribute_type_t type, void *object,
|
||||
break;
|
||||
|
||||
default:
|
||||
if (need_lock) {
|
||||
OPAL_THREAD_UNLOCK(&alock);
|
||||
}
|
||||
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 */
|
||||
@ -1141,11 +1119,6 @@ static int set_value(ompi_attribute_type_t type, void *object,
|
||||
OBJ_RETAIN(keyval);
|
||||
}
|
||||
|
||||
/* Release the lock if we grabbed it */
|
||||
|
||||
if (need_lock) {
|
||||
OPAL_THREAD_UNLOCK(&alock);
|
||||
}
|
||||
if (OMPI_SUCCESS != ret) {
|
||||
return ret;
|
||||
}
|
||||
@ -1174,25 +1147,26 @@ static int get_value(opal_hash_table_t *attr_hash, int key,
|
||||
flag argument */
|
||||
|
||||
*flag = 0;
|
||||
OPAL_THREAD_LOCK(&alock);
|
||||
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 (OMPI_ERR_NOT_FOUND == OPAL_SOS_GET_ERROR_CODE(ret)) {
|
||||
OPAL_THREAD_UNLOCK(&alock);
|
||||
return MPI_KEYVAL_INVALID;
|
||||
}
|
||||
|
||||
/* If we have a null attr_hash table, that means that nothing has
|
||||
been cached on this object yet. So just return *flag = 0. */
|
||||
|
||||
OPAL_THREAD_LOCK(&attr_hash_lock);
|
||||
if (NULL == attr_hash) {
|
||||
OPAL_THREAD_UNLOCK(&alock);
|
||||
OPAL_THREAD_UNLOCK(&attr_hash_lock);
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
ret = opal_hash_table_get_value_uint32(attr_hash, key, &attr);
|
||||
OPAL_THREAD_UNLOCK(&alock);
|
||||
OPAL_THREAD_UNLOCK(&attr_hash_lock);
|
||||
if (OMPI_SUCCESS == ret) {
|
||||
*attribute = (attribute_value_t*)attr;
|
||||
*flag = 1;
|
||||
|
@ -292,18 +292,11 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
|
||||
* @param key Key val for the attribute (IN)
|
||||
* @param attribute The actual attribute pointer (IN)
|
||||
* @param predefined Whether the key is predefined or not 0/1 (IN)
|
||||
* @param need_lock Whether we need to need to lock the keyval_lock or not
|
||||
* @return OMPI error code
|
||||
*
|
||||
* If (*attr_hash) == NULL, a new hash will be created and
|
||||
* initialized.
|
||||
*
|
||||
* Note that need_lock should *always* be true when this function is
|
||||
* invoked from an top-level MPI function. It is only false when this
|
||||
* function is invoked internally (i.e., when we already hold the
|
||||
* relevant locks, and we don't want to try to lock them again,
|
||||
* recursively).
|
||||
*
|
||||
* All three of these functions (ompi_attr_set_c(),
|
||||
* ompi_attr_set_fortran_mpi1(), and ompi_attr_set_fortran_mpi2())
|
||||
* could have been combined into one function that took some kind of
|
||||
@ -317,7 +310,7 @@ int ompi_attr_free_keyval(ompi_attribute_type_t type, int *key,
|
||||
*/
|
||||
int ompi_attr_set_c(ompi_attribute_type_t type, void *object,
|
||||
opal_hash_table_t **attr_hash,
|
||||
int key, void *attribute, bool predefined, bool need_lock);
|
||||
int key, void *attribute, bool predefined);
|
||||
|
||||
/**
|
||||
* Set an attribute on the comm/win/datatype in a form valid for
|
||||
@ -329,18 +322,11 @@ int ompi_attr_set_c(ompi_attribute_type_t type, void *object,
|
||||
* @param key Key val for the attribute (IN)
|
||||
* @param attribute The actual attribute pointer (IN)
|
||||
* @param predefined Whether the key is predefined or not 0/1 (IN)
|
||||
* @param need_lock Whether we need to need to lock the keyval_lock or not
|
||||
* @return OMPI error code
|
||||
*
|
||||
* If (*attr_hash) == NULL, a new hash will be created and
|
||||
* initialized.
|
||||
*
|
||||
* Note that need_lock should *always* be true when this function is
|
||||
* invoked from an top-level MPI function. It is only false when this
|
||||
* function is invoked internally (i.e., when we already hold the
|
||||
* relevant locks, and we don't want to try to lock them again,
|
||||
* recursively).
|
||||
*
|
||||
* All three of these functions (ompi_attr_set_c(),
|
||||
* ompi_attr_set_fortran_mpi1(), and ompi_attr_set_fortran_mpi2())
|
||||
* could have been combined into one function that took some kind of
|
||||
@ -355,7 +341,7 @@ int ompi_attr_set_c(ompi_attribute_type_t type, void *object,
|
||||
OMPI_DECLSPEC int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *object,
|
||||
opal_hash_table_t **attr_hash,
|
||||
int key, MPI_Fint attribute,
|
||||
bool predefined, bool need_lock);
|
||||
bool predefined);
|
||||
|
||||
/**
|
||||
* Set an attribute on the comm/win/datatype in a form valid for
|
||||
@ -367,18 +353,11 @@ OMPI_DECLSPEC int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *o
|
||||
* @param key Key val for the attribute (IN)
|
||||
* @param attribute The actual attribute pointer (IN)
|
||||
* @param predefined Whether the key is predefined or not 0/1 (IN)
|
||||
* @param need_lock Whether we need to need to lock the keyval_lock or not
|
||||
* @return OMPI error code
|
||||
*
|
||||
* If (*attr_hash) == NULL, a new hash will be created and
|
||||
* initialized.
|
||||
*
|
||||
* Note that need_lock should *always* be true when this function is
|
||||
* invoked from an top-level MPI function. It is only false when this
|
||||
* function is invoked internally (i.e., when we already hold the
|
||||
* relevant locks, and we don't want to try to lock them again,
|
||||
* recursively).
|
||||
*
|
||||
* All three of these functions (ompi_attr_set_c(),
|
||||
* ompi_attr_set_fortran_mpi1(), and ompi_attr_set_fortran_mpi2())
|
||||
* could have been combined into one function that took some kind of
|
||||
@ -393,7 +372,7 @@ OMPI_DECLSPEC int ompi_attr_set_fortran_mpi1(ompi_attribute_type_t type, void *o
|
||||
OMPI_DECLSPEC int ompi_attr_set_fortran_mpi2(ompi_attribute_type_t type, void *object,
|
||||
opal_hash_table_t **attr_hash,
|
||||
int key, MPI_Aint attribute,
|
||||
bool predefined, bool need_lock);
|
||||
bool predefined);
|
||||
|
||||
/**
|
||||
* Get an attribute on the comm/win/datatype in a form valid for C.
|
||||
@ -482,19 +461,13 @@ OMPI_DECLSPEC int ompi_attr_get_fortran_mpi2(opal_hash_table_t *attr_hash, int k
|
||||
* @param attr_hash The attribute hash table hanging on the object(IN)
|
||||
* @param key Key val for the attribute (IN)
|
||||
* @param predefined Whether the key is predefined or not 0/1 (IN)
|
||||
* @param need_lock Whether we need to need to lock the keyval_lock or not
|
||||
* @return OMPI error code
|
||||
*
|
||||
* Note that need_lock should *always* be true when this function is
|
||||
* invoked from an top-level MPI function. It is only false when this
|
||||
* function is invoked internally (i.e., when we already hold the
|
||||
* relevant locks, and we don't want to try to lock them again,
|
||||
* recursively).
|
||||
*/
|
||||
|
||||
int ompi_attr_delete(ompi_attribute_type_t type, void *object,
|
||||
opal_hash_table_t *attr_hash , int key,
|
||||
bool predefined, bool need_lock);
|
||||
bool predefined);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -272,5 +272,5 @@ static int set_f(int keyval, MPI_Fint value)
|
||||
return ompi_attr_set_fortran_mpi1(COMM_ATTR, MPI_COMM_WORLD,
|
||||
&MPI_COMM_WORLD->c_keyhash,
|
||||
keyval, value,
|
||||
true, true);
|
||||
true);
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ int MPI_Add_error_class(int *errorclass)
|
||||
&MPI_COMM_WORLD->c_keyhash,
|
||||
MPI_LASTUSEDCODE,
|
||||
ompi_mpi_errcode_lastused,
|
||||
true, true);
|
||||
true);
|
||||
if ( MPI_SUCCESS != rc ) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, rc, FUNC_NAME);
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ int MPI_Add_error_code(int errorclass, int *errorcode)
|
||||
&MPI_COMM_WORLD->c_keyhash,
|
||||
MPI_LASTUSEDCODE,
|
||||
ompi_mpi_errcode_lastused,
|
||||
true, true);
|
||||
true);
|
||||
if ( MPI_SUCCESS != rc ) {
|
||||
return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, rc, FUNC_NAME);
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ int MPI_Attr_delete(MPI_Comm comm, int keyval)
|
||||
OPAL_CR_ENTER_LIBRARY();
|
||||
|
||||
ret = ompi_attr_delete(COMM_ATTR, comm, comm->c_keyhash, keyval,
|
||||
false, true);
|
||||
false);
|
||||
|
||||
OMPI_ERRHANDLER_RETURN(ret, comm, MPI_ERR_OTHER, FUNC_NAME);
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ int MPI_Attr_put(MPI_Comm comm, int keyval, void *attribute_val)
|
||||
OPAL_CR_ENTER_LIBRARY();
|
||||
|
||||
ret = ompi_attr_set_c(COMM_ATTR, comm, &comm->c_keyhash,
|
||||
keyval, attribute_val, false, true);
|
||||
keyval, attribute_val, false);
|
||||
|
||||
OMPI_ERRHANDLER_RETURN(ret, comm, MPI_ERR_OTHER, FUNC_NAME);
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ int MPI_Comm_delete_attr(MPI_Comm comm, int comm_keyval)
|
||||
OPAL_CR_ENTER_LIBRARY();
|
||||
|
||||
ret = ompi_attr_delete(COMM_ATTR, comm, comm->c_keyhash, comm_keyval,
|
||||
false, true);
|
||||
false);
|
||||
|
||||
OMPI_ERRHANDLER_RETURN(ret, comm, MPI_ERR_OTHER, FUNC_NAME);
|
||||
}
|
||||
|
@ -56,6 +56,6 @@ int MPI_Comm_set_attr(MPI_Comm comm, int comm_keyval, void *attribute_val)
|
||||
OPAL_CR_ENTER_LIBRARY();
|
||||
|
||||
ret = ompi_attr_set_c(COMM_ATTR, comm, &comm->c_keyhash,
|
||||
comm_keyval, attribute_val, false, true);
|
||||
comm_keyval, attribute_val, false);
|
||||
OMPI_ERRHANDLER_RETURN(ret, comm, MPI_ERR_OTHER, FUNC_NAME);
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ int MPI_Type_delete_attr (MPI_Datatype type, int type_keyval)
|
||||
OPAL_CR_ENTER_LIBRARY();
|
||||
|
||||
ret = ompi_attr_delete(TYPE_ATTR, type, type->d_keyhash, type_keyval,
|
||||
false, true);
|
||||
false);
|
||||
OMPI_ERRHANDLER_RETURN(ret, MPI_COMM_WORLD,
|
||||
MPI_ERR_OTHER, FUNC_NAME);
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ int MPI_Type_set_attr (MPI_Datatype type,
|
||||
OPAL_CR_ENTER_LIBRARY();
|
||||
|
||||
ret = ompi_attr_set_c(TYPE_ATTR, type, &type->d_keyhash,
|
||||
type_keyval, attribute_val, false, true);
|
||||
type_keyval, attribute_val, false);
|
||||
|
||||
OMPI_ERRHANDLER_RETURN(ret, MPI_COMM_WORLD,
|
||||
MPI_ERR_OTHER, FUNC_NAME);
|
||||
|
@ -51,6 +51,6 @@ int MPI_Win_delete_attr(MPI_Win win, int win_keyval)
|
||||
OPAL_CR_ENTER_LIBRARY();
|
||||
|
||||
ret = ompi_attr_delete(WIN_ATTR, win, win->w_keyhash, win_keyval,
|
||||
false, true);
|
||||
false);
|
||||
OMPI_ERRHANDLER_RETURN(ret, win, MPI_ERR_OTHER, FUNC_NAME);
|
||||
}
|
||||
|
@ -51,6 +51,6 @@ int MPI_Win_set_attr(MPI_Win win, int win_keyval, void *attribute_val)
|
||||
OPAL_CR_ENTER_LIBRARY();
|
||||
|
||||
ret = ompi_attr_set_c(WIN_ATTR, win, &win->w_keyhash,
|
||||
win_keyval, attribute_val, false, true);
|
||||
win_keyval, attribute_val, false);
|
||||
OMPI_ERRHANDLER_RETURN(ret, win, MPI_ERR_OTHER, FUNC_NAME);
|
||||
}
|
||||
|
@ -73,6 +73,6 @@ void mpi_attr_put_f(MPI_Fint *comm, MPI_Fint *keyval, MPI_Fint *attribute_val,
|
||||
&c_comm->c_keyhash,
|
||||
OMPI_FINT_2_INT(*keyval),
|
||||
*attribute_val,
|
||||
false, true);
|
||||
false);
|
||||
*ierr = OMPI_INT_2_FINT(c_err);
|
||||
}
|
||||
|
@ -73,6 +73,6 @@ void mpi_comm_set_attr_f(MPI_Fint *comm, MPI_Fint *comm_keyval,
|
||||
&c_comm->c_keyhash,
|
||||
OMPI_FINT_2_INT(*comm_keyval),
|
||||
*attribute_val,
|
||||
false, true);
|
||||
false);
|
||||
*ierr = OMPI_INT_2_FINT(c_err);
|
||||
}
|
||||
|
@ -72,6 +72,6 @@ void mpi_type_set_attr_f(MPI_Fint *type, MPI_Fint *type_keyval, MPI_Aint *attrib
|
||||
&c_type->d_keyhash,
|
||||
OMPI_FINT_2_INT(*type_keyval),
|
||||
*attribute_val,
|
||||
false, true);
|
||||
false);
|
||||
*ierr = OMPI_INT_2_FINT(c_err);
|
||||
}
|
||||
|
@ -74,6 +74,6 @@ void mpi_win_set_attr_f(MPI_Fint *win, MPI_Fint *win_keyval,
|
||||
&c_win->w_keyhash,
|
||||
OMPI_FINT_2_INT(*win_keyval),
|
||||
*attribute_val,
|
||||
false, true);
|
||||
false);
|
||||
*ierr = OMPI_INT_2_FINT(c_err);
|
||||
}
|
||||
|
@ -103,14 +103,14 @@ ompi_win_create(void *base, size_t size,
|
||||
|
||||
/* Fill in required attributes */
|
||||
ret = ompi_attr_set_c(WIN_ATTR, win, &win->w_keyhash,
|
||||
MPI_WIN_BASE, win->w_baseptr, true, true);
|
||||
MPI_WIN_BASE, win->w_baseptr, true);
|
||||
if (OMPI_SUCCESS != ret) {
|
||||
OBJ_RELEASE(win);
|
||||
return ret;
|
||||
}
|
||||
ret = ompi_attr_set_fortran_mpi2(WIN_ATTR, win,
|
||||
&win->w_keyhash,
|
||||
MPI_WIN_SIZE, win->w_size, true, true);
|
||||
MPI_WIN_SIZE, win->w_size, true);
|
||||
if (OMPI_SUCCESS != ret) {
|
||||
OBJ_RELEASE(win);
|
||||
return ret;
|
||||
@ -118,7 +118,7 @@ ompi_win_create(void *base, size_t size,
|
||||
ret = ompi_attr_set_fortran_mpi2(WIN_ATTR, win,
|
||||
&win->w_keyhash,
|
||||
MPI_WIN_DISP_UNIT, win->w_disp_unit,
|
||||
true, true);
|
||||
true);
|
||||
if (OMPI_SUCCESS != ret) {
|
||||
OBJ_RELEASE(win);
|
||||
return ret;
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user