clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name tls.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/isvv/naviserver/nsthread -resource-dir /usr/local/lib/clang/15.0.0 -D _FORTIFY_SOURCE=2 -D NDEBUG -D SYSTEM_MALLOC -I ../include -I /usr/include/tcl8.6 -D HAVE_CONFIG_H -internal-isystem /usr/local/lib/clang/15.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -std=c99 -fdebug-compilation-dir=/home/isvv/naviserver/nsthread -ferror-limit 19 -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker alpha -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-07-23-130959-11103-1 -x c tls.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | #include "thread.h" |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | static uintptr_t nsThreadMaxTls = NS_THREAD_MAXTLS; |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | static Ns_TlsCleanup *cleanupProcs[NS_THREAD_MAXTLS]; |
52 | |
53 |
|
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | void |
71 | Ns_TlsAlloc(Ns_Tls *keyPtr, Ns_TlsCleanup *cleanup) |
72 | { |
73 | static uintptr_t nextkey = 1u; |
74 | uintptr_t key; |
75 | |
76 | NS_NONNULL_ASSERT(keyPtr != NULL); |
77 | |
78 | Ns_MasterLock(); |
79 | if (nextkey == nsThreadMaxTls) { |
| 1 | Assuming 'nextkey' is not equal to 'nsThreadMaxTls' | |
|
| |
80 | Tcl_Panic("Ns_TlsAlloc: exceeded max tls: %" PRIuPTR, nsThreadMaxTls); |
81 | } |
82 | key = nextkey++; |
83 | cleanupProcs[key] = cleanup; |
84 | Ns_MasterUnlock(); |
85 | |
86 | *keyPtr = (void *) key; |
| 3 | | Using a fixed address is not portable because that address will probably not be valid in all environments or platforms |
|
87 | } |
88 | |
89 |
|
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | void |
107 | Ns_TlsSet(const Ns_Tls *keyPtr, void *value) |
108 | { |
109 | uintptr_t key; |
110 | |
111 | NS_NONNULL_ASSERT(keyPtr != NULL); |
112 | |
113 | key = (uintptr_t) *keyPtr; |
114 | if (key < 1 || key >= NS_THREAD_MAXTLS) { |
115 | Tcl_Panic("Ns_TlsSet: invalid key: %" PRIuPTR |
116 | ": should be between 1 and %" PRIuPTR, |
117 | key, nsThreadMaxTls); |
118 | } else { |
119 | void **slots = NsGetTls(); |
120 | |
121 | slots[key] = value; |
122 | } |
123 | } |
124 | |
125 |
|
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | void * |
143 | Ns_TlsGet(const Ns_Tls *keyPtr) |
144 | { |
145 | uintptr_t key; |
146 | void *result; |
147 | |
148 | NS_NONNULL_ASSERT(keyPtr != NULL); |
149 | |
150 | key = (uintptr_t) *keyPtr; |
151 | if (key < 1 || key >= NS_THREAD_MAXTLS) { |
152 | result = NULL; |
153 | Tcl_Panic("Ns_TlsGet: invalid key: %" PRIuPTR |
154 | ": should be between 1 and %" PRIuPTR, |
155 | key, nsThreadMaxTls); |
156 | } else { |
157 | void **slots = NsGetTls(); |
158 | |
159 | result = slots[key]; |
160 | } |
161 | return result; |
162 | } |
163 | |
164 |
|
165 | |
166 | |
167 | |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | |
178 | |
179 | |
180 | |
181 | |
182 | |
183 | |
184 | |
185 | void |
186 | NsCleanupTls(void **slots) |
187 | { |
188 | NS_NONNULL_ASSERT(slots != NULL); |
189 | |
190 | if ( |
191 | #if defined(TCL_IS_FIXED) |
192 | 1 |
193 | #else |
194 | NS_finalshutdown != 1 |
195 | #endif |
196 | ) { |
197 | int tries, retry; |
198 | |
199 | tries = 0; |
200 | do { |
201 | int i; |
202 | |
203 | retry = 0; |
204 | i = NS_THREAD_MAXTLS; |
205 | while (i-- > 0) { |
206 | if (cleanupProcs[i] != NULL && slots[i] != NULL) { |
207 | void *arg; |
208 | |
209 | arg = slots[i]; |
210 | slots[i] = NULL; |
211 | (*cleanupProcs[i])(arg); |
212 | retry = 1; |
213 | } |
214 | } |
215 | } while (retry && tries++ < 5); |
216 | } |
217 | } |
218 | |
219 | |
220 | |
221 | |
222 | |
223 | |
224 | |
225 | |
226 | |