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