OSDN Git Service

Copyright updates for 2007.
[pf3gnuchains/pf3gnuchains3x.git] / gdb / testsuite / gdb.threads / tls.exp
1 # tls.exp -- Expect script to test thread-local storage
2 # Copyright (C) 1992, 2003, 2007 Free Software Foundation, Inc.
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
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
8
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.
13
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 # Please email any bugs, comments, and/or additions to this file to:
19 # bug-gdb@prep.ai.mit.edu
20
21 set testfile tls
22 set srcfile ${testfile}.c
23 set binfile ${objdir}/${subdir}/${testfile}
24
25 if [istarget "*-*-linux"] then {
26     set target_cflags "-D_MIT_POSIX_THREADS"
27 } else {
28     set target_cflags ""
29 }
30
31 if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } {
32     return -1
33 }
34
35 ### Compute the value of the a_thread_local variable.
36 proc compute_expected_value {value} {
37     set expected_value 0
38     set i 0
39     while { $i <= $value} {
40         incr expected_value $i
41         incr i
42     }
43     return $expected_value
44 }
45
46 ### Get the value of the variable 'me' for the current thread.
47 proc get_me_variable {tnum} {
48     global expect_out
49     global gdb_prompt
50     global decimal
51
52     set value_of_me -1
53     send_gdb "print me\n"
54     gdb_expect {
55         -re ".*= ($decimal).*\r\n$gdb_prompt $" {
56             set value_of_me $expect_out(1,string)
57             pass "$tnum thread print me"
58         }
59         -re "$gdb_prompt $" {
60             fail "$tnum thread print me"
61         }
62         timeout {
63             fail "$tnum thread print me (timeout)" 
64         }
65     }
66     return ${value_of_me}
67 }
68
69 ### Check the values of the thread local variables in the thread.
70 ### Also check that info address print the right things.
71 proc check_thread_local {number} {
72     set me_variable [get_me_variable $number]
73     set expected_value [compute_expected_value ${me_variable}]
74
75     gdb_test "p a_thread_local" \
76             "= $expected_value" \
77             "${number} thread local storage"
78
79     gdb_test "p another_thread_local" \
80             "= $me_variable" \
81             "${number} another thread local storage"
82
83     gdb_test "info address a_thread_local" \
84             ".*a_thread_local.*a thread-local variable at offset.*" \
85             "${number} info address a_thread_local"
86
87     gdb_test "info address another_thread_local" \
88             ".*another_thread_local.*a thread-local variable at offset.*" \
89             "${number} info address another_thread_local"
90 }
91
92 ### Select a particular thread.
93 proc select_thread {thread} {
94     global gdb_prompt
95
96     send_gdb "thread $thread\n"
97     gdb_expect {
98         -re "\\\[Switching to thread .*\\\].*\r\n$gdb_prompt $" {
99             pass "selected thread: $thread"
100         }
101         -re "$gdb_prompt $" {
102             fail "selected thread: $thread"
103         }
104         timeout {
105             fail "selected thread: $thread (timeout)"
106         }
107     }
108 }
109
110 ### Do a backtrace for the current thread, and check that the 'spin' routine
111 ### is in it. This means we have one of the threads we created, rather
112 ### than the main thread. Record the thread in the spin_threads 
113 ### array. Also remember the level of the 'spin' routine in the backtrace, for 
114 ### later use.
115 proc check_thread_stack {number spin_threads spin_threads_level} {
116     global gdb_prompt
117     global expect_out
118     global decimal
119     global hex
120     upvar $spin_threads tarr
121     upvar $spin_threads_level tarrl
122
123     select_thread $number
124     send_gdb "where\n"
125     gdb_expect {
126         -re ".*(\[0-9\]+)\[ \t\]+$hex in spin \\(vp=(0x\[0-9a-f\]+).*\r\n$gdb_prompt $" {
127             if {[info exists tarr($number)]} {
128                 fail "backtrace of thread number $number in spin"
129             } else {
130                 pass "backtrace of thread number $number in spin"
131                 set level $expect_out(1,string)
132                 set tarrl($number) $level
133                 set tarr($number) 1
134             }
135         }
136         -re ".*$gdb_prompt $" {
137          set tarr($number) 0
138          set tarrl($number) 0
139          pass "backtrace of thread number $number not relevant"
140         }
141         timeout {
142             fail "backtrace of thread number $number (timeout)" 
143         }
144     }
145 }
146
147 gdb_exit
148 gdb_start
149 gdb_reinitialize_dir $srcdir/$subdir
150
151 gdb_load ${binfile}
152 if ![runto_main] then {
153    fail "Can't run to main"
154    return 0
155 }
156
157 # Set a breakpoint at the "spin" routine to
158 # test the thread local's value.  
159 #
160 gdb_test "b [gdb_get_line_number "here we know tls value"]" \
161          ".*Breakpoint 2.*tls.*"   "set breakpoint at all threads"
162
163 # Set a bp at a point where we know all threads are alive.
164 #
165 gdb_test "b [gdb_get_line_number "still alive"]" \
166          ".*Breakpoint 3.*tls.*" "set breakpoint at synch point"
167
168 # Set a bp at the end to see if all threads are finished.
169 #
170 gdb_test "b [gdb_get_line_number "before exit"]" \
171          ".*Breakpoint 4.*tls.*" "set breakpoint at exit"
172
173 send_gdb "continue\n"
174 gdb_expect {
175     -re ".*Program received signal SIGSEGV.*a_thread_local = 0;.*$gdb_prompt $" {
176         # This is the first symptom if the gcc and binutils versions
177         # in use support TLS, but the system glibc does not.
178         unsupported "continue to first thread: system does not support TLS"
179         return -1
180     }
181     -re ".*Program exited normally.*$gdb_prompt $" {
182         fail "continue to first thread: program runaway"
183     }
184     -re ".*Pass 0 done.*Pass 1 done.*$gdb_prompt $" {
185         fail "continue to first thread: program runaway 2"
186     }
187     -re ".*Breakpoint 2.*tls value.*$gdb_prompt $" {
188         pass "continue to first thread: get to thread"
189     }
190     -re ".*$gdb_prompt $" {
191         fail "continue to first thread: no progress?"
192     }
193     timeout { fail "continue to first thread (timeout)" }
194 }
195
196 gdb_test "info thread" ".*Thread.*spin.*" \
197         "at least one th in spin while stopped at first th"
198
199 check_thread_local "first"
200
201 gdb_test "continue" ".*Breakpoint 2.*tls value.*" "continue to second thread"
202 gdb_test "info thread" "Thread.*spin.*" \
203         "at least one th in spin while stopped at second th"
204
205 check_thread_local "second"
206
207 gdb_test "continue" ".*Breakpoint 2.*tls value.*" "continue to third thread"
208 gdb_test "info thread" ".*Thread.*spin.*" \
209         "at least one th in spin while stopped at third th"
210
211 check_thread_local "third"
212
213 gdb_test "continue" ".*Breakpoint 3.*still alive.*" "continue to synch point"
214
215 set no_of_threads 0
216 send_gdb "info thread\n"
217 gdb_expect {
218         -re "^info thread\[ \t\r\n\]+(\[0-9\]+) Thread.*$gdb_prompt $" {
219            set no_of_threads $expect_out(1,string)
220            pass "get number of threads"
221         }
222         -re "$gdb_prompt $" {
223             fail "get number of threads"
224         }
225         timeout {
226             fail "get number of threads (timeout)"
227         }
228 }
229
230 array set spin_threads {}
231 unset spin_threads
232 array set spin_threads_level {}
233 unset spin_threads_level
234
235 # For each thread check its backtrace to see if it is stopped at the
236 # spin routine. 
237 for {set i 1} {$i <= $no_of_threads} {incr i} {
238     check_thread_stack $i spin_threads spin_threads_level
239 }
240
241 ### Loop through the threads and check the values of the tls variables.
242 ### keep track of how many threads we find in the spin routine.
243 set thrs_in_spin 0
244 foreach i [array names spin_threads] {
245     if {$spin_threads($i) == 1} {
246       incr thrs_in_spin
247       select_thread $i
248       set level $spin_threads_level($i)
249       # We expect to be in sem_wait, but if the thread has not yet
250       # been scheduled, we might be in sem_post still.  We could be at
251       # any intermediate point in spin, too, but that is much less
252       # likely.
253       gdb_test "up $level" ".*spin.*sem_(wait|post).*" "thread $i up"
254       check_thread_local $i 
255     }
256 }
257
258 if {$thrs_in_spin == 0} {
259   fail "No thread backtrace reported spin (vsyscall kernel problem?)"
260 }
261
262 gdb_test "continue" ".*Breakpoint 4.*before exit.*" "threads exited"
263
264 send_gdb "info thread\n" 
265 gdb_expect {
266     -re ".* 1 Thread.*2 Thread.*$gdb_prompt $" {
267         fail "Too many threads left at end"
268     }
269     -re ".*\\\* 1 Thread.*main.*$gdb_prompt $" {
270         pass "Expect only base thread at end"
271     }
272     -re ".*No stack.*$gdb_prompt $" {
273         fail "runaway at end"
274     }
275     -re ".*$gdb_prompt $" {
276         fail "mess at end"
277     }
278     timeout { fail "at end (timeout)" }
279 }
280
281 # Start over and do some "info address" stuff
282 #
283 runto spin
284
285 gdb_test "info address a_global" \
286         ".*a_global.*static storage at address.*" "info address a_global"
287
288 setup_kfail "gdb/1294" "*-*-*"
289 gdb_test "info address me" ".*me.*is a variable at offset.*" "info address me"
290
291 # Done!
292 #
293 gdb_exit
294
295 return 0