1 #ifndef CLANG_TSA_H 2 #define CLANG_TSA_H 3 4 /* 5 * Copyright 2018 Jarkko Hietaniemi <jhi@iki.fi> 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining 8 * a copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without 10 * limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sublicense, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be 16 * included in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27 /* http://clang.llvm.org/docs/ThreadSafetyAnalysis.html 28 * 29 * TSA is available since clang 3.6-ish. 30 */ 31 #ifdef __clang__ 32 # define TSA(x) __attribute__((x)) 33 #else 34 # define TSA(x) /* No TSA, make TSA attributes no-ops. */ 35 #endif 36 37 /* TSA_CAPABILITY() is used to annotate typedefs: 38 * 39 * typedef pthread_mutex_t TSA_CAPABILITY("mutex") tsa_mutex; 40 */ 41 #define TSA_CAPABILITY(x) TSA(capability(x)) 42 43 /* TSA_GUARDED_BY() is used to annotate global variables, 44 * the data is guarded: 45 * 46 * Foo foo TSA_GUARDED_BY(mutex); 47 */ 48 #define TSA_GUARDED_BY(x) TSA(guarded_by(x)) 49 50 /* TSA_PT_GUARDED_BY() is used to annotate global pointers, the data 51 * behind the pointer is guarded. 52 * 53 * Foo* ptr TSA_PT_GUARDED_BY(mutex); 54 */ 55 #define TSA_PT_GUARDED_BY(x) TSA(pt_guarded_by(x)) 56 57 /* The TSA_REQUIRES() is used to annotate functions: the caller of the 58 * function MUST hold the resource, the function will NOT release it. 59 * 60 * More than one mutex may be specified, comma-separated. 61 * 62 * void Foo(void) TSA_REQUIRES(mutex); 63 */ 64 #define TSA_REQUIRES(...) TSA(requires_capability(__VA_ARGS__)) 65 #define TSA_REQUIRES_SHARED(...) TSA(requires_shared_capability(__VA_ARGS__)) 66 67 /* TSA_EXCLUDES() is used to annotate functions: the caller of the 68 * function MUST NOT hold resource, the function first acquires the 69 * resource, and then releases it. 70 * 71 * More than one mutex may be specified, comma-separated. 72 * 73 * void Foo(void) TSA_EXCLUDES(mutex); 74 */ 75 #define TSA_EXCLUDES(...) TSA(locks_excluded(__VA_ARGS__)) 76 77 /* TSA_ACQUIRE() is used to annotate functions: the caller of the 78 * function MUST NOT hold the resource, the function will acquire the 79 * resource, but NOT release it. 80 * 81 * More than one mutex may be specified, comma-separated. 82 * 83 * void Foo(void) TSA_ACQUIRE(mutex); 84 */ 85 #define TSA_ACQUIRE(...) TSA(acquire_capability(__VA_ARGS__)) 86 #define TSA_ACQUIRE_SHARED(...) TSA(acquire_shared_capability(__VA_ARGS__)) 87 88 /* TSA_RELEASE() is used to annotate functions: the caller of the 89 * function MUST hold the resource, but the function will then release it. 90 * 91 * More than one mutex may be specified, comma-separated. 92 * 93 * void Foo(void) TSA_RELEASE(mutex); 94 */ 95 #define TSA_RELEASE(...) TSA(release_capability(__VA_ARGS__)) 96 #define TSA_RELEASE_SHARED(...) TSA(release_shared_capability(__VA_ARGS__)) 97 98 /* TSA_NO_TSA is used to annotate functions. Use only when you need to. 99 * 100 * void Foo(void) TSA_NO_TSA; 101 */ 102 #define TSA_NO_TSA TSA(no_thread_safety_analysis) 103 104 /* 105 * TSA_ASSERT() is used to annotate functions: This function will assert that 106 * the lock is held. When it returns, the caller of the function is assumed to 107 * already hold the resource. 108 * 109 * More than one mutex may be specified, comma-separated. 110 */ 111 #define TSA_ASSERT(...) TSA(assert_capability(__VA_ARGS__)) 112 #define TSA_ASSERT_SHARED(...) TSA(assert_shared_capability(__VA_ARGS__)) 113 114 #endif /* #ifndef CLANG_TSA_H */ 115