xref: /libCEED/backends/memcheck/ceed-memcheck-qfunctioncontext.c (revision 544be873e4f477177e7f8c17bfd35ebcd452b114)
1 // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
2 // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3 //
4 // SPDX-License-Identifier: BSD-2-Clause
5 //
6 // This file is part of CEED:  http://github.com/ceed
7 
8 #include <ceed/ceed.h>
9 #include <ceed/backend.h>
10 #include <string.h>
11 #include <valgrind/memcheck.h>
12 #include "ceed-memcheck.h"
13 
14 //------------------------------------------------------------------------------
15 // QFunctionContext has valid data
16 //------------------------------------------------------------------------------
17 static int CeedQFunctionContextHasValidData_Memcheck(CeedQFunctionContext ctx,
18     bool *has_valid_data) {
19   int ierr;
20   CeedQFunctionContext_Memcheck *impl;
21   ierr = CeedQFunctionContextGetBackendData(ctx, (void *)&impl);
22   CeedChkBackend(ierr);
23 
24   *has_valid_data = !!impl->data;
25 
26   return CEED_ERROR_SUCCESS;
27 }
28 
29 //------------------------------------------------------------------------------
30 // QFunctionContext has borrowed data
31 //------------------------------------------------------------------------------
32 static int CeedQFunctionContextHasBorrowedDataOfType_Memcheck(
33   CeedQFunctionContext ctx, CeedMemType mem_type,
34   bool *has_borrowed_data_of_type) {
35   int ierr;
36   CeedQFunctionContext_Memcheck *impl;
37   ierr = CeedQFunctionContextGetBackendData(ctx, (void *)&impl);
38   CeedChkBackend(ierr);
39   Ceed ceed;
40   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
41 
42   switch (mem_type) {
43   case CEED_MEM_HOST:
44     *has_borrowed_data_of_type = !!impl->data_borrowed;
45     break;
46   default:
47     // LCOV_EXCL_START
48     return CeedError(ceed, CEED_ERROR_BACKEND,
49                      "Can only set HOST memory for this backend");
50     // LCOV_EXCL_STOP
51     break;
52   }
53 
54   return CEED_ERROR_SUCCESS;
55 }
56 
57 //------------------------------------------------------------------------------
58 // QFunctionContext Set Data
59 //------------------------------------------------------------------------------
60 static int CeedQFunctionContextSetData_Memcheck(CeedQFunctionContext ctx,
61     CeedMemType mem_type, CeedCopyMode copy_mode, void *data) {
62   int ierr;
63   CeedQFunctionContext_Memcheck *impl;
64   ierr = CeedQFunctionContextGetBackendData(ctx, (void *)&impl);
65   CeedChkBackend(ierr);
66   size_t ctx_size;
67   ierr = CeedQFunctionContextGetContextSize(ctx, &ctx_size); CeedChkBackend(ierr);
68   Ceed ceed;
69   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
70 
71   if (mem_type != CEED_MEM_HOST)
72     // LCOV_EXCL_START
73     return CeedError(ceed, CEED_ERROR_BACKEND,
74                      "Can only set HOST memory for this backend");
75   // LCOV_EXCL_STOP
76 
77   ierr = CeedFree(&impl->data_allocated); CeedChkBackend(ierr);
78   ierr = CeedFree(&impl->data_owned); CeedChkBackend(ierr);
79   switch (copy_mode) {
80   case CEED_COPY_VALUES:
81     ierr = CeedMallocArray(1, ctx_size, &impl->data_owned); CeedChkBackend(ierr);
82     impl->data_borrowed = NULL;
83     impl->data = impl->data_owned;
84     memcpy(impl->data, data, ctx_size);
85     break;
86   case CEED_OWN_POINTER:
87     impl->data_owned = data;
88     impl->data_borrowed = NULL;
89     impl->data = data;
90     break;
91   case CEED_USE_POINTER:
92     impl->data_borrowed = data;
93     impl->data = data;
94   }
95   // Copy data to check ctx_size bounds
96   ierr = CeedMallocArray(1, ctx_size, &impl->data_allocated);
97   CeedChkBackend(ierr);
98   memcpy(impl->data_allocated, impl->data, ctx_size);
99   impl->data = impl->data_allocated;
100   VALGRIND_DISCARD(impl->mem_block_id);
101   impl->mem_block_id = VALGRIND_CREATE_BLOCK(impl->data, ctx_size,
102                        "'QFunction backend context data copy'");
103 
104   return CEED_ERROR_SUCCESS;
105 }
106 
107 //------------------------------------------------------------------------------
108 // QFunctionContext Take Data
109 //------------------------------------------------------------------------------
110 static int CeedQFunctionContextTakeData_Memcheck(CeedQFunctionContext ctx,
111     CeedMemType mem_type, void *data) {
112   int ierr;
113   CeedQFunctionContext_Memcheck *impl;
114   ierr = CeedQFunctionContextGetBackendData(ctx, (void *)&impl);
115   CeedChkBackend(ierr);
116   Ceed ceed;
117   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
118 
119   if (mem_type != CEED_MEM_HOST)
120     // LCOV_EXCL_START
121     return CeedError(ceed, CEED_ERROR_BACKEND,
122                      "Can only provide HOST memory for this backend");
123   // LCOV_EXCL_STOP
124 
125   *(void **)data = impl->data_borrowed;
126   impl->data_borrowed = NULL;
127   impl->data = NULL;
128   VALGRIND_DISCARD(impl->mem_block_id);
129   ierr = CeedFree(&impl->data_allocated); CeedChkBackend(ierr);
130 
131   return CEED_ERROR_SUCCESS;
132 }
133 
134 //------------------------------------------------------------------------------
135 // QFunctionContext Get Data
136 //------------------------------------------------------------------------------
137 static int CeedQFunctionContextGetData_Memcheck(CeedQFunctionContext ctx,
138     CeedMemType mem_type, void *data) {
139   int ierr;
140   CeedQFunctionContext_Memcheck *impl;
141   ierr = CeedQFunctionContextGetBackendData(ctx, (void *)&impl);
142   CeedChkBackend(ierr);
143   Ceed ceed;
144   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
145 
146   if (mem_type != CEED_MEM_HOST)
147     // LCOV_EXCL_START
148     return CeedError(ceed, CEED_ERROR_BACKEND,
149                      "Can only provide HOST memory for this backend");
150   // LCOV_EXCL_STOP
151 
152   *(void **)data = impl->data;
153 
154   return CEED_ERROR_SUCCESS;
155 }
156 
157 //------------------------------------------------------------------------------
158 // QFunctionContext Get Data Read-Only
159 //------------------------------------------------------------------------------
160 static int CeedQFunctionContextGetDataRead_Memcheck(CeedQFunctionContext ctx,
161     CeedMemType mem_type, void *data) {
162   int ierr;
163   CeedQFunctionContext_Memcheck *impl;
164   ierr = CeedQFunctionContextGetBackendData(ctx, (void *)&impl);
165   CeedChkBackend(ierr);
166   size_t ctx_size;
167   ierr = CeedQFunctionContextGetContextSize(ctx, &ctx_size); CeedChkBackend(ierr);
168   Ceed ceed;
169   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
170 
171   ierr = CeedQFunctionContextGetData_Memcheck(ctx, mem_type, data);
172   CeedChkBackend(ierr);
173 
174   // Make copy to verify no write occured
175   ierr = CeedMallocArray(1, ctx_size, &impl->data_read_only_copy);
176   CeedChkBackend(ierr);
177   memcpy(impl->data_read_only_copy, *(void **)data, ctx_size);
178 
179   return CEED_ERROR_SUCCESS;
180 }
181 
182 //------------------------------------------------------------------------------
183 // QFunctionContext Restore Data
184 //------------------------------------------------------------------------------
185 static int CeedQFunctionContextRestoreData_Memcheck(CeedQFunctionContext ctx) {
186   int ierr;
187   size_t ctx_size;
188   ierr = CeedQFunctionContextGetContextSize(ctx, &ctx_size); CeedChkBackend(ierr);
189   CeedQFunctionContext_Memcheck *impl;
190   ierr = CeedQFunctionContextGetBackendData(ctx, (void *)&impl);
191   CeedChkBackend(ierr);
192 
193   if (impl->data_borrowed) {
194     memcpy(impl->data_borrowed, impl->data, ctx_size);
195   }
196   if (impl->data_owned) {
197     memcpy(impl->data_owned, impl->data, ctx_size);
198   }
199 
200   return CEED_ERROR_SUCCESS;
201 }
202 
203 //------------------------------------------------------------------------------
204 // QFunctionContext Restore Data Read-Only
205 //------------------------------------------------------------------------------
206 static int CeedQFunctionContextRestoreDataRead_Memcheck(
207   CeedQFunctionContext ctx) {
208   int ierr;
209   size_t ctx_size;
210   ierr = CeedQFunctionContextGetContextSize(ctx, &ctx_size); CeedChkBackend(ierr);
211   CeedQFunctionContext_Memcheck *impl;
212   ierr = CeedQFunctionContextGetBackendData(ctx, (void *)&impl);
213   CeedChkBackend(ierr);
214   Ceed ceed;
215   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
216 
217   if (memcmp(impl->data, impl->data_read_only_copy, ctx_size))
218     // LCOV_EXCL_START
219     return CeedError(ceed, CEED_ERROR_BACKEND,
220                      "Context data changed while accessed in read-only mode");
221   // LCOV_EXCL_STOP
222 
223   ierr = CeedFree(&impl->data_read_only_copy); CeedChkBackend(ierr);
224 
225   return CEED_ERROR_SUCCESS;
226 }
227 
228 //------------------------------------------------------------------------------
229 // QFunctionContext destroy user data
230 //------------------------------------------------------------------------------
231 static int CeedQFunctionContextDataDestroy_Memcheck(CeedQFunctionContext ctx) {
232   int ierr;
233   CeedQFunctionContext_Memcheck *impl;
234   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
235   CeedQFunctionContextDataDestroyUser data_destroy_function;
236   CeedMemType data_destroy_mem_type;
237   ierr = CeedQFunctionContextGetDataDestroy(ctx, &data_destroy_mem_type,
238          &data_destroy_function); CeedChk(ierr);
239   Ceed ceed;
240   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
241 
242   if (data_destroy_mem_type != CEED_MEM_HOST)
243     // LCOV_EXCL_START
244     return CeedError(ceed, CEED_ERROR_BACKEND,
245                      "Can only destroy HOST memory for this backend");
246   // LCOV_EXCL_STOP
247 
248   if (data_destroy_function) {
249     ierr = data_destroy_function(impl->data_borrowed ? impl->data_borrowed :
250                                  impl->data_owned); CeedChk(ierr);
251   }
252   ierr = CeedFree(&impl->data_allocated); CeedChkBackend(ierr);
253 
254   return CEED_ERROR_SUCCESS;
255 }
256 
257 //------------------------------------------------------------------------------
258 // QFunctionContext Destroy
259 //------------------------------------------------------------------------------
260 static int CeedQFunctionContextDestroy_Memcheck(CeedQFunctionContext ctx) {
261   int ierr;
262   CeedQFunctionContext_Memcheck *impl;
263   ierr = CeedQFunctionContextGetBackendData(ctx, &impl); CeedChkBackend(ierr);
264 
265   ierr = CeedFree(&impl->data_allocated); CeedChkBackend(ierr);
266   ierr = CeedFree(&impl->data_owned); CeedChkBackend(ierr);
267   ierr = CeedFree(&impl); CeedChkBackend(ierr);
268   return CEED_ERROR_SUCCESS;
269 }
270 
271 //------------------------------------------------------------------------------
272 // QFunctionContext Create
273 //------------------------------------------------------------------------------
274 int CeedQFunctionContextCreate_Memcheck(CeedQFunctionContext ctx) {
275   int ierr;
276   CeedQFunctionContext_Memcheck *impl;
277   Ceed ceed;
278   ierr = CeedQFunctionContextGetCeed(ctx, &ceed); CeedChkBackend(ierr);
279 
280   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "HasValidData",
281                                 CeedQFunctionContextHasValidData_Memcheck);
282   CeedChkBackend(ierr);
283   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx,
284                                 "HasBorrowedDataOfType",
285                                 CeedQFunctionContextHasBorrowedDataOfType_Memcheck);
286   CeedChkBackend(ierr);
287   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "SetData",
288                                 CeedQFunctionContextSetData_Memcheck); CeedChkBackend(ierr);
289   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "TakeData",
290                                 CeedQFunctionContextTakeData_Memcheck); CeedChkBackend(ierr);
291   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "GetData",
292                                 CeedQFunctionContextGetData_Memcheck); CeedChkBackend(ierr);
293   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "GetDataRead",
294                                 CeedQFunctionContextGetDataRead_Memcheck); CeedChkBackend(ierr);
295   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "RestoreData",
296                                 CeedQFunctionContextRestoreData_Memcheck); CeedChkBackend(ierr);
297   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "RestoreDataRead",
298                                 CeedQFunctionContextRestoreDataRead_Memcheck); CeedChkBackend(ierr);
299   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "DataDestroy",
300                                 CeedQFunctionContextDataDestroy_Memcheck); CeedChkBackend(ierr);
301   ierr = CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "Destroy",
302                                 CeedQFunctionContextDestroy_Memcheck); CeedChkBackend(ierr);
303 
304   ierr = CeedCalloc(1, &impl); CeedChkBackend(ierr);
305   ierr = CeedQFunctionContextSetBackendData(ctx, impl); CeedChkBackend(ierr);
306 
307   return CEED_ERROR_SUCCESS;
308 }
309 //------------------------------------------------------------------------------
310