2005-08-09 23:32:49 +04:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2004-2005 The Trustees of Indiana University.
|
|
|
|
* All rights reserved.
|
|
|
|
* Copyright (c) 2004-2005 The Trustees of the University of Tennessee.
|
|
|
|
* All rights reserved.
|
|
|
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
|
|
|
* University of Stuttgart. All rights reserved.
|
|
|
|
* Copyright (c) 2004-2005 The Regents of the University of California.
|
|
|
|
* All rights reserved.
|
|
|
|
* $COPYRIGHT$
|
|
|
|
*
|
|
|
|
* Additional copyrights may follow
|
|
|
|
*
|
|
|
|
* $HEADER$
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ompi_config.h"
|
|
|
|
|
2005-08-10 23:20:47 +04:00
|
|
|
#include <sys/types.h>
|
|
|
|
|
2005-08-09 23:32:49 +04:00
|
|
|
#include "opal/memory/memory.h"
|
|
|
|
#include "opal/memory/memory_internal.h"
|
|
|
|
#include "opal/class/opal_list.h"
|
2005-08-10 02:40:42 +04:00
|
|
|
#include "opal/class/opal_object.h"
|
2005-08-13 00:46:25 +04:00
|
|
|
#include "ompi/include/constants.h"
|
2005-08-09 23:32:49 +04:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* local types
|
|
|
|
*/
|
|
|
|
struct callback_list_item_t {
|
|
|
|
opal_list_item_t super;
|
2005-08-10 02:40:42 +04:00
|
|
|
opal_mem_free_unpin_fn_t *cbfunc;
|
2005-08-09 23:32:49 +04:00
|
|
|
void *cbdata;
|
|
|
|
};
|
|
|
|
typedef struct callback_list_item_t callback_list_item_t;
|
2005-08-10 02:40:42 +04:00
|
|
|
static OBJ_CLASS_INSTANCE(callback_list_item_t, opal_list_item_t, NULL, NULL);
|
2005-08-09 23:32:49 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* local data
|
|
|
|
*/
|
|
|
|
static opal_list_t callback_list;
|
|
|
|
static opal_atomic_lock_t callback_lock;
|
2005-08-12 17:35:01 +04:00
|
|
|
static int have_free_support = false;
|
|
|
|
static int run_callbacks = false;
|
2005-08-10 02:40:42 +04:00
|
|
|
|
2005-08-09 23:32:49 +04:00
|
|
|
|
|
|
|
int
|
|
|
|
opal_mem_free_init(void)
|
|
|
|
{
|
2005-08-10 02:40:42 +04:00
|
|
|
OBJ_CONSTRUCT(&callback_list, opal_list_t);
|
2005-08-09 23:32:49 +04:00
|
|
|
opal_atomic_init(&callback_lock, OPAL_ATOMIC_UNLOCKED);
|
2005-08-10 02:40:42 +04:00
|
|
|
|
2005-08-12 17:35:01 +04:00
|
|
|
/* delay running callbacks until there is something in the
|
|
|
|
registration */
|
|
|
|
run_callbacks = false;
|
2005-08-10 04:43:47 +04:00
|
|
|
opal_atomic_mb();
|
|
|
|
|
2005-08-10 02:40:42 +04:00
|
|
|
return OMPI_SUCCESS;
|
2005-08-09 23:32:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
opal_mem_free_finalize(void)
|
|
|
|
{
|
|
|
|
opal_list_item_t *item;
|
2005-08-10 04:43:47 +04:00
|
|
|
|
|
|
|
run_callbacks = false;
|
|
|
|
opal_atomic_mb();
|
|
|
|
|
|
|
|
/* aquire the lock, just to make sure no one is currently
|
|
|
|
twiddling with the list. We know this won't last long, since
|
|
|
|
no new calls will come in twiddle with the list */
|
|
|
|
opal_atomic_lock(&callback_lock);
|
2005-08-09 23:32:49 +04:00
|
|
|
|
|
|
|
while (NULL != (item = opal_list_remove_first(&callback_list))) {
|
|
|
|
OBJ_RELEASE(item);
|
|
|
|
}
|
|
|
|
OBJ_DESTRUCT(&callback_list);
|
2005-08-10 02:40:42 +04:00
|
|
|
|
2005-08-10 04:43:47 +04:00
|
|
|
opal_atomic_unlock(&callback_lock);
|
|
|
|
|
2005-08-10 02:40:42 +04:00
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* called from memory manager / memory-manager specific hooks */
|
|
|
|
void
|
2005-08-12 17:35:01 +04:00
|
|
|
opal_mem_free_set_free_support(int support)
|
2005-08-10 02:40:42 +04:00
|
|
|
{
|
|
|
|
have_free_support = support;
|
2005-08-09 23:32:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* called from the memory manager / memory-manager specific hooks */
|
|
|
|
void
|
|
|
|
opal_mem_free_release_hook(void *buf, size_t length)
|
|
|
|
{
|
|
|
|
opal_list_item_t *item;
|
|
|
|
|
2005-08-10 04:43:47 +04:00
|
|
|
if (!run_callbacks) return;
|
|
|
|
|
2005-08-09 23:32:49 +04:00
|
|
|
opal_atomic_lock(&callback_lock);
|
|
|
|
|
|
|
|
for (item = opal_list_get_first(&callback_list) ;
|
|
|
|
item != opal_list_get_end(&callback_list) ;
|
|
|
|
item = opal_list_get_next(item)) {
|
|
|
|
callback_list_item_t *cbitem = (callback_list_item_t*) item;
|
|
|
|
|
|
|
|
cbitem->cbfunc(buf, length, cbitem->cbdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
opal_atomic_unlock(&callback_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
opal_mem_free_is_supported(void)
|
|
|
|
{
|
2005-08-12 17:35:01 +04:00
|
|
|
return (bool) have_free_support;
|
2005-08-09 23:32:49 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2005-08-10 02:40:42 +04:00
|
|
|
opal_mem_free_register_handler(opal_mem_free_unpin_fn_t *func, void *cbdata)
|
2005-08-09 23:32:49 +04:00
|
|
|
{
|
|
|
|
opal_list_item_t *item;
|
|
|
|
callback_list_item_t *cbitem;
|
|
|
|
int ret = OMPI_SUCCESS;
|
|
|
|
|
|
|
|
if (!have_free_support) return OMPI_ERR_NOT_SUPPORTED;
|
|
|
|
|
2005-08-12 17:35:01 +04:00
|
|
|
/* we either have or are about to have a registration that needs
|
|
|
|
calling back. Let the system know it needs to run callbacks
|
|
|
|
now */
|
|
|
|
run_callbacks = true;
|
|
|
|
opal_atomic_mb();
|
|
|
|
|
2005-08-09 23:32:49 +04:00
|
|
|
opal_atomic_lock(&callback_lock);
|
|
|
|
|
|
|
|
/* make sure the callback isn't already in the list */
|
|
|
|
for (item = opal_list_get_first(&callback_list) ;
|
|
|
|
item != opal_list_get_end(&callback_list) ;
|
|
|
|
item = opal_list_get_next(item)) {
|
|
|
|
cbitem = (callback_list_item_t*) item;
|
|
|
|
|
|
|
|
if (cbitem->cbfunc == func) {
|
|
|
|
ret = OMPI_EXISTS;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cbitem = OBJ_NEW(callback_list_item_t);
|
|
|
|
if (NULL == cbitem) {
|
|
|
|
ret = OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
cbitem->cbfunc = func;
|
|
|
|
cbitem->cbdata = cbdata;
|
|
|
|
|
2005-08-10 02:40:42 +04:00
|
|
|
opal_list_append(&callback_list, (opal_list_item_t*) cbitem);
|
2005-08-09 23:32:49 +04:00
|
|
|
|
|
|
|
done:
|
|
|
|
opal_atomic_unlock(&callback_lock);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2005-08-10 02:40:42 +04:00
|
|
|
opal_mem_free_unregister_handler(opal_mem_free_unpin_fn_t *func)
|
2005-08-09 23:32:49 +04:00
|
|
|
{
|
|
|
|
opal_list_item_t *item;
|
2005-08-25 20:28:41 +04:00
|
|
|
opal_list_item_t *found_item = NULL;
|
2005-08-09 23:32:49 +04:00
|
|
|
callback_list_item_t *cbitem;
|
|
|
|
int ret = OMPI_ERR_NOT_FOUND;
|
|
|
|
|
|
|
|
opal_atomic_lock(&callback_lock);
|
|
|
|
|
|
|
|
/* make sure the callback isn't already in the list */
|
|
|
|
for (item = opal_list_get_first(&callback_list) ;
|
|
|
|
item != opal_list_get_end(&callback_list) ;
|
|
|
|
item = opal_list_get_next(item)) {
|
|
|
|
cbitem = (callback_list_item_t*) item;
|
|
|
|
|
|
|
|
if (cbitem->cbfunc == func) {
|
|
|
|
opal_list_remove_item(&callback_list, item);
|
2005-08-25 20:28:41 +04:00
|
|
|
found_item = item;
|
2005-08-09 23:32:49 +04:00
|
|
|
ret = OMPI_SUCCESS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
opal_atomic_unlock(&callback_lock);
|
|
|
|
|
2005-08-25 20:28:41 +04:00
|
|
|
/* OBJ_RELEASE calls free, so we can't release until we get out of
|
|
|
|
the lock */
|
|
|
|
if (NULL != found_item) {
|
|
|
|
OBJ_RELEASE(item);
|
|
|
|
}
|
|
|
|
|
2005-08-09 23:32:49 +04:00
|
|
|
return ret;
|
|
|
|
}
|