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