1
1

* fix deadlock in memory code that occurs if OBJ_NEW calls realloc to

expand it's class list array by pre-allocating the callback item before
  we obtain the lock (we free it if we ended up not needing it)

This commit was SVN r7533.
Этот коммит содержится в:
Brian Barrett 2005-09-28 16:40:19 +00:00
родитель 67dd52efb1
Коммит ad62411a15

Просмотреть файл

@ -154,7 +154,7 @@ int
opal_mem_free_register_handler(opal_mem_free_unpin_fn_t *func, void *cbdata) opal_mem_free_register_handler(opal_mem_free_unpin_fn_t *func, void *cbdata)
{ {
opal_list_item_t *item; opal_list_item_t *item;
callback_list_item_t *cbitem; callback_list_item_t *cbitem, *new_cbitem;
int ret = OMPI_SUCCESS; int ret = OMPI_SUCCESS;
if (!have_free_support) return OMPI_ERR_NOT_SUPPORTED; if (!have_free_support) return OMPI_ERR_NOT_SUPPORTED;
@ -165,6 +165,15 @@ opal_mem_free_register_handler(opal_mem_free_unpin_fn_t *func, void *cbdata)
run_callbacks = true; run_callbacks = true;
opal_atomic_mb(); opal_atomic_mb();
/* pre-allocate a callback item on the assumption it won't be
found. We can't call OBJ_NEW inside the lock because it might
call realloc */
new_cbitem = OBJ_NEW(callback_list_item_t);
if (NULL == new_cbitem) {
ret = OMPI_ERR_OUT_OF_RESOURCE;
goto done;
}
opal_atomic_lock(&callback_lock); opal_atomic_lock(&callback_lock);
/* make sure the callback isn't already in the list */ /* make sure the callback isn't already in the list */
@ -179,18 +188,16 @@ opal_mem_free_register_handler(opal_mem_free_unpin_fn_t *func, void *cbdata)
} }
} }
cbitem = OBJ_NEW(callback_list_item_t); new_cbitem->cbfunc = func;
if (NULL == cbitem) { new_cbitem->cbdata = cbdata;
ret = OMPI_ERR_OUT_OF_RESOURCE;
goto done;
}
cbitem->cbfunc = func; opal_list_append(&callback_list, (opal_list_item_t*) new_cbitem);
cbitem->cbdata = cbdata;
opal_list_append(&callback_list, (opal_list_item_t*) cbitem);
done: done:
if (OMPI_EXISTS == rc && NULL != new_cbitem) {
OBJ_RELEASE(new_cbitem);
}
opal_atomic_unlock(&callback_lock); opal_atomic_unlock(&callback_lock);
return ret; return ret;
} }