OLD | NEW |
1 // Copyright (c) 2008, Google Inc. | 1 // Copyright (c) 2008, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 27 matching lines...) Expand all Loading... |
38 // The annotations are implemented using GCC's "attributes" extension. | 38 // The annotations are implemented using GCC's "attributes" extension. |
39 // Using the macros defined here instead of the raw GCC attributes allows | 39 // Using the macros defined here instead of the raw GCC attributes allows |
40 // for portability and future compatibility. | 40 // for portability and future compatibility. |
41 // | 41 // |
42 // This functionality is not yet fully implemented in perftools, | 42 // This functionality is not yet fully implemented in perftools, |
43 // but may be one day. | 43 // but may be one day. |
44 | 44 |
45 #ifndef BASE_THREAD_ANNOTATIONS_H_ | 45 #ifndef BASE_THREAD_ANNOTATIONS_H_ |
46 #define BASE_THREAD_ANNOTATIONS_H_ | 46 #define BASE_THREAD_ANNOTATIONS_H_ |
47 | 47 |
48 #if defined(__GNUC__) && defined(__SUPPORT_TS_ANNOTATION__) && (!defined(SWIG)) | 48 |
| 49 #if defined(__GNUC__) \ |
| 50 && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) \ |
| 51 && defined(__SUPPORT_TS_ANNOTATION__) && (!defined(SWIG)) |
| 52 #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) |
| 53 #else |
| 54 #define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op |
| 55 #endif |
| 56 |
49 | 57 |
50 // Document if a shared variable/field needs to be protected by a lock. | 58 // Document if a shared variable/field needs to be protected by a lock. |
51 // GUARDED_BY allows the user to specify a particular lock that should be | 59 // GUARDED_BY allows the user to specify a particular lock that should be |
52 // held when accessing the annotated variable, while GUARDED_VAR only | 60 // held when accessing the annotated variable, while GUARDED_VAR only |
53 // indicates a shared variable should be guarded (by any lock). GUARDED_VAR | 61 // indicates a shared variable should be guarded (by any lock). GUARDED_VAR |
54 // is primarily used when the client cannot express the name of the lock. | 62 // is primarily used when the client cannot express the name of the lock. |
55 #define GUARDED_BY(x) __attribute__ ((guarded_by(x))) | 63 #define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) |
56 #define GUARDED_VAR __attribute__ ((guarded)) | 64 #define GUARDED_VAR THREAD_ANNOTATION_ATTRIBUTE__(guarded) |
57 | 65 |
58 // Document if the memory location pointed to by a pointer should be guarded | 66 // Document if the memory location pointed to by a pointer should be guarded |
59 // by a lock when dereferencing the pointer. Similar to GUARDED_VAR, | 67 // by a lock when dereferencing the pointer. Similar to GUARDED_VAR, |
60 // PT_GUARDED_VAR is primarily used when the client cannot express the name | 68 // PT_GUARDED_VAR is primarily used when the client cannot express the name |
61 // of the lock. Note that a pointer variable to a shared memory location | 69 // of the lock. Note that a pointer variable to a shared memory location |
62 // could itself be a shared variable. For example, if a shared global pointer | 70 // could itself be a shared variable. For example, if a shared global pointer |
63 // q, which is guarded by mu1, points to a shared memory location that is | 71 // q, which is guarded by mu1, points to a shared memory location that is |
64 // guarded by mu2, q should be annotated as follows: | 72 // guarded by mu2, q should be annotated as follows: |
65 // int *q GUARDED_BY(mu1) PT_GUARDED_BY(mu2); | 73 // int *q GUARDED_BY(mu1) PT_GUARDED_BY(mu2); |
66 #define PT_GUARDED_BY(x) __attribute__ ((point_to_guarded_by(x))) | 74 #define PT_GUARDED_BY(x) \ |
67 #define PT_GUARDED_VAR __attribute__ ((point_to_guarded)) | 75 THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded_by(x)) |
| 76 #define PT_GUARDED_VAR \ |
| 77 THREAD_ANNOTATION_ATTRIBUTE__(point_to_guarded) |
68 | 78 |
69 // Document the acquisition order between locks that can be held | 79 // Document the acquisition order between locks that can be held |
70 // simultaneously by a thread. For any two locks that need to be annotated | 80 // simultaneously by a thread. For any two locks that need to be annotated |
71 // to establish an acquisition order, only one of them needs the annotation. | 81 // to establish an acquisition order, only one of them needs the annotation. |
72 // (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER | 82 // (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER |
73 // and ACQUIRED_BEFORE.) | 83 // and ACQUIRED_BEFORE.) |
74 #define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__))) | 84 #define ACQUIRED_AFTER(x) \ |
75 #define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__))) | 85 THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(x)) |
| 86 #define ACQUIRED_BEFORE(x) \ |
| 87 THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(x)) |
76 | 88 |
77 // The following three annotations document the lock requirements for | 89 // The following three annotations document the lock requirements for |
78 // functions/methods. | 90 // functions/methods. |
79 | 91 |
80 // Document if a function expects certain locks to be held before it is called | 92 // Document if a function expects certain locks to be held before it is called |
81 #define EXCLUSIVE_LOCKS_REQUIRED(...) \ | 93 #define EXCLUSIVE_LOCKS_REQUIRED(x) \ |
82 __attribute__ ((exclusive_locks_required(__VA_ARGS__))) | 94 THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(x)) |
83 | 95 |
84 #define SHARED_LOCKS_REQUIRED(...) \ | 96 #define SHARED_LOCKS_REQUIRED(x) \ |
85 __attribute__ ((shared_locks_required(__VA_ARGS__))) | 97 THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(x)) |
86 | 98 |
87 // Document the locks acquired in the body of the function. These locks | 99 // Document the locks acquired in the body of the function. These locks |
88 // cannot be held when calling this function (as google3's Mutex locks are | 100 // cannot be held when calling this function (as google3's Mutex locks are |
89 // non-reentrant). | 101 // non-reentrant). |
90 #define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__))) | 102 #define LOCKS_EXCLUDED(x) \ |
| 103 THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(x)) |
91 | 104 |
92 // Document the lock the annotated function returns without acquiring it. | 105 // Document the lock the annotated function returns without acquiring it. |
93 #define LOCK_RETURNED(x) __attribute__ ((lock_returned(x))) | 106 #define LOCK_RETURNED(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) |
94 | 107 |
95 // Document if a class/type is a lockable type (such as the Mutex class). | 108 // Document if a class/type is a lockable type (such as the Mutex class). |
96 #define LOCKABLE __attribute__ ((lockable)) | 109 #define LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(lockable) |
97 | 110 |
98 // Document if a class is a scoped lockable type (such as the MutexLock class). | 111 // Document if a class is a scoped lockable type (such as the MutexLock class). |
99 #define SCOPED_LOCKABLE __attribute__ ((scoped_lockable)) | 112 #define SCOPED_LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) |
100 | 113 |
101 // The following annotations specify lock and unlock primitives. | 114 // The following annotations specify lock and unlock primitives. |
102 #define EXCLUSIVE_LOCK_FUNCTION(...) \ | 115 #define EXCLUSIVE_LOCK_FUNCTION(x) \ |
103 __attribute__ ((exclusive_lock(__VA_ARGS__))) | 116 THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock(x)) |
104 | 117 |
105 #define SHARED_LOCK_FUNCTION(...) \ | 118 #define SHARED_LOCK_FUNCTION(x) \ |
106 __attribute__ ((shared_lock(__VA_ARGS__))) | 119 THREAD_ANNOTATION_ATTRIBUTE__(shared_lock(x)) |
107 | 120 |
108 #define EXCLUSIVE_TRYLOCK_FUNCTION(...) \ | 121 #define EXCLUSIVE_TRYLOCK_FUNCTION(x) \ |
109 __attribute__ ((exclusive_trylock(__VA_ARGS__))) | 122 THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock(x)) |
110 | 123 |
111 #define SHARED_TRYLOCK_FUNCTION(...) \ | 124 #define SHARED_TRYLOCK_FUNCTION(x) \ |
112 __attribute__ ((shared_trylock(__VA_ARGS__))) | 125 THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock(x)) |
113 | 126 |
114 #define UNLOCK_FUNCTION(...) __attribute__ ((unlock(__VA_ARGS__))) | 127 #define UNLOCK_FUNCTION(x) \ |
| 128 THREAD_ANNOTATION_ATTRIBUTE__(unlock(x)) |
115 | 129 |
116 // An escape hatch for thread safety analysis to ignore the annotated function. | 130 // An escape hatch for thread safety analysis to ignore the annotated function. |
117 #define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis)) | 131 #define NO_THREAD_SAFETY_ANALYSIS \ |
118 | 132 THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) |
119 | |
120 #else | |
121 | |
122 // When the compiler is not GCC, these annotations are simply no-ops. | |
123 | |
124 // NOTE: in theory, the macros that take "arg" below *could* take | |
125 // multiple arguments, but in practice so far they only take one. | |
126 // Since not all non-gcc compilers support ... -- notably MSVC 7.1 -- | |
127 // I just hard-code in a single arg. If this assumption ever breaks, | |
128 // we can change it back to "...", or handle it some other way. | |
129 | |
130 #define GUARDED_BY(x) // no-op | |
131 #define GUARDED_VAR // no-op | |
132 #define PT_GUARDED_BY(x) // no-op | |
133 #define PT_GUARDED_VAR // no-op | |
134 #define ACQUIRED_AFTER(arg) // no-op | |
135 #define ACQUIRED_BEFORE(arg) // no-op | |
136 #define EXCLUSIVE_LOCKS_REQUIRED(arg) // no-op | |
137 #define SHARED_LOCKS_REQUIRED(arg) // no-op | |
138 #define LOCKS_EXCLUDED(arg) // no-op | |
139 #define LOCK_RETURNED(x) // no-op | |
140 #define LOCKABLE // no-op | |
141 #define SCOPED_LOCKABLE // no-op | |
142 #define EXCLUSIVE_LOCK_FUNCTION(arg) // no-op | |
143 #define SHARED_LOCK_FUNCTION(arg) // no-op | |
144 #define EXCLUSIVE_TRYLOCK_FUNCTION(arg) // no-op | |
145 #define SHARED_TRYLOCK_FUNCTION(arg) // no-op | |
146 #define UNLOCK_FUNCTION(arg) // no-op | |
147 #define NO_THREAD_SAFETY_ANALYSIS // no-op | |
148 | |
149 #endif // defined(__GNUC__) && defined(__SUPPORT_TS_ANNOTATION__) | |
150 // && !defined(SWIG) | |
151 | 133 |
152 #endif // BASE_THREAD_ANNOTATIONS_H_ | 134 #endif // BASE_THREAD_ANNOTATIONS_H_ |
OLD | NEW |