diff options
author | Pierre Langlois <pierre.langlois@arm.com> | 2015-09-21 15:01:05 +0100 |
---|---|---|
committer | Yao Qi <yao.qi@linaro.org> | 2015-09-21 15:01:05 +0100 |
commit | 06da0f77c2a447348127e072e34bf541597154a2 (patch) | |
tree | 19514d587b97f763c4fa5aaa49660b216e8c716f /gdb/testsuite/gdb.trace/ftrace-lock.c | |
parent | 4f51c22aca0d53526e65954b99d1ab3abfbb8bc8 (diff) | |
download | fsf-binutils-gdb-06da0f77c2a447348127e072e34bf541597154a2.zip fsf-binutils-gdb-06da0f77c2a447348127e072e34bf541597154a2.tar.gz fsf-binutils-gdb-06da0f77c2a447348127e072e34bf541597154a2.tar.bz2 |
Add a test case for fast tracepoints' locking mechanism
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.
Diffstat (limited to 'gdb/testsuite/gdb.trace/ftrace-lock.c')
-rw-r--r-- | gdb/testsuite/gdb.trace/ftrace-lock.c | 106 |
1 files changed, 106 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>. */ + +#include <pthread.h> + +#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; +} |