19798701eSJeremy L Thompson // Copyright (c) 2017-2022, 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 8*49aac155SJeremy L Thompson #include <ceed.h> 99798701eSJeremy L Thompson #include <ceed/backend.h> 109798701eSJeremy L Thompson #include <math.h> 11*49aac155SJeremy 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; 229798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 239798701eSJeremy L Thompson 249798701eSJeremy L Thompson *has_valid_array = !!impl->array; 259798701eSJeremy L Thompson 269798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 279798701eSJeremy L Thompson } 289798701eSJeremy L Thompson 299798701eSJeremy L Thompson //------------------------------------------------------------------------------ 309798701eSJeremy L Thompson // Check if has borrowed array of given type 319798701eSJeremy L Thompson //------------------------------------------------------------------------------ 329798701eSJeremy L Thompson static inline int CeedVectorHasBorrowedArrayOfType_Memcheck(const CeedVector vec, CeedMemType mem_type, bool *has_borrowed_array_of_type) { 339798701eSJeremy L Thompson CeedVector_Memcheck *impl; 349798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 359798701eSJeremy L Thompson Ceed ceed; 369798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 379798701eSJeremy L Thompson 389798701eSJeremy L Thompson switch (mem_type) { 399798701eSJeremy L Thompson case CEED_MEM_HOST: 409798701eSJeremy L Thompson *has_borrowed_array_of_type = !!impl->array_borrowed; 419798701eSJeremy L Thompson break; 429798701eSJeremy L Thompson default: 439798701eSJeremy L Thompson // LCOV_EXCL_START 449798701eSJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "Can only set HOST memory for this backend"); 459798701eSJeremy L Thompson // LCOV_EXCL_STOP 469798701eSJeremy L Thompson break; 479798701eSJeremy L Thompson } 489798701eSJeremy L Thompson 499798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 509798701eSJeremy L Thompson } 519798701eSJeremy L Thompson 529798701eSJeremy L Thompson //------------------------------------------------------------------------------ 539798701eSJeremy L Thompson // Vector Set Array 549798701eSJeremy L Thompson //------------------------------------------------------------------------------ 559798701eSJeremy L Thompson static int CeedVectorSetArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedCopyMode copy_mode, CeedScalar *array) { 569798701eSJeremy L Thompson CeedVector_Memcheck *impl; 579798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 589798701eSJeremy L Thompson CeedSize length; 599798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 609798701eSJeremy L Thompson Ceed ceed; 619798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 629798701eSJeremy L Thompson 639798701eSJeremy L Thompson if (mem_type != CEED_MEM_HOST) { 649798701eSJeremy L Thompson // LCOV_EXCL_START 659798701eSJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "Can only set HOST memory for this backend"); 669798701eSJeremy L Thompson // LCOV_EXCL_STOP 679798701eSJeremy L Thompson } 689798701eSJeremy L Thompson 699798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_allocated)); 709798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_owned)); 719798701eSJeremy L Thompson switch (copy_mode) { 729798701eSJeremy L Thompson case CEED_COPY_VALUES: 739798701eSJeremy L Thompson CeedCallBackend(CeedCalloc(length, &impl->array_owned)); 749798701eSJeremy L Thompson impl->array_borrowed = NULL; 759798701eSJeremy L Thompson impl->array = impl->array_owned; 769798701eSJeremy L Thompson if (array) { 779798701eSJeremy L Thompson memcpy(impl->array, array, length * sizeof(array[0])); 789798701eSJeremy L Thompson } else { 799798701eSJeremy L Thompson for (CeedInt i = 0; i < length; i++) impl->array[i] = NAN; 809798701eSJeremy L Thompson } 819798701eSJeremy L Thompson break; 829798701eSJeremy L Thompson case CEED_OWN_POINTER: 839798701eSJeremy L Thompson impl->array_owned = array; 849798701eSJeremy L Thompson impl->array_borrowed = NULL; 859798701eSJeremy L Thompson impl->array = array; 869798701eSJeremy L Thompson break; 879798701eSJeremy L Thompson case CEED_USE_POINTER: 889798701eSJeremy L Thompson impl->array_borrowed = array; 899798701eSJeremy L Thompson impl->array = array; 909798701eSJeremy L Thompson } 919798701eSJeremy L Thompson // Copy data to check access 929798701eSJeremy L Thompson CeedCallBackend(CeedCalloc(length, &impl->array_allocated)); 939798701eSJeremy L Thompson memcpy(impl->array_allocated, impl->array, length * sizeof(array[0])); 949798701eSJeremy L Thompson impl->array = impl->array_allocated; 959798701eSJeremy L Thompson VALGRIND_DISCARD(impl->mem_block_id); 969798701eSJeremy L Thompson impl->mem_block_id = VALGRIND_CREATE_BLOCK(impl->array, length * sizeof(array[0]), "'Vector backend array data copy'"); 979798701eSJeremy L Thompson 989798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 999798701eSJeremy L Thompson } 1009798701eSJeremy L Thompson 1019798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1029798701eSJeremy L Thompson // Vector Take Array 1039798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1049798701eSJeremy L Thompson static int CeedVectorTakeArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 1059798701eSJeremy L Thompson CeedVector_Memcheck *impl; 1069798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 1079798701eSJeremy L Thompson Ceed ceed; 1089798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 1099798701eSJeremy L Thompson 1109798701eSJeremy L Thompson if (mem_type != CEED_MEM_HOST) { 1119798701eSJeremy L Thompson // LCOV_EXCL_START 1129798701eSJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend"); 1139798701eSJeremy L Thompson // LCOV_EXCL_STOP 1149798701eSJeremy L Thompson } 1159798701eSJeremy L Thompson 1169798701eSJeremy L Thompson (*array) = impl->array_borrowed; 1179798701eSJeremy L Thompson impl->array_borrowed = NULL; 1189798701eSJeremy L Thompson impl->array = NULL; 1199798701eSJeremy L Thompson VALGRIND_DISCARD(impl->mem_block_id); 1209798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_allocated)); 1219798701eSJeremy L Thompson 1229798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 1239798701eSJeremy L Thompson } 1249798701eSJeremy L Thompson 1259798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1269798701eSJeremy L Thompson // Vector Get Array 1279798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1289798701eSJeremy L Thompson static int CeedVectorGetArray_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 1299798701eSJeremy L Thompson CeedVector_Memcheck *impl; 1309798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 1319798701eSJeremy L Thompson Ceed ceed; 1329798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 1339798701eSJeremy L Thompson 1349798701eSJeremy L Thompson if (mem_type != CEED_MEM_HOST) { 1359798701eSJeremy L Thompson // LCOV_EXCL_START 1369798701eSJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend"); 1379798701eSJeremy L Thompson // LCOV_EXCL_STOP 1389798701eSJeremy L Thompson } 1399798701eSJeremy L Thompson 1409798701eSJeremy L Thompson *array = impl->array; 1419798701eSJeremy L Thompson 1429798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 1439798701eSJeremy L Thompson } 1449798701eSJeremy L Thompson 1459798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1469798701eSJeremy L Thompson // Vector Get Array Read 1479798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1489798701eSJeremy L Thompson static int CeedVectorGetArrayRead_Memcheck(CeedVector vec, CeedMemType mem_type, const CeedScalar **array) { 1499798701eSJeremy L Thompson CeedVector_Memcheck *impl; 1509798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 1519798701eSJeremy L Thompson CeedSize length; 1529798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 1539798701eSJeremy L Thompson Ceed ceed; 1549798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 1559798701eSJeremy L Thompson 1569798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetArray_Memcheck(vec, mem_type, (CeedScalar **)array)); 1579798701eSJeremy L Thompson 1589798701eSJeremy L Thompson // Make copy to verify no write occurred 1599798701eSJeremy L Thompson CeedCallBackend(CeedCalloc(length, &impl->array_read_only_copy)); 1609798701eSJeremy L Thompson memcpy(impl->array_read_only_copy, *array, length * sizeof((*array)[0])); 1619798701eSJeremy L Thompson 1629798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 1639798701eSJeremy L Thompson } 1649798701eSJeremy L Thompson 1659798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1669798701eSJeremy L Thompson // Vector Get Array Write 1679798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1689798701eSJeremy L Thompson static int CeedVectorGetArrayWrite_Memcheck(CeedVector vec, CeedMemType mem_type, CeedScalar **array) { 1699798701eSJeremy L Thompson CeedVector_Memcheck *impl; 1709798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 1719798701eSJeremy L Thompson CeedSize length; 1729798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 1739798701eSJeremy L Thompson Ceed ceed; 1749798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 1759798701eSJeremy L Thompson 1769798701eSJeremy L Thompson // Invalidate data to make sure no read occurs 1779798701eSJeremy L Thompson if (!impl->array) CeedCallBackend(CeedVectorSetArray_Memcheck(vec, mem_type, CEED_COPY_VALUES, NULL)); 1789798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetArray_Memcheck(vec, mem_type, array)); 1799798701eSJeremy L Thompson for (CeedInt i = 0; i < length; i++) (*array)[i] = NAN; 1809798701eSJeremy L Thompson 1819798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 1829798701eSJeremy L Thompson } 1839798701eSJeremy L Thompson 1849798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1859798701eSJeremy L Thompson // Vector Restore Array 1869798701eSJeremy L Thompson //------------------------------------------------------------------------------ 1879798701eSJeremy L Thompson static int CeedVectorRestoreArray_Memcheck(CeedVector vec) { 1889798701eSJeremy L Thompson CeedVector_Memcheck *impl; 1899798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 1909798701eSJeremy L Thompson CeedSize length; 1919798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 1929798701eSJeremy L Thompson Ceed ceed; 1939798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 1949798701eSJeremy L Thompson 1959798701eSJeremy L Thompson if (impl->array_borrowed) { 1969798701eSJeremy L Thompson memcpy(impl->array_borrowed, impl->array, length * sizeof(impl->array[0])); 1979798701eSJeremy L Thompson } 1989798701eSJeremy L Thompson if (impl->array_owned) { 1999798701eSJeremy L Thompson memcpy(impl->array_owned, impl->array, length * sizeof(impl->array[0])); 2009798701eSJeremy L Thompson } 2019798701eSJeremy L Thompson 2029798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 2039798701eSJeremy L Thompson } 2049798701eSJeremy L Thompson 2059798701eSJeremy L Thompson //------------------------------------------------------------------------------ 2069798701eSJeremy L Thompson // Vector Restore Array Read-Only 2079798701eSJeremy L Thompson //------------------------------------------------------------------------------ 2089798701eSJeremy L Thompson static int CeedVectorRestoreArrayRead_Memcheck(CeedVector vec) { 2099798701eSJeremy L Thompson CeedVector_Memcheck *impl; 2109798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 2119798701eSJeremy L Thompson CeedSize length; 2129798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetLength(vec, &length)); 2139798701eSJeremy L Thompson Ceed ceed; 2149798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 2159798701eSJeremy L Thompson 2169798701eSJeremy L Thompson if (memcmp(impl->array, impl->array_read_only_copy, length * sizeof(impl->array[0]))) { 2179798701eSJeremy L Thompson // LCOV_EXCL_START 2189798701eSJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "Array data changed while accessed in read-only mode"); 2199798701eSJeremy L Thompson // LCOV_EXCL_STOP 2209798701eSJeremy L Thompson } 2219798701eSJeremy L Thompson 2229798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_read_only_copy)); 2239798701eSJeremy L Thompson 2249798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 2259798701eSJeremy L Thompson } 2269798701eSJeremy L Thompson 2279798701eSJeremy L Thompson //------------------------------------------------------------------------------ 2289798701eSJeremy L Thompson // Vector Destroy 2299798701eSJeremy L Thompson //------------------------------------------------------------------------------ 2309798701eSJeremy L Thompson static int CeedVectorDestroy_Memcheck(CeedVector vec) { 2319798701eSJeremy L Thompson CeedVector_Memcheck *impl; 2329798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetData(vec, &impl)); 2339798701eSJeremy L Thompson 2349798701eSJeremy L Thompson VALGRIND_DISCARD(impl->mem_block_id); 2359798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_allocated)); 2369798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl->array_owned)); 2379798701eSJeremy L Thompson CeedCallBackend(CeedFree(&impl)); 2389798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 2399798701eSJeremy L Thompson } 2409798701eSJeremy L Thompson 2419798701eSJeremy L Thompson //------------------------------------------------------------------------------ 2429798701eSJeremy L Thompson // Vector Create 2439798701eSJeremy L Thompson //------------------------------------------------------------------------------ 2449798701eSJeremy L Thompson int CeedVectorCreate_Memcheck(CeedSize n, CeedVector vec) { 2459798701eSJeremy L Thompson CeedVector_Memcheck *impl; 2469798701eSJeremy L Thompson Ceed ceed; 2479798701eSJeremy L Thompson CeedCallBackend(CeedVectorGetCeed(vec, &ceed)); 2489798701eSJeremy L Thompson 2499798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "HasValidArray", CeedVectorHasValidArray_Memcheck)); 2509798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "HasBorrowedArrayOfType", CeedVectorHasBorrowedArrayOfType_Memcheck)); 2519798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "SetArray", CeedVectorSetArray_Memcheck)); 2529798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "TakeArray", CeedVectorTakeArray_Memcheck)); 2539798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArray", CeedVectorGetArray_Memcheck)); 2549798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayRead", CeedVectorGetArrayRead_Memcheck)); 2559798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "GetArrayWrite", CeedVectorGetArrayWrite_Memcheck)); 2569798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArray", CeedVectorRestoreArray_Memcheck)); 2579798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "RestoreArrayRead", CeedVectorRestoreArrayRead_Memcheck)); 2589798701eSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "Vector", vec, "Destroy", CeedVectorDestroy_Memcheck)); 2599798701eSJeremy L Thompson 2609798701eSJeremy L Thompson CeedCallBackend(CeedCalloc(1, &impl)); 2619798701eSJeremy L Thompson CeedCallBackend(CeedVectorSetData(vec, impl)); 2629798701eSJeremy L Thompson 2639798701eSJeremy L Thompson return CEED_ERROR_SUCCESS; 2649798701eSJeremy L Thompson } 2659798701eSJeremy L Thompson //------------------------------------------------------------------------------ 266