|
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 |
=== BEGIN_MPI_T_CVAR_INFO_BLOCK ===
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
categories:
|
|
Packit Service |
c5cf8c |
- name : MEMORY
|
|
Packit Service |
c5cf8c |
description : affects memory allocation and usage, including MPI object handles
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
cvars:
|
|
Packit Service |
c5cf8c |
- name : MPIR_CVAR_ABORT_ON_LEAKED_HANDLES
|
|
Packit Service |
c5cf8c |
category : MEMORY
|
|
Packit Service |
c5cf8c |
type : boolean
|
|
Packit Service |
c5cf8c |
default : false
|
|
Packit Service |
c5cf8c |
class : device
|
|
Packit Service |
c5cf8c |
verbosity : MPI_T_VERBOSITY_USER_BASIC
|
|
Packit Service |
c5cf8c |
scope : MPI_T_SCOPE_ALL_EQ
|
|
Packit Service |
c5cf8c |
description : >-
|
|
Packit Service |
c5cf8c |
If true, MPI will call MPI_Abort at MPI_Finalize if any MPI object
|
|
Packit Service |
c5cf8c |
handles have been leaked. For example, if MPI_Comm_dup is called
|
|
Packit Service |
c5cf8c |
without calling a corresponding MPI_Comm_free. For uninteresting
|
|
Packit Service |
c5cf8c |
reasons, enabling this option may prevent all known object leaks from
|
|
Packit Service |
c5cf8c |
being reported. MPICH must have been configure with
|
|
Packit Service |
c5cf8c |
"--enable-g=handlealloc" or better in order for this functionality to
|
|
Packit Service |
c5cf8c |
work.
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
=== END_MPI_T_CVAR_INFO_BLOCK ===
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
#include "mpiimpl.h"
|
|
Packit Service |
c5cf8c |
#include <stdio.h>
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* style: allow:printf:5 sig:0 */
|
|
Packit Service |
c5cf8c |
#ifdef MPICH_DEBUG_HANDLEALLOC
|
|
Packit Service |
c5cf8c |
/* The following is a handler that may be added to finalize to test whether
|
|
Packit Service |
c5cf8c |
handles remain allocated, including those from the direct blocks.
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
When adding memory checking, this routine should be invoked as
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
MPIR_Add_finalize(MPIR_check_handles_on_finalize, objmem, 1);
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
as part of the object intialization.
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
The algorithm follows the following approach:
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
The memory allocation approach manages a list of available objects.
|
|
Packit Service |
c5cf8c |
These objects are allocated from several places:
|
|
Packit Service |
c5cf8c |
"direct" - this is a block of preallocated space
|
|
Packit Service |
c5cf8c |
"indirect" - this is a block of blocks that are allocated as necessary.
|
|
Packit Service |
c5cf8c |
E.g., objmem_ptr->indirect[0..objmem_ptr->indirect_size-1]
|
|
Packit Service |
c5cf8c |
are pointers (or null) to a block of memory. This block is
|
|
Packit Service |
c5cf8c |
then divided into objects that are added to the avail list.
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
To provide information on the handles that are still in use, we must
|
|
Packit Service |
c5cf8c |
"repatriate" all of the free objects, at least virtually. To give
|
|
Packit Service |
c5cf8c |
the best information, for each free item, we determine to which block
|
|
Packit Service |
c5cf8c |
it belongs.
|
|
Packit Service |
c5cf8c |
*/
|
|
Packit Service |
c5cf8c |
int MPIR_check_handles_on_finalize(void *objmem_ptr)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
MPIR_Object_alloc_t *objmem = (MPIR_Object_alloc_t *) objmem_ptr;
|
|
Packit Service |
c5cf8c |
int i;
|
|
Packit Service |
c5cf8c |
MPIR_Handle_common *ptr;
|
|
Packit Service |
c5cf8c |
int leaked_handles = FALSE;
|
|
Packit Service |
c5cf8c |
int directSize = objmem->direct_size;
|
|
Packit Service |
c5cf8c |
char *direct = (char *) objmem->direct;
|
|
Packit Service |
c5cf8c |
char *directEnd = (char *) direct + directSize * objmem->size - 1;
|
|
Packit Service |
c5cf8c |
int nDirect = 0;
|
|
Packit Service |
c5cf8c |
int *nIndirect = 0;
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* Return immediately if this object has not allocated any space */
|
|
Packit Service |
c5cf8c |
if (!objmem->initialized) {
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (objmem->indirect_size > 0) {
|
|
Packit Service |
c5cf8c |
nIndirect = (int *) MPL_calloc(objmem->indirect_size, sizeof(int), MPL_MEM_OBJECT);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
/* Count the number of items in the avail list. These include
|
|
Packit Service |
c5cf8c |
* all objects, whether direct or indirect allocation */
|
|
Packit Service |
c5cf8c |
ptr = objmem->avail;
|
|
Packit Service |
c5cf8c |
while (ptr) {
|
|
Packit Service |
c5cf8c |
/* printf("Looking at %p\n", ptr); */
|
|
Packit Service |
c5cf8c |
/* Find where this object belongs */
|
|
Packit Service |
c5cf8c |
if ((char *) ptr >= direct && (char *) ptr < directEnd) {
|
|
Packit Service |
c5cf8c |
nDirect++;
|
|
Packit Service |
c5cf8c |
} else {
|
|
Packit Service |
c5cf8c |
void **indirect = (void **) objmem->indirect;
|
|
Packit Service |
c5cf8c |
for (i = 0; i < objmem->indirect_size; i++) {
|
|
Packit Service |
c5cf8c |
char *start = indirect[i];
|
|
Packit Service |
c5cf8c |
char *end = start + HANDLE_NUM_INDICES * objmem->size;
|
|
Packit Service |
c5cf8c |
if ((char *) ptr >= start && (char *) ptr < end) {
|
|
Packit Service |
c5cf8c |
nIndirect[i]++;
|
|
Packit Service |
c5cf8c |
break;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (i == objmem->indirect_size) {
|
|
Packit Service |
c5cf8c |
/* Error - could not find the owning memory */
|
|
Packit Service |
c5cf8c |
/* Temp */
|
|
Packit Service |
c5cf8c |
printf("Could not place object at %p in handle memory for type %s\n", ptr,
|
|
Packit Service |
c5cf8c |
MPIR_Handle_get_kind_str(objmem->kind));
|
|
Packit Service |
c5cf8c |
printf("direct block is [%p,%p]\n", direct, directEnd);
|
|
Packit Service |
c5cf8c |
if (objmem->indirect_size) {
|
|
Packit Service |
c5cf8c |
printf("indirect block is [%p,%p]\n", indirect[0],
|
|
Packit Service |
c5cf8c |
(char *) indirect[0] + HANDLE_NUM_INDICES * objmem->size);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
ptr = ptr->next;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (0) {
|
|
Packit Service |
c5cf8c |
/* Produce a report */
|
|
Packit Service |
c5cf8c |
printf("Object handles:\n\ttype \t%s\n\tsize \t%d\n\tdirect size\t%d\n\
|
|
Packit Service |
c5cf8c |
\tindirect size\t%d\n", MPIR_Handle_get_kind_str(objmem->kind), objmem->size, objmem->direct_size, objmem->indirect_size);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
if (nDirect != directSize) {
|
|
Packit Service |
c5cf8c |
leaked_handles = TRUE;
|
|
Packit Service |
c5cf8c |
printf("In direct memory block for handle type %s, %d handles are still allocated\n",
|
|
Packit Service |
c5cf8c |
MPIR_Handle_get_kind_str(objmem->kind), directSize - nDirect);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
for (i = 0; i < objmem->indirect_size; i++) {
|
|
Packit Service |
c5cf8c |
if (nIndirect[i] != HANDLE_NUM_INDICES) {
|
|
Packit Service |
c5cf8c |
leaked_handles = TRUE;
|
|
Packit Service |
c5cf8c |
printf
|
|
Packit Service |
c5cf8c |
("In indirect memory block %d for handle type %s, %d handles are still allocated\n",
|
|
Packit Service |
c5cf8c |
i, MPIR_Handle_get_kind_str(objmem->kind), HANDLE_NUM_INDICES - nIndirect[i]);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (nIndirect) {
|
|
Packit Service |
c5cf8c |
MPL_free(nIndirect);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
if (leaked_handles && MPIR_CVAR_ABORT_ON_LEAKED_HANDLES) {
|
|
Packit Service |
c5cf8c |
/* comm_world has been (or should have been) destroyed by this point,
|
|
Packit Service |
c5cf8c |
* pass comm=NULL */
|
|
Packit Service |
c5cf8c |
MPID_Abort(NULL, MPI_ERR_OTHER, 1, "ERROR: leaked handles detected, aborting");
|
|
Packit Service |
c5cf8c |
MPIR_Assert(0);
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
return 0;
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#endif
|
|
Packit Service |
c5cf8c |
|
|
Packit Service |
c5cf8c |
/* returns the name of the handle kind for debugging/logging purposes */
|
|
Packit Service |
c5cf8c |
const char *MPIR_Handle_get_kind_str(int kind)
|
|
Packit Service |
c5cf8c |
{
|
|
Packit Service |
c5cf8c |
#define mpiu_name_case_(name_) case MPIR_##name_: return (#name_)
|
|
Packit Service |
c5cf8c |
switch (kind) {
|
|
Packit Service |
c5cf8c |
mpiu_name_case_(COMM);
|
|
Packit Service |
c5cf8c |
mpiu_name_case_(GROUP);
|
|
Packit Service |
c5cf8c |
mpiu_name_case_(DATATYPE);
|
|
Packit Service |
c5cf8c |
mpiu_name_case_(FILE);
|
|
Packit Service |
c5cf8c |
mpiu_name_case_(ERRHANDLER);
|
|
Packit Service |
c5cf8c |
mpiu_name_case_(OP);
|
|
Packit Service |
c5cf8c |
mpiu_name_case_(INFO);
|
|
Packit Service |
c5cf8c |
mpiu_name_case_(WIN);
|
|
Packit Service |
c5cf8c |
mpiu_name_case_(KEYVAL);
|
|
Packit Service |
c5cf8c |
mpiu_name_case_(ATTR);
|
|
Packit Service |
c5cf8c |
mpiu_name_case_(REQUEST);
|
|
Packit Service |
c5cf8c |
mpiu_name_case_(PROCGROUP);
|
|
Packit Service |
c5cf8c |
mpiu_name_case_(VCONN);
|
|
Packit Service |
c5cf8c |
mpiu_name_case_(WORKQ_ELEM);
|
|
Packit Service |
c5cf8c |
mpiu_name_case_(GREQ_CLASS);
|
|
Packit Service |
c5cf8c |
default:
|
|
Packit Service |
c5cf8c |
return "unknown";
|
|
Packit Service |
c5cf8c |
}
|
|
Packit Service |
c5cf8c |
#undef mpiu_name_case_
|
|
Packit Service |
c5cf8c |
}
|