Home | History | Annotate | Line # | Download | only in urcu
      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