aboutsummaryrefslogtreecommitdiff
blob: e73b87612dbe03d37731934c5e9b64bd7841d061 (plain)
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# Copyright 2008, 2009, 2010, 2011 Free Software Foundation, Inc.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

load_lib mi-support.exp
set MIFLAGS "-i=mi"

gdb_exit
if {[mi_gdb_start]} {
    continue
}

#
# Start here
#
set testfile "nsmoribund"
set srcfile "$testfile.c"
set binfile "$objdir/$subdir/mi-$testfile"

set options [list debug incdir=$objdir]
if {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $options] != "" } {
    return -1
}

mi_gdb_reinitialize_dir $srcdir/$subdir
mi_gdb_load $binfile

set supported 0
gdb_test_multiple "-gdb-show non-stop" "" {
    -re ".*\\^done,value=\"off\",supported=\"(\[^\"\]+)\"\r\n$mi_gdb_prompt$" {
	if { $expect_out(1,string) == "1" } {
	    set supported 1
	}
    }
    -re ".*$mi_gdb_prompt$" {
    }
}

mi_gdb_test "-gdb-set non-stop 1" ".*"
mi_gdb_test "-gdb-set target-async 1" ".*"
detect_async

if { [mi_run_to_main] < 0 } {
    continue
}

# Keep this in sync with THREADS in the the $srcfile.
set nthreads 10

# Set a breakpoint and let all threads hit it (except the main
# thread).

set bkpt_line [gdb_get_line_number "set breakpoint here"]

mi_create_breakpoint "$srcfile:$bkpt_line" 2 keep thread_function .* .* .* \
    "breakpoint at thread_function"

mi_send_resuming_command "exec-continue --all" "resume all"
for {set i 0} {$i < $nthreads} {incr i} {
    mi_expect_stop "breakpoint-hit" "thread_function" "\[^\n\]*" "$srcfile" \
	"\[0-9\]*" {"" "disp=\"keep\""} "stop $i"
}

# All but the main thread should have hit it.

mi_check_thread_states \
    {"running" "stopped" "stopped" "stopped" "stopped" "stopped" "stopped" "stopped" "stopped" "stopped" "stopped"} \
    "thread state: all stopped except the main thread"

# Select a stopped thread to make sure we're able to delete
# breakpoints
mi_gdb_test "-thread-select 5" "\\^done.*" "select thread 5"

# Now that we know about all the threads, we can get rid of
# breakpoint.
mi_delete_breakpoints

# Recreate the same breakpoint, but this time, specific to thread 5.
mi_create_breakpoint "-p 5 $srcfile:$bkpt_line" 3 keep thread_function .* .* .* \
    "thread specific breakpoint at thread_function"

# Resume all threads.  Only thread 5 should report a stop.

set running_re ""
for {set i $nthreads} {$i > 0} {incr i -1} {
    set running_re "$running_re\\*running,thread-id=\"$decimal\"\r\n"
}

gdb_test_multiple "-exec-continue --all" "resume all, thread specific breakpoint" {
    -re ".*$running_re$mi_gdb_prompt" {
	pass "resume all, thread specific breakpoint"
    }
}

mi_expect_stop "breakpoint-hit" "thread_function" "\[^\n\]*" "$srcfile" \
    "\[0-9\]*" {"" "disp=\"keep\""} "hit thread specific breakpoint"

# All threads except both thread 5 (and the main thread) should now be
# repeatedly hitting the thread specific breakpoint and stepping over
# it transparently.  These are internal events, so the frontend should
# see those threads as running.

mi_check_thread_states \
    {"running" "running" "running" "running" "stopped" "running" "running" "running" "running"} \
    "thread state: all running except the breakpoint thread"

# Get rid of the breakpoint while the other threads are stepping over
# it, and tell all threads to exit.  The program should exit
# gracefully shortly.  Send all commands in a row, since if something
# goes wrong with moribund locations support or displaced stepping (or
# a target bug if it can step over breakpoints itself), a spurious
# SIGTRAP/SIGSEGV can come at any time after deleting the breakpoint.
# Note that this causes multiple prompts to appear before the output
# we are interested in, so we can't use mi_gdb_test or
# gdb_test_multiple (or an MI equivalent)

send_gdb "102-break-delete\n"
send_gdb "print done = 1\n"
send_gdb "103-exec-continue --all\n"

gdb_expect {
    -re "\\*stopped,reason=\"exited-normally\"" {
       pass "resume all, program exited normally"
    }
    timeout {
       fail "resume all, waiting for program exit (timeout)"
    }
}

mi_gdb_exit