Commit | Line | Data |
---|---|---|
601922a8 OD |
1 | /* |
2 | * urcu/annotate.h | |
3 | * | |
4 | * Userspace RCU - annotation header. | |
5 | * | |
6 | * Copyright 2023 - Olivier Dion <odion@efficios.com> | |
7 | * | |
8 | * This library is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License as published by the Free Software Foundation; either | |
11 | * version 2.1 of the License, or (at your option) any later version. | |
12 | * | |
13 | * This library is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | * Lesser General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU Lesser General Public | |
19 | * License along with this library; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
21 | */ | |
22 | ||
23 | /* | |
24 | * WARNING! | |
25 | * | |
26 | * This API is highly experimental. There is zero guarantees of stability | |
27 | * between releases. | |
28 | * | |
29 | * You have been warned. | |
30 | */ | |
31 | #ifndef _URCU_ANNOTATE_H | |
32 | #define _URCU_ANNOTATE_H | |
33 | ||
34 | #include <stdio.h> | |
35 | #include <stdlib.h> | |
36 | ||
37 | #include <urcu/compiler.h> | |
38 | ||
39 | enum cmm_annotate { | |
40 | CMM_ANNOTATE_VOID, | |
41 | CMM_ANNOTATE_LOAD, | |
42 | CMM_ANNOTATE_STORE, | |
43 | CMM_ANNOTATE_MB, | |
44 | }; | |
45 | ||
46 | typedef enum cmm_annotate cmm_annotate_t __attribute__((unused)); | |
47 | ||
48 | #define cmm_annotate_define(name) \ | |
49 | cmm_annotate_t name = CMM_ANNOTATE_VOID | |
50 | ||
51 | #ifdef CMM_SANITIZE_THREAD | |
52 | ||
53 | # ifdef __cplusplus | |
54 | extern "C" { | |
55 | # endif | |
56 | extern void __tsan_acquire(void *); | |
57 | extern void __tsan_release(void *); | |
58 | # ifdef __cplusplus | |
59 | } | |
60 | # endif | |
61 | ||
62 | # define cmm_annotate_die(msg) \ | |
63 | do { \ | |
64 | fprintf(stderr, \ | |
65 | "(" __FILE__ ":%s@%u) Annotation ERROR: %s\n", \ | |
66 | __func__, __LINE__, msg); \ | |
67 | abort(); \ | |
68 | } while (0) | |
69 | ||
70 | /* Only used for typechecking in macros. */ | |
71 | static inline cmm_annotate_t cmm_annotate_dereference(cmm_annotate_t *group) | |
72 | { | |
73 | return *group; | |
74 | } | |
75 | ||
76 | # define cmm_annotate_group_mb_acquire(group) \ | |
77 | do { \ | |
78 | switch (cmm_annotate_dereference(group)) { \ | |
79 | case CMM_ANNOTATE_VOID: \ | |
80 | break; \ | |
81 | case CMM_ANNOTATE_LOAD: \ | |
82 | break; \ | |
83 | case CMM_ANNOTATE_STORE: \ | |
84 | cmm_annotate_die("store for acquire group"); \ | |
85 | break; \ | |
86 | case CMM_ANNOTATE_MB: \ | |
87 | cmm_annotate_die( \ | |
88 | "redundant mb for acquire group" \ | |
89 | ); \ | |
90 | break; \ | |
91 | } \ | |
92 | *(group) = CMM_ANNOTATE_MB; \ | |
93 | } while (0) | |
94 | ||
95 | # define cmm_annotate_group_mb_release(group) \ | |
96 | do { \ | |
97 | switch (cmm_annotate_dereference(group)) { \ | |
98 | case CMM_ANNOTATE_VOID: \ | |
99 | break; \ | |
100 | case CMM_ANNOTATE_LOAD: \ | |
101 | cmm_annotate_die("load before release group"); \ | |
102 | break; \ | |
103 | case CMM_ANNOTATE_STORE: \ | |
104 | cmm_annotate_die( \ | |
105 | "store before release group" \ | |
106 | ); \ | |
107 | break; \ | |
108 | case CMM_ANNOTATE_MB: \ | |
109 | cmm_annotate_die( \ | |
110 | "redundant mb of release group" \ | |
111 | ); \ | |
112 | break; \ | |
113 | } \ | |
114 | *(group) = CMM_ANNOTATE_MB; \ | |
115 | } while (0) | |
116 | ||
117 | # define cmm_annotate_group_mem_acquire(group, mem) \ | |
118 | do { \ | |
119 | __tsan_acquire((void*)(mem)); \ | |
120 | switch (cmm_annotate_dereference(group)) { \ | |
121 | case CMM_ANNOTATE_VOID: \ | |
122 | *(group) = CMM_ANNOTATE_LOAD; \ | |
123 | break; \ | |
124 | case CMM_ANNOTATE_MB: \ | |
125 | cmm_annotate_die( \ | |
126 | "load after mb for acquire group" \ | |
127 | ); \ | |
128 | break; \ | |
129 | default: \ | |
130 | break; \ | |
131 | } \ | |
132 | } while (0) | |
133 | ||
134 | # define cmm_annotate_group_mem_release(group, mem) \ | |
135 | do { \ | |
136 | __tsan_release((void*)(mem)); \ | |
137 | switch (cmm_annotate_dereference(group)) { \ | |
138 | case CMM_ANNOTATE_MB: \ | |
139 | break; \ | |
140 | default: \ | |
141 | cmm_annotate_die( \ | |
142 | "missing mb for release group" \ | |
143 | ); \ | |
144 | } \ | |
145 | } while (0) | |
146 | ||
147 | # define cmm_annotate_mem_acquire(mem) \ | |
148 | __tsan_acquire((void*)(mem)) | |
149 | ||
150 | # define cmm_annotate_mem_release(mem) \ | |
151 | __tsan_release((void*)(mem)) | |
152 | #else | |
153 | ||
154 | # define cmm_annotate_group_mb_acquire(group) \ | |
155 | (void) (group) | |
156 | ||
157 | # define cmm_annotate_group_mb_release(group) \ | |
158 | (void) (group) | |
159 | ||
160 | # define cmm_annotate_group_mem_acquire(group, mem) \ | |
161 | (void) (group) | |
162 | ||
163 | # define cmm_annotate_group_mem_release(group, mem) \ | |
164 | (void) (group) | |
165 | ||
166 | # define cmm_annotate_mem_acquire(mem) \ | |
167 | do { } while (0) | |
168 | ||
169 | # define cmm_annotate_mem_release(mem) \ | |
170 | do { } while (0) | |
171 | ||
172 | #endif /* CMM_SANITIZE_THREAD */ | |
173 | ||
174 | #endif /* _URCU_ANNOTATE_H */ |