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