|
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 */
|