Copyright year update in most files of the GDB Project.
[deliverable/binutils-gdb.git] / gdb / testsuite / gdb.threads / tls.exp
CommitLineData
8bc2021f 1# tls.exp -- Expect script to test thread-local storage
c5a57081 2# Copyright (C) 1992, 2003, 2007-2012 Free Software Foundation, Inc.
8bc2021f
EZ
3
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
e22f8b7c 6# the Free Software Foundation; either version 3 of the License, or
8bc2021f 7# (at your option) any later version.
e22f8b7c 8#
8bc2021f
EZ
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
e22f8b7c 13#
8bc2021f 14# You should have received a copy of the GNU General Public License
e22f8b7c 15# along with this program. If not, see <http://www.gnu.org/licenses/>. */
8bc2021f 16
8bc2021f 17set testfile tls
e0740f77 18set testfile2 tls2
8bc2021f 19set srcfile ${testfile}.c
e0740f77 20set srcfile2 ${testfile2}.c
8bc2021f
EZ
21set binfile ${objdir}/${subdir}/${testfile}
22
23if [istarget "*-*-linux"] then {
24 set target_cflags "-D_MIT_POSIX_THREADS"
25} else {
26 set target_cflags ""
27}
28
515ed532 29if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile} ${srcdir}/${subdir}/${srcfile2}" "${binfile}" executable [list c++ debug "incdir=${objdir}"]] != "" } {
8bc2021f
EZ
30 return -1
31}
32
33### Compute the value of the a_thread_local variable.
34proc compute_expected_value {value} {
35 set expected_value 0
36 set i 0
37 while { $i <= $value} {
38 incr expected_value $i
39 incr i
40 }
41 return $expected_value
42}
43
44### Get the value of the variable 'me' for the current thread.
45proc get_me_variable {tnum} {
46 global expect_out
47 global gdb_prompt
48 global decimal
49
50 set value_of_me -1
51 send_gdb "print me\n"
52 gdb_expect {
53 -re ".*= ($decimal).*\r\n$gdb_prompt $" {
54 set value_of_me $expect_out(1,string)
55 pass "$tnum thread print me"
56 }
57 -re "$gdb_prompt $" {
58 fail "$tnum thread print me"
59 }
60 timeout {
61 fail "$tnum thread print me (timeout)"
62 }
63 }
64 return ${value_of_me}
65}
66
67### Check the values of the thread local variables in the thread.
68### Also check that info address print the right things.
69proc check_thread_local {number} {
70 set me_variable [get_me_variable $number]
71 set expected_value [compute_expected_value ${me_variable}]
72
73 gdb_test "p a_thread_local" \
74 "= $expected_value" \
75 "${number} thread local storage"
76
515ed532 77 gdb_test "p K::another_thread_local" \
8bc2021f
EZ
78 "= $me_variable" \
79 "${number} another thread local storage"
80
81 gdb_test "info address a_thread_local" \
82 ".*a_thread_local.*a thread-local variable at offset.*" \
83 "${number} info address a_thread_local"
84
515ed532 85 gdb_test "info address K::another_thread_local" \
8bc2021f
EZ
86 ".*another_thread_local.*a thread-local variable at offset.*" \
87 "${number} info address another_thread_local"
88}
89
90### Select a particular thread.
91proc select_thread {thread} {
92 global gdb_prompt
93
94 send_gdb "thread $thread\n"
95 gdb_expect {
96 -re "\\\[Switching to thread .*\\\].*\r\n$gdb_prompt $" {
97 pass "selected thread: $thread"
98 }
99 -re "$gdb_prompt $" {
100 fail "selected thread: $thread"
101 }
102 timeout {
103 fail "selected thread: $thread (timeout)"
104 }
105 }
106}
107
108### Do a backtrace for the current thread, and check that the 'spin' routine
109### is in it. This means we have one of the threads we created, rather
110### than the main thread. Record the thread in the spin_threads
111### array. Also remember the level of the 'spin' routine in the backtrace, for
112### later use.
113proc check_thread_stack {number spin_threads spin_threads_level} {
114 global gdb_prompt
115 global expect_out
116 global decimal
117 global hex
118 upvar $spin_threads tarr
119 upvar $spin_threads_level tarrl
120
121 select_thread $number
122 send_gdb "where\n"
123 gdb_expect {
124 -re ".*(\[0-9\]+)\[ \t\]+$hex in spin \\(vp=(0x\[0-9a-f\]+).*\r\n$gdb_prompt $" {
125 if {[info exists tarr($number)]} {
126 fail "backtrace of thread number $number in spin"
127 } else {
128 pass "backtrace of thread number $number in spin"
129 set level $expect_out(1,string)
130 set tarrl($number) $level
131 set tarr($number) 1
132 }
133 }
134 -re ".*$gdb_prompt $" {
135 set tarr($number) 0
136 set tarrl($number) 0
137 pass "backtrace of thread number $number not relevant"
138 }
139 timeout {
140 fail "backtrace of thread number $number (timeout)"
141 }
142 }
143}
144
145gdb_exit
146gdb_start
147gdb_reinitialize_dir $srcdir/$subdir
148
149gdb_load ${binfile}
150if ![runto_main] then {
151 fail "Can't run to main"
152 return 0
153}
154
155# Set a breakpoint at the "spin" routine to
156# test the thread local's value.
157#
158gdb_test "b [gdb_get_line_number "here we know tls value"]" \
159 ".*Breakpoint 2.*tls.*" "set breakpoint at all threads"
160
161# Set a bp at a point where we know all threads are alive.
162#
163gdb_test "b [gdb_get_line_number "still alive"]" \
164 ".*Breakpoint 3.*tls.*" "set breakpoint at synch point"
165
166# Set a bp at the end to see if all threads are finished.
167#
168gdb_test "b [gdb_get_line_number "before exit"]" \
169 ".*Breakpoint 4.*tls.*" "set breakpoint at exit"
170
171send_gdb "continue\n"
172gdb_expect {
4ee6625b
DJ
173 -re ".*Program received signal SIGSEGV.*a_thread_local = 0;.*$gdb_prompt $" {
174 # This is the first symptom if the gcc and binutils versions
175 # in use support TLS, but the system glibc does not.
176 unsupported "continue to first thread: system does not support TLS"
177 return -1
178 }
fda326dd 179 -re ".*$inferior_exited_re normally.*$gdb_prompt $" {
8bc2021f
EZ
180 fail "continue to first thread: program runaway"
181 }
182 -re ".*Pass 0 done.*Pass 1 done.*$gdb_prompt $" {
183 fail "continue to first thread: program runaway 2"
184 }
185 -re ".*Breakpoint 2.*tls value.*$gdb_prompt $" {
186 pass "continue to first thread: get to thread"
187 }
188 -re ".*$gdb_prompt $" {
189 fail "continue to first thread: no progress?"
190 }
191 timeout { fail "continue to first thread (timeout)" }
192}
193
194gdb_test "info thread" ".*Thread.*spin.*" \
195 "at least one th in spin while stopped at first th"
196
197check_thread_local "first"
198
199gdb_test "continue" ".*Breakpoint 2.*tls value.*" "continue to second thread"
200gdb_test "info thread" "Thread.*spin.*" \
201 "at least one th in spin while stopped at second th"
202
203check_thread_local "second"
204
205gdb_test "continue" ".*Breakpoint 2.*tls value.*" "continue to third thread"
206gdb_test "info thread" ".*Thread.*spin.*" \
207 "at least one th in spin while stopped at third th"
208
209check_thread_local "third"
210
211gdb_test "continue" ".*Breakpoint 3.*still alive.*" "continue to synch point"
212
51514e06 213set no_of_threads 0
8bc2021f
EZ
214send_gdb "info thread\n"
215gdb_expect {
5d3d9cba 216 -re "^info thread\[ \t\r\n\]+ *Id .*Frame\[ \t\r\n\]+(\[0-9\]+) *Thread.*$gdb_prompt $" {
8bc2021f
EZ
217 set no_of_threads $expect_out(1,string)
218 pass "get number of threads"
219 }
220 -re "$gdb_prompt $" {
221 fail "get number of threads"
222 }
223 timeout {
224 fail "get number of threads (timeout)"
225 }
226}
227
228array set spin_threads {}
229unset spin_threads
230array set spin_threads_level {}
231unset spin_threads_level
232
233# For each thread check its backtrace to see if it is stopped at the
234# spin routine.
235for {set i 1} {$i <= $no_of_threads} {incr i} {
236 check_thread_stack $i spin_threads spin_threads_level
237}
238
239### Loop through the threads and check the values of the tls variables.
240### keep track of how many threads we find in the spin routine.
241set thrs_in_spin 0
242foreach i [array names spin_threads] {
243 if {$spin_threads($i) == 1} {
244 incr thrs_in_spin
245 select_thread $i
246 set level $spin_threads_level($i)
61a771aa
DJ
247 # We expect to be in sem_wait, but if the thread has not yet
248 # been scheduled, we might be in sem_post still. We could be at
249 # any intermediate point in spin, too, but that is much less
250 # likely.
251 gdb_test "up $level" ".*spin.*sem_(wait|post).*" "thread $i up"
8bc2021f
EZ
252 check_thread_local $i
253 }
254}
255
256if {$thrs_in_spin == 0} {
257 fail "No thread backtrace reported spin (vsyscall kernel problem?)"
258}
259
260gdb_test "continue" ".*Breakpoint 4.*before exit.*" "threads exited"
261
262send_gdb "info thread\n"
263gdb_expect {
a7658b96 264 -re ".* 1 *Thread.*2 *Thread.*$gdb_prompt $" {
8bc2021f
EZ
265 fail "Too many threads left at end"
266 }
a7658b96 267 -re ".*\\\* 1 *Thread.*main.*$gdb_prompt $" {
8bc2021f
EZ
268 pass "Expect only base thread at end"
269 }
270 -re ".*No stack.*$gdb_prompt $" {
271 fail "runaway at end"
272 }
273 -re ".*$gdb_prompt $" {
274 fail "mess at end"
275 }
276 timeout { fail "at end (timeout)" }
277}
278
279# Start over and do some "info address" stuff
280#
281runto spin
282
283gdb_test "info address a_global" \
284 ".*a_global.*static storage at address.*" "info address a_global"
285
fc529d80 286gdb_test "info address me" ".*me.*is a (complex DWARF expression:|variable).*" \
7155d578 287 "info address me"
8bc2021f 288
e0740f77
JK
289
290# Test LOC_UNRESOLVED references resolving for `extern' TLS variables.
291
292gdb_test "p a_thread_local" " = \[0-9\]+"
293# Here it could crash with: Cannot access memory at address 0x0
294gdb_test "p file2_thread_local" " = \[0-9\]+"
295# Depending on the current lookup scope we get LOC_UNRESOLVED or LOC_COMPUTED
296# both printing:
297# Symbol "file2_thread_local" is a thread-local variable at offset 8 in the thread-local storage for `.../gdb.threads/tls'.
298gdb_test "info address file2_thread_local" "Symbol \"file2_thread_local\" is a thread-local variable.*"
299# Here it could also crash with: Cannot access memory at address 0x0
300gdb_test "p a_thread_local" " = \[0-9\]+" "p a_thread_local second time"
301gdb_test "info address a_thread_local" "Symbol \"a_thread_local\" is a thread-local variable.*"
302
8bc2021f
EZ
303# Done!
304#
305gdb_exit
306
307return 0
This page took 0.915437 seconds and 4 git commands to generate.