15aed82e4SJeremy L Thompson // Copyright (c) 2017-2024, Lawrence Livermore National Security, LLC and other CEED contributors. 29798701eSJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 39798701eSJeremy L Thompson // 49798701eSJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 59798701eSJeremy L Thompson // 69798701eSJeremy L Thompson // This file is part of CEED: http://github.com/ceed 79798701eSJeremy L Thompson 849aac155SJeremy L Thompson #include <ceed.h> 99798701eSJeremy L Thompson #include <ceed/backend.h> 109798701eSJeremy L Thompson #include <math.h> 1149aac155SJeremy L Thompson #include <stdbool.h> 129798701eSJeremy L Thompson #include <string.h> 139798701eSJeremy L Thompson #include <valgrind/memcheck.h> 149798701eSJeremy L Thompson 159798701eSJeremy L Thompson #include "ceed-memcheck.h" 169798701eSJeremy L Thompson 179798701eSJeremy L Thompson //------------------------------------------------------------------------------ 189798701eSJeremy L Thompson // Has Valid Array 199798701eSJeremy L Thompson //------------------------------------------------------------------------------ 209798701eSJeremy L Thompson static int CeedVectorHasValidArray_Memcheck(CeedVector vec, bool *has_valid_array) { 219798701eSJeremy L Thompson CeedVector_Memcheck *impl; 22ad70ee2cSJeremy L Thompson 239798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 241c66c397SJeremy L Thompson *has_valid_array = impl->array; 259798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 269798701eSJeremy L Thompson } 279798701eSJeremy L Thompson 289798701eSJeremy L Thompson //------------------------------------------------------------------------------ 299798701eSJeremy L Thompson // Check if has borrowed array of given type 309798701eSJeremy L Thompson //------------------------------------------------------------------------------ 319798701eSJeremy L Thompson static inline int CeedVectorHasBorrowedArrayOfType_Memcheck(const CeedVector vec, CeedMemType mem_type, bool *has_borrowed_array_of_type) { 32ad70ee2cSJeremy L Thompson CeedVector_Memcheck *impl; 33ad70ee2cSJeremy L Thompson 34ad70ee2cSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 356e536b99SJeremy L Thompson CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only set HOST memory for this backend"); 361c66c397SJeremy L Thompson *has_borrowed_array_of_type = impl->array_borrowed; 379798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 389798701eSJeremy L Thompson } 399798701eSJeremy L Thompson 409798701eSJeremy L Thompson //------------------------------------------------------------------------------ 419798701eSJeremy L Thompson // Vector Set Array 429798701eSJeremy L Thompson //------------------------------------------------------------------------------ 439798701eSJeremy L Thompson static int CeedVectorSetArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedCopyMode copy_mode, CeedScalar *array) { 44ad70ee2cSJeremy L Thompson CeedSize length; 45ad70ee2cSJeremy L Thompson CeedVector_Memcheck *impl; 46ad70ee2cSJeremy L Thompson 47ad70ee2cSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 48ad70ee2cSJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 499798701eSJeremy L Thompson 506e536b99SJeremy L Thompson CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only set HOST memory for this backend"); 519798701eSJeremy L Thompson 52*d1931fc8SJeremy L Thompson if (impl->array_allocated) { 53*d1931fc8SJeremy L Thompson for (CeedSize i = 0; i < length; i++) impl->array_allocated[i] = NAN; 54*d1931fc8SJeremy L Thompson } 559798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_allocated)); 56*d1931fc8SJeremy L Thompson if (impl->array_owned) { 57*d1931fc8SJeremy L Thompson for (CeedSize i = 0; i < length; i++) impl->array_owned[i] = NAN; 58*d1931fc8SJeremy L Thompson } 599798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_owned)); 609798701eSJeremy L Thompson switch (copy_mode) { 619798701eSJeremy L Thompson case CEED_COPY_VALUES: 629798701eSJeremy L Thompson CeedCallBackend(CeedCalloc(length, &impl->array_owned)); 639798701eSJeremy L Thompson impl->array_borrowed = NULL; 649798701eSJeremy L Thompson impl->array = impl->array_owned; 659798701eSJeremy L Thompson if (array) { 66*d1931fc8SJeremy L Thompson memcpy(impl->array, array, length * sizeof(CeedScalar)); 679798701eSJeremy L Thompson } else { 689798701eSJeremy L Thompson for (CeedInt i = 0; i < length; i++) impl->array[i] = NAN; 699798701eSJeremy L Thompson } 709798701eSJeremy L Thompson break; 719798701eSJeremy L Thompson case CEED_OWN_POINTER: 729798701eSJeremy L Thompson impl->array_owned = array; 739798701eSJeremy L Thompson impl->array_borrowed = NULL; 749798701eSJeremy L Thompson impl->array = array; 759798701eSJeremy L Thompson break; 769798701eSJeremy L Thompson case CEED_USE_POINTER: 779798701eSJeremy L Thompson impl->array_borrowed = array; 789798701eSJeremy L Thompson impl->array = array; 799798701eSJeremy L Thompson } 809798701eSJeremy L Thompson // Copy data to check access 819798701eSJeremy L Thompson CeedCallBackend(CeedCalloc(length, &impl->array_allocated)); 82*d1931fc8SJeremy L Thompson memcpy(impl->array_allocated, impl->array, length * sizeof(CeedScalar)); 839798701eSJeremy L Thompson impl->array = impl->array_allocated; 849798701eSJeremy L Thompson VALGRIND_DISCARD(impl->mem_block_id); 85*d1931fc8SJeremy L Thompson impl->mem_block_id = VALGRIND_CREATE_BLOCK(impl->array, length * sizeof(CeedScalar), "'Vector backend array data copy'"); 869798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 879798701eSJeremy L Thompson } 889798701eSJeremy L Thompson 899798701eSJeremy L Thompson //------------------------------------------------------------------------------ 909798701eSJeremy L Thompson // Vector Take Array 919798701eSJeremy L Thompson //------------------------------------------------------------------------------ 929798701eSJeremy L Thompson static int CeedVectorTakeArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 93*d1931fc8SJeremy L Thompson CeedSize length; 94ad70ee2cSJeremy L Thompson CeedVector_Memcheck *impl; 95ad70ee2cSJeremy L Thompson 96ad70ee2cSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 97*d1931fc8SJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 989798701eSJeremy L Thompson 996e536b99SJeremy L Thompson CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend"); 1009798701eSJeremy L Thompson 1019798701eSJeremy L Thompson (*array) = impl->array_borrowed; 1029798701eSJeremy L Thompson impl->array_borrowed = NULL; 1039798701eSJeremy L Thompson impl->array = NULL; 1049798701eSJeremy L Thompson VALGRIND_DISCARD(impl->mem_block_id); 105*d1931fc8SJeremy L Thompson if (impl->array_allocated) { 106*d1931fc8SJeremy L Thompson for (CeedSize i = 0; i < length; i++) impl->array_allocated[i] = NAN; 107*d1931fc8SJeremy L Thompson } 1089798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_allocated)); 1099798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 1109798701eSJeremy L Thompson } 1119798701eSJeremy L Thompson 1129798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1139798701eSJeremy L Thompson // Vector Get Array 1149798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1159798701eSJeremy L Thompson static int CeedVectorGetArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 1161a3e18b3SJeremy L Thompson CeedSize length; 117ad70ee2cSJeremy L Thompson CeedVector_Memcheck *impl; 118ad70ee2cSJeremy L Thompson 119ad70ee2cSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 1201a3e18b3SJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 1219798701eSJeremy L Thompson 1226e536b99SJeremy L Thompson CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend"); 1239798701eSJeremy L Thompson 1241a3e18b3SJeremy L Thompson CeedCallBackend(CeedCalloc(length, &impl->array_writable_copy)); 125*d1931fc8SJeremy L Thompson memcpy(impl->array_writable_copy, impl->array, length * sizeof(CeedScalar)); 1261a3e18b3SJeremy L Thompson *array = impl->array_writable_copy; 1279798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 1289798701eSJeremy L Thompson } 1299798701eSJeremy L Thompson 1309798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1319798701eSJeremy L Thompson // Vector Get Array Read 1329798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1339798701eSJeremy L Thompson static int CeedVectorGetArrayRead_Memcheck(CeedVector vec, CeedMemType mem_type, const CeedScalar **array) { 134ad70ee2cSJeremy L Thompson CeedSize length; 135ad70ee2cSJeremy L Thompson CeedVector_Memcheck *impl; 136ad70ee2cSJeremy L Thompson 137ad70ee2cSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 138ad70ee2cSJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 1399798701eSJeremy L Thompson 1401a3e18b3SJeremy L Thompson CeedCheck(mem_type == CEED_MEM_HOST, CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend"); 1419798701eSJeremy L Thompson 1429798701eSJeremy L Thompson // Make copy to verify no write occurred 1435b5dc0c8SJeremy L Thompson if (!impl->array_read_only_copy) { 1449798701eSJeremy L Thompson CeedCallBackend(CeedCalloc(length, &impl->array_read_only_copy)); 145*d1931fc8SJeremy L Thompson memcpy(impl->array_read_only_copy, impl->array, length * sizeof(CeedScalar)); 1465b5dc0c8SJeremy L Thompson } 147*d1931fc8SJeremy L Thompson *array = impl->array_read_only_copy; 1489798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 1499798701eSJeremy L Thompson } 1509798701eSJeremy L Thompson 1519798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1529798701eSJeremy L Thompson // Vector Get Array Write 1539798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1549798701eSJeremy L Thompson static int CeedVectorGetArrayWrite_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 155ad70ee2cSJeremy L Thompson CeedSize length; 156ad70ee2cSJeremy L Thompson CeedVector_Memcheck *impl; 157ad70ee2cSJeremy L Thompson 158ad70ee2cSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 159ad70ee2cSJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 1609798701eSJeremy L Thompson 1619798701eSJeremy L Thompson // Invalidate data to make sure no read occurs 1629798701eSJeremy L Thompson if (!impl->array) CeedCallBackend(CeedVectorSetArray_Memcheck(vec, mem_type, CEED_COPY_VALUES, NULL)); 1639798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetArray_Memcheck(vec, mem_type, array)); 164dd39767dSJeremy L Thompson for (CeedSize i = 0; i < length; i++) (*array)[i] = NAN; 165df852985SJeremy L Thompson impl->is_write_only_access = true; 1669798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 1679798701eSJeremy L Thompson } 1689798701eSJeremy L Thompson 1699798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1709798701eSJeremy L Thompson // Vector Restore Array 1719798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1729798701eSJeremy L Thompson static int CeedVectorRestoreArray_Memcheck(CeedVector vec) { 1739798701eSJeremy L Thompson Ceed ceed; 174ad70ee2cSJeremy L Thompson CeedSize length; 175ad70ee2cSJeremy L Thompson CeedVector_Memcheck *impl; 176ad70ee2cSJeremy L Thompson 177ad70ee2cSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 178ad70ee2cSJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 1799798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 1809798701eSJeremy L Thompson 181*d1931fc8SJeremy L Thompson memcpy(impl->array, impl->array_writable_copy, length * sizeof(CeedScalar)); 182*d1931fc8SJeremy L Thompson for (CeedSize i = 0; i < length; i++) impl->array_writable_copy[i] = NAN; 1831a3e18b3SJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_writable_copy)); 184df852985SJeremy L Thompson if (impl->is_write_only_access) { 185dd39767dSJeremy L Thompson for (CeedSize i = 0; i < length; i++) { 186249f8407SJeremy L Thompson if (isnan(impl->array[i])) 187249f8407SJeremy L Thompson CeedDebug256(ceed, CEED_DEBUG_COLOR_WARNING, "WARNING: Vec entry %" CeedSize_FMT " is NaN after restoring write-only access", i); 188df852985SJeremy L Thompson } 189df852985SJeremy L Thompson impl->is_write_only_access = false; 190df852985SJeremy L Thompson } 1919798701eSJeremy L Thompson if (impl->array_borrowed) { 192*d1931fc8SJeremy L Thompson memcpy(impl->array_borrowed, impl->array, length * sizeof(CeedScalar)); 1939798701eSJeremy L Thompson } 1949798701eSJeremy L Thompson if (impl->array_owned) { 195*d1931fc8SJeremy L Thompson memcpy(impl->array_owned, impl->array, length * sizeof(CeedScalar)); 1969798701eSJeremy L Thompson } 1979798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 1989798701eSJeremy L Thompson } 1999798701eSJeremy L Thompson 2009798701eSJeremy L Thompson //------------------------------------------------------------------------------ 2019798701eSJeremy L Thompson // Vector Restore Array Read-Only 2029798701eSJeremy L Thompson //------------------------------------------------------------------------------ 2039798701eSJeremy L Thompson static int CeedVectorRestoreArrayRead_Memcheck(CeedVector vec) { 204ad70ee2cSJeremy L Thompson CeedSize length; 205ad70ee2cSJeremy L Thompson CeedVector_Memcheck *impl; 206ad70ee2cSJeremy L Thompson 207ad70ee2cSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 208ad70ee2cSJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 2099798701eSJeremy L Thompson 210*d1931fc8SJeremy L Thompson CeedCheck(!memcmp(impl->array, impl->array_read_only_copy, length * sizeof(CeedScalar)), CeedVectorReturnCeed(vec), CEED_ERROR_BACKEND, 2116574a04fSJeremy L Thompson "Array data changed while accessed in read-only mode"); 2129798701eSJeremy L Thompson 213*d1931fc8SJeremy L Thompson for (CeedSize i = 0; i < length; i++) impl->array_read_only_copy[i] = NAN; 2149798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_read_only_copy)); 2159798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 2169798701eSJeremy L Thompson } 2179798701eSJeremy L Thompson 2189798701eSJeremy L Thompson //------------------------------------------------------------------------------ 2199798701eSJeremy L Thompson // Vector Destroy 2209798701eSJeremy L Thompson //------------------------------------------------------------------------------ 2219798701eSJeremy L Thompson static int CeedVectorDestroy_Memcheck(CeedVector vec) { 2229798701eSJeremy L Thompson CeedVector_Memcheck *impl; 2239798701eSJeremy L Thompson 224ad70ee2cSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 2259798701eSJeremy L Thompson VALGRIND_DISCARD(impl->mem_block_id); 2269798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_allocated)); 2279798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_owned)); 2289798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl)); 2299798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 2309798701eSJeremy L Thompson } 2319798701eSJeremy L Thompson 2329798701eSJeremy L Thompson //------------------------------------------------------------------------------ 2339798701eSJeremy L Thompson // Vector Create 2349798701eSJeremy L Thompson //------------------------------------------------------------------------------ 2359798701eSJeremy L Thompson int CeedVectorCreate_Memcheck(CeedSize n, CeedVector vec) { 2369798701eSJeremy L Thompson Ceed ceed; 237ad70ee2cSJeremy L Thompson CeedVector_Memcheck *impl; 2389798701eSJeremy L Thompson 2399e82028bSJeremy L Thompson CeedCallBackend(CeedCalloc(1, &impl)); 2409e82028bSJeremy L Thompson CeedCallBackend(CeedVectorSetData(vec, impl)); 2419e82028bSJeremy L Thompson 242ad70ee2cSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 2439798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "HasValidArray", CeedVectorHasValidArray_Memcheck)); 2449798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "HasBorrowedArrayOfType", CeedVectorHasBorrowedArrayOfType_Memcheck)); 2459798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SetArray", CeedVectorSetArray_Memcheck)); 2469798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "TakeArray", CeedVectorTakeArray_Memcheck)); 2479798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArray", CeedVectorGetArray_Memcheck)); 2489798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayRead", CeedVectorGetArrayRead_Memcheck)); 2499798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayWrite", CeedVectorGetArrayWrite_Memcheck)); 2509798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArray", CeedVectorRestoreArray_Memcheck)); 2519798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArrayRead", CeedVectorRestoreArrayRead_Memcheck)); 2529798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "Destroy", CeedVectorDestroy_Memcheck)); 2539798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 2549798701eSJeremy L Thompson } 2552a86cc9dSSebastian Grimberg 2569798701eSJeremy L Thompson //------------------------------------------------------------------------------ 257