Blame src/include/mpir_handlemem.h

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 *  (C) 2001 by Argonne National Laboratory.
Packit Service c5cf8c
 *      See COPYRIGHT in top-level directory.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 */
Packit Service c5cf8c
Packit Service c5cf8c
#ifndef MPIR_HANDLEMEM_H_INCLUDED
Packit Service c5cf8c
#define MPIR_HANDLEMEM_H_INCLUDED
Packit Service c5cf8c
Packit Service c5cf8c
#include "mpichconfconst.h"
Packit Service c5cf8c
#include "mpichconf.h"
Packit Service c5cf8c
#include "mpir_objects.h"
Packit Service c5cf8c
#include "mpir_thread.h"
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef MPICH_DEBUG_HANDLEALLOC
Packit Service c5cf8c
int MPIR_check_handles_on_finalize(void *objmem_ptr);
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
/* This is the utility file for info that contains routines used to
Packit Service c5cf8c
   manage the arrays used to store handle objects.
Packit Service c5cf8c
Packit Service c5cf8c
   To use these routines, allocate the following in a utility file
Packit Service c5cf8c
   used by each object (e.g., info, datatype, comm, group, ...).
Packit Service c5cf8c
   (The comment format // is used in this example but the usual
Packit Service c5cf8c
   C comment convention should be used of course.)  The usage is described
Packit Service c5cf8c
   below.
Packit Service c5cf8c
Packit Service c5cf8c
   // Declarations begin here
Packit Service c5cf8c
   // Static declaration of the information about the block
Packit Service c5cf8c
   // Define the number of preallocated entries # omitted)
Packit Service c5cf8c
   define MPID_<OBJ>_PREALLOC 256
Packit Service c5cf8c
   MPIR_Object_alloc_t MPID_<obj>_mem = { 0, 0, 0, 0, MPID_<obj>,
Packit Service c5cf8c
                                          sizeof(MPID_<obj>), MPID_<obj>_direct,
Packit Service c5cf8c
                                          MPID_<OBJ>_PREALLOC, };
Packit Service c5cf8c
Packit Service c5cf8c
   // Preallocated objects
Packit Service c5cf8c
   MPID_<obj> MPID_<obj>_direct[MPID_<OBJ>_PREALLOC];
Packit Service c5cf8c
   static int initialized = 0;
Packit Service c5cf8c
Packit Service c5cf8c
   // Next available object
Packit Service c5cf8c
   static int MPID_<obj> *avail = 0;
Packit Service c5cf8c
Packit Service c5cf8c
   // Extension (indirect) objects
Packit Service c5cf8c
   static MPID_<obj> *(*MPID_<obj>_indirect)[] = 0;
Packit Service c5cf8c
   static int MPID_<obj>_indirect_size = 0;
Packit Service c5cf8c
    // Declarations end here
Packit Service c5cf8c
Packit Service c5cf8c
   These provide for lazy initialization; applications that do not need a
Packit Service c5cf8c
   particular object will not include any of the code or even reference
Packit Service c5cf8c
   the space.
Packit Service c5cf8c
Packit Service c5cf8c
   Note that these routines are designed for the MPI objects, and include the
Packit Service c5cf8c
   creation of a "handle" that is appropriate for the MPI object value.
Packit Service c5cf8c
Packit Service c5cf8c
   None of these routines is thread-safe.  Any routine that uses them
Packit Service c5cf8c
   must ensure that only one thread at a time may call them.
Packit Service c5cf8c
*/
Packit Service c5cf8c
Packit Service c5cf8c
/* This routine is called by finalize when MPI exits */
Packit Service c5cf8c
static inline int MPIR_Handle_free(void *((*indirect)[]), int indirect_size)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int i;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Remove any allocated storage */
Packit Service c5cf8c
    for (i = 0; i < indirect_size; i++) {
Packit Service c5cf8c
        MPL_free((*indirect)[i]);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if (indirect) {
Packit Service c5cf8c
        MPL_free(indirect);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    /* This does *not* remove any objects that the user created
Packit Service c5cf8c
     * and then did not destroy */
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#if defined(MPL_VG_AVAILABLE)
Packit Service c5cf8c
#define HANDLE_VG_LABEL(objptr_, objsize_, handle_type_, is_direct_)                             \
Packit Service c5cf8c
    do {                                                                                         \
Packit Service c5cf8c
        if (MPL_VG_RUNNING_ON_VALGRIND()) {                                                      \
Packit Service c5cf8c
            char desc_str[256];                                                                  \
Packit Service c5cf8c
            MPL_snprintf(desc_str, sizeof(desc_str)-1,                                           \
Packit Service c5cf8c
                          "[MPICH handle: objptr=%p handle=0x%x %s/%s]",                         \
Packit Service c5cf8c
                          (objptr_), (objptr_)->handle,                                          \
Packit Service c5cf8c
                          ((is_direct_) ? "DIRECT" : "INDIRECT"),                                \
Packit Service c5cf8c
                          MPIR_Handle_get_kind_str(handle_type_));                               \
Packit Service c5cf8c
            /* we don't keep track of the block descriptor because the handle */                 \
Packit Service c5cf8c
            /* values never change once allocated */                                             \
Packit Service c5cf8c
            MPL_VG_CREATE_BLOCK((objptr_), (objsize_), desc_str);                                \
Packit Service c5cf8c
        }                                                                                        \
Packit Service c5cf8c
    } while (0)
Packit Service c5cf8c
#else
Packit Service c5cf8c
#define HANDLE_VG_LABEL(objptr_, objsize_, handle_type_, is_direct_) do {} while (0)
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
static inline void *MPIR_Handle_direct_init(void *direct,
Packit Service c5cf8c
                                            int direct_size, int obj_size, int handle_type)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int i;
Packit Service c5cf8c
    MPIR_Handle_common *hptr = 0;
Packit Service c5cf8c
    char *ptr = (char *) direct;
Packit Service c5cf8c
Packit Service c5cf8c
    for (i = 0; i < direct_size; i++) {
Packit Service c5cf8c
        /* printf("Adding %p in %d\n", ptr, handle_type); */
Packit Service c5cf8c
        /* First cast to (void*) to avoid false warnings about alignment
Packit Service c5cf8c
         * (consider that a requirement of the input parameters) */
Packit Service c5cf8c
        hptr = (MPIR_Handle_common *) (void *) ptr;
Packit Service c5cf8c
        ptr = ptr + obj_size;
Packit Service c5cf8c
        hptr->next = ptr;
Packit Service c5cf8c
        hptr->handle = ((unsigned) HANDLE_KIND_DIRECT << HANDLE_KIND_SHIFT) |
Packit Service c5cf8c
            (handle_type << HANDLE_MPI_KIND_SHIFT) | i;
Packit Service c5cf8c
Packit Service c5cf8c
        HANDLE_VG_LABEL(hptr, obj_size, handle_type, 1);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if (hptr)
Packit Service c5cf8c
        hptr->next = 0;
Packit Service c5cf8c
    return direct;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* indirect is really a pointer to a pointer to an array of pointers */
Packit Service c5cf8c
static inline void *MPIR_Handle_indirect_init(void *(**indirect)[],
Packit Service c5cf8c
                                              int *indirect_size,
Packit Service c5cf8c
                                              int indirect_num_blocks,
Packit Service c5cf8c
                                              int indirect_num_indices,
Packit Service c5cf8c
                                              int obj_size, int handle_type)
Packit Service c5cf8c
{
Packit Service c5cf8c
    void *block_ptr;
Packit Service c5cf8c
    MPIR_Handle_common *hptr = 0;
Packit Service c5cf8c
    char *ptr;
Packit Service c5cf8c
    int i;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Must create new storage for dynamically allocated objects */
Packit Service c5cf8c
    /* Create the table */
Packit Service c5cf8c
    if (!*indirect) {
Packit Service c5cf8c
        /* printf("Creating indirect table with %d pointers to blocks in it\n", indirect_num_blocks); */
Packit Service c5cf8c
        *indirect = (void *) MPL_calloc(indirect_num_blocks, sizeof(void *), MPL_MEM_OBJECT);
Packit Service c5cf8c
        if (!*indirect) {
Packit Service c5cf8c
            return 0;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        *indirect_size = 0;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* See if we can allocate another block */
Packit Service c5cf8c
    if (*indirect_size >= indirect_num_blocks) {
Packit Service c5cf8c
        /* printf("Out of space in indirect table\n"); */
Packit Service c5cf8c
        return 0;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* Create the next block */
Packit Service c5cf8c
    /* printf("Creating indirect block number %d with %d objects in it\n", *indirect_size, indirect_num_indices); */
Packit Service c5cf8c
    block_ptr = (void *) MPL_calloc(indirect_num_indices, obj_size, MPL_MEM_OBJECT);
Packit Service c5cf8c
    if (!block_ptr) {
Packit Service c5cf8c
        return 0;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    ptr = (char *) block_ptr;
Packit Service c5cf8c
    for (i = 0; i < indirect_num_indices; i++) {
Packit Service c5cf8c
        /* Cast to (void*) to avoid false warning about alignment */
Packit Service c5cf8c
        hptr = (MPIR_Handle_common *) (void *) ptr;
Packit Service c5cf8c
        ptr = ptr + obj_size;
Packit Service c5cf8c
        hptr->next = ptr;
Packit Service c5cf8c
        hptr->handle = ((unsigned) HANDLE_KIND_INDIRECT << HANDLE_KIND_SHIFT) |
Packit Service c5cf8c
            (handle_type << HANDLE_MPI_KIND_SHIFT) | (*indirect_size << HANDLE_INDIRECT_SHIFT) | i;
Packit Service c5cf8c
        /* printf("handle=%#x handle_type=%x *indirect_size=%d i=%d\n", hptr->handle, handle_type, *indirect_size, i); */
Packit Service c5cf8c
Packit Service c5cf8c
        HANDLE_VG_LABEL(hptr, obj_size, handle_type, 0);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    hptr->next = 0;
Packit Service c5cf8c
    /* We're here because avail is null, so there is no need to set
Packit Service c5cf8c
     * the last block ptr to avail */
Packit Service c5cf8c
    /* printf("loc of update is %x\n", &(**indirect)[*indirect_size]);  */
Packit Service c5cf8c
    (**indirect)[*indirect_size] = block_ptr;
Packit Service c5cf8c
    *indirect_size = *indirect_size + 1;
Packit Service c5cf8c
    return block_ptr;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
static inline int MPIR_Handle_finalize(void *objmem_ptr)
Packit Service c5cf8c
{
Packit Service c5cf8c
    MPIR_Object_alloc_t *objmem = (MPIR_Object_alloc_t *) objmem_ptr;
Packit Service c5cf8c
Packit Service c5cf8c
    (void) MPIR_Handle_free(objmem->indirect, objmem->indirect_size);
Packit Service c5cf8c
    /* This does *not* remove any Info objects that the user created
Packit Service c5cf8c
     * and then did not destroy */
Packit Service c5cf8c
Packit Service c5cf8c
    /* at this point we are done with the memory pool, inform valgrind */
Packit Service c5cf8c
    MPL_VG_DESTROY_MEMPOOL(objmem_ptr);
Packit Service c5cf8c
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/*+
Packit Service c5cf8c
  MPIR_Handle_obj_alloc - Create an object using the handle allocator
Packit Service c5cf8c
Packit Service c5cf8c
Input Parameters:
Packit Service c5cf8c
. objmem - Pointer to object memory block.
Packit Service c5cf8c
Packit Service c5cf8c
  Return Value:
Packit Service c5cf8c
  Pointer to new object.  Null if no more objects are available or can
Packit Service c5cf8c
  be allocated.
Packit Service c5cf8c
Packit Service c5cf8c
  Notes:
Packit Service c5cf8c
  In addition to returning a pointer to a new object, this routine may
Packit Service c5cf8c
  allocate additional space for more objects.
Packit Service c5cf8c
Packit Service c5cf8c
  This routine is thread-safe.
Packit Service c5cf8c
Packit Service c5cf8c
  This routine is performance-critical (it may be used to allocate
Packit Service c5cf8c
  MPI_Requests) and should not call any other routines in the common
Packit Service c5cf8c
  case.
Packit Service c5cf8c
Packit Service c5cf8c
  Threading: The 'MPID_THREAD_CS_ENTER/EXIT(POBJ/VNI, MPIR_THREAD_POBJ_HANDLE_MUTEX)' enables both
Packit Service c5cf8c
  finer-grain
Packit Service c5cf8c
  locking with a single global mutex and with a mutex specific for handles.
Packit Service c5cf8c
Packit Service c5cf8c
  +*/
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPIR_Handle_obj_alloc
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
static inline void *MPIR_Handle_obj_alloc(MPIR_Object_alloc_t * objmem)
Packit Service c5cf8c
{
Packit Service c5cf8c
    void *ret;
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(POBJ, MPIR_THREAD_POBJ_HANDLE_MUTEX);
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(VNI, MPIR_THREAD_POBJ_HANDLE_MUTEX);
Packit Service c5cf8c
    ret = MPIR_Handle_obj_alloc_unsafe(objmem);
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(VNI, MPIR_THREAD_POBJ_HANDLE_MUTEX);
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(POBJ, MPIR_THREAD_POBJ_HANDLE_MUTEX);
Packit Service c5cf8c
    return ret;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPIR_Handle_obj_alloc_unsafe
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
static inline void *MPIR_Handle_obj_alloc_unsafe(MPIR_Object_alloc_t * objmem)
Packit Service c5cf8c
{
Packit Service c5cf8c
    MPIR_Handle_common *ptr;
Packit Service c5cf8c
Packit Service c5cf8c
    if (objmem->avail) {
Packit Service c5cf8c
        ptr = objmem->avail;
Packit Service c5cf8c
        objmem->avail = objmem->avail->next;
Packit Service c5cf8c
        /* We do not clear ptr->next as we set it to an invalid pattern
Packit Service c5cf8c
         * when doing memory debugging and we don't need to set it
Packit Service c5cf8c
         * for the production/default case */
Packit Service c5cf8c
        /* ptr points to object to allocate */
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        int objsize, objkind;
Packit Service c5cf8c
Packit Service c5cf8c
        objsize = objmem->size;
Packit Service c5cf8c
        objkind = objmem->kind;
Packit Service c5cf8c
Packit Service c5cf8c
        if (!objmem->initialized) {
Packit Service c5cf8c
            MPL_VG_CREATE_MEMPOOL(objmem, 0 /*rzB */ , 0 /*is_zeroed */);
Packit Service c5cf8c
Packit Service c5cf8c
            /* Setup the first block.  This is done here so that short MPI
Packit Service c5cf8c
             * jobs do not need to include any of the Info code if no
Packit Service c5cf8c
             * Info-using routines are used */
Packit Service c5cf8c
            objmem->initialized = 1;
Packit Service c5cf8c
            ptr = MPIR_Handle_direct_init(objmem->direct, objmem->direct_size, objsize, objkind);
Packit Service c5cf8c
            if (ptr) {
Packit Service c5cf8c
                objmem->avail = ptr->next;
Packit Service c5cf8c
            }
Packit Service c5cf8c
#ifdef MPICH_DEBUG_HANDLEALLOC
Packit Service c5cf8c
            /* The priority of these callbacks must be greater than
Packit Service c5cf8c
             * the priority of the callback that frees the objmem direct and
Packit Service c5cf8c
             * indirect storage. */
Packit Service c5cf8c
            MPIR_Add_finalize(MPIR_check_handles_on_finalize, objmem,
Packit Service c5cf8c
                              MPIR_FINALIZE_CALLBACK_HANDLE_CHECK_PRIO);
Packit Service c5cf8c
#endif
Packit Service c5cf8c
            MPIR_Add_finalize(MPIR_Handle_finalize, objmem, 0);
Packit Service c5cf8c
            /* ptr points to object to allocate */
Packit Service c5cf8c
        } else {
Packit Service c5cf8c
            /* no space left in direct block; setup the indirect block. */
Packit Service c5cf8c
Packit Service c5cf8c
            ptr = MPIR_Handle_indirect_init(&objmem->indirect,
Packit Service c5cf8c
                                            &objmem->indirect_size,
Packit Service c5cf8c
                                            HANDLE_NUM_BLOCKS,
Packit Service c5cf8c
                                            HANDLE_NUM_INDICES, objsize, objkind);
Packit Service c5cf8c
            if (ptr) {
Packit Service c5cf8c
                objmem->avail = ptr->next;
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            /* ptr points to object to allocate */
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if (ptr) {
Packit Service c5cf8c
#ifdef USE_MEMORY_TRACING
Packit Service c5cf8c
        /* We set the object to an invalid pattern.  This is similar to
Packit Service c5cf8c
         * what is done by MPL_trmalloc by default (except that trmalloc uses
Packit Service c5cf8c
         * 0xda as the byte in the memset)
Packit Service c5cf8c
         */
Packit Service c5cf8c
        /* if the object was previously freed then MEMPOOL_FREE marked it as
Packit Service c5cf8c
         * NOACCESS, so we need to make it addressable again before memsetting
Packit Service c5cf8c
         * it */
Packit Service c5cf8c
        /* save and restore the handle -- it's a more robust method than
Packit Service c5cf8c
         * encoding the layout of the structure */
Packit Service c5cf8c
        int tmp_handle;
Packit Service c5cf8c
        MPL_VG_MAKE_MEM_DEFINED(ptr, objmem->size);
Packit Service c5cf8c
        tmp_handle = ptr->handle;
Packit Service c5cf8c
        memset(ptr, 0xef, objmem->size);
Packit Service c5cf8c
        ptr->handle = tmp_handle;
Packit Service c5cf8c
#endif /* USE_MEMORY_TRACING */
Packit Service c5cf8c
        /* mark the mem as addressable yet undefined if valgrind is available */
Packit Service c5cf8c
        MPL_VG_MEMPOOL_ALLOC(objmem, ptr, objmem->size);
Packit Service c5cf8c
        /* the handle value is always valid at return from this function */
Packit Service c5cf8c
        MPL_VG_MAKE_MEM_DEFINED(&ptr->handle, sizeof(ptr->handle));
Packit Service c5cf8c
Packit Service c5cf8c
        /* necessary to prevent annotations from being misinterpreted.  HB/HA
Packit Service c5cf8c
         * arcs will be drawn between a req object in across a free/alloc
Packit Service c5cf8c
         * boundary otherwise */
Packit Service c5cf8c
        /* NOTE: basically causes DRD's --trace-addr option to be useless for
Packit Service c5cf8c
         * handlemem-allocated objects. Consider one of the trace-inducing
Packit Service c5cf8c
         * annotations instead. */
Packit Service c5cf8c
        MPL_VG_ANNOTATE_NEW_MEMORY(ptr, objmem->size);
Packit Service c5cf8c
Packit Service c5cf8c
        MPL_DBG_MSG_FMT(MPIR_DBG_HANDLE, TYPICAL, (MPL_DBG_FDEST,
Packit Service c5cf8c
                                                   "Allocating object ptr %p (handle val 0x%08x)",
Packit Service c5cf8c
                                                   ptr, ptr->handle));
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return ptr;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/*+
Packit Service c5cf8c
  MPIR_Handle_obj_free - Free an object allocated with MPID_Handle_obj_new
Packit Service c5cf8c
Packit Service c5cf8c
Input Parameters:
Packit Service c5cf8c
+ objmem - Pointer to object block
Packit Service c5cf8c
- object - Object to delete
Packit Service c5cf8c
Packit Service c5cf8c
  Notes:
Packit Service c5cf8c
  This routine assumes that only a single thread calls it at a time; this
Packit Service c5cf8c
  is true for the SINGLE_CS approach to thread safety
Packit Service c5cf8c
  +*/
Packit Service c5cf8c
static inline void MPIR_Handle_obj_free(MPIR_Object_alloc_t * objmem, void *object)
Packit Service c5cf8c
{
Packit Service c5cf8c
    MPIR_Handle_common *obj = (MPIR_Handle_common *) object;
Packit Service c5cf8c
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(POBJ, MPIR_THREAD_POBJ_HANDLE_MUTEX);
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(VNI, MPIR_THREAD_POBJ_HANDLE_MUTEX);
Packit Service c5cf8c
Packit Service c5cf8c
    MPL_DBG_MSG_FMT(MPIR_DBG_HANDLE, TYPICAL, (MPL_DBG_FDEST,
Packit Service c5cf8c
                                               "Freeing object ptr %p (0x%08x kind=%s) refcount=%d",
Packit Service c5cf8c
                                               (obj),
Packit Service c5cf8c
                                               (obj)->handle,
Packit Service c5cf8c
                                               MPIR_Handle_get_kind_str(HANDLE_GET_MPI_KIND
Packit Service c5cf8c
                                                                        ((obj)->handle)),
Packit Service c5cf8c
                                               MPIR_Object_get_ref(obj)));
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef USE_MEMORY_TRACING
Packit Service c5cf8c
    {
Packit Service c5cf8c
        /* set the object memory to an invalid value (0xec), except for the handle field */
Packit Service c5cf8c
        int tmp_handle;
Packit Service c5cf8c
        tmp_handle = obj->handle;
Packit Service c5cf8c
        memset(obj, 0xec, objmem->size);
Packit Service c5cf8c
        obj->handle = tmp_handle;
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
    if (MPL_VG_RUNNING_ON_VALGRIND()) {
Packit Service c5cf8c
        int tmp_handle = obj->handle;
Packit Service c5cf8c
Packit Service c5cf8c
        MPL_VG_MEMPOOL_FREE(objmem, obj);
Packit Service c5cf8c
        /* MEMPOOL_FREE marks the object NOACCESS, so we have to make the
Packit Service c5cf8c
         * MPIR_Handle_common area that is used for internal book keeping
Packit Service c5cf8c
         * addressable again. */
Packit Service c5cf8c
        MPL_VG_MAKE_MEM_DEFINED(&obj->handle, sizeof(obj->handle));
Packit Service c5cf8c
        MPL_VG_MAKE_MEM_UNDEFINED(&obj->next, sizeof(obj->next));
Packit Service c5cf8c
Packit Service c5cf8c
        /* tt#1626: MEMPOOL_FREE also uses the value of `--free-fill=0x..` to
Packit Service c5cf8c
         * memset the object, so we need to restore the handle */
Packit Service c5cf8c
        obj->handle = tmp_handle;
Packit Service c5cf8c
Packit Service c5cf8c
        /* Necessary to prevent annotations from being misinterpreted.  HB/HA arcs
Packit Service c5cf8c
         * will be drawn between a req object in across a free/alloc boundary
Packit Service c5cf8c
         * otherwise.  Specifically, stores to obj->next when obj is actually an
Packit Service c5cf8c
         * MPIR_Request falsely look like a race to DRD and Helgrind because of the
Packit Service c5cf8c
         * other lockfree synchronization used with requests. */
Packit Service c5cf8c
        MPL_VG_ANNOTATE_NEW_MEMORY(obj, objmem->size);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    obj->next = objmem->avail;
Packit Service c5cf8c
    objmem->avail = obj;
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(VNI, MPIR_THREAD_POBJ_HANDLE_MUTEX);
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(POBJ, MPIR_THREAD_POBJ_HANDLE_MUTEX);
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/*
Packit Service c5cf8c
 * Get an pointer to dynamically allocated storage for objects.
Packit Service c5cf8c
 */
Packit Service c5cf8c
static inline void *MPIR_Handle_get_ptr_indirect(int handle, MPIR_Object_alloc_t * objmem)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int block_num, index_num;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Check for a valid handle type */
Packit Service c5cf8c
    if (HANDLE_GET_MPI_KIND(handle) != objmem->kind) {
Packit Service c5cf8c
        return 0;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* Find the block */
Packit Service c5cf8c
    block_num = HANDLE_BLOCK(handle);
Packit Service c5cf8c
    if (block_num >= objmem->indirect_size) {
Packit Service c5cf8c
        return 0;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* Find the entry */
Packit Service c5cf8c
    index_num = HANDLE_BLOCK_INDEX(handle);
Packit Service c5cf8c
    /* If we could declare the blocks to a known size object, we
Packit Service c5cf8c
     * could do something like
Packit Service c5cf8c
     * return &((MPIR_Info**)*MPIU_Info_mem.indirect)[block_num][index_num];
Packit Service c5cf8c
     * since we cannot, we do the calculation by hand.
Packit Service c5cf8c
     */
Packit Service c5cf8c
    /* Get the pointer to the block of addresses.  This is an array of
Packit Service c5cf8c
     * void * */
Packit Service c5cf8c
    {
Packit Service c5cf8c
        char *block_ptr;
Packit Service c5cf8c
        /* Get the pointer to the block */
Packit Service c5cf8c
        block_ptr = (char *) (*(objmem->indirect))[block_num];
Packit Service c5cf8c
        /* Get the item */
Packit Service c5cf8c
        block_ptr += index_num * objmem->size;
Packit Service c5cf8c
        return block_ptr;
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
#endif /* MPIR_HANDLEMEM_H_INCLUDED */