xref: /libCEED/backends/memcheck/ceed-memcheck-qfunctioncontext.c (revision b6972d7456611f84b0e462eb1490bcb662442e6a)
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 
22   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl));
23   *has_valid_data = impl->data;
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   Ceed                           ceed;
32   CeedQFunctionContext_Memcheck *impl;
33 
34   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl));
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       // LCOV_EXCL_START
42     default:
43       return CeedError(ceed, CEED_ERROR_BACKEND, "Can only set HOST memory for this backend");
44       // LCOV_EXCL_STOP
45       break;
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   Ceed                           ceed;
55   size_t                         ctx_size;
56   CeedQFunctionContext_Memcheck *impl;
57 
58   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl));
59   CeedCallBackend(CeedQFunctionContextGetContextSize(ctx, &ctx_size));
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   return CEED_ERROR_SUCCESS;
89 }
90 
91 //------------------------------------------------------------------------------
92 // QFunctionContext Take Data
93 //------------------------------------------------------------------------------
94 static int CeedQFunctionContextTakeData_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
95   Ceed                           ceed;
96   CeedQFunctionContext_Memcheck *impl;
97 
98   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl));
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   return CEED_ERROR_SUCCESS;
109 }
110 
111 //------------------------------------------------------------------------------
112 // QFunctionContext Get Data
113 //------------------------------------------------------------------------------
114 static int CeedQFunctionContextGetData_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
115   Ceed                           ceed;
116   CeedQFunctionContext_Memcheck *impl;
117 
118   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl));
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   return CEED_ERROR_SUCCESS;
125 }
126 
127 //------------------------------------------------------------------------------
128 // QFunctionContext Get Data Read-Only
129 //------------------------------------------------------------------------------
130 static int CeedQFunctionContextGetDataRead_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) {
131   Ceed                           ceed;
132   size_t                         ctx_size;
133   CeedQFunctionContext_Memcheck *impl;
134 
135   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl));
136   CeedCallBackend(CeedQFunctionContextGetContextSize(ctx, &ctx_size));
137   CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed));
138   CeedCallBackend(CeedQFunctionContextGetData_Memcheck(ctx, mem_type, data));
139 
140   // Make copy to verify no write occurred
141   CeedCallBackend(CeedMallocArray(1, ctx_size, &impl->data_read_only_copy));
142   memcpy(impl->data_read_only_copy, *(void **)data, ctx_size);
143   return CEED_ERROR_SUCCESS;
144 }
145 
146 //------------------------------------------------------------------------------
147 // QFunctionContext Restore Data
148 //------------------------------------------------------------------------------
149 static int CeedQFunctionContextRestoreData_Memcheck(CeedQFunctionContext ctx) {
150   size_t                         ctx_size;
151   CeedQFunctionContext_Memcheck *impl;
152 
153   CeedCallBackend(CeedQFunctionContextGetContextSize(ctx, &ctx_size));
154   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl));
155 
156   if (impl->data_borrowed) memcpy(impl->data_borrowed, impl->data, ctx_size);
157   if (impl->data_owned) memcpy(impl->data_owned, impl->data, ctx_size);
158   return CEED_ERROR_SUCCESS;
159 }
160 
161 //------------------------------------------------------------------------------
162 // QFunctionContext Restore Data Read-Only
163 //------------------------------------------------------------------------------
164 static int CeedQFunctionContextRestoreDataRead_Memcheck(CeedQFunctionContext ctx) {
165   Ceed                           ceed;
166   size_t                         ctx_size;
167   CeedQFunctionContext_Memcheck *impl;
168 
169   CeedCallBackend(CeedQFunctionContextGetContextSize(ctx, &ctx_size));
170   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl));
171   CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed));
172 
173   CeedCheck(!memcmp(impl->data, impl->data_read_only_copy, ctx_size), ceed, CEED_ERROR_BACKEND,
174             "Context data changed while accessed in read-only mode");
175 
176   CeedCallBackend(CeedFree(&impl->data_read_only_copy));
177   return CEED_ERROR_SUCCESS;
178 }
179 
180 //------------------------------------------------------------------------------
181 // QFunctionContext destroy user data
182 //------------------------------------------------------------------------------
183 static int CeedQFunctionContextDataDestroy_Memcheck(CeedQFunctionContext ctx) {
184   Ceed                                ceed;
185   CeedMemType                         data_destroy_mem_type;
186   CeedQFunctionContextDataDestroyUser data_destroy_function;
187   CeedQFunctionContext_Memcheck      *impl;
188 
189   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, &impl));
190   CeedCallBackend(CeedQFunctionContextGetDataDestroy(ctx, &data_destroy_mem_type, &data_destroy_function));
191   CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed));
192 
193   CeedCheck(data_destroy_mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only destroy HOST memory for this backend");
194 
195   if (data_destroy_function) {
196     CeedCallBackend(data_destroy_function(impl->data_borrowed ? impl->data_borrowed : impl->data_owned));
197   }
198   CeedCallBackend(CeedFree(&impl->data_allocated));
199   return CEED_ERROR_SUCCESS;
200 }
201 
202 //------------------------------------------------------------------------------
203 // QFunctionContext Destroy
204 //------------------------------------------------------------------------------
205 static int CeedQFunctionContextDestroy_Memcheck(CeedQFunctionContext ctx) {
206   CeedQFunctionContext_Memcheck *impl;
207 
208   CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, &impl));
209   CeedCallBackend(CeedFree(&impl->data_allocated));
210   CeedCallBackend(CeedFree(&impl->data_owned));
211   CeedCallBackend(CeedFree(&impl));
212   return CEED_ERROR_SUCCESS;
213 }
214 
215 //------------------------------------------------------------------------------
216 // QFunctionContext Create
217 //------------------------------------------------------------------------------
218 int CeedQFunctionContextCreate_Memcheck(CeedQFunctionContext ctx) {
219   Ceed                           ceed;
220   CeedQFunctionContext_Memcheck *impl;
221 
222   CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed));
223   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "HasValidData", CeedQFunctionContextHasValidData_Memcheck));
224   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "HasBorrowedDataOfType", CeedQFunctionContextHasBorrowedDataOfType_Memcheck));
225   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "SetData", CeedQFunctionContextSetData_Memcheck));
226   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "TakeData", CeedQFunctionContextTakeData_Memcheck));
227   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "GetData", CeedQFunctionContextGetData_Memcheck));
228   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "GetDataRead", CeedQFunctionContextGetDataRead_Memcheck));
229   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "RestoreData", CeedQFunctionContextRestoreData_Memcheck));
230   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "RestoreDataRead", CeedQFunctionContextRestoreDataRead_Memcheck));
231   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "DataDestroy", CeedQFunctionContextDataDestroy_Memcheck));
232   CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "Destroy", CeedQFunctionContextDestroy_Memcheck));
233   CeedCallBackend(CeedCalloc(1, &impl));
234   CeedCallBackend(CeedQFunctionContextSetBackendData(ctx, impl));
235   return CEED_ERROR_SUCCESS;
236 }
237 
238 //------------------------------------------------------------------------------
239