1 //------------------------------------------------------------------------------
2 // GB_malloc_memory: wrapper for malloc
3 //------------------------------------------------------------------------------
4 
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
6 // SPDX-License-Identifier: Apache-2.0
7 
8 //------------------------------------------------------------------------------
9 
10 // A wrapper for malloc.  Space is not initialized.
11 
12 #include "GB.h"
13 
14 //------------------------------------------------------------------------------
15 // GB_malloc_helper:  use malloc to allocate an uninitialized memory block
16 //------------------------------------------------------------------------------
17 
GB_malloc_helper(size_t * size,bool malloc_tracking)18 static inline void *GB_malloc_helper
19 (
20     // input/output:
21     size_t *size,           // on input: # of bytes requested
22                             // on output: # of bytes actually allocated
23     // input:
24     bool malloc_tracking
25 )
26 {
27     void *p = NULL ;
28 
29     // determine the next higher power of 2
30     (*size) = GB_IMAX (*size, 8) ;
31     int k = GB_CEIL_LOG2 (*size) ;
32 
33     // if available, get the block from the pool
34     if (GB_Global_free_pool_limit_get (k) > 0)
35     {
36         // round up the size to the nearest power of two
37         (*size) = ((size_t) 1) << k ;
38         p = GB_Global_free_pool_get (k) ;
39 //      if (p != NULL) printf ("malloc from pool: %p %ld\n", p, *size) ;
40     }
41 
42     if (p == NULL)
43     {
44         // no block in the free_pool, so allocate it
45 
46 //          if (GB_Global_rmm_get ( ))
47 //          {
48 //              p = GB_rmm_alloc (size) ;
49 //          }
50 //          else
51             {
52                 p = GB_Global_malloc_function (*size) ;
53             }
54 
55         if (p != NULL && malloc_tracking)
56         {
57             // success
58             GB_Global_nmalloc_increment ( ) ;
59         }
60 //      printf ("hard malloc %p %ld\n", p, *size) ;
61     }
62 //  GB_Global_free_pool_dump (2) ; GB_Global_memtable_dump ( ) ;
63 
64     return (p) ;
65 }
66 
67 //------------------------------------------------------------------------------
68 // GB_malloc_memory
69 //------------------------------------------------------------------------------
70 
71 GB_PUBLIC   // accessed by the MATLAB tests in GraphBLAS/Test only
GB_malloc_memory(size_t nitems,size_t size_of_item,size_t * size_allocated)72 void *GB_malloc_memory      // pointer to allocated block of memory
73 (
74     size_t nitems,          // number of items to allocate
75     size_t size_of_item,    // sizeof each item
76     // output
77     size_t *size_allocated  // # of bytes actually allocated
78 )
79 {
80 
81     //--------------------------------------------------------------------------
82     // check inputs
83     //--------------------------------------------------------------------------
84 
85     ASSERT (size_allocated != NULL) ;
86 
87     void *p ;
88     size_t size ;
89 
90     // make sure at least one item is allocated
91     nitems = GB_IMAX (1, nitems) ;
92 
93     // make sure at least one byte is allocated
94     size_of_item = GB_IMAX (1, size_of_item) ;
95 
96     bool ok = GB_size_t_multiply (&size, nitems, size_of_item) ;
97     if (!ok || nitems > GxB_INDEX_MAX || size_of_item > GxB_INDEX_MAX)
98     {
99         // overflow
100         (*size_allocated) = 0 ;
101         return (NULL) ;
102     }
103 
104     //--------------------------------------------------------------------------
105     // allocate the memory block
106     //--------------------------------------------------------------------------
107 
108     if (GB_Global_malloc_tracking_get ( ))
109     {
110 
111         //----------------------------------------------------------------------
112         // for memory usage testing only
113         //----------------------------------------------------------------------
114 
115         // brutal memory debug; pretend to fail if (count-- <= 0).
116         bool pretend_to_fail = false ;
117         if (GB_Global_malloc_debug_get ( ))
118         {
119             pretend_to_fail = GB_Global_malloc_debug_count_decrement ( ) ;
120         }
121 
122         // allocate the memory
123         if (pretend_to_fail)
124         {
125             p = NULL ;
126         }
127         else
128         {
129             p = GB_malloc_helper (&size, true) ;
130         }
131 
132     }
133     else
134     {
135 
136         //----------------------------------------------------------------------
137         // normal use, in production
138         //----------------------------------------------------------------------
139 
140         p = GB_malloc_helper (&size, false) ;
141     }
142 
143     //--------------------------------------------------------------------------
144     // return result
145     //--------------------------------------------------------------------------
146 
147     (*size_allocated) = (p == NULL) ? 0 : size ;
148     ASSERT (GB_IMPLIES (p != NULL, size == GB_Global_memtable_size (p))) ;
149 //  GB_Global_free_pool_dump (2) ;
150     return (p) ;
151 }
152 
153