xref: /libCEED/backends/memcheck/ceed-memcheck-qfunctioncontext.c (revision bb229da952f7e9779ba6cb3cd1ca2ebeac5feb1f)
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   CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only set HOST memory for this backend");
63 
64   CeedCallBackend(CeedFree(&impl->data_allocated));
65   CeedCallBackend(CeedFree(&impl->data_owned));
66   switch (copy_mode) {
67     case CEED_COPY_VALUES:
68       CeedCallBackend(CeedMallocArray(1, ctx_size, &impl->data_owned));
69       impl->data_borrowed = NULL;
70       impl->data          = impl->data_owned;
71       memcpy(impl->data, data, ctx_size);
72       break;
73     case CEED_OWN_POINTER:
74       impl->data_owned    = data;
75       impl->data_borrowed = NULL;
76       impl->data          = data;
77       break;
78     case CEED_USE_POINTER:
79       impl->data_borrowed = data;
80       impl->data          = data;
81   }
82   // Copy data to check ctx_size bounds
83   CeedCallBackend(CeedMallocArray(1, ctx_size, &impl->data_allocated));
84   memcpy(impl->data_allocated, impl->data, ctx_size);
85   impl->data = impl->data_allocated;
86   VALGRIND_DISCARD(impl->mem_block_id);
87   impl->mem_block_id = VALGRIND_CREATE_BLOCK(impl->data, ctx_size, "'QFunction backend context data copy'");
88 
89   return CEED_ERROR_SUCCESS;
90 }
91 
92 //------------------------------------------------------------------------------
93 // QFunctionContext Take Data
94 //------------------------------------------------------------------------------
95 static int CeedQFunctionContextTakeData_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
96   CeedQFunctionContext_Memcheck *impl;
97   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl));
98   Ceed ceed;
99   CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed));
100 
101   CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
102 
103   *(void **)data      = impl->data_borrowed;
104   impl->data_borrowed = NULL;
105   impl->data          = NULL;
106   VALGRIND_DISCARD(impl->mem_block_id);
107   CeedCallBackend(CeedFree(&impl->data_allocated));
108 
109   return CEED_ERROR_SUCCESS;
110 }
111 
112 //------------------------------------------------------------------------------
113 // QFunctionContext Get Data
114 //------------------------------------------------------------------------------
115 static int CeedQFunctionContextGetData_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
116   CeedQFunctionContext_Memcheck *impl;
117   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl));
118   Ceed ceed;
119   CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed));
120 
121   CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend");
122 
123   *(void **)data = impl->data;
124 
125   return CEED_ERROR_SUCCESS;
126 }
127 
128 //------------------------------------------------------------------------------
129 // QFunctionContext Get Data Read-Only
130 //------------------------------------------------------------------------------
131 static int CeedQFunctionContextGetDataRead_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
132   CeedQFunctionContext_Memcheck *impl;
133   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl));
134   size_t ctx_size;
135   CeedCallBackend(CeedQFunctionContextGetContextSize(ctx, &ctx_size));
136   Ceed ceed;
137   CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed));
138 
139   CeedCallBackend(CeedQFunctionContextGetData_Memcheck(ctx, mem_type, data));
140 
141   // Make copy to verify no write occurred
142   CeedCallBackend(CeedMallocArray(1, ctx_size, &impl->data_read_only_copy));
143   memcpy(impl->data_read_only_copy, *(void **)data, ctx_size);
144 
145   return CEED_ERROR_SUCCESS;
146 }
147 
148 //------------------------------------------------------------------------------
149 // QFunctionContext Restore Data
150 //------------------------------------------------------------------------------
151 static int CeedQFunctionContextRestoreData_Memcheck(CeedQFunctionContext ctx) {
152   size_t ctx_size;
153   CeedCallBackend(CeedQFunctionContextGetContextSize(ctx, &ctx_size));
154   CeedQFunctionContext_Memcheck *impl;
155   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl));
156 
157   if (impl->data_borrowed) {
158     memcpy(impl->data_borrowed, impl->data, ctx_size);
159   }
160   if (impl->data_owned) {
161     memcpy(impl->data_owned, impl->data, ctx_size);
162   }
163 
164   return CEED_ERROR_SUCCESS;
165 }
166 
167 //------------------------------------------------------------------------------
168 // QFunctionContext Restore Data Read-Only
169 //------------------------------------------------------------------------------
170 static int CeedQFunctionContextRestoreDataRead_Memcheck(CeedQFunctionContext ctx) {
171   size_t ctx_size;
172   CeedCallBackend(CeedQFunctionContextGetContextSize(ctx, &ctx_size));
173   CeedQFunctionContext_Memcheck *impl;
174   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl));
175   Ceed ceed;
176   CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed));
177 
178   CeedCheck(!memcmp(impl->data, impl->data_read_only_copy, ctx_size), ceed, CEED_ERROR_BACKEND,
179             "Context data changed while accessed in read-only mode");
180 
181   CeedCallBackend(CeedFree(&impl->data_read_only_copy));
182 
183   return CEED_ERROR_SUCCESS;
184 }
185 
186 //------------------------------------------------------------------------------
187 // QFunctionContext destroy user data
188 //------------------------------------------------------------------------------
189 static int CeedQFunctionContextDataDestroy_Memcheck(CeedQFunctionContext ctx) {
190   CeedQFunctionContext_Memcheck *impl;
191   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, &impl));
192   CeedQFunctionContextDataDestroyUser data_destroy_function;
193   CeedMemType                         data_destroy_mem_type;
194   CeedCallBackend(CeedQFunctionContextGetDataDestroy(ctx, &data_destroy_mem_type, &data_destroy_function));
195   Ceed ceed;
196   CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed));
197 
198   CeedCheck(data_destroy_mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only destroy HOST memory for this backend");
199 
200   if (data_destroy_function) {
201     CeedCallBackend(data_destroy_function(impl->data_borrowed ? impl->data_borrowed : impl->data_owned));
202   }
203   CeedCallBackend(CeedFree(&impl->data_allocated));
204 
205   return CEED_ERROR_SUCCESS;
206 }
207 
208 //------------------------------------------------------------------------------
209 // QFunctionContext Destroy
210 //------------------------------------------------------------------------------
211 static int CeedQFunctionContextDestroy_Memcheck(CeedQFunctionContext ctx) {
212   CeedQFunctionContext_Memcheck *impl;
213   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, &impl));
214 
215   CeedCallBackend(CeedFree(&impl->data_allocated));
216   CeedCallBackend(CeedFree(&impl->data_owned));
217   CeedCallBackend(CeedFree(&impl));
218   return CEED_ERROR_SUCCESS;
219 }
220 
221 //------------------------------------------------------------------------------
222 // QFunctionContext Create
223 //------------------------------------------------------------------------------
224 int CeedQFunctionContextCreate_Memcheck(CeedQFunctionContext ctx) {
225   CeedQFunctionContext_Memcheck *impl;
226   Ceed                           ceed;
227   CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed));
228 
229   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "HasValidData", CeedQFunctionContextHasValidData_Memcheck));
230   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "HasBorrowedDataOfType", CeedQFunctionContextHasBorrowedDataOfType_Memcheck));
231   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "SetData", CeedQFunctionContextSetData_Memcheck));
232   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "TakeData", CeedQFunctionContextTakeData_Memcheck));
233   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "GetData", CeedQFunctionContextGetData_Memcheck));
234   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "GetDataRead", CeedQFunctionContextGetDataRead_Memcheck));
235   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "RestoreData", CeedQFunctionContextRestoreData_Memcheck));
236   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "RestoreDataRead", CeedQFunctionContextRestoreDataRead_Memcheck));
237   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "DataDestroy", CeedQFunctionContextDataDestroy_Memcheck));
238   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "Destroy", CeedQFunctionContextDestroy_Memcheck));
239 
240   CeedCallBackend(CeedCalloc(1, &impl));
241   CeedCallBackend(CeedQFunctionContextSetBackendData(ctx, impl));
242 
243   return CEED_ERROR_SUCCESS;
244 }
245 
246 //------------------------------------------------------------------------------
247