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