1 // SPDX-FileCopyrightText: 2023 Olivier Dion <odion (at) efficios.com> 2 // 3 // SPDX-License-Identifier: LGPL-2.1-or-later 4 5 #ifndef _URCU_ANNOTATE_H 6 #define _URCU_ANNOTATE_H 7 8 /* 9 * urcu/annotate.h 10 * 11 * Userspace RCU - annotation header. 12 */ 13 14 /* 15 * WARNING! 16 * 17 * This API is highly experimental. There is zero guarantees of stability 18 * between releases. 19 * 20 * You have been warned. 21 */ 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 26 #include <urcu/compiler.h> 27 28 enum cmm_annotate { 29 CMM_ANNOTATE_VOID, 30 CMM_ANNOTATE_LOAD, 31 CMM_ANNOTATE_STORE, 32 CMM_ANNOTATE_MB, 33 }; 34 35 typedef enum cmm_annotate cmm_annotate_t __attribute__((unused)); 36 37 #define cmm_annotate_define(name) \ 38 cmm_annotate_t name = CMM_ANNOTATE_VOID 39 40 #ifdef CMM_SANITIZE_THREAD 41 42 # ifdef __cplusplus 43 extern "C" { 44 # endif 45 extern void __tsan_acquire(void *); 46 extern void __tsan_release(void *); 47 # ifdef __cplusplus 48 } 49 # endif 50 51 # define cmm_annotate_die(msg) \ 52 do { \ 53 fprintf(stderr, \ 54 "(" __FILE__ ":%s@%u) Annotation ERROR: %s\n", \ 55 __func__, __LINE__, msg); \ 56 abort(); \ 57 } while (0) 58 59 /* Only used for typechecking in macros. */ 60 static inline cmm_annotate_t cmm_annotate_dereference(cmm_annotate_t *group) 61 { 62 return *group; 63 } 64 65 # define cmm_annotate_group_mb_acquire(group) \ 66 do { \ 67 switch (cmm_annotate_dereference(group)) { \ 68 case CMM_ANNOTATE_VOID: \ 69 break; \ 70 case CMM_ANNOTATE_LOAD: \ 71 break; \ 72 case CMM_ANNOTATE_STORE: \ 73 cmm_annotate_die("store for acquire group"); \ 74 break; \ 75 case CMM_ANNOTATE_MB: \ 76 cmm_annotate_die( \ 77 "redundant mb for acquire group" \ 78 ); \ 79 break; \ 80 } \ 81 *(group) = CMM_ANNOTATE_MB; \ 82 } while (0) 83 84 # define cmm_annotate_group_mb_release(group) \ 85 do { \ 86 switch (cmm_annotate_dereference(group)) { \ 87 case CMM_ANNOTATE_VOID: \ 88 break; \ 89 case CMM_ANNOTATE_LOAD: \ 90 cmm_annotate_die("load before release group"); \ 91 break; \ 92 case CMM_ANNOTATE_STORE: \ 93 cmm_annotate_die( \ 94 "store before release group" \ 95 ); \ 96 break; \ 97 case CMM_ANNOTATE_MB: \ 98 cmm_annotate_die( \ 99 "redundant mb of release group" \ 100 ); \ 101 break; \ 102 } \ 103 *(group) = CMM_ANNOTATE_MB; \ 104 } while (0) 105 106 # define cmm_annotate_group_mem_acquire(group, mem) \ 107 do { \ 108 __tsan_acquire((void*)(mem)); \ 109 switch (cmm_annotate_dereference(group)) { \ 110 case CMM_ANNOTATE_VOID: \ 111 *(group) = CMM_ANNOTATE_LOAD; \ 112 break; \ 113 case CMM_ANNOTATE_MB: \ 114 cmm_annotate_die( \ 115 "load after mb for acquire group" \ 116 ); \ 117 break; \ 118 default: \ 119 break; \ 120 } \ 121 } while (0) 122 123 # define cmm_annotate_group_mem_release(group, mem) \ 124 do { \ 125 __tsan_release((void*)(mem)); \ 126 switch (cmm_annotate_dereference(group)) { \ 127 case CMM_ANNOTATE_MB: \ 128 break; \ 129 default: \ 130 cmm_annotate_die( \ 131 "missing mb for release group" \ 132 ); \ 133 } \ 134 } while (0) 135 136 # define cmm_annotate_mem_acquire(mem) \ 137 __tsan_acquire((void*)(mem)) 138 139 # define cmm_annotate_mem_release(mem) \ 140 __tsan_release((void*)(mem)) 141 #else 142 143 # define cmm_annotate_group_mb_acquire(group) \ 144 (void) (group) 145 146 # define cmm_annotate_group_mb_release(group) \ 147 (void) (group) 148 149 # define cmm_annotate_group_mem_acquire(group, mem) \ 150 (void) (group) 151 152 # define cmm_annotate_group_mem_release(group, mem) \ 153 (void) (group) 154 155 # define cmm_annotate_mem_acquire(mem) \ 156 do { } while (0) 157 158 # define cmm_annotate_mem_release(mem) \ 159 do { } while (0) 160 161 #endif /* CMM_SANITIZE_THREAD */ 162 163 #endif /* _URCU_ANNOTATE_H */ 164