* breakpoint.c: (watch_command_1): Parse additional optional

"thread" parameter to the watchpoint command and set the
      "thread" member of the breakpoint struct.
      * doc/gdb.texinfo: Add new parameter's description.
      * testsuite/gdb.base/watch_thread_num.c: New testcase source file.
      * testsuite/gdb.base/watch_thread_num.exp: New testcase expect file.
This commit is contained in:
Luis Machado
2007-12-17 12:32:23 +00:00
parent 28e78778f5
commit 37e4754d76
7 changed files with 215 additions and 3 deletions

View File

@@ -1,3 +1,9 @@
2007-12-17 Luis Machado <luisgpm@br.ibm.com>
* breakpoint.c: (watch_command_1): Parse additional optional
"thread" parameter to the watchpoint command and set the
"thread" member of the breakpoint struct.
2007-12-17 Luis Machado <luisgpm@br.ibm.com>
* breakpoint.c (bpstat_stop_status): Check an additional

View File

@@ -5606,7 +5606,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty)
struct frame_info *prev_frame = NULL;
char *exp_start = NULL;
char *exp_end = NULL;
char *tok, *end_tok;
char *tok, *id_tok_start, *end_tok;
int toklen;
char *cond_start = NULL;
char *cond_end = NULL;
@@ -5614,10 +5614,72 @@ watch_command_1 (char *arg, int accessflag, int from_tty)
int i, other_type_used, target_resources_ok = 0;
enum bptype bp_type;
int mem_cnt = 0;
int thread = -1;
init_sal (&sal); /* initialize to zeroes */
/* Parse arguments. */
/* Make sure that we actually have parameters to parse. */
if (arg != NULL && arg[0] != '\0')
{
toklen = strlen (arg); /* Size of argument list. */
/* Points tok to the end of the argument list. */
tok = arg + toklen - 1;
/* Go backwards in the parameters list. Skip the last parameter.
If we're expecting a 'thread <thread_num>' parameter, this should
be the thread identifier. */
while (tok > arg && (*tok == ' ' || *tok == '\t'))
tok--;
while (tok > arg && (*tok != ' ' && *tok != '\t'))
tok--;
/* Points end_tok to the beginning of the last token. */
id_tok_start = tok + 1;
/* Go backwards in the parameters list. Skip one more parameter.
If we're expecting a 'thread <thread_num>' parameter, we should
reach a "thread" token. */
while (tok > arg && (*tok == ' ' || *tok == '\t'))
tok--;
end_tok = tok;
while (tok > arg && (*tok != ' ' && *tok != '\t'))
tok--;
/* Move the pointer forward to skip the whitespace and
calculate the length of the token. */
tok++;
toklen = end_tok - tok;
if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
{
/* At this point we've found a "thread" token, which means
the user is trying to set a watchpoint that triggers
only in a specific thread. */
char *endp;
/* Extract the thread ID from the next token. */
thread = strtol (id_tok_start, &endp, 0);
/* Check if the user provided a valid numeric value for the
thread ID. */
if (*endp != ' ' && *endp != '\t' && *endp != '\0')
error (_("Invalid thread ID specification %s."), id_tok_start);
/* Check if the thread actually exists. */
if (!valid_thread_id (thread))
error (_("Unknown thread %d."), thread);
/* Truncate the string and get rid of the thread <thread_num>
parameter before the parameter list is parsed by the
evaluate_expression() function. */
*tok = '\0';
}
}
/* Parse the rest of the arguments. */
innermost_block = NULL;
exp_start = arg;
exp = parse_exp_1 (&arg, 0, 0);
@@ -5710,6 +5772,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty)
b = set_raw_breakpoint (sal, bp_type);
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
b->thread = thread;
b->disposition = disp_donttouch;
b->exp = exp;
b->exp_valid_block = exp_valid_block;

View File

@@ -1,3 +1,7 @@
2007-12-17 Luis Machado <luisgpm@br.ibm.com>
* doc/gdb.texinfo: Add new parameter's description.
2007-12-16 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.texinfo (Overview): Clarify run-length encoding

View File

@@ -3216,7 +3216,7 @@ times slower than normal execution. (But this may still be worth it, to
catch errors where you have no clue what part of your program is the
culprit.)
On some systems, such as HP-UX, @sc{gnu}/Linux and most other
On some systems, such as HP-UX, PowerPC, @sc{gnu}/Linux and most other
x86-based targets, @value{GDBN} includes support for hardware
watchpoints, which do not slow down the running of your program.
@@ -3357,6 +3357,13 @@ way of doing that would be to set a code breakpoint at the entry to the
In multi-threaded programs, watchpoints will detect changes to the
watched expression from every thread.
@kindex watch thread thread_num
@item watch @var{expr} thread @var{threadnum}
Set a watchpoint that will break when @var{expr} is either read from
or written into by the thread identified by @var{threadnum}. If @var{expr}
is modified by any other threads not matching @var{threadnum}, @value{GDBN}
will not break. Note that this will only work with Hardware Watchpoints.
@quotation
@emph{Warning:} In multi-threaded programs, software watchpoints
have only limited usefulness. If @value{GDBN} creates a software

View File

@@ -1,3 +1,8 @@
2007-12-17 Luis Machado <luisgpm@br.ibm.com>
* testsuite/gdb.base/watch_thread_num.c: New testcase source file.
* testsuite/gdb.base/watch_thread_num.exp: New testcase expect file.
2007-12-17 Joel Brobecker <brobecker@adacore.com>
* gdb.ada/frame_args/foo.adb: New file.

View File

@@ -0,0 +1,63 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2002, 2003, 2004, 2007 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 2 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
This file is copied from schedlock.c. */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
void *thread_function (void *arg); /* Pointer to function executed by each thread */
#define NUM 5
static unsigned int shared_var = 1;
int main () {
int res;
pthread_t threads[NUM];
void *thread_result;
long i;
for (i = 0; i < NUM; i++)
{
res = pthread_create (&threads[i],
NULL,
thread_function,
(void *) i);
}
thread_result = thread_function ((void *) i);
exit (EXIT_SUCCESS);
}
void *thread_function (void *arg) {
int my_number = (long) arg;
/* Don't run forever. Run just short of it :) */
while (shared_var > 0)
{
shared_var++;
usleep (1); /* Loop increment. */
}
pthread_exit (NULL);
}

View File

@@ -0,0 +1,64 @@
# This testcase is part of GDB, the GNU debugger.
# Copyright 2007
# 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/>. */
# watch-thread_num.exp Test thread <thread_num> parameter for
# watch commands.
#
if $tracelevel then {
strace $tracelevel
}
set testfile watch_thread_num
set srcfile ${testfile}.c
set binfile ${objdir}/${subdir}/${testfile}
# What compiler are we using?
#
if [get_compiler_info ${binfile}] {
return -1
}
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug libs=-lpthread}] != "" } {
untested watch_thread_num.exp
return -1
}
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
if { ![runto main] } then {
fail "run to main"
return
}
gdb_test "watch shared_var thread 0" "Unknown thread 0\." "Watchpoint on invalid thread"
gdb_test "watch shared_var thread" "A syntax error in expression, near `thread'\." "Invalid watch syntax"
gdb_test "Next 5" ""
gdb_test "watch shared_var thread 2" "Hardware watchpoint 2: shared_var" "Watchpoint on shared variable"
gdb_test "info breakpoint 2" "stop only in thread 2"
for {set i 0} {$i < 10} {incr i 1} {
gdb_test "continue" "Hardware watchpoint 2: shared_var.*" "Watchpoint triggered"
gdb_test "thread" "\\\[Current thread is 2 \\\(Thread $hex \\\(LWP $decimal\\\)\\\)\\\]" "Check thread that triggered"
}