1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
//------------------------------------------------------------------------------
// LG_test.h: include file for LAGraph test library
//------------------------------------------------------------------------------
// LAGraph, (c) 2021 by The LAGraph Contributors, All Rights Reserved.
// SPDX-License-Identifier: BSD-2-Clause
// See additional acknowledgments in the LICENSE file,
// or contact permission@sei.cmu.edu for the full terms.
// Contributed by Timothy A. Davis, Texas A&M University
//------------------------------------------------------------------------------
// compiling LAGraph itself, exporting symbols to user apps
// compiling the user application, importing symbols from LAGraph
// for other compilers
int ;
int LG_check_tri // -1 if out of memory, 0 if successful
;
int ;
int ;
int ;
int ;
//------------------------------------------------------------------------------
// LG_brutal_*: brutal memory tests
//------------------------------------------------------------------------------
// Brutal memory tests use a global variable (LG_brutal) to tell them how many
// times malloc may be successfully called. Once this counter reaches zero,
// LG_brutal_malloc, LG_brutal_calloc, and LG_brutal_realloc all return NULL.
// SuiteSparse:GraphBLAS is required for brutal memory testing. The
// LG_brutal_malloc/calloc/realloc/free methods are passed to SuiteSparse
// GraphBLAS via GxB_init. This way, out-of-memory conditions returned by
// GraphBLAS can be checked and handled by LAGraph.
// Use LG_brutal_setup to start LAGraph for brutal memory tests, and
// LG_brutal_teardown to finish. To test a method with brutal memory tests,
// use LG_BRUTAL (LAGraph_method (...)). The LAGraph_method(...) will be
// called with LG_brutal set to 0 (no mallocs allowed), 1 (one malloc), 2, ...
// until the method succeeds by returning a result >= 0. If a method never
// returns a non-negative result, LG_BRUTAL will get stuck in an infinite loop.
// If LG_brutal starts as negative, then the brutal memory tests are not
// performed, and LG_brutal_malloc/calloc/etc never pretend to fail.
// A count (LG_nmalloc) is kept of the number of allocated blocks that have not
// yet been freed. If this count is not zero after finalizing GraphBLAS
// and LAGraph, an error is reported. No report is provided as to what blocks
// of memory are still allocated; use valgrind if that occurs.
// For methods that access files, or have other side effects, the LG_BRUTAL
// macro will not work. It will reach a failure state from which it cannot
// recover. For example:
//
// (1) LG_BRUTAL (LAGraph_MMRead (...)) would fail, because it would read the
// file and then fail because LG_brutal_malloc returns a NULL. To handle
// this, each iteration of the brutal loop must rewind the file for the
// next brutal trial. See src/test/test_MMRead for details.
//
// (2) If any GrB_Matrix or GrB_Vector component of G has pending work (G->A
// for example), and GraphBLAS attempts to finish it, the method will fail
// if LG_brutal_malloc returns NULL. In this case, GraphBLAS will return
// the GrB_Matrix or GrB_Vector as an invalid object, and then LG_BRUTAL
// will never succeed. If this occurs, simply use GrB_wait to finalize
// all components of G first, before trying a brutal test on a method that
// uses G. See src/test/test_Graph_Print.c for an example.
//
// (3) LG_BRUTAL will fail for methods that unpack/pack their input matrix
// G->A (such as several of the LG_check_* methods, and the current draft
// of LG_CC_FastSV6). Those methods will return an empty G->A with no
// entries, if they fail in the middle. For these methods, the brutal
// tests must keep a copy of G->A outside of G, and reconstruct G->A for
// each trial.
//
// (4) Some GrB* methods leave their output matrix in an invalid state, with
// all entries cleared, if an out-of-memory failure occurs (GrB_assign
// in particular). See src/test/test_vector for an example.
//
// If CUDA is enabled in GraphBLAS, the brutal tests will not yet be
// guaranteed to work, since the use of CUDA overrides the use of the
// LG_brutal_malloc family of functions, and uses the Rapids Memory
// Manager methods instead.
LG_TEST_PUBLIC int ;
LG_TEST_PUBLIC int ;
LG_TEST_PUBLIC extern int64_t LG_brutal ;
LG_TEST_PUBLIC extern int64_t LG_nmalloc ;
void *LG_brutal_malloc // return pointer to allocated block of memory
;
void *LG_brutal_calloc // return pointer to allocated block of memory
;
void ;
void *LG_brutal_realloc // return pointer to reallocated memory
;
// brutal memory testing of a GraphBLAS or LAGraph method, no burble
// brutal memory testing of a GraphBLAS or LAGraph method, and print results