/*BHEADER********************************************************************** * Copyright (c) 2008, Lawrence Livermore National Security, LLC. * Produced at the Lawrence Livermore National Laboratory. * This file is part of HYPRE. See file COPYRIGHT for details. * * HYPRE is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License (as published by the Free * Software Foundation) version 2.1 dated February 1999. * * $Revision: 2.4 $ ***********************************************************************EHEADER*/ /****************************************************************************** * * Memory management utilities * *****************************************************************************/ #include #include #include "utilities.h" #ifdef HYPRE_USE_PTHREADS #include "threading.h" #ifdef HYPRE_USE_UMALLOC #include "umalloc_local.h" #define _umalloc_(size) (threadid == hypre_NumThreads) ? \ (char *) malloc(size) : \ (char *) _umalloc(_uparam[threadid].myheap, size) #define _ucalloc_(count, size) (threadid == hypre_NumThreads) ? \ (char *) calloc(count, size) : \ (char *) _ucalloc(_uparam[threadid].myheap,\ count, size) #define _urealloc_(ptr, size) (threadid == hypre_NumThreads) ? \ (char *) realloc(ptr, size) : \ (char *) _urealloc(ptr, size) #define _ufree_(ptr) (threadid == hypre_NumThreads) ? \ free(ptr) : _ufree(ptr) #endif #else #ifdef HYPRE_USE_UMALLOC #undef HYPRE_USE_UMALLOC #endif #endif /****************************************************************************** * * Standard routines * *****************************************************************************/ /*-------------------------------------------------------------------------- * hypre_OutOfMemory *--------------------------------------------------------------------------*/ int hypre_OutOfMemory( int size ) { printf("Out of memory trying to allocate %d bytes\n", size); fflush(stdout); hypre_error(HYPRE_ERROR_MEMORY); return 0; } /*-------------------------------------------------------------------------- * hypre_MAlloc *--------------------------------------------------------------------------*/ char * hypre_MAlloc( int size ) { char *ptr; if (size > 0) { #ifdef HYPRE_USE_UMALLOC int threadid = hypre_GetThreadID(); ptr = _umalloc_(size); #else ptr = malloc(size); #endif #if 1 if (ptr == NULL) { hypre_OutOfMemory(size); } #endif } else { ptr = NULL; } return ptr; } /*-------------------------------------------------------------------------- * hypre_CAlloc *--------------------------------------------------------------------------*/ char * hypre_CAlloc( int count, int elt_size ) { char *ptr; int size = count*elt_size; if (size > 0) { #ifdef HYPRE_USE_UMALLOC int threadid = hypre_GetThreadID(); ptr = _ucalloc_(count, elt_size); #else ptr = calloc(count, elt_size); #endif #if 1 if (ptr == NULL) { hypre_OutOfMemory(size); } #endif } else { ptr = NULL; } return ptr; } /*-------------------------------------------------------------------------- * hypre_ReAlloc *--------------------------------------------------------------------------*/ char * hypre_ReAlloc( char *ptr, int size ) { #ifdef HYPRE_USE_UMALLOC if (ptr == NULL) { ptr = hypre_MAlloc(size); } else if (size == 0) { hypre_Free(ptr); } else { int threadid = hypre_GetThreadID(); ptr = _urealloc_(ptr, size); } #else if (ptr == NULL) { ptr = malloc(size); } else { ptr = realloc(ptr, size); } #endif #if 1 if ((ptr == NULL) && (size > 0)) { hypre_OutOfMemory(size); } #endif return ptr; } /*-------------------------------------------------------------------------- * hypre_Free *--------------------------------------------------------------------------*/ void hypre_Free( char *ptr ) { if (ptr) { #ifdef HYPRE_USE_UMALLOC int threadid = hypre_GetThreadID(); _ufree_(ptr); #else free(ptr); #endif } } /*-------------------------------------------------------------------------- * These Shared routines are for one thread to allocate memory for data * will be visible to all threads. The file-scope pointer * global_alloc_ptr is used in these routines. *--------------------------------------------------------------------------*/ #ifdef HYPRE_USE_PTHREADS char *global_alloc_ptr; double *global_data_ptr; /*-------------------------------------------------------------------------- * hypre_SharedMAlloc *--------------------------------------------------------------------------*/ char * hypre_SharedMAlloc( int size ) { char *ptr; int unthreaded = pthread_equal(initial_thread, pthread_self()); int I_call_malloc = unthreaded || pthread_equal(hypre_thread[0],pthread_self()); if (I_call_malloc) { global_alloc_ptr = hypre_MAlloc( size ); } hypre_barrier(&talloc_mtx, unthreaded); ptr = global_alloc_ptr; hypre_barrier(&talloc_mtx, unthreaded); return ptr; } /*-------------------------------------------------------------------------- * hypre_SharedCAlloc *--------------------------------------------------------------------------*/ char * hypre_SharedCAlloc( int count, int elt_size ) { char *ptr; int unthreaded = pthread_equal(initial_thread, pthread_self()); int I_call_calloc = unthreaded || pthread_equal(hypre_thread[0],pthread_self()); if (I_call_calloc) { global_alloc_ptr = hypre_CAlloc( count, elt_size ); } hypre_barrier(&talloc_mtx, unthreaded); ptr = global_alloc_ptr; hypre_barrier(&talloc_mtx, unthreaded); return ptr; } /*-------------------------------------------------------------------------- * hypre_SharedReAlloc *--------------------------------------------------------------------------*/ char * hypre_SharedReAlloc( char *ptr, int size ) { int unthreaded = pthread_equal(initial_thread, pthread_self()); int I_call_realloc = unthreaded || pthread_equal(hypre_thread[0],pthread_self()); if (I_call_realloc) { global_alloc_ptr = hypre_ReAlloc( ptr, size ); } hypre_barrier(&talloc_mtx, unthreaded); ptr = global_alloc_ptr; hypre_barrier(&talloc_mtx, unthreaded); return ptr; } /*-------------------------------------------------------------------------- * hypre_SharedFree *--------------------------------------------------------------------------*/ void hypre_SharedFree( char *ptr ) { int unthreaded = pthread_equal(initial_thread, pthread_self()); int I_call_free = unthreaded || pthread_equal(hypre_thread[0],pthread_self()); hypre_barrier(&talloc_mtx, unthreaded); if (I_call_free) { hypre_Free(ptr); } hypre_barrier(&talloc_mtx, unthreaded); } /*-------------------------------------------------------------------------- * hypre_IncrementSharedDataPtr *--------------------------------------------------------------------------*/ double * hypre_IncrementSharedDataPtr( double *ptr, int size ) { int unthreaded = pthread_equal(initial_thread, pthread_self()); int I_increment = unthreaded || pthread_equal(hypre_thread[0],pthread_self()); if (I_increment) { global_data_ptr = ptr + size; } hypre_barrier(&talloc_mtx, unthreaded); ptr = global_data_ptr; hypre_barrier(&talloc_mtx, unthreaded); return ptr; } #endif