Amesos Package Browser (Single Doxygen Collection) Development
amesos_klu_memory.c
Go to the documentation of this file.
00001 /* ========================================================================== */
00002 /* === KLU_memory =========================================================== */
00003 /* ========================================================================== */
00004 
00005 /* KLU memory management routines:
00006  *
00007  * KLU_malloc     malloc wrapper
00008  * KLU_free     free wrapper
00009  * KLU_realloc      realloc wrapper
00010  */
00011 
00012 #include "amesos_klu_internal.h"
00013 
00014 /* ========================================================================== */
00015 /* === KLU_add_size_t ======================================================= */
00016 /* ========================================================================== */
00017 
00018 /* Safely compute a+b, and check for size_t overflow */
00019 
00020 size_t KLU_add_size_t (size_t a, size_t b, Int *ok)
00021 {
00022     (*ok) = (*ok) && ((a + b) >= MAX (a,b)) ;
00023     return ((*ok) ? (a + b) : ((size_t) -1)) ;
00024 }
00025 
00026 /* ========================================================================== */
00027 /* === KLU_mult_size_t ====================================================== */
00028 /* ========================================================================== */
00029 
00030 /* Safely compute a*k, where k should be small, and check for size_t overflow */
00031 
00032 size_t KLU_mult_size_t (size_t a, size_t k, Int *ok)
00033 {
00034     size_t i, s = 0 ;
00035     for (i = 0 ; i < k ; i++)
00036     {
00037   s = KLU_add_size_t (s, a, ok) ;
00038     }
00039     return ((*ok) ? s : ((size_t) -1)) ;
00040 }
00041 
00042 /* ========================================================================== */
00043 /* === KLU_malloc =========================================================== */
00044 /* ========================================================================== */
00045 
00046 /* Wrapper around malloc routine (mxMalloc for a mexFunction).  Allocates
00047  * space of size MAX(1,n)*size, where size is normally a sizeof (...).
00048  *
00049  * This routine and KLU_realloc do not set Common->status to KLU_OK on success,
00050  * so that a sequence of KLU_malloc's or KLU_realloc's can be used.  If any of
00051  * them fails, the Common->status will hold the most recent error status.
00052  *
00053  * Usage, for a pointer to Int:
00054  *
00055  *  p = KLU_malloc (n, sizeof (Int), Common)
00056  *
00057  * Uses a pointer to the malloc routine (or its equivalent) defined in Common.
00058  */
00059 
00060 void *KLU_malloc  /* returns pointer to the newly malloc'd block */
00061 (
00062     /* ---- input ---- */
00063     size_t n,   /* number of items */
00064     size_t size,  /* size of each item */
00065     /* --------------- */
00066     KLU_common *Common
00067 )
00068 {
00069     void *p ;
00070     size_t s ;
00071     Int ok = TRUE ;
00072 
00073     if (Common == NULL)
00074     {
00075   p = NULL ;
00076     }
00077     else if (size == 0)
00078     {
00079   /* size must be > 0 */
00080   Common->status = KLU_INVALID ;
00081   p = NULL ;
00082     }
00083     else if (n >= INT_MAX)
00084     {
00085   /* object is too big to allocate; p[i] where i is an Int will not
00086    * be enough. */
00087   Common->status = KLU_TOO_LARGE ;
00088   p = NULL ;
00089     }
00090     else
00091     {
00092   /* call malloc, or its equivalent */
00093   s = KLU_mult_size_t (MAX (1,n), size, &ok) ;
00094   p = ok ? ((Common->malloc_memory) (s)) : NULL ;
00095   if (p == NULL)
00096   {
00097       /* failure: out of memory */
00098       Common->status = KLU_OUT_OF_MEMORY ;
00099   }
00100   else
00101   {
00102       Common->memusage += s ;
00103       Common->mempeak = MAX (Common->mempeak, Common->memusage) ;
00104   }
00105     }
00106     return (p) ;
00107 }
00108 
00109 
00110 /* ========================================================================== */
00111 /* === KLU_free ============================================================= */
00112 /* ========================================================================== */
00113 
00114 /* Wrapper around free routine (mxFree for a mexFunction).  Returns NULL,
00115  * which can be assigned to the pointer being freed, as in:
00116  *
00117  *  p = KLU_free (p, n, sizeof (int), Common) ;
00118  */
00119 
00120 void *KLU_free    /* always returns NULL */
00121 (
00122     /* ---- in/out --- */
00123     void *p,    /* block of memory to free */
00124     /* ---- input --- */
00125     size_t n,   /* size of block to free, in # of items */
00126     size_t size,  /* size of each item */
00127     /* --------------- */
00128     KLU_common *Common
00129 )
00130 {
00131     size_t s ;
00132     Int ok = TRUE ;
00133     if (p != NULL && Common != NULL)
00134     {
00135   /* only free the object if the pointer is not NULL */
00136   /* call free, or its equivalent */
00137   (Common->free_memory) (p) ;
00138   s = KLU_mult_size_t (MAX (1,n), size, &ok) ;
00139   Common->memusage -= s ;
00140     }
00141     /* return NULL, and the caller should assign this to p.  This avoids
00142      * freeing the same pointer twice. */
00143     return (NULL) ;
00144 }
00145 
00146 
00147 /* ========================================================================== */
00148 /* === KLU_realloc ========================================================== */
00149 /* ========================================================================== */
00150 
00151 /* Wrapper around realloc routine (mxRealloc for a mexFunction).  Given a
00152  * pointer p to a block allocated by KLU_malloc, it changes the size of the
00153  * block pointed to by p to be MAX(1,nnew)*size in size.  It may return a
00154  * pointer different than p.  This should be used as (for a pointer to Int):
00155  *
00156  *  p = KLU_realloc (nnew, nold, sizeof (Int), p, Common) ;
00157  *
00158  * If p is NULL, this is the same as p = KLU_malloc (...).
00159  * A size of nnew=0 is treated as nnew=1.
00160  *
00161  * If the realloc fails, p is returned unchanged and Common->status is set
00162  * to KLU_OUT_OF_MEMORY.  If successful, Common->status is not modified,
00163  * and p is returned (possibly changed) and pointing to a large block of memory.
00164  *
00165  * Uses a pointer to the realloc routine (or its equivalent) defined in Common.
00166  */
00167 
00168 void *KLU_realloc /* returns pointer to reallocated block */
00169 (
00170     /* ---- input ---- */
00171     size_t nnew,  /* requested # of items in reallocated block */
00172     size_t nold,  /* old # of items */
00173     size_t size,  /* size of each item */
00174     /* ---- in/out --- */
00175     void *p,    /* block of memory to realloc */
00176     /* --------------- */
00177     KLU_common *Common
00178 )
00179 {
00180     void *pnew ;
00181     size_t snew, sold ;
00182     Int ok = TRUE ;
00183 
00184     if (Common == NULL)
00185     {
00186   p = NULL ;
00187     }
00188     else if (size == 0)
00189     {
00190   /* size must be > 0 */
00191   Common->status = KLU_INVALID ;
00192   p = NULL ;
00193     }
00194     else if (p == NULL)
00195     {
00196   /* A fresh object is being allocated. */
00197   p = KLU_malloc (nnew, size, Common) ;
00198     }
00199     else if (nnew >= INT_MAX)
00200     {
00201   /* failure: nnew is too big.  Do not change p */
00202   Common->status = KLU_TOO_LARGE ;
00203     }
00204     else
00205     {
00206   /* The object exists, and is changing to some other nonzero size. */
00207   /* call realloc, or its equivalent */
00208   snew = KLU_mult_size_t (MAX (1,nnew), size, &ok) ;
00209   sold = KLU_mult_size_t (MAX (1,nold), size, &ok) ;
00210   pnew = ok ? ((Common->realloc_memory) (p, snew)) : NULL ;
00211   if (pnew == NULL)
00212   {
00213       /* Do not change p, since it still points to allocated memory */
00214       Common->status = KLU_OUT_OF_MEMORY ;
00215   }
00216   else
00217   {
00218       /* success: return the new p and change the size of the block */
00219       Common->memusage += (snew - sold) ;
00220       Common->mempeak = MAX (Common->mempeak, Common->memusage) ;
00221       p = pnew ;
00222   }
00223     }
00224     return (p) ;
00225 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines