10f58c348SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 20f58c348SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 30f58c348SJeremy L Thompson // 40f58c348SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause 50f58c348SJeremy L Thompson // 60f58c348SJeremy L Thompson // This file is part of CEED: http://github.com/ceed 70f58c348SJeremy L Thompson 849aac155SJeremy L Thompson #include <ceed.h> 90f58c348SJeremy L Thompson #include <ceed/backend.h> 1049aac155SJeremy L Thompson #include <stdbool.h> 110f58c348SJeremy L Thompson #include <string.h> 120f58c348SJeremy L Thompson #include <valgrind/memcheck.h> 132b730f8bSJeremy L Thompson 140f58c348SJeremy L Thompson #include "ceed-memcheck.h" 150f58c348SJeremy L Thompson 160f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 170f58c348SJeremy L Thompson // QFunctionContext has valid data 180f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 192b730f8bSJeremy L Thompson static int CeedQFunctionContextHasValidData_Memcheck(CeedQFunctionContext ctx, bool *has_valid_data) { 200f58c348SJeremy L Thompson CeedQFunctionContext_Memcheck *impl; 212b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 220f58c348SJeremy L Thompson 230f58c348SJeremy L Thompson *has_valid_data = !!impl->data; 240f58c348SJeremy L Thompson 250f58c348SJeremy L Thompson return CEED_ERROR_SUCCESS; 260f58c348SJeremy L Thompson } 270f58c348SJeremy L Thompson 280f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 290f58c348SJeremy L Thompson // QFunctionContext has borrowed data 300f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 312b730f8bSJeremy L Thompson static int CeedQFunctionContextHasBorrowedDataOfType_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, bool *has_borrowed_data_of_type) { 320f58c348SJeremy L Thompson CeedQFunctionContext_Memcheck *impl; 332b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 340f58c348SJeremy L Thompson Ceed ceed; 352b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 360f58c348SJeremy L Thompson 370f58c348SJeremy L Thompson switch (mem_type) { 380f58c348SJeremy L Thompson case CEED_MEM_HOST: 390f58c348SJeremy L Thompson *has_borrowed_data_of_type = !!impl->data_borrowed; 400f58c348SJeremy L Thompson break; 410f58c348SJeremy L Thompson default: 420f58c348SJeremy L Thompson // LCOV_EXCL_START 432b730f8bSJeremy L Thompson return CeedError(ceed, CEED_ERROR_BACKEND, "Can only set HOST memory for this backend"); 440f58c348SJeremy L Thompson // LCOV_EXCL_STOP 450f58c348SJeremy L Thompson break; 460f58c348SJeremy L Thompson } 470f58c348SJeremy L Thompson 480f58c348SJeremy L Thompson return CEED_ERROR_SUCCESS; 490f58c348SJeremy L Thompson } 500f58c348SJeremy L Thompson 510f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 520f58c348SJeremy L Thompson // QFunctionContext Set Data 530f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 542b730f8bSJeremy L Thompson static int CeedQFunctionContextSetData_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, CeedCopyMode copy_mode, void *data) { 550f58c348SJeremy L Thompson CeedQFunctionContext_Memcheck *impl; 562b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 570f58c348SJeremy L Thompson size_t ctx_size; 582b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetContextSize(ctx, &ctx_size)); 590f58c348SJeremy L Thompson Ceed ceed; 602b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 610f58c348SJeremy L Thompson 62*6574a04fSJeremy L Thompson CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only set HOST memory for this backend"); 630f58c348SJeremy L Thompson 642b730f8bSJeremy L Thompson CeedCallBackend(CeedFree(&impl->data_allocated)); 652b730f8bSJeremy L Thompson CeedCallBackend(CeedFree(&impl->data_owned)); 660f58c348SJeremy L Thompson switch (copy_mode) { 670f58c348SJeremy L Thompson case CEED_COPY_VALUES: 682b730f8bSJeremy L Thompson CeedCallBackend(CeedMallocArray(1, ctx_size, &impl->data_owned)); 690f58c348SJeremy L Thompson impl->data_borrowed = NULL; 700f58c348SJeremy L Thompson impl->data = impl->data_owned; 710f58c348SJeremy L Thompson memcpy(impl->data, data, ctx_size); 720f58c348SJeremy L Thompson break; 730f58c348SJeremy L Thompson case CEED_OWN_POINTER: 740f58c348SJeremy L Thompson impl->data_owned = data; 750f58c348SJeremy L Thompson impl->data_borrowed = NULL; 760f58c348SJeremy L Thompson impl->data = data; 770f58c348SJeremy L Thompson break; 780f58c348SJeremy L Thompson case CEED_USE_POINTER: 790f58c348SJeremy L Thompson impl->data_borrowed = data; 800f58c348SJeremy L Thompson impl->data = data; 810f58c348SJeremy L Thompson } 820f58c348SJeremy L Thompson // Copy data to check ctx_size bounds 832b730f8bSJeremy L Thompson CeedCallBackend(CeedMallocArray(1, ctx_size, &impl->data_allocated)); 840f58c348SJeremy L Thompson memcpy(impl->data_allocated, impl->data, ctx_size); 850f58c348SJeremy L Thompson impl->data = impl->data_allocated; 860f58c348SJeremy L Thompson VALGRIND_DISCARD(impl->mem_block_id); 872b730f8bSJeremy L Thompson impl->mem_block_id = VALGRIND_CREATE_BLOCK(impl->data, ctx_size, "'QFunction backend context data copy'"); 880f58c348SJeremy L Thompson 890f58c348SJeremy L Thompson return CEED_ERROR_SUCCESS; 900f58c348SJeremy L Thompson } 910f58c348SJeremy L Thompson 920f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 930f58c348SJeremy L Thompson // QFunctionContext Take Data 940f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 952b730f8bSJeremy L Thompson static int CeedQFunctionContextTakeData_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) { 960f58c348SJeremy L Thompson CeedQFunctionContext_Memcheck *impl; 972b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 980f58c348SJeremy L Thompson Ceed ceed; 992b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 1000f58c348SJeremy L Thompson 101*6574a04fSJeremy L Thompson CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend"); 1020f58c348SJeremy L Thompson 1030f58c348SJeremy L Thompson *(void **)data = impl->data_borrowed; 1040f58c348SJeremy L Thompson impl->data_borrowed = NULL; 1050f58c348SJeremy L Thompson impl->data = NULL; 1060f58c348SJeremy L Thompson VALGRIND_DISCARD(impl->mem_block_id); 1072b730f8bSJeremy L Thompson CeedCallBackend(CeedFree(&impl->data_allocated)); 1080f58c348SJeremy L Thompson 1090f58c348SJeremy L Thompson return CEED_ERROR_SUCCESS; 1100f58c348SJeremy L Thompson } 1110f58c348SJeremy L Thompson 1120f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 1130f58c348SJeremy L Thompson // QFunctionContext Get Data 1140f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 1152b730f8bSJeremy L Thompson static int CeedQFunctionContextGetData_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) { 1160f58c348SJeremy L Thompson CeedQFunctionContext_Memcheck *impl; 1172b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 1180f58c348SJeremy L Thompson Ceed ceed; 1192b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 1200f58c348SJeremy L Thompson 121*6574a04fSJeremy L Thompson CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend"); 1220f58c348SJeremy L Thompson 1230f58c348SJeremy L Thompson *(void **)data = impl->data; 1240f58c348SJeremy L Thompson 1250f58c348SJeremy L Thompson return CEED_ERROR_SUCCESS; 1260f58c348SJeremy L Thompson } 1270f58c348SJeremy L Thompson 1280f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 1298e457467SJeremy L Thompson // QFunctionContext Get Data Read-Only 1308e457467SJeremy L Thompson //------------------------------------------------------------------------------ 1312b730f8bSJeremy L Thompson static int CeedQFunctionContextGetDataRead_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) { 1328e457467SJeremy L Thompson CeedQFunctionContext_Memcheck *impl; 1332b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 1348e457467SJeremy L Thompson size_t ctx_size; 1352b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetContextSize(ctx, &ctx_size)); 1368e457467SJeremy L Thompson Ceed ceed; 1372b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 1388e457467SJeremy L Thompson 1392b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetData_Memcheck(ctx, mem_type, data)); 1408e457467SJeremy L Thompson 141ea61e9acSJeremy L Thompson // Make copy to verify no write occurred 1422b730f8bSJeremy L Thompson CeedCallBackend(CeedMallocArray(1, ctx_size, &impl->data_read_only_copy)); 1438e457467SJeremy L Thompson memcpy(impl->data_read_only_copy, *(void **)data, ctx_size); 1448e457467SJeremy L Thompson 1458e457467SJeremy L Thompson return CEED_ERROR_SUCCESS; 1468e457467SJeremy L Thompson } 1478e457467SJeremy L Thompson 1488e457467SJeremy L Thompson //------------------------------------------------------------------------------ 1490f58c348SJeremy L Thompson // QFunctionContext Restore Data 1500f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 1510f58c348SJeremy L Thompson static int CeedQFunctionContextRestoreData_Memcheck(CeedQFunctionContext ctx) { 1520f58c348SJeremy L Thompson size_t ctx_size; 1532b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetContextSize(ctx, &ctx_size)); 1540f58c348SJeremy L Thompson CeedQFunctionContext_Memcheck *impl; 1552b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 1560f58c348SJeremy L Thompson 1570f58c348SJeremy L Thompson if (impl->data_borrowed) { 1580f58c348SJeremy L Thompson memcpy(impl->data_borrowed, impl->data, ctx_size); 1590f58c348SJeremy L Thompson } 1600f58c348SJeremy L Thompson if (impl->data_owned) { 1610f58c348SJeremy L Thompson memcpy(impl->data_owned, impl->data, ctx_size); 1620f58c348SJeremy L Thompson } 1630f58c348SJeremy L Thompson 1640f58c348SJeremy L Thompson return CEED_ERROR_SUCCESS; 1650f58c348SJeremy L Thompson } 1660f58c348SJeremy L Thompson 1670f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 1688e457467SJeremy L Thompson // QFunctionContext Restore Data Read-Only 1698e457467SJeremy L Thompson //------------------------------------------------------------------------------ 1702b730f8bSJeremy L Thompson static int CeedQFunctionContextRestoreDataRead_Memcheck(CeedQFunctionContext ctx) { 1718e457467SJeremy L Thompson size_t ctx_size; 1722b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetContextSize(ctx, &ctx_size)); 1738e457467SJeremy L Thompson CeedQFunctionContext_Memcheck *impl; 1742b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 1758e457467SJeremy L Thompson Ceed ceed; 1762b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 1778e457467SJeremy L Thompson 178*6574a04fSJeremy L Thompson CeedCheck(!memcmp(impl->data, impl->data_read_only_copy, ctx_size), ceed, CEED_ERROR_BACKEND, 179*6574a04fSJeremy L Thompson "Context data changed while accessed in read-only mode"); 1808e457467SJeremy L Thompson 1812b730f8bSJeremy L Thompson CeedCallBackend(CeedFree(&impl->data_read_only_copy)); 1828e457467SJeremy L Thompson 1838e457467SJeremy L Thompson return CEED_ERROR_SUCCESS; 1848e457467SJeremy L Thompson } 1858e457467SJeremy L Thompson 1868e457467SJeremy L Thompson //------------------------------------------------------------------------------ 1872e64a2b9SJeremy L Thompson // QFunctionContext destroy user data 1882e64a2b9SJeremy L Thompson //------------------------------------------------------------------------------ 1892e64a2b9SJeremy L Thompson static int CeedQFunctionContextDataDestroy_Memcheck(CeedQFunctionContext ctx) { 1902e64a2b9SJeremy L Thompson CeedQFunctionContext_Memcheck *impl; 1912b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, &impl)); 1922e64a2b9SJeremy L Thompson CeedQFunctionContextDataDestroyUser data_destroy_function; 1932e64a2b9SJeremy L Thompson CeedMemType data_destroy_mem_type; 1942b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetDataDestroy(ctx, &data_destroy_mem_type, &data_destroy_function)); 1952e64a2b9SJeremy L Thompson Ceed ceed; 1962b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 1972e64a2b9SJeremy L Thompson 198*6574a04fSJeremy L Thompson CeedCheck(data_destroy_mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only destroy HOST memory for this backend"); 1992e64a2b9SJeremy L Thompson 2002e64a2b9SJeremy L Thompson if (data_destroy_function) { 2012b730f8bSJeremy L Thompson CeedCallBackend(data_destroy_function(impl->data_borrowed ? impl->data_borrowed : impl->data_owned)); 2022e64a2b9SJeremy L Thompson } 2032b730f8bSJeremy L Thompson CeedCallBackend(CeedFree(&impl->data_allocated)); 2042e64a2b9SJeremy L Thompson 2052e64a2b9SJeremy L Thompson return CEED_ERROR_SUCCESS; 2062e64a2b9SJeremy L Thompson } 2072e64a2b9SJeremy L Thompson 2082e64a2b9SJeremy L Thompson //------------------------------------------------------------------------------ 2090f58c348SJeremy L Thompson // QFunctionContext Destroy 2100f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 2110f58c348SJeremy L Thompson static int CeedQFunctionContextDestroy_Memcheck(CeedQFunctionContext ctx) { 2120f58c348SJeremy L Thompson CeedQFunctionContext_Memcheck *impl; 2132b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, &impl)); 2140f58c348SJeremy L Thompson 2152b730f8bSJeremy L Thompson CeedCallBackend(CeedFree(&impl->data_allocated)); 2162b730f8bSJeremy L Thompson CeedCallBackend(CeedFree(&impl->data_owned)); 2172b730f8bSJeremy L Thompson CeedCallBackend(CeedFree(&impl)); 2180f58c348SJeremy L Thompson return CEED_ERROR_SUCCESS; 2190f58c348SJeremy L Thompson } 2200f58c348SJeremy L Thompson 2210f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 2220f58c348SJeremy L Thompson // QFunctionContext Create 2230f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 2240f58c348SJeremy L Thompson int CeedQFunctionContextCreate_Memcheck(CeedQFunctionContext ctx) { 2250f58c348SJeremy L Thompson CeedQFunctionContext_Memcheck *impl; 2260f58c348SJeremy L Thompson Ceed ceed; 2272b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 2280f58c348SJeremy L Thompson 2292b730f8bSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "HasValidData", CeedQFunctionContextHasValidData_Memcheck)); 2302b730f8bSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "HasBorrowedDataOfType", CeedQFunctionContextHasBorrowedDataOfType_Memcheck)); 2312b730f8bSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "SetData", CeedQFunctionContextSetData_Memcheck)); 2322b730f8bSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "TakeData", CeedQFunctionContextTakeData_Memcheck)); 2332b730f8bSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "GetData", CeedQFunctionContextGetData_Memcheck)); 2342b730f8bSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "GetDataRead", CeedQFunctionContextGetDataRead_Memcheck)); 2352b730f8bSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "RestoreData", CeedQFunctionContextRestoreData_Memcheck)); 2362b730f8bSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "RestoreDataRead", CeedQFunctionContextRestoreDataRead_Memcheck)); 2372b730f8bSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "DataDestroy", CeedQFunctionContextDataDestroy_Memcheck)); 2382b730f8bSJeremy L Thompson CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "Destroy", CeedQFunctionContextDestroy_Memcheck)); 2390f58c348SJeremy L Thompson 2402b730f8bSJeremy L Thompson CeedCallBackend(CeedCalloc(1, &impl)); 2412b730f8bSJeremy L Thompson CeedCallBackend(CeedQFunctionContextSetBackendData(ctx, impl)); 2420f58c348SJeremy L Thompson 2430f58c348SJeremy L Thompson return CEED_ERROR_SUCCESS; 2440f58c348SJeremy L Thompson } 2450f58c348SJeremy L Thompson //------------------------------------------------------------------------------ 246