1*9798701eSJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 2*9798701eSJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 3*9798701eSJeremy L Thompson // 4*9798701eSJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 5*9798701eSJeremy L Thompson // 6*9798701eSJeremy L Thompson // This file is part of CEED: http://github.com/ceed 7*9798701eSJeremy L Thompson 8*9798701eSJeremy L Thompson #include <ceed/backend.h> 9*9798701eSJeremy L Thompson #include <ceed/ceed.h> 10*9798701eSJeremy L Thompson #include <math.h> 11*9798701eSJeremy L Thompson #include <string.h> 12*9798701eSJeremy L Thompson #include <valgrind/memcheck.h> 13*9798701eSJeremy L Thompson 14*9798701eSJeremy L Thompson #include "ceed-memcheck.h" 15*9798701eSJeremy L Thompson 16*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 17*9798701eSJeremy L Thompson // Has Valid Array 18*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 19*9798701eSJeremy L Thompson static int CeedVectorHasValidArray_Memcheck(CeedVector vec, bool *has_valid_array) { 20*9798701eSJeremy L Thompson CeedVector_Memcheck *impl; 21*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 22*9798701eSJeremy L Thompson 23*9798701eSJeremy L Thompson *has_valid_array = !!impl->array; 24*9798701eSJeremy L Thompson 25*9798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 26*9798701eSJeremy L Thompson } 27*9798701eSJeremy L Thompson 28*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 29*9798701eSJeremy L Thompson // Check if has borrowed array of given type 30*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 31*9798701eSJeremy L Thompson static inline int CeedVectorHasBorrowedArrayOfType_Memcheck(const CeedVector vec, CeedMemType mem_type, bool *has_borrowed_array_of_type) { 32*9798701eSJeremy L Thompson CeedVector_Memcheck *impl; 33*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 34*9798701eSJeremy L Thompson Ceed ceed; 35*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 36*9798701eSJeremy L Thompson 37*9798701eSJeremy L Thompson switch (mem_type) { 38*9798701eSJeremy L Thompson case CEED_MEM_HOST: 39*9798701eSJeremy L Thompson *has_borrowed_array_of_type = !!impl->array_borrowed; 40*9798701eSJeremy L Thompson break; 41*9798701eSJeremy L Thompson default: 42*9798701eSJeremy L Thompson // LCOV_EXCL_START 43*9798701eSJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "Can only set HOST memory for this backend"); 44*9798701eSJeremy L Thompson // LCOV_EXCL_STOP 45*9798701eSJeremy L Thompson break; 46*9798701eSJeremy L Thompson } 47*9798701eSJeremy L Thompson 48*9798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 49*9798701eSJeremy L Thompson } 50*9798701eSJeremy L Thompson 51*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 52*9798701eSJeremy L Thompson // Vector Set Array 53*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 54*9798701eSJeremy L Thompson static int CeedVectorSetArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedCopyMode copy_mode, CeedScalar *array) { 55*9798701eSJeremy L Thompson CeedVector_Memcheck *impl; 56*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 57*9798701eSJeremy L Thompson CeedSize length; 58*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 59*9798701eSJeremy L Thompson Ceed ceed; 60*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 61*9798701eSJeremy L Thompson 62*9798701eSJeremy L Thompson if (mem_type != CEED_MEM_HOST) { 63*9798701eSJeremy L Thompson // LCOV_EXCL_START 64*9798701eSJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "Can only set HOST memory for this backend"); 65*9798701eSJeremy L Thompson // LCOV_EXCL_STOP 66*9798701eSJeremy L Thompson } 67*9798701eSJeremy L Thompson 68*9798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_allocated)); 69*9798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_owned)); 70*9798701eSJeremy L Thompson switch (copy_mode) { 71*9798701eSJeremy L Thompson case CEED_COPY_VALUES: 72*9798701eSJeremy L Thompson CeedCallBackend(CeedCalloc(length, &impl->array_owned)); 73*9798701eSJeremy L Thompson impl->array_borrowed = NULL; 74*9798701eSJeremy L Thompson impl->array = impl->array_owned; 75*9798701eSJeremy L Thompson if (array) { 76*9798701eSJeremy L Thompson memcpy(impl->array, array, length * sizeof(array[0])); 77*9798701eSJeremy L Thompson } else { 78*9798701eSJeremy L Thompson for (CeedInt i = 0; i < length; i++) impl->array[i] = NAN; 79*9798701eSJeremy L Thompson } 80*9798701eSJeremy L Thompson break; 81*9798701eSJeremy L Thompson case CEED_OWN_POINTER: 82*9798701eSJeremy L Thompson impl->array_owned = array; 83*9798701eSJeremy L Thompson impl->array_borrowed = NULL; 84*9798701eSJeremy L Thompson impl->array = array; 85*9798701eSJeremy L Thompson break; 86*9798701eSJeremy L Thompson case CEED_USE_POINTER: 87*9798701eSJeremy L Thompson impl->array_borrowed = array; 88*9798701eSJeremy L Thompson impl->array = array; 89*9798701eSJeremy L Thompson } 90*9798701eSJeremy L Thompson // Copy data to check access 91*9798701eSJeremy L Thompson CeedCallBackend(CeedCalloc(length, &impl->array_allocated)); 92*9798701eSJeremy L Thompson memcpy(impl->array_allocated, impl->array, length * sizeof(array[0])); 93*9798701eSJeremy L Thompson impl->array = impl->array_allocated; 94*9798701eSJeremy L Thompson VALGRIND_DISCARD(impl->mem_block_id); 95*9798701eSJeremy L Thompson impl->mem_block_id = VALGRIND_CREATE_BLOCK(impl->array, length * sizeof(array[0]), "'Vector backend array data copy'"); 96*9798701eSJeremy L Thompson 97*9798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 98*9798701eSJeremy L Thompson } 99*9798701eSJeremy L Thompson 100*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 101*9798701eSJeremy L Thompson // Vector Take Array 102*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 103*9798701eSJeremy L Thompson static int CeedVectorTakeArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 104*9798701eSJeremy L Thompson CeedVector_Memcheck *impl; 105*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 106*9798701eSJeremy L Thompson Ceed ceed; 107*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 108*9798701eSJeremy L Thompson 109*9798701eSJeremy L Thompson if (mem_type != CEED_MEM_HOST) { 110*9798701eSJeremy L Thompson // LCOV_EXCL_START 111*9798701eSJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend"); 112*9798701eSJeremy L Thompson // LCOV_EXCL_STOP 113*9798701eSJeremy L Thompson } 114*9798701eSJeremy L Thompson 115*9798701eSJeremy L Thompson (*array) = impl->array_borrowed; 116*9798701eSJeremy L Thompson impl->array_borrowed = NULL; 117*9798701eSJeremy L Thompson impl->array = NULL; 118*9798701eSJeremy L Thompson VALGRIND_DISCARD(impl->mem_block_id); 119*9798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_allocated)); 120*9798701eSJeremy L Thompson 121*9798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 122*9798701eSJeremy L Thompson } 123*9798701eSJeremy L Thompson 124*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 125*9798701eSJeremy L Thompson // Vector Get Array 126*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 127*9798701eSJeremy L Thompson static int CeedVectorGetArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 128*9798701eSJeremy L Thompson CeedVector_Memcheck *impl; 129*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 130*9798701eSJeremy L Thompson Ceed ceed; 131*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 132*9798701eSJeremy L Thompson 133*9798701eSJeremy L Thompson if (mem_type != CEED_MEM_HOST) { 134*9798701eSJeremy L Thompson // LCOV_EXCL_START 135*9798701eSJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend"); 136*9798701eSJeremy L Thompson // LCOV_EXCL_STOP 137*9798701eSJeremy L Thompson } 138*9798701eSJeremy L Thompson 139*9798701eSJeremy L Thompson *array = impl->array; 140*9798701eSJeremy L Thompson 141*9798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 142*9798701eSJeremy L Thompson } 143*9798701eSJeremy L Thompson 144*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 145*9798701eSJeremy L Thompson // Vector Get Array Read 146*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 147*9798701eSJeremy L Thompson static int CeedVectorGetArrayRead_Memcheck(CeedVector vec, CeedMemType mem_type, const CeedScalar **array) { 148*9798701eSJeremy L Thompson CeedVector_Memcheck *impl; 149*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 150*9798701eSJeremy L Thompson CeedSize length; 151*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 152*9798701eSJeremy L Thompson Ceed ceed; 153*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 154*9798701eSJeremy L Thompson 155*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetArray_Memcheck(vec, mem_type, (CeedScalar **)array)); 156*9798701eSJeremy L Thompson 157*9798701eSJeremy L Thompson // Make copy to verify no write occurred 158*9798701eSJeremy L Thompson CeedCallBackend(CeedCalloc(length, &impl->array_read_only_copy)); 159*9798701eSJeremy L Thompson memcpy(impl->array_read_only_copy, *array, length * sizeof((*array)[0])); 160*9798701eSJeremy L Thompson 161*9798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 162*9798701eSJeremy L Thompson } 163*9798701eSJeremy L Thompson 164*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 165*9798701eSJeremy L Thompson // Vector Get Array Write 166*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 167*9798701eSJeremy L Thompson static int CeedVectorGetArrayWrite_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 168*9798701eSJeremy L Thompson CeedVector_Memcheck *impl; 169*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 170*9798701eSJeremy L Thompson CeedSize length; 171*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 172*9798701eSJeremy L Thompson Ceed ceed; 173*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 174*9798701eSJeremy L Thompson 175*9798701eSJeremy L Thompson // Invalidate data to make sure no read occurs 176*9798701eSJeremy L Thompson if (!impl->array) CeedCallBackend(CeedVectorSetArray_Memcheck(vec, mem_type, CEED_COPY_VALUES, NULL)); 177*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetArray_Memcheck(vec, mem_type, array)); 178*9798701eSJeremy L Thompson for (CeedInt i = 0; i < length; i++) (*array)[i] = NAN; 179*9798701eSJeremy L Thompson 180*9798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 181*9798701eSJeremy L Thompson } 182*9798701eSJeremy L Thompson 183*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 184*9798701eSJeremy L Thompson // Vector Restore Array 185*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 186*9798701eSJeremy L Thompson static int CeedVectorRestoreArray_Memcheck(CeedVector vec) { 187*9798701eSJeremy L Thompson CeedVector_Memcheck *impl; 188*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 189*9798701eSJeremy L Thompson CeedSize length; 190*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 191*9798701eSJeremy L Thompson Ceed ceed; 192*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 193*9798701eSJeremy L Thompson 194*9798701eSJeremy L Thompson if (impl->array_borrowed) { 195*9798701eSJeremy L Thompson memcpy(impl->array_borrowed, impl->array, length * sizeof(impl->array[0])); 196*9798701eSJeremy L Thompson } 197*9798701eSJeremy L Thompson if (impl->array_owned) { 198*9798701eSJeremy L Thompson memcpy(impl->array_owned, impl->array, length * sizeof(impl->array[0])); 199*9798701eSJeremy L Thompson } 200*9798701eSJeremy L Thompson 201*9798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 202*9798701eSJeremy L Thompson } 203*9798701eSJeremy L Thompson 204*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 205*9798701eSJeremy L Thompson // Vector Restore Array Read-Only 206*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 207*9798701eSJeremy L Thompson static int CeedVectorRestoreArrayRead_Memcheck(CeedVector vec) { 208*9798701eSJeremy L Thompson CeedVector_Memcheck *impl; 209*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 210*9798701eSJeremy L Thompson CeedSize length; 211*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 212*9798701eSJeremy L Thompson Ceed ceed; 213*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 214*9798701eSJeremy L Thompson 215*9798701eSJeremy L Thompson if (memcmp(impl->array, impl->array_read_only_copy, length * sizeof(impl->array[0]))) { 216*9798701eSJeremy L Thompson // LCOV_EXCL_START 217*9798701eSJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "Array data changed while accessed in read-only mode"); 218*9798701eSJeremy L Thompson // LCOV_EXCL_STOP 219*9798701eSJeremy L Thompson } 220*9798701eSJeremy L Thompson 221*9798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_read_only_copy)); 222*9798701eSJeremy L Thompson 223*9798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 224*9798701eSJeremy L Thompson } 225*9798701eSJeremy L Thompson 226*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 227*9798701eSJeremy L Thompson // Vector Destroy 228*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 229*9798701eSJeremy L Thompson static int CeedVectorDestroy_Memcheck(CeedVector vec) { 230*9798701eSJeremy L Thompson CeedVector_Memcheck *impl; 231*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 232*9798701eSJeremy L Thompson 233*9798701eSJeremy L Thompson VALGRIND_DISCARD(impl->mem_block_id); 234*9798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_allocated)); 235*9798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_owned)); 236*9798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl)); 237*9798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 238*9798701eSJeremy L Thompson } 239*9798701eSJeremy L Thompson 240*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 241*9798701eSJeremy L Thompson // Vector Create 242*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 243*9798701eSJeremy L Thompson int CeedVectorCreate_Memcheck(CeedSize n, CeedVector vec) { 244*9798701eSJeremy L Thompson CeedVector_Memcheck *impl; 245*9798701eSJeremy L Thompson Ceed ceed; 246*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 247*9798701eSJeremy L Thompson 248*9798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "HasValidArray", CeedVectorHasValidArray_Memcheck)); 249*9798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "HasBorrowedArrayOfType", CeedVectorHasBorrowedArrayOfType_Memcheck)); 250*9798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SetArray", CeedVectorSetArray_Memcheck)); 251*9798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "TakeArray", CeedVectorTakeArray_Memcheck)); 252*9798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArray", CeedVectorGetArray_Memcheck)); 253*9798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayRead", CeedVectorGetArrayRead_Memcheck)); 254*9798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayWrite", CeedVectorGetArrayWrite_Memcheck)); 255*9798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArray", CeedVectorRestoreArray_Memcheck)); 256*9798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArrayRead", CeedVectorRestoreArrayRead_Memcheck)); 257*9798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "Destroy", CeedVectorDestroy_Memcheck)); 258*9798701eSJeremy L Thompson 259*9798701eSJeremy L Thompson CeedCallBackend(CeedCalloc(1, &impl)); 260*9798701eSJeremy L Thompson CeedCallBackend(CeedVectorSetData(vec, impl)); 261*9798701eSJeremy L Thompson 262*9798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 263*9798701eSJeremy L Thompson } 264*9798701eSJeremy L Thompson //------------------------------------------------------------------------------ 265