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