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.h> 9 #include <ceed/backend.h> 10 #include <stdbool.h> 11 #include <string.h> 12 #include <valgrind/memcheck.h> 13 14 #include "ceed-memcheck.h" 15 16 //------------------------------------------------------------------------------ 17 // QFunctionContext has valid data 18 //------------------------------------------------------------------------------ 19 static int CeedQFunctionContextHasValidData_Memcheck(CeedQFunctionContext ctx, bool *has_valid_data) { 20 CeedQFunctionContext_Memcheck *impl; 21 22 CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 23 *has_valid_data = impl->data; 24 return CEED_ERROR_SUCCESS; 25 } 26 27 //------------------------------------------------------------------------------ 28 // QFunctionContext has borrowed data 29 //------------------------------------------------------------------------------ 30 static int CeedQFunctionContextHasBorrowedDataOfType_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, bool *has_borrowed_data_of_type) { 31 Ceed ceed; 32 CeedQFunctionContext_Memcheck *impl; 33 34 CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 35 CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 36 CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only set HOST memory for this backend"); 37 *has_borrowed_data_of_type = impl->data_borrowed; 38 return CEED_ERROR_SUCCESS; 39 } 40 41 //------------------------------------------------------------------------------ 42 // QFunctionContext Set Data 43 //------------------------------------------------------------------------------ 44 static int CeedQFunctionContextSetData_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, CeedCopyMode copy_mode, void *data) { 45 Ceed ceed; 46 size_t ctx_size; 47 CeedQFunctionContext_Memcheck *impl; 48 49 CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 50 CeedCallBackend(CeedQFunctionContextGetContextSize(ctx, &ctx_size)); 51 CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 52 53 CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only set HOST memory for this backend"); 54 55 CeedCallBackend(CeedFree(&impl->data_allocated)); 56 CeedCallBackend(CeedFree(&impl->data_owned)); 57 switch (copy_mode) { 58 case CEED_COPY_VALUES: 59 CeedCallBackend(CeedMallocArray(1, ctx_size, &impl->data_owned)); 60 impl->data_borrowed = NULL; 61 impl->data = impl->data_owned; 62 memcpy(impl->data, data, ctx_size); 63 break; 64 case CEED_OWN_POINTER: 65 impl->data_owned = data; 66 impl->data_borrowed = NULL; 67 impl->data = data; 68 break; 69 case CEED_USE_POINTER: 70 impl->data_borrowed = data; 71 impl->data = data; 72 } 73 // Copy data to check ctx_size bounds 74 CeedCallBackend(CeedMallocArray(1, ctx_size, &impl->data_allocated)); 75 memcpy(impl->data_allocated, impl->data, ctx_size); 76 impl->data = impl->data_allocated; 77 VALGRIND_DISCARD(impl->mem_block_id); 78 impl->mem_block_id = VALGRIND_CREATE_BLOCK(impl->data, ctx_size, "'QFunction backend context data copy'"); 79 return CEED_ERROR_SUCCESS; 80 } 81 82 //------------------------------------------------------------------------------ 83 // QFunctionContext Take Data 84 //------------------------------------------------------------------------------ 85 static int CeedQFunctionContextTakeData_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) { 86 Ceed ceed; 87 CeedQFunctionContext_Memcheck *impl; 88 89 CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 90 CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 91 92 CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend"); 93 94 *(void **)data = impl->data_borrowed; 95 impl->data_borrowed = NULL; 96 impl->data = NULL; 97 VALGRIND_DISCARD(impl->mem_block_id); 98 CeedCallBackend(CeedFree(&impl->data_allocated)); 99 return CEED_ERROR_SUCCESS; 100 } 101 102 //------------------------------------------------------------------------------ 103 // QFunctionContext Get Data 104 //------------------------------------------------------------------------------ 105 static int CeedQFunctionContextGetData_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) { 106 Ceed ceed; 107 CeedQFunctionContext_Memcheck *impl; 108 109 CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 110 CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 111 112 CeedCheck(mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only provide HOST memory for this backend"); 113 114 *(void **)data = impl->data; 115 return CEED_ERROR_SUCCESS; 116 } 117 118 //------------------------------------------------------------------------------ 119 // QFunctionContext Get Data Read-Only 120 //------------------------------------------------------------------------------ 121 static int CeedQFunctionContextGetDataRead_Memcheck(CeedQFunctionContext ctx, CeedMemType mem_type, void *data) { 122 Ceed ceed; 123 size_t ctx_size; 124 CeedQFunctionContext_Memcheck *impl; 125 126 CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 127 CeedCallBackend(CeedQFunctionContextGetContextSize(ctx, &ctx_size)); 128 CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 129 CeedCallBackend(CeedQFunctionContextGetData_Memcheck(ctx, mem_type, data)); 130 131 // Make copy to verify no write occurred 132 CeedCallBackend(CeedMallocArray(1, ctx_size, &impl->data_read_only_copy)); 133 memcpy(impl->data_read_only_copy, *(void **)data, ctx_size); 134 return CEED_ERROR_SUCCESS; 135 } 136 137 //------------------------------------------------------------------------------ 138 // QFunctionContext Restore Data 139 //------------------------------------------------------------------------------ 140 static int CeedQFunctionContextRestoreData_Memcheck(CeedQFunctionContext ctx) { 141 size_t ctx_size; 142 CeedQFunctionContext_Memcheck *impl; 143 144 CeedCallBackend(CeedQFunctionContextGetContextSize(ctx, &ctx_size)); 145 CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 146 147 if (impl->data_borrowed) memcpy(impl->data_borrowed, impl->data, ctx_size); 148 if (impl->data_owned) memcpy(impl->data_owned, impl->data, ctx_size); 149 return CEED_ERROR_SUCCESS; 150 } 151 152 //------------------------------------------------------------------------------ 153 // QFunctionContext Restore Data Read-Only 154 //------------------------------------------------------------------------------ 155 static int CeedQFunctionContextRestoreDataRead_Memcheck(CeedQFunctionContext ctx) { 156 Ceed ceed; 157 size_t ctx_size; 158 CeedQFunctionContext_Memcheck *impl; 159 160 CeedCallBackend(CeedQFunctionContextGetContextSize(ctx, &ctx_size)); 161 CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, (void *)&impl)); 162 CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 163 164 CeedCheck(!memcmp(impl->data, impl->data_read_only_copy, ctx_size), ceed, CEED_ERROR_BACKEND, 165 "Context data changed while accessed in read-only mode"); 166 167 CeedCallBackend(CeedFree(&impl->data_read_only_copy)); 168 return CEED_ERROR_SUCCESS; 169 } 170 171 //------------------------------------------------------------------------------ 172 // QFunctionContext destroy user data 173 //------------------------------------------------------------------------------ 174 static int CeedQFunctionContextDataDestroy_Memcheck(CeedQFunctionContext ctx) { 175 Ceed ceed; 176 CeedMemType data_destroy_mem_type; 177 CeedQFunctionContextDataDestroyUser data_destroy_function; 178 CeedQFunctionContext_Memcheck *impl; 179 180 CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, &impl)); 181 CeedCallBackend(CeedQFunctionContextGetDataDestroy(ctx, &data_destroy_mem_type, &data_destroy_function)); 182 CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 183 184 CeedCheck(data_destroy_mem_type == CEED_MEM_HOST, ceed, CEED_ERROR_BACKEND, "Can only destroy HOST memory for this backend"); 185 186 if (data_destroy_function) { 187 CeedCallBackend(data_destroy_function(impl->data_borrowed ? impl->data_borrowed : impl->data_owned)); 188 } 189 CeedCallBackend(CeedFree(&impl->data_allocated)); 190 return CEED_ERROR_SUCCESS; 191 } 192 193 //------------------------------------------------------------------------------ 194 // QFunctionContext Destroy 195 //------------------------------------------------------------------------------ 196 static int CeedQFunctionContextDestroy_Memcheck(CeedQFunctionContext ctx) { 197 CeedQFunctionContext_Memcheck *impl; 198 199 CeedCallBackend(CeedQFunctionContextGetBackendData(ctx, &impl)); 200 CeedCallBackend(CeedFree(&impl->data_allocated)); 201 CeedCallBackend(CeedFree(&impl->data_owned)); 202 CeedCallBackend(CeedFree(&impl)); 203 return CEED_ERROR_SUCCESS; 204 } 205 206 //------------------------------------------------------------------------------ 207 // QFunctionContext Create 208 //------------------------------------------------------------------------------ 209 int CeedQFunctionContextCreate_Memcheck(CeedQFunctionContext ctx) { 210 Ceed ceed; 211 CeedQFunctionContext_Memcheck *impl; 212 213 CeedCallBackend(CeedQFunctionContextGetCeed(ctx, &ceed)); 214 CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "HasValidData", CeedQFunctionContextHasValidData_Memcheck)); 215 CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "HasBorrowedDataOfType", CeedQFunctionContextHasBorrowedDataOfType_Memcheck)); 216 CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "SetData", CeedQFunctionContextSetData_Memcheck)); 217 CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "TakeData", CeedQFunctionContextTakeData_Memcheck)); 218 CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "GetData", CeedQFunctionContextGetData_Memcheck)); 219 CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "GetDataRead", CeedQFunctionContextGetDataRead_Memcheck)); 220 CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "RestoreData", CeedQFunctionContextRestoreData_Memcheck)); 221 CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "RestoreDataRead", CeedQFunctionContextRestoreDataRead_Memcheck)); 222 CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "DataDestroy", CeedQFunctionContextDataDestroy_Memcheck)); 223 CeedCallBackend(CeedSetBackendFunction(ceed, "QFunctionContext", ctx, "Destroy", CeedQFunctionContextDestroy_Memcheck)); 224 CeedCallBackend(CeedCalloc(1, &impl)); 225 CeedCallBackend(CeedQFunctionContextSetBackendData(ctx, impl)); 226 return CEED_ERROR_SUCCESS; 227 } 228 229 //------------------------------------------------------------------------------ 230