root/opal/memoryhooks/memory.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. opal_mem_hooks_finalize
  2. opal_mem_hooks_init
  3. opal_mem_hooks_set_support
  4. opal_mem_hooks_release_hook
  5. opal_mem_hooks_support_level
  6. opal_mem_hooks_register_release
  7. opal_mem_hooks_unregister_release

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2006 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2017      Los Alamos National Security, LLC.  All rights
  14  *                         reserved.
  15  * $COPYRIGHT$
  16  *
  17  * Additional copyrights may follow
  18  *
  19  * $HEADER$
  20  */
  21 
  22 #include "opal_config.h"
  23 
  24 #ifdef HAVE_SYS_TYPES_H
  25 #include <sys/types.h>
  26 #endif  /* HAVE_SYS_TYPES_H */
  27 #ifdef HAVE_SYS_MMAN_H
  28 #include <sys/mman.h>
  29 #endif  /* HAVE_SYS_MMAN_H */
  30 
  31 #include "opal/constants.h"
  32 #include "opal/memoryhooks/memory.h"
  33 #include "opal/memoryhooks/memory_internal.h"
  34 #include "opal/class/opal_list.h"
  35 #include "opal/class/opal_object.h"
  36 #include "opal/sys/atomic.h"
  37 #include "opal/runtime/opal.h"
  38 
  39 /*
  40  * local types
  41  */
  42 struct callback_list_item_t {
  43     opal_list_item_t super;
  44     opal_mem_hooks_callback_fn_t *cbfunc;
  45     void *cbdata;
  46 };
  47 typedef struct callback_list_item_t callback_list_item_t;
  48 static OBJ_CLASS_INSTANCE(callback_list_item_t, opal_list_item_t, NULL, NULL);
  49 
  50 /*
  51  * local data
  52  */
  53 static int hooks_support = 0;
  54 
  55 static opal_list_t release_cb_list;
  56 static opal_atomic_lock_t release_lock;
  57 static int release_run_callbacks;
  58 
  59 /**
  60  * Finalize the memory hooks subsystem
  61  *
  62  * Finalize the memory hooks subsystem.  This is generally called
  63  * during opal_finalize() and no other memory hooks functions should
  64  * be called after this function is called.  opal_mem_hooks_finalize()
  65  * will automatically deregister any callbacks that have not already
  66  * been deregistered.  In a multi-threaded application, it is possible
  67  * that one thread will have a memory hook callback while the other
  68  * thread is in opal_mem_hooks_finalize(), however, no threads will
  69  * receive a callback once the calling thread has exited
  70  * opal_mem_hooks_finalize().
  71  *
  72  * @retval OPAL_SUCCESS Shutdown completed successfully
  73  */
  74 static void opal_mem_hooks_finalize(void)
  75 {
  76     /* don't try to run callbacks any more */
  77     release_run_callbacks = false;
  78     opal_atomic_mb();
  79 
  80     /* aquire the lock, just to make sure no one is currently
  81        twiddling with the list.  We know this won't last long, since
  82        no new calls will come in after we set run_callbacks to false */
  83     opal_atomic_lock(&release_lock);
  84 
  85     /* clean out the lists */
  86     OPAL_LIST_DESTRUCT(&release_cb_list);
  87 
  88     opal_atomic_unlock(&release_lock);
  89 }
  90 
  91 int opal_mem_hooks_init (void)
  92 {
  93     OBJ_CONSTRUCT(&release_cb_list, opal_list_t);
  94 
  95     opal_atomic_lock_init(&release_lock, OPAL_ATOMIC_LOCK_UNLOCKED);
  96 
  97     /* delay running callbacks until there is something in the
  98        registration */
  99     release_run_callbacks = false;
 100     opal_atomic_mb();
 101 
 102     opal_finalize_register_cleanup (opal_mem_hooks_finalize);
 103 
 104     return OPAL_SUCCESS;
 105 }
 106 
 107 
 108 
 109 /* called from memory manager / memory-manager specific hooks */
 110 void
 111 opal_mem_hooks_set_support(int support)
 112 {
 113     hooks_support = support;
 114 }
 115 
 116 
 117 /* called from the memory manager / memory-manager specific hooks */
 118 void
 119 opal_mem_hooks_release_hook(void *buf, size_t length, bool from_alloc)
 120 {
 121     callback_list_item_t *cbitem, *next;
 122 
 123     if (!release_run_callbacks) return;
 124 
 125     /*
 126      * This is not really thread safe - but we can't hold the lock
 127      * while calling the callback function as this routine can
 128      * be called recursively.
 129      *
 130      * Instead, we could set a flag if we are already in the callback,
 131      * and if called recursively queue the new address/length and allow
 132      * the initial callback to dispatch this
 133      */
 134 
 135     opal_atomic_lock(&release_lock);
 136     OPAL_LIST_FOREACH_SAFE(cbitem, next, &release_cb_list, callback_list_item_t) {
 137         opal_atomic_unlock(&release_lock);
 138         cbitem->cbfunc(buf, length, cbitem->cbdata, (bool) from_alloc);
 139         opal_atomic_lock(&release_lock);
 140     }
 141     opal_atomic_unlock(&release_lock);
 142 }
 143 
 144 
 145 int
 146 opal_mem_hooks_support_level(void)
 147 {
 148     return hooks_support;
 149 }
 150 
 151 
 152 int
 153 opal_mem_hooks_register_release(opal_mem_hooks_callback_fn_t *func, void *cbdata)
 154 {
 155     callback_list_item_t *cbitem, *new_cbitem;
 156     int ret = OPAL_SUCCESS;
 157 
 158     if (0 == ((OPAL_MEMORY_FREE_SUPPORT|OPAL_MEMORY_MUNMAP_SUPPORT) & hooks_support)) {
 159         return OPAL_ERR_NOT_SUPPORTED;
 160     }
 161 
 162     /* pre-allocate a callback item on the assumption it won't be
 163        found.  We can't call OBJ_NEW inside the lock because it might
 164        call alloc / realloc */
 165     new_cbitem = OBJ_NEW(callback_list_item_t);
 166     if (NULL == new_cbitem) {
 167         ret = OPAL_ERR_OUT_OF_RESOURCE;
 168         goto done;
 169     }
 170 
 171     opal_atomic_lock(&release_lock);
 172     /* we either have or are about to have a registration that needs
 173        calling back.  Let the system know it needs to run callbacks
 174        now */
 175     release_run_callbacks = true;
 176     opal_atomic_mb();
 177 
 178     /* make sure the callback isn't already in the list */
 179     OPAL_LIST_FOREACH(cbitem, &release_cb_list, callback_list_item_t) {
 180         if (cbitem->cbfunc == func) {
 181             ret = OPAL_EXISTS;
 182             goto done;
 183         }
 184     }
 185 
 186     new_cbitem->cbfunc = func;
 187     new_cbitem->cbdata = cbdata;
 188 
 189     opal_list_append(&release_cb_list, (opal_list_item_t*) new_cbitem);
 190 
 191  done:
 192     opal_atomic_unlock(&release_lock);
 193 
 194     if (OPAL_EXISTS == ret && NULL != new_cbitem) {
 195         OBJ_RELEASE(new_cbitem);
 196     }
 197 
 198     return ret;
 199 }
 200 
 201 
 202 int
 203 opal_mem_hooks_unregister_release(opal_mem_hooks_callback_fn_t* func)
 204 {
 205     callback_list_item_t *cbitem, *found_item = NULL;
 206     int ret = OPAL_ERR_NOT_FOUND;
 207 
 208     opal_atomic_lock(&release_lock);
 209 
 210     /* make sure the callback isn't already in the list */
 211     OPAL_LIST_FOREACH(cbitem, &release_cb_list, callback_list_item_t) {
 212         if (cbitem->cbfunc == func) {
 213             opal_list_remove_item(&release_cb_list, (opal_list_item_t *) cbitem);
 214             found_item = cbitem;
 215             ret = OPAL_SUCCESS;
 216             break;
 217         }
 218     }
 219 
 220     opal_atomic_unlock(&release_lock);
 221 
 222     /* OBJ_RELEASE calls free, so we can't release until we get out of
 223        the lock */
 224     if (NULL != found_item) {
 225         OBJ_RELEASE(found_item);
 226     }
 227 
 228     return ret;
 229 }

/* [<][>][^][v][top][bottom][index][help] */