From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24027 invoked by alias); 14 Nov 2007 12:20:20 -0000 Received: (qmail 24011 invoked by uid 22791); 14 Nov 2007 12:20:18 -0000 X-Spam-Check-By: sourceware.org Received: from igw3.br.ibm.com (HELO igw3.br.ibm.com) (32.104.18.26) by sourceware.org (qpsmtpd/0.31) with ESMTP; Wed, 14 Nov 2007 12:20:13 +0000 Received: from mailhub3.br.ibm.com (unknown [9.18.232.110]) by igw3.br.ibm.com (Postfix) with ESMTP id B46BD39021F for ; Wed, 14 Nov 2007 10:12:38 -0200 (BRDT) Received: from d24av01.br.ibm.com (d24av01.br.ibm.com [9.18.232.46]) by mailhub3.br.ibm.com (8.13.8/8.13.8/NCO v8.6) with ESMTP id lAECK6HX1970326 for ; Wed, 14 Nov 2007 10:20:07 -0200 Received: from d24av01.br.ibm.com (loopback [127.0.0.1]) by d24av01.br.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id lAECK4MQ030530 for ; Wed, 14 Nov 2007 10:20:05 -0200 Received: from [9.18.197.63] ([9.18.197.63]) by d24av01.br.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id lAECK2oH030265; Wed, 14 Nov 2007 10:20:04 -0200 Subject: Re: [patch] Watchpoints: support for thread parameters From: Luis Machado Reply-To: luisgpm@linux.vnet.ibm.com To: Eli Zaretskii Cc: drow@false.org, gdb-patches@sourceware.org In-Reply-To: References: <1187298178.5853.11.camel@localhost> <1187365616.4520.14.camel@localhost> <20071011193558.GE30810@caradoc.them.org> <1192134591.18528.1.camel@localhost> <1194961811.4820.3.camel@localhost> Content-Type: multipart/mixed; boundary="=-Q00RA5Rl3QeHuRii29y+" Date: Wed, 14 Nov 2007 12:20:00 -0000 Message-Id: <1195042801.4908.2.camel@localhost> Mime-Version: 1.0 X-Mailer: Evolution 2.6.1 X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2007-11/txt/msg00268.txt.bz2 --=-Q00RA5Rl3QeHuRii29y+ Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-length: 177 Thanks! > The documentation part is okay with me, provided that you fix the > following two small gotchas: Got those fixed and changed thread_num to threadnum. Regards, Luis --=-Q00RA5Rl3QeHuRii29y+ Content-Disposition: attachment; filename=watch_thread_param.diff Content-Type: text/x-patch; name=watch_thread_param.diff; charset=utf-8 Content-Transfer-Encoding: 7bit Content-length: 9400 2007-11-14 Luis Machado * 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. Index: gdb/breakpoint.c =================================================================== --- gdb.orig/breakpoint.c 2007-11-12 11:22:15.000000000 -0800 +++ gdb/breakpoint.c 2007-11-13 07:57:36.000000000 -0800 @@ -5882,7 +5882,7 @@ 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; @@ -5890,10 +5890,72 @@ 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 ' 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 ' 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 + 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); @@ -5986,6 +6048,7 @@ 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; Index: gdb/testsuite/gdb.base/watch_thread_num.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gdb/testsuite/gdb.base/watch_thread_num.c 2007-11-13 06:35:30.000000000 -0800 @@ -0,0 +1,63 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2002, 2003, 2004 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 +#include +#include +#include + +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); +} + Index: gdb/testsuite/gdb.base/watch_thread_num.exp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gdb/testsuite/gdb.base/watch_thread_num.exp 2007-11-12 11:26:37.000000000 -0800 @@ -0,0 +1,67 @@ +# 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 . */ + +# watch-thread_num.exp Test thread 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 +} + +# use this to debug: +#log_user 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" +} + Index: gdb/doc/gdb.texinfo =================================================================== --- gdb.orig/doc/gdb.texinfo 2007-11-12 11:22:15.000000000 -0800 +++ gdb/doc/gdb.texinfo 2007-11-14 04:11:06.000000000 -0800 @@ -3210,7 +3210,7 @@ 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. @@ -3351,6 +3351,13 @@ 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 --=-Q00RA5Rl3QeHuRii29y+--