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