From patchwork Mon Sep 14 11:31:22 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pierre Langlois X-Patchwork-Id: 8670 Received: (qmail 77055 invoked by alias); 14 Sep 2015 11:38:08 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 77044 invoked by uid 89); 14 Sep 2015 11:38:08 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.7 required=5.0 tests=AWL, BAYES_00, KAM_STOCKGEN, SPF_PASS autolearn=no version=3.3.2 X-HELO: eu-smtp-delivery-143.mimecast.com Received: from eu-smtp-delivery-143.mimecast.com (HELO eu-smtp-delivery-143.mimecast.com) (207.82.80.143) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 14 Sep 2015 11:38:06 +0000 Received: from cam-owa1.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) by eu-smtp-1.mimecast.com with ESMTP id uk-mta-38-gYoFlX7-SBK88q3CWG7m3A-17; Mon, 14 Sep 2015 12:31:27 +0100 Received: from e105615-lin.cambridge.arm.com ([10.1.2.79]) by cam-owa1.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Mon, 14 Sep 2015 12:31:24 +0100 From: Pierre Langlois To: gdb-patches@sourceware.org Cc: Pierre Langlois Subject: [PATCH 8/8] [testsuite] Add a test case for fast tracepoints' locking mechanism Date: Mon, 14 Sep 2015 12:31:22 +0100 Message-Id: <1442230282-20751-9-git-send-email-pierre.langlois@arm.com> In-Reply-To: <1442230282-20751-1-git-send-email-pierre.langlois@arm.com> References: <1442230282-20751-1-git-send-email-pierre.langlois@arm.com> X-MC-Unique: gYoFlX7-SBK88q3CWG7m3A-17 X-IsSubscribed: yes When installing a fast tracepoint, we create a jump pad with a spin-lock. This way, only one thread can collect a given tracepoint at any time. This test case checks that this lock actually works as expected. This test works by creating a function which overrides the in-process agent library's gdb_collect function. On start up, GDBserver will ask GDB with the 'qSymbol' packet about symbols present in the inferior. GDB will reply with the gdb_agent_gdb_collect function from the test case instead of the one from the agent. gdb/testsuite/ChangeLog: * gdb.trace/ftrace-lock.c: New file. * gdb.trace/ftrace-lock.exp: New file. --- gdb/testsuite/gdb.trace/ftrace-lock.c | 106 ++++++++++++++++++++++++++++++++ gdb/testsuite/gdb.trace/ftrace-lock.exp | 95 ++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+) create mode 100644 gdb/testsuite/gdb.trace/ftrace-lock.c create mode 100644 gdb/testsuite/gdb.trace/ftrace-lock.exp diff --git a/gdb/testsuite/gdb.trace/ftrace-lock.c b/gdb/testsuite/gdb.trace/ftrace-lock.c new file mode 100644 index 0000000..8ed45f4 --- /dev/null +++ b/gdb/testsuite/gdb.trace/ftrace-lock.c @@ -0,0 +1,106 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2015 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 . */ + +#include + +#ifdef SYMBOL_PREFIX +#define SYMBOL(str) SYMBOL_PREFIX #str +#else +#define SYMBOL(str) #str +#endif + +/* Called if the testcase failed. */ +static void +fail (void) +{ +} + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +/* This function overrides gdb_collect in the in-process agent library. + See gdbserver/tracepoint.c (gdb_collect). We want this function to + be ran instead of the one from the library to easily check that only + one thread is tracing at a time. + + This works as expected because GDBserver will ask GDB about symbols + present in the inferior with the 'qSymbol' packet. And GDB will + reply with the address of this function instead of the one from the + in-process agent library. */ + +void +gdb_agent_gdb_collect (void *tpoint, unsigned char *regs) +{ + /* If we cannot acquire a lock, then this means another thread is + tracing and the lock implemented by the jump pad is not working! */ + if (pthread_mutex_trylock (&mutex) != 0) + { + fail (); + return; + } + + sleep (1); + + if (pthread_mutex_unlock (&mutex) != 0) + { + fail (); + return; + } +} + +/* Called from asm. */ +static void __attribute__((used)) +func (void) +{ +} + +static void * +thread_function (void *arg) +{ + /* `set_point' is the label at which to set a fast tracepoint. The + insn at the label must be large enough to fit a fast tracepoint + jump. */ + asm (" .global " SYMBOL (set_point) "\n" + SYMBOL (set_point) ":\n" +#if (defined __x86_64__ || defined __i386__) + " call " SYMBOL (func) "\n" +#elif (defined __aarch64__) + " nop\n" +#endif + ); +} + +static void +end (void) +{ +} + +int +main (int argc, char *argv[], char *envp[]) +{ + pthread_t threads[NUM_THREADS]; + int i; + + for (i = 0; i < NUM_THREADS; i++) + pthread_create (&threads[i], NULL, thread_function, NULL); + + for (i = 0; i < NUM_THREADS; i++) + pthread_join (threads[i], NULL); + + end (); + + return 0; +} diff --git a/gdb/testsuite/gdb.trace/ftrace-lock.exp b/gdb/testsuite/gdb.trace/ftrace-lock.exp new file mode 100644 index 0000000..1b3c35a --- /dev/null +++ b/gdb/testsuite/gdb.trace/ftrace-lock.exp @@ -0,0 +1,95 @@ +# Copyright 2015 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 . + +load_lib "trace-support.exp" + +standard_testfile +set executable $testfile +set expfile $testfile.exp + +# make check RUNTESTFLAGS='gdb.trace/ftrace-lock.exp NUM_THREADS=2' +if ![info exists NUM_THREADS] { + set NUM_THREADS 2 +} + +# If NUM_THREADS is high then this test case may timeout. Increase the +# timeout temporarily. +global timeout +set savedtimeout $timeout +set timeout [expr $NUM_THREADS * $timeout] + +# Some targets have leading underscores on assembly symbols. +set additional_flags [gdb_target_symbol_prefix_flags] +set options [list debug [gdb_target_symbol_prefix_flags] \ + additional_flags=-DNUM_THREADS=$NUM_THREADS] + +# Check that the target supports trace. +if { [gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $options] != "" } { + untested "Couldn't compile test program" + return -1 +} + +clean_restart ${testfile} + +if ![runto_main] { + fail "Can't run to main to check for trace support" + return -1 +} + +if ![gdb_target_supports_trace] { + unsupported "target does not support trace" + return -1 +} + +# Compile the test case with the in-process agent library. +set libipa [get_in_proc_agent] +gdb_load_shlibs $libipa + +lappend options shlib=$libipa + +if { [gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $options] != "" } { + untested "Couldn't compile test program with in-process agent library" + return -1 +} + +clean_restart ${executable} + +if ![runto_main] { + fail "Can't run to main to check for trace support" + return -1 +} + +gdb_reinitialize_dir $srcdir/$subdir + +if { [gdb_test "info sharedlibrary" ".*${libipa}.*" "IPA loaded"] != 0 } { + untested "Could not find IPA lib loaded" + return 1 +} + +gdb_test "break end" "" +gdb_test "break fail" "" + +gdb_test "ftrace set_point" "Fast tracepoint .*" \ + "fast tracepoint at a long insn" + +gdb_test "tstart" "" + +# If the fail function is hit, then the testcase will fail. +gdb_test "continue" ".*Breakpoint \[0-9\]+, end \(\).*" \ + "do not hit the fail function" + +gdb_test "tstop" "" + +# Reset the timeout to its previous value. +set timeout $savedtimeout