# Copyright (C) 2013-2022 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/>.
#
# Verify that a thread-specific breakpoint is deleted when the
# corresponding thread is gone.

standard_testfile

if {[gdb_compile_pthreads \
	 "${srcdir}/${subdir}/${srcfile}" \
	 "${binfile}" executable {debug} ] != "" } {
    return -1
}

clean_restart ${binfile}

# Extract and return the thread ID of the thread stopped at function
# FUNC.

proc get_thread_id {func} {
    global gdb_prompt

    set thre -1
    set test "get $func thread id"
    gdb_test_multiple "info threads" $test {
	-re "(\[0-9\]+)\[^\n\r\]*Thread\[^\n\r\]*$func.*$gdb_prompt $" {
	    # Get the thread's id.
	    set thre $expect_out(1,string)
	    pass $test
	}
    }

    return $thre
}

proc check_thread_specific_breakpoint {mode} {
    with_test_prefix "$mode" {
	global gdb_prompt

	if ![runto_main] {
	    return -1
	}

	set main_thre [get_thread_id "main"]
	if { $main_thre < 0 } {
	    return -1
	}

	gdb_breakpoint "start"
	gdb_continue_to_breakpoint "start"

	set start_thre [get_thread_id "start"]
	if { $start_thre < 0 } {
	    return -1
	}

	# Set a thread-specific breakpoint at "main".  This can't ever
	# be hit, but that's OK.
	gdb_breakpoint "main thread $start_thre"
	gdb_test "info break" ".*breakpoint.*thread $start_thre" "breakpoint set"

	# Set breakpoint at a place only reacheable after the "start"
	# thread exits.
	gdb_breakpoint "end"

	# Switch back to the main thread, and resume all threads.  The
	# "start" thread exits, and the main thread reaches "end".
	gdb_test "thread $main_thre" \
	    "Switching to thread $main_thre.*" \
	    "thread $main_thre selected"

	if { $mode == "non-stop" } {
	    set cmd "continue -a"
	} else {
	    set cmd "continue"
	}
	set test "continue to end"
	set thread_exited 0
	set prompt 0
	gdb_test_multiple "$cmd" $test -lbl {
	    -re "(^|\r\n)\\\[Thread \[^\r\n\]* exited](?=\r\n)" {
		if { $prompt } {
		    pass $gdb_test_name
		} else {
		    set thread_exited 1
		    exp_continue
		}
	    }
	    -re "\r\n$gdb_prompt " {
		if { $thread_exited } {
		    pass $gdb_test_name
		} else {
		    set prompt 1
		    exp_continue
		}
	    }
	}

	set test "thread-specific breakpoint was deleted"
	gdb_test_multiple "info breakpoint" $test {
	    -re "thread $start_thre\n$gdb_prompt $" {
		fail $test
	    }
	    -re "$gdb_prompt $" {
		pass $test
	    }
	}
    }
}

# Test all-stop mode.
check_thread_specific_breakpoint "all-stop"

clean_restart ${binfile}

# Test non-stop mode.
gdb_test_no_output "set non-stop on" "set non-stop mode"
check_thread_specific_breakpoint "non-stop"
