⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 handlemem.c

📁 fortran并行计算包
💻 C
字号:
/* -*- Mode: C; c-basic-offset:4 ; -*- *//*  $Id: handlemem.c,v 1.29 2007/03/08 22:12:32 buntinas Exp $ * *  (C) 2001 by Argonne National Laboratory. *      See COPYRIGHT in top-level directory. */#include "mpiimpl.h"#include <stdio.h>#ifdef NEEDS_PRINT_HANDLEstatic void MPIU_Print_handle( int handle );#endif/* This is the utility file for info that contains routines used to    manage the arrays used to store handle objects.     To use these routines, allocate the following in a utility file    used by each object (e.g., info, datatype, comm, group, ... ).     (The comment format // is used in this example but the usual    C comment convention should be used of course.)  The usage is described   below.   // Declarations begin here   // Static declaration of the information about the block   // Define the number of preallocated entries # omitted)   define MPID_<OBJ>_PREALLOC 256   MPIU_Object_alloc_t MPID_<obj>_mem = { 0, 0, 0, 0, MPID_<obj>, 				      sizeof(MPID_<obj>), MPID_<obj>_direct,                                      MPID_<OBJ>_PREALLOC, };   // Preallocated objects   MPID_<obj> MPID_<obj>_direct[MPID_<OBJ>_PREALLOC];   static int initialized = 0;      // Next available object    static int MPID_<obj> *avail = 0;      // Extension (indirect) objects   static MPID_<obj> *(*MPID_<obj>_indirect)[] = 0;   static int MPID_<obj>_indirect_size = 0;    // Declarations end here   These provide for lazy initialization; applications that do not need a    particular object will not include any of the code or even reference   the space.      Note that these routines are designed for the MPI objects, and include the   creation of a "handle" that is appropriate for the MPI object value.      The following routines are provided:   void *MPIU_Handle_direct_init( void *direct, int direct_size, int obj_size,                                  int handle_type )        Initialize the preallocated array (MPID_<obj>_direct) with        direct_size elements each of obj_size.  Returns the first available        element (which should usually be assigned to "avail").	handle_type is the kind of object (e.g., MPID_INFO)   void *MPIU_Handle_indirect_init( void (**indirect)[], int *indirect_size,                                     int indirect_max_size,                                    int indirect_block_size,                                     int obj_size,                                    int handle_type )	Initialize the indirect array (MPID_<obj>_indirect) of size        indirect_size, each block of which contains indirect_block_size	members of size obj_size.  Returns the first available element, or	NULL if no memory is available.          Also incrementes indirect_size and assigns to indirect if it is null.	The Handle_indirect routine and the data structures that it manages	require a little more discussion.	This routine allocates an array of pointers to a block of storage.	The block of storage contains space for indirect_block_size 	instances of an object of obj_size.  These blocks are allocated	as needed; the pointers to these blocks are stored in the 	indirect array.  The value of indirect_size is the number of 	valid pointers in indirect.  In other words, indirect[0] through        indirect[*indirect_size-1] contain pointers to blocks of 	storage of size indirect_block_size * obj_size.  The array 	indirect has indirect_max_size entries, each holding a pointer.	The rationale for this approach is that this approach can 	handle large amounts of memory; however, relatively little	memory is used unless needed.  The definitions in         mpich2/src/include/mpihandlemem.h define defaults for the	indirect_max_size (HANDLE_BLOCK_INDEX_SIZE = 1024) and	indirect_block_size (HANDLE_BLOCK_SIZE = 256) that permits	the allocation of 256K objects.     int MPIU_Handle_free( void *(*indirect)[], int indirect_size )        Frees any memory allocated for the indirect handles.  Returns 0 on	success and nonzero on failure   None of these routines is thread-safe.  Any routine that uses them    must ensure that only one thread at a time may call them.     *//* * You can use this to allocated that necessary local structures */#define MPID_HANDLE_MEM_ALLOC(Name,NAME) \MPID_##Name MPID_##Name_direct[MPID_##NAME##_PREALLOC]; \static int initialize = 0;\static int MPID_##Name *avail=0;\static MPID_##Name *(*MPID_##Name##_indirect)[] = 0;\static int MPID_##Name##_indirect_size = 0;/* This routine is called by finalize when MPI exits */static int MPIU_Handle_free( void *((*indirect)[]), int indirect_size ){    int i;        /* Remove any allocated storage */    for (i=0; i<indirect_size; i++) {	MPIU_Free( (*indirect)[i] );    }    if (indirect) {	MPIU_Free( indirect );    }    /* This does *not* remove any objects that the user created        and then did not destroy */    return 0;}void *MPIU_Handle_direct_init(void *direct,			      int direct_size, 			      int obj_size, 			      int handle_type){    int                i;    MPIU_Handle_common *hptr=0;    char               *ptr = (char *)direct;        for (i=0; i<direct_size; i++) {	hptr = (MPIU_Handle_common *)ptr;	ptr  = ptr + obj_size;	hptr->next = ptr;	hptr->handle = ((unsigned)HANDLE_KIND_DIRECT << HANDLE_KIND_SHIFT) | 	    (handle_type << HANDLE_MPI_KIND_SHIFT) | i;    }    hptr->next = 0;    return direct;}/* indirect is really a pointer to a pointer to an array of pointers */static void *MPIU_Handle_indirect_init( void *(**indirect)[], 					int *indirect_size, 					int indirect_max_size,					int indirect_block_size, int obj_size, 					int handle_type ){    void               *block_ptr;    MPIU_Handle_common *hptr=0;    char               *ptr;    int                i;    /* Must create new storage for dynamically allocated objects */    /* Create the table */    if (!*indirect) {	/* printf( "Creating indirect table\n" ); */	*indirect = (void *)MPIU_Calloc( indirect_max_size, 					      sizeof(void *) );	if (!*indirect) {	    return 0;	}	*indirect_size = 0;    }    /* See if we can allocate another block */    if (*indirect_size >= indirect_max_size-1) {	return 0;    }        /* Create the next block */    /* printf( "Adding indirect block %d\n", MPID_Info_indirect_size ); */    block_ptr = (void *)MPIU_Calloc( indirect_block_size, obj_size );    if (!block_ptr) { 	return 0;    }    ptr = (char *)block_ptr;    for (i=0; i<indirect_block_size; i++) {	hptr       = (MPIU_Handle_common *)ptr;	ptr        = ptr + obj_size;	hptr->next = ptr;	hptr->handle   = ((unsigned)HANDLE_KIND_INDIRECT << HANDLE_KIND_SHIFT) | 	    (handle_type << HANDLE_MPI_KIND_SHIFT) | 	    (*indirect_size << HANDLE_INDIRECT_SHIFT) | i;    }    hptr->next = 0;    /* We're here because avail is null, so there is no need to set        the last block ptr to avail */    /* printf( "loc of update is %x\n", &(**indirect)[*indirect_size] );  */    (**indirect)[*indirect_size] = block_ptr;    *indirect_size = *indirect_size + 1;    return block_ptr;}/*  Create and return a pointer to an info object.  Returns null if there is   an error such as out-of-memory.  Does not allocate space for the  key or value. */static int MPIU_Handle_finalize( void *objmem_ptr ){    MPIU_Object_alloc_t *objmem = (MPIU_Object_alloc_t *)objmem_ptr;    (void)MPIU_Handle_free( objmem->indirect, objmem->indirect_size );    /* This does *not* remove any Info objects that the user created        and then did not destroy */    return 0;}/* FIXME: The alloc_complete routine should be removed.   It is used only in typeutil.c (in MPIR_Datatype_init, which is only    executed from within the MPI_Init/MPI_Init_thread startup and hence is   guaranteed to be single threaded).  When used by the obj_alloc, it   adds unnecessary overhead, particularly when MPI is single threaded */void MPIU_Handle_obj_alloc_complete(MPIU_Object_alloc_t *objmem,				    int initialized){    if (initialized) {	/* obj_alloc initialized region during this allocation;	 * perform any ancillary operations associated with	 * initialization prior to releasing control over region.	 */	/* Tell finalize to free up any memory that we allocate.	 * The 0 makes this the lowest priority callback, so 	 * that other callbacks will finish before this one is invoked.	 */	MPIR_Add_finalize(MPIU_Handle_finalize, objmem, 0);    }}/*+  MPIU_Handle_obj_alloc - Create an object using the handle allocator  Input Parameter:. objmem - Pointer to object memory block.  Return Value:  Pointer to new object.  Null if no more objects are available or can   be allocated.  Notes:  In addition to returning a pointer to a new object, this routine may  allocate additional space for more objects.  This routine is thread-safe.  This routine is performance-critical (it may be used to allocate   MPI_Requests) and should not call any other routines in the common  case.  +*/void *MPIU_Handle_obj_alloc(MPIU_Object_alloc_t *objmem){    MPIU_Handle_common *ptr;    if (objmem->avail) {	ptr	      = objmem->avail;	objmem->avail = objmem->avail->next;	/* We do not clear ptr->next as we set it to an invalid pattern	   when doing memory debugging and we don't need to set it 	   for the production/default case */	/* ptr points to object to allocate */    }    else {	int objsize, objkind;	int performed_initialize = 0;	objsize = objmem->size;	objkind = objmem->kind;	if (!objmem->initialized) {	    performed_initialize = 1;	    /* Setup the first block.  This is done here so that short MPI	       jobs do not need to include any of the Info code if no	       Info-using routines are used */	    objmem->initialized = 1;	    ptr = MPIU_Handle_direct_init(objmem->direct,					  objmem->direct_size,					  objsize,					  objkind);	    if (ptr) {		objmem->avail = ptr->next;	    }	    /* ptr points to object to allocate */	}	else {	    /* no space left in direct block; setup the indirect block. */	    ptr = MPIU_Handle_indirect_init(&objmem->indirect, 					    &objmem->indirect_size, 					    HANDLE_BLOCK_INDEX_SIZE,					    HANDLE_BLOCK_SIZE, 					    objsize,					    objkind);	    if (ptr) {		objmem->avail = ptr->next;	    }	    /* ptr points to object to allocate */	}	MPIU_Handle_obj_alloc_complete(objmem, performed_initialize);    }    MPIU_DBG_MSG_FMT(HANDLE,TYPICAL,(MPIU_DBG_FDEST,				     "Allocating handle %x (0x%08x)\n",				     (unsigned) (MPI_Aint)ptr, ptr->handle));#ifdef USE_MEMORY_TRACING    /* We set the object to an invalid pattern.  This is similar to        what is done by MPIU_trmalloc by default (except that trmalloc uses       0xda as the byte in the memset)    */    if (ptr) {	memset( (void*)&ptr->ref_count, 0xef, objmem->size-sizeof(int));    }#endif    return ptr;}   /*+  MPIU_Handle_obj_free - Free an object allocated with MPID_Handle_obj_new  Input Parameters:+ objmem - Pointer to object block- object - Object to delete  Notes:   This routine assumes that only a single thread calls it at a time; this  is true for the SINGLE_CS approach to thread safety  +*/void MPIU_Handle_obj_free( MPIU_Object_alloc_t *objmem, void *object ){    MPIU_Handle_common *obj = (MPIU_Handle_common *)object;    obj->next	        = objmem->avail;    objmem->avail	= obj;}/*  * Get an pointer to dynamically allocated storage for objects. */void *MPIU_Handle_get_ptr_indirect( int handle, MPIU_Object_alloc_t *objmem ){    int block_num, index_num;    /* Check for a valid handle type */    if (HANDLE_GET_MPI_KIND(handle) != objmem->kind) {	return 0;    }    /* Find the block */    block_num = HANDLE_BLOCK(handle);    if (block_num >= objmem->indirect_size) {	return 0;    }        /* Find the entry */    index_num = HANDLE_BLOCK_INDEX(handle);    /* If we could declare the blocks to a known size object, we     could do something like        return &( (MPID_Info**)*MPIU_Info_mem.indirect)[block_num][index_num];     since we cannot, we do the calculation by hand.    */    /* Get the pointer to the block of addresses.  This is an array of        void * */    {	char *block_ptr;	/* Get the pointer to the block */	block_ptr = (char *)(*(objmem->indirect))[block_num];	/* Get the item */	block_ptr += index_num * objmem->size;	return block_ptr;    }}#ifdef NEEDS_PRINT_HANDLE/* For debugging *//* style: allow:printf:4 sig:0 */static void MPIU_Print_handle( int handle ){    int type, kind, block, index;    type = HANDLE_GET_MPI_KIND(handle);    kind = HANDLE_GET_KIND(handle);    switch (type) {    case HANDLE_KIND_INVALID:	printf( "invalid" );	break;    case HANDLE_KIND_BUILTIN:	printf( "builtin" );	break;    case HANDLE_KIND_DIRECT:	index = HANDLE_INDEX(handle);	printf( "direct: %d", index );	break;    case HANDLE_KIND_INDIRECT:	block = HANDLE_BLOCK(handle);	index = HANDLE_BLOCK_INDEX(handle);	printf( "indirect: block %d index %d", block, index );	break;    }}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -