2007-06-25 Jan Kratochvil * gdb.threads/atomic-seq-threaded.c, gdb.threads/atomic-seq-threaded.exp: New files. Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/atomic-seq-threaded.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/atomic-seq-threaded.c 2008-12-08 22:27:01.000000000 +0100 @@ -0,0 +1,171 @@ +/* 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 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., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/* Test stepping over RISC atomic sequences. + This variant testcases the code for stepping another thread while skipping + over the atomic sequence in the former thread + (STEPPING_PAST_SINGLESTEP_BREAKPOINT). + Code comes from gcc/testsuite/gcc.dg/sync-2.c */ + +/* { dg-options "-march=i486" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */ +/* { dg-options "-mcpu=v9" { target sparc*-*-* } } */ + +/* Test functionality of the intrinsics for 'short' and 'char'. */ + +#include +#include +#include +#include +#include + +#define LOOPS 2 + +static int unused; + +static char AI[18]; +static char init_qi[18] = { 3,5,7,9,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0 }; +static char test_qi[18] = { 3,5,7,9,1,4,22,-12,7,8,9,7,1,-12,7,8,9,7 }; + +static void +do_qi (void) +{ + if (__sync_fetch_and_add(AI+4, 1) != 0) + abort (); + if (__sync_fetch_and_add(AI+5, 4) != 0) + abort (); + if (__sync_fetch_and_add(AI+6, 22) != 0) + abort (); + if (__sync_fetch_and_sub(AI+7, 12) != 0) + abort (); + if (__sync_fetch_and_and(AI+8, 7) != (char)-1) + abort (); + if (__sync_fetch_and_or(AI+9, 8) != 0) + abort (); + if (__sync_fetch_and_xor(AI+10, 9) != 0) + abort (); + if (__sync_fetch_and_nand(AI+11, 7) != 0) + abort (); + + if (__sync_add_and_fetch(AI+12, 1) != 1) + abort (); + if (__sync_sub_and_fetch(AI+13, 12) != (char)-12) + abort (); + if (__sync_and_and_fetch(AI+14, 7) != 7) + abort (); + if (__sync_or_and_fetch(AI+15, 8) != 8) + abort (); + if (__sync_xor_and_fetch(AI+16, 9) != 9) + abort (); + if (__sync_nand_and_fetch(AI+17, 7) != 7) + abort (); +} + +static short AL[18]; +static short init_hi[18] = { 3,5,7,9,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0 }; +static short test_hi[18] = { 3,5,7,9,1,4,22,-12,7,8,9,7,1,-12,7,8,9,7 }; + +static void +do_hi (void) +{ + if (__sync_fetch_and_add(AL+4, 1) != 0) + abort (); + if (__sync_fetch_and_add(AL+5, 4) != 0) + abort (); + if (__sync_fetch_and_add(AL+6, 22) != 0) + abort (); + if (__sync_fetch_and_sub(AL+7, 12) != 0) + abort (); + if (__sync_fetch_and_and(AL+8, 7) != -1) + abort (); + if (__sync_fetch_and_or(AL+9, 8) != 0) + abort (); + if (__sync_fetch_and_xor(AL+10, 9) != 0) + abort (); + if (__sync_fetch_and_nand(AL+11, 7) != 0) + abort (); + + if (__sync_add_and_fetch(AL+12, 1) != 1) + abort (); + if (__sync_sub_and_fetch(AL+13, 12) != -12) + abort (); + if (__sync_and_and_fetch(AL+14, 7) != 7) + abort (); + if (__sync_or_and_fetch(AL+15, 8) != 8) + abort (); + if (__sync_xor_and_fetch(AL+16, 9) != 9) + abort (); + if (__sync_nand_and_fetch(AL+17, 7) != 7) + abort (); +} + +static void * +start1 (void *arg) +{ + unsigned loop; + sleep(1); + + for (loop = 0; loop < LOOPS; loop++) + { + memcpy(AI, init_qi, sizeof(init_qi)); + + do_qi (); + + if (memcmp (AI, test_qi, sizeof(test_qi))) + abort (); + } + + return arg; /* _delete1_ */ +} + +static void * +start2 (void *arg) +{ + unsigned loop; + + for (loop = 0; loop < LOOPS; loop++) + { + memcpy(AL, init_hi, sizeof(init_hi)); + + do_hi (); + + if (memcmp (AL, test_hi, sizeof(test_hi))) + abort (); + } + + return arg; /* _delete2_ */ +} + +int +main (int argc, char **argv) +{ + pthread_t thread; + int i; + + i = pthread_create (&thread, NULL, start1, NULL); /* _create_ */ + assert (i == 0); /* _create_after_ */ + + sleep (1); + + start2 (NULL); + + i = pthread_join (thread, NULL); /* _delete_ */ + assert (i == 0); + + return 0; /* _exit_ */ +} Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/atomic-seq-threaded.exp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gdb-6.8.50.20081128/gdb/testsuite/gdb.threads/atomic-seq-threaded.exp 2008-12-08 22:31:01.000000000 +0100 @@ -0,0 +1,84 @@ +# atomic-seq-threaded.exp -- Test case for stepping over RISC atomic code seqs. +# This variant testcases the code for stepping another thread while skipping +# over the atomic sequence in the former thread +# (STEPPING_PAST_SINGLESTEP_BREAKPOINT). +# Copyright (C) 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. */ + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@prep.ai.mit.edu + +set testfile atomic-seq-threaded +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +foreach opts {{} {compiler=gcc4} {FAIL}} { + if {$opts eq "FAIL"} { + return -1 + } + if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug $opts]] eq "" } { + break + } +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir + +gdb_load ${binfile} +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +# pthread_create () will not pass even on x86_64 with software watchpoint. +# Pass after pthread_create () without any watchpoint active. +set line [gdb_get_line_number "_create_after_"] +gdb_test "tbreak $line" \ + "reakpoint (\[0-9\]+) at .*$srcfile, line $line\..*" \ + "set breakpoint after pthread_create ()" +gdb_test "c" \ + ".*/\\* _create_after_ \\*/.*" \ + "run till after pthread_create ()" + +# Without a watchpoint being software no single-stepping would be used. +set test "Start (software) watchpoint" +gdb_test_multiple "watch unused" $test { + -re "Watchpoint \[0-9\]+: unused.*$gdb_prompt $" { + pass $test + } + -re "Hardware watchpoint \[0-9\]+: unused.*$gdb_prompt $" { + # We do not test the goal but still the whole testcase should pass. + unsupported $test + } +} + +# More thorough testing of the scheduling logic. +gdb_test "set scheduler-locking step" "" + +# Critical code path is stepped through at this point. +set line [gdb_get_line_number "_exit_"] +gdb_test "tbreak $line" \ + "reakpoint \[0-9\]+ at .*$srcfile, line $line\..*" \ + "set breakpoint at _exit_" +gdb_test "c" \ + ".*/\\* _exit_ \\*/.*" \ + "run till _exit_" + +# Just a nonproblematic program exit. +gdb_test "c" \ + ".*Program exited normally\\..*" \ + "run till program exit"