1 # Copyright
1999, 2001, 2002, 2003 Free Software Foundation
, Inc.
3 # This
program is free software
; you can redistribute it and
/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation
; either version
2 of the License
, or
6 #
(at your option
) any later version.
8 # This
program is distributed in the hope that it will be useful
,
9 # but WITHOUT
ANY WARRANTY
; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License
for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this
program; if not
, write to the Free Software
15 # Foundation
, Inc.
, 59 Temple Place
- Suite
330, Boston
, MA
02111-1307, USA.
17 # Please email
any bugs
, comments
, and
/or additions to this file to
:
20 #### Dining Philosophers
, on LinuxThreads
- Jim Blandy
<jimb@cygnus.com
>
22 #### At the moment
, GDB
's support for LinuxThreads is pretty
23 #### idiosyncratic --- GDB's output doesn
't look much like the output
24 #### it produces for other thread implementations, messages appear at
25 #### different times, etc. So these tests are specific to LinuxThreads.
27 #### However, if all goes well, Linux will soon have a libthread_db
28 #### interface, and GDB will manage it the same way it does other
29 #### libthread_db-based systems. Then, we can adjust this file to
30 #### work with any such system.
32 ### Other things we ought to test:
33 ### stepping a thread while others are running
34 ### killing and restarting
35 ### quitting gracefully
44 # This only works with Linux configurations.
45 if ![istarget *-*-linux-gnu*] then {
49 set testfile "linux-dp"
50 set srcfile ${testfile}.c
51 set binfile ${objdir}/${subdir}/${testfile}
52 if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug libs=-lpthread}] != ""} {
57 gdb_reinitialize_dir $srcdir/$subdir
59 send_gdb "set print sevenbit-strings\n" ; gdb_expect -re "$gdb_prompt $"
62 # There should be no threads initially.
63 gdb_test "info threads" "" "info threads 1"
65 # Try stepping over the thread creation function.
66 gdb_breakpoint [gdb_get_line_number "linuxthreads.exp: create philosopher"]
68 for {set i 0} {$i < 5} {incr i} {
69 gdb_continue_to_breakpoint "about to create philosopher: $i"
72 -re "\\\[New .*\\\].*\\\[New .*\\\].*$gdb_prompt $" {
73 # Two threads are created the first time in LinuxThreads,
74 # where the second is the manager thread. In NPTL, there is none.
78 pass "create philosopher: $i"
80 -re "\\\[New .*\\\].*$gdb_prompt $" {
84 pass "create philosopher: $i"
86 -re "Program received signal.*(Unknown signal|SIGUSR|Real-time event).*$gdb_prompt $" {
87 # It would be nice if we could catch the message that GDB prints
88 # when it first notices that the thread library doesn't support
89 # debugging
, or
if we could explicitly ask GDB somehow.
90 unsupported
"This GDB does not support threads on this system."
94 # We used to fail here
, but not all targets announce new
95 # threads as they are created.
For example
, the GDB
96 # remote protocol target only finds out about threads when
97 # they actually
report some event like a breakpoint hit
,
98 # or when the user types
'info threads'.
99 unresolved
"create philosopher: $i"
102 fail
"(timeout) create philosopher: $i"
109 # Run until there are some threads.
110 gdb_breakpoint
[gdb_get_line_number
"linuxthreads.exp: info threads 2"]
111 gdb_continue_to_breakpoint
"main thread's sleep"
112 set info_threads_ptn
""
113 for {set i $nthreads
} {$i
> 0} {incr i
-1} {
114 append info_threads_ptn
"$i Thread .*"
116 append info_threads_ptn
"\[\r\n\]+$gdb_prompt $"
117 set info_threads_manager_ptn
"[expr $nthreads + 1] Thread .*$info_threads_ptn"
119 gdb_test_multiple
"info threads" "info threads 2" {
120 -re
"$info_threads_manager_ptn" {
121 # We did see a manager thread. Check that against what we expected.
122 switch -exact
-- $expect_manager
{
124 # We weren
't sure whether to expect a manager thread.
125 pass "info threads 2"
128 # We were expecting a manager thread.
129 pass "info threads 2"
132 # We were not expecting to see the manager thread.
133 fail "info threads 2"
139 -re "$info_threads_ptn" {
140 # We did not see a manager thread. Check that against what we
142 switch -exact -- $expect_manager {
144 # We weren't sure whether to expect a manager thread.
145 # Don
't expect it from here on out.
146 pass "info threads 2"
149 # We were expecting a manager thread, but we didn't see one.
150 fail
"info threads 2"
153 # We were not expecting to see the manager thread.
154 pass
"info threads 2"
162 # Try setting a thread
-specific breakpoint.
163 gdb_breakpoint
"print_philosopher thread 5"
164 gdb_continue_to_breakpoint
"thread 5's print"
165 # When there is no debugging
info available
for the thread library
,
166 # the backtrace entry
for philosopher
's caller looks like:
167 # #1 0x4001c548 in pthread_create () from /lib/libpthread.so.0
168 # If you do have debug info, the output obviously depends more on the
169 # exact library in use; under NPTL, you get:
170 # #2 0x0012b7fc in start_thread (arg=0x21) at pthread_create.c:264
171 gdb_test "where" "print_philosopher.*philosopher.* \(from .*libpthread\|at pthread_create\).*" \
172 "first thread-specific breakpoint hit"
174 # Make sure it's catching the right thread. Try hitting the
175 # breakpoint ten times
, and make sure we don
't get anyone else.
177 for {set i 0} {$only_five > 0 && $i < 10} {incr i} {
178 gdb_continue_to_breakpoint "thread 5's print
, pass
: $i
"
179 send_gdb
"info threads\n"
181 -re
"\\* 5 Thread .* print_philosopher .*\r\n$gdb_prompt $" {
184 -re
".*$gdb_prompt $" {
193 set name "thread-specific breakpoint is thread-specific"
194 if {$only_five
== 1} { pass $
name }
195 if {$only_five
== 0} { fail $
name }
196 if {$only_five
== -1} { fail
"$name (timeout)" }
199 ### Select a particular thread.
200 proc select_thread
{thread
} {
203 send_gdb
"thread $thread\n"
205 -re
"\\\[Switching to thread .*\\\].*\r\n$gdb_prompt $" {
206 pass
"selected thread: $thread"
208 -re
"$gdb_prompt $" {
209 fail
"selected thread: $thread"
212 fail
"selected thread: $thread (timeout)"
217 ### Select THREAD
, check
for a plausible backtrace
, and make sure
218 ### we
're actually selecting a different philosopher each time.
219 ### Return true if the thread had a stack which was not only
220 ### acceptable, but interesting. SEEN should be an array in which
221 ### SEEN(N) exists iff we have found philosopher number N before.
226 proc check_philosopher_stack {thread seen_name} {
228 upvar $seen_name seen
230 global expect_manager manager_seen
232 set name "philosopher is distinct: $thread"
235 select_thread $thread
238 -re ".* in philosopher \\(data=(0x\[0-9a-f\]+).*\r\n$gdb_prompt $" {
239 set data $expect_out(1,string)
240 if {[info exists seen($data)]} {
248 -re ".* in __pthread_manager \\(.*$gdb_prompt $" {
249 if {$manager_seen == 1} {
250 fail "manager thread is distinct: $thread"
253 pass "manager thread is distinct: $thread"
257 -re "pthread_start_thread.*\r\n$gdb_prompt $" {
258 ## Maybe the thread hasn't started yet.
261 -re
".* in main \\(.*$gdb_prompt $" {
262 if {$main_seen
== 1} {
263 fail
"main is distinct: $thread"
266 pass
"main is distinct: $thread"
270 -re
" in \\?\\?.*\r\n$gdb_prompt $" {
271 ## Sometimes we can
't get a backtrace. I'm going to
call
272 ## this a pass
, since we
do verify that at least one
273 ## thread was interesting
, so we can
get more consistent
274 ## test suite totals. But in my heart
, I think it should
278 -re
"$gdb_prompt $" {
282 fail
"$name (timeout)"
289 set any_interesting
0
292 for {set i
1} {$i
<= $nthreads
} {incr i
} {
293 if [check_philosopher_stack $i seen
] {
294 set any_interesting
1
298 if {$any_interesting
} {
299 pass
"found an interesting thread"
301 fail
"found an interesting thread"
304 if {$manager_seen
== $expect_manager
} {
305 pass
"manager thread found (not found) when expected"
307 fail
"manager thread found (not found) when expected"