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