atomic_stack.c: New test.

2013-12-05  Max Ostapenko  <m.ostapenko@partner.samsung.com>

	* c-c++-common/tsan/atomic_stack.c: New test.
	* c-c++-common/tsan/fd_pipe_race.c: New test.
	* c-c++-common/tsan/free_race.c: New test.
	* c-c++-common/tsan/mutexset1.c: New test.
	* c-c++-common/tsan/race_on_barrier.c: New test.
	* c-c++-common/tsan/sleep_sync.c: New test.
	* c-c++-common/tsan/thread_leak.c: New test.
	* c-c++-common/tsan/thread_leak1.c: New test.
	* c-c++-common/tsan/thread_leak2.c: New test.
	* c-c++-common/tsan/tiny_race.c: New test.
	* c-c++-common/tsan/tls_race.c: New test.
	* c-c++-common/tsan/write_in_reader_lock.c: New test.	
	* lib/tsan-dg.exp: New file.
	* gcc.dg/tsan/tsan.exp: New file.
	* g++.dg/tsan/tsan.exp: New file.
	* g++.dg/dg.exp: Prune tsan subdirectory.

From-SVN: r205704
This commit is contained in:
Max Ostapenko 2013-12-05 13:35:09 +02:00 committed by Yury Gribov
parent 9bbd48d120
commit 8582650466
17 changed files with 557 additions and 0 deletions

View File

@ -1,3 +1,22 @@
2013-12-05 Max Ostapenko <m.ostapenko@partner.samsung.com>
* c-c++-common/tsan/atomic_stack.c: New test.
* c-c++-common/tsan/fd_pipe_race.c: New test.
* c-c++-common/tsan/free_race.c: New test.
* c-c++-common/tsan/mutexset1.c: New test.
* c-c++-common/tsan/race_on_barrier.c: New test.
* c-c++-common/tsan/sleep_sync.c: New test.
* c-c++-common/tsan/thread_leak.c: New test.
* c-c++-common/tsan/thread_leak1.c: New test.
* c-c++-common/tsan/thread_leak2.c: New test.
* c-c++-common/tsan/tiny_race.c: New test.
* c-c++-common/tsan/tls_race.c: New test.
* c-c++-common/tsan/write_in_reader_lock.c: New test.
* lib/tsan-dg.exp: New file.
* gcc.dg/tsan/tsan.exp: New file.
* g++.dg/tsan/tsan.exp: New file.
* g++.dg/dg.exp: Prune tsan subdirectory.
2013-12-05 Kirill Yukhin <kirill.yukhin@intel.com>
* gcc.target/i386/readeflags-1.c: New.

View File

@ -0,0 +1,32 @@
/* { dg-do run } */
/* { dg-shouldfail "tsan" } */
#include <pthread.h>
#include <unistd.h>
int Global;
void *Thread1(void *x) {
sleep(1);
__atomic_fetch_add(&Global, 1, __ATOMIC_RELAXED);
return NULL;
}
void *Thread2(void *x) {
Global++;
return NULL;
}
int main() {
pthread_t t[2];
pthread_create(&t[0], NULL, Thread1, NULL);
pthread_create(&t[1], NULL, Thread2, NULL);
pthread_join(t[0], NULL);
pthread_join(t[1], NULL);
return 0;
}
/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */
/* { dg-output " Atomic write of size 4.*" } */
/* { dg-output " #0 __tsan_atomic32_fetch_add.*" } */
/* { dg-output " #1 Thread1.*" } */

View File

@ -0,0 +1,37 @@
/* { dg-do run } */
/* { dg-shouldfail "tsan" } */
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
int fds[2];
void *Thread1(void *x) {
write(fds[1], "a", 1);
return NULL;
}
void *Thread2(void *x) {
sleep(1);
close(fds[0]);
close(fds[1]);
return NULL;
}
int main() {
pipe(fds);
pthread_t t[2];
pthread_create(&t[0], NULL, Thread1, NULL);
pthread_create(&t[1], NULL, Thread2, NULL);
pthread_join(t[0], NULL);
pthread_join(t[1], NULL);
}
/* { dg-output "WARNING: ThreadSanitizer: data race.*\n" } */
/* { dg-output " Write of size 8.*\n" } */
/* { dg-output " #0 close.*\n" } */
/* { dg-output " #1 Thread2.*\n" } */
/* { dg-output " Previous read of size 8.*\n" } */
/* { dg-output " #0 write.*\n" } */
/* { dg-output " #1 Thread1.*\n" } */

View File

@ -0,0 +1,28 @@
/* { dg-do run } */
/* { dg-shouldfail "tsan" } */
#include <stdlib.h>
void __attribute__((noinline)) foo(int *mem) {
free(mem);
}
void __attribute__((noinline)) bar(int *mem) {
mem[0] = 42;
}
int main() {
int *mem =(int*)malloc (100);
foo(mem);
bar(mem);
return 0;
}
/* { dg-output "WARNING: ThreadSanitizer: heap-use-after-free.*(\n|\r\n|\r)" } */
/* { dg-output " Write of size 4 at.* by main thread:(\n|\r\n|\r)" } */
/* { dg-output " #0 bar.*(\n|\r\n|\r)" } */
/* { dg-output " #1 main.*(\n|\r\n|\r)" } */
/* { dg-output " Previous write of size 8 at.* by main thread:(\n|\r\n|\r)" } */
/* { dg-output " #0 free.*(\n|\r\n|\r)" } */
/* { dg-output " #\(1|2\) foo.*(\n|\r\n|\r)" } */
/* { dg-output " #\(2|3\) main.*(\n|\r\n|\r)" } */

View File

@ -0,0 +1,41 @@
/* { dg-do run } */
/* { dg-shouldfail "tsan" } */
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
int Global;
pthread_mutex_t mtx;
void *Thread1(void *x) {
sleep(1);
pthread_mutex_lock(&mtx);
Global++;
pthread_mutex_unlock(&mtx);
return NULL;
}
void *Thread2(void *x) {
Global--;
return NULL;/* { dg-output ".*" } */
}
int main() {
pthread_mutex_init(&mtx, 0);
pthread_t t[2];
pthread_create(&t[0], NULL, Thread1, NULL);
pthread_create(&t[1], NULL, Thread2, NULL);
pthread_join(t[0], NULL);
pthread_join(t[1], NULL);
pthread_mutex_destroy(&mtx);
return 0;
}
/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */
/* { dg-output " Read of size 4 at 0x\[0-9a-f\]+ by thread T1 \\(mutexes: write M\[0-9\]\\):.*" } */
/* { dg-output " Previous write of size 4 at 0x\[0-9a-f\]+ by thread T2:.*" } */
/* { dg-output " Mutex M\[0-9\] created at:.*" } */
/* { dg-output " #0 pthread_mutex_init.*" } */
/* { dg-output " #1 main (.*mutexset1.c|\\?{2}):\[0-9]+.*" } */

View File

@ -0,0 +1,33 @@
/* { dg-do run } */
/* { dg-shouldfail "tsan" } */
#include <pthread.h>
#include <stdio.h>
#include <stddef.h>
#include <unistd.h>
pthread_barrier_t B;
int Global;
void *Thread1(void *x) {
pthread_barrier_init(&B, 0, 2);
pthread_barrier_wait(&B);
return NULL;
}
void *Thread2(void *x) {
sleep(1);
pthread_barrier_wait(&B);
return NULL;
}
int main() {
pthread_t t;
pthread_create(&t, NULL, Thread1, NULL);
Thread2(0);
pthread_join(t, NULL);
pthread_barrier_destroy(&B);
return 0;
}
/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */

View File

@ -0,0 +1,31 @@
/* { dg-do run } */
/* { dg-shouldfail "tsan" } */
#include <pthread.h>
#include <unistd.h>
int X = 0;
void MySleep() {
sleep(1);
}
void *Thread(void *p) {
MySleep(); // Assume the main thread has done the write.
X = 42;
return 0;
}
int main() {
pthread_t t;
pthread_create(&t, 0, Thread, 0);
X = 43;
pthread_join(t, 0);
return 0;
}
/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r).*} */
/* { dg-output " As if synchronized via sleep:(\n|\r\n|\r)} */
/* { dg-output " #0 sleep.*"*} */
/* { dg-output " #1 MySleep.*"*} */
/* { dg-output " #2 Thread.*"*} */

View File

@ -0,0 +1,18 @@
/* { dg-do run } */
#include <pthread.h>
#include <stdio.h>
void *Thread(void *x) {
return 0;
}
int main() {
pthread_t t;
pthread_create(&t, 0, Thread, 0);
pthread_join(t, 0);
printf("PASS\n");
return 0;
}
/* { dg-prune-output "WARNING: ThreadSanitizer: thread leak.*" } */

View File

@ -0,0 +1,19 @@
/* { dg-do run } */
/* { dg-shouldfail "tsan" } */
#include <pthread.h>
#include <unistd.h>
void *Thread(void *x) {
return 0;
}
int main() {
pthread_t t;
pthread_create(&t, 0, Thread, 0);
sleep(1);
return 0;
}
/* { dg-output "WARNING: ThreadSanitizer: thread leak.*(\n|\r\n|\r)" } */
/* { dg-output "SUMMARY: ThreadSanitizer: thread leak.*main.*(\n|\r\n|\r)" } */

View File

@ -0,0 +1,23 @@
/* { dg-do run } */
/* { dg-shouldfail "tsan" } */
/* { dg-skip-if "" { *-*-* } { "-O3 -funroll-loops" "-O3 -funroll-all-loops" } { "" } } */
#include <pthread.h>
#include <unistd.h>
void *Thread(void *x) {
return 0;
}
int main() {
int i;
for (i = 0; i < 5; i++) {
pthread_t t;
pthread_create(&t, 0, Thread, 0);
}
sleep(1);
return 0;
}
/* { dg-output "WARNING: ThreadSanitizer: thread leak.*(\n|\r\n|\r)" } */
/* { dg-output " And 4 more similar thread leaks.*" } */

View File

@ -0,0 +1,23 @@
/* { dg-do run } */
/* { dg-shouldfail "tsan" } */
#include <pthread.h>
#include <unistd.h>
int Global;
void *Thread1(void *x) {
sleep(1);
Global = 42;
return x;
}
int main() {
pthread_t t;
pthread_create(&t, 0, Thread1, 0);
Global = 43;
pthread_join(t, 0);
return Global;
}
/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */

View File

@ -0,0 +1,21 @@
/* { dg-do run } */
/* { dg-shouldfail "tsan" } */
#include <pthread.h>
#include <stddef.h>
void *Thread(void *a) {
*(int*)a = 43;
return 0;
}
int main() {
static __thread int Var = 42;
pthread_t t;
pthread_create(&t, 0, Thread, &Var);
Var = 43;
pthread_join(t, 0);
}
/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r).*" } */
/* { dg-output " Location is TLS of main thread.(\n|\r\n|\r).*" } */

View File

@ -0,0 +1,37 @@
/* { dg-do run } */
/* { dg-shouldfail "tsan" } */
#include <pthread.h>
#include <unistd.h>
pthread_rwlock_t rwlock;
int GLOB;
void *Thread1(void *p) {
(void)p;
pthread_rwlock_rdlock(&rwlock);
// Write under reader lock.
sleep(1);
GLOB++;
pthread_rwlock_unlock(&rwlock);
return 0;
}
int main(int argc, char *argv[]) {
pthread_rwlock_init(&rwlock, NULL);
pthread_rwlock_rdlock(&rwlock);
pthread_t t;
pthread_create(&t, 0, Thread1, 0);
volatile int x = GLOB;
(void)x;
pthread_rwlock_unlock(&rwlock);
pthread_join(t, 0);
pthread_rwlock_destroy(&rwlock);
return 0;
}
/* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */
/* { dg-output " Write of size 4 at 0x\[0-9a-f\]+ by thread T1.*:(\n|\r\n|\r).*" } */
/* { dg-output " #0 Thread1.*\(write_in_reader_lock.c|\\?{2}\):\[0-9\]+ .*" } */
/* { dg-output " Previous read of size 4 at.* by main thread.*:(\n|\r\n|\r).*" } */
/* { dg-output " #0 main.*\(write_in_reader_lock.c|\\?{2}\):\[0-9\]+.*" } */

View File

@ -54,6 +54,7 @@ set tests [prune $tests $srcdir/$subdir/guality/*]
set tests [prune $tests $srcdir/$subdir/simulate-thread/*]
set tests [prune $tests $srcdir/$subdir/asan/*]
set tests [prune $tests $srcdir/$subdir/ubsan/*]
set tests [prune $tests $srcdir/$subdir/tsan/*]
# Main loop.
g++-dg-runtest $tests $DEFAULT_CXXFLAGS

View File

@ -0,0 +1,40 @@
# Copyright (C) 2013 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
# GCC 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, or (at your option)
# any later version.
#
# GCC 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 GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
# GCC testsuite that uses the `dg.exp' driver.
# Load support procs.
load_lib g++-dg.exp
load_lib tsan-dg.exp
if ![check_effective_target_fthread_sanitizer] {
return
}
# Initialize `dg'.
dg-init
if [tsan_init] {
# Main loop.
gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c $srcdir/c-c++-common/tsan/*.c]] ""
}
# All done.
tsan_finish
dg-finish

View File

@ -0,0 +1,40 @@
# Copyright (C) 2013 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
# GCC 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, or (at your option)
# any later version.
#
# GCC 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 GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
# GCC testsuite that uses the `dg.exp' driver.
# Load support procs.
load_lib gcc-dg.exp
load_lib tsan-dg.exp
if ![check_effective_target_fthread_sanitizer] {
return
}
# Initialize `dg'.
dg-init
if [tsan_init] {
# Main loop.
gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c $srcdir/c-c++-common/tsan/*.c]] ""
}
# All done.
tsan_finish
dg-finish

View File

@ -0,0 +1,114 @@
# Copyright (C) 2013 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 GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
# Return 1 if compilation with -fsanitize=thread is error-free for trivial
# code, 0 otherwise.
proc check_effective_target_fthread_sanitizer {} {
return [check_no_compiler_messages faddress_sanitizer object {
void foo (void) { }
} "-fPIE -pie -fsanitize=thread"]
}
#
# tsan_link_flags -- compute library path and flags to find libtsan.
# (originally from g++.exp)
#
proc tsan_link_flags { paths } {
global srcdir
global ld_library_path
global shlib_ext
set gccpath ${paths}
set flags ""
set shlib_ext [get_shlib_extension]
if { $gccpath != "" } {
if { [file exists "${gccpath}/libsanitizer/tsan/.libs/libtsan.a"]
|| [file exists "${gccpath}/libsanitizer/tsan/.libs/libtsan.${shlib_ext}"] } {
append flags " -B${gccpath}/libsanitizer/tsan/ "
append flags " -L${gccpath}/libsanitizer/tsan/.libs "
append ld_library_path ":${gccpath}/libsanitizer/tsan/.libs"
}
} else {
global tool_root_dir
set libtsan [lookfor_file ${tool_root_dir} libtsan]
if { $libtsan != "" } {
append flags "-L${libtsan} "
append ld_library_path ":${libtsan}"
}
}
set_ld_library_path_env_vars
return "$flags"
}
#
# tsan_init -- called at the start of each subdir of tests
#
proc tsan_init { args } {
global TEST_ALWAYS_FLAGS
global ALWAYS_CXXFLAGS
global TOOL_OPTIONS
global tsan_saved_TEST_ALWAYS_FLAGS
set link_flags ""
if ![is_remote host] {
if [info exists TOOL_OPTIONS] {
set link_flags "[tsan_link_flags [get_multilibs ${TOOL_OPTIONS}]]"
} else {
set link_flags "[tsan_link_flags [get_multilibs]]"
}
}
if [info exists TEST_ALWAYS_FLAGS] {
set tsan_saved_TEST_ALWAYS_FLAGS $TEST_ALWAYS_FLAGS
}
if [info exists ALWAYS_CXXFLAGS] {
set ALWAYS_CXXFLAGS [concat "{ldflags=$link_flags}" $ALWAYS_CXXFLAGS]
set ALWAYS_CXXFLAGS [concat "{additional_flags=-fPIE -pie -fsanitize=thread -g}" $ALWAYS_CXXFLAGS]
} else {
if [info exists TEST_ALWAYS_FLAGS] {
set TEST_ALWAYS_FLAGS "$link_flags -fPIE -pie -fsanitize=thread -g $TEST_ALWAYS_FLAGS"
} else {
set TEST_ALWAYS_FLAGS "$link_flags -fPIE -pie -fsanitize=thread -g"
}
}
if { $link_flags != "" } {
return 1
}
return 0
}
#
# tsan_finish -- called at the start of each subdir of tests
#
proc tsan_finish { args } {
global TEST_ALWAYS_FLAGS
global tsan_saved_TEST_ALWAYS_FLAGS
if [info exists tsan_saved_TEST_ALWAYS_FLAGS] {
set TEST_ALWAYS_FLAGS $tsan_saved_TEST_ALWAYS_FLAGS
} else {
unset TEST_ALWAYS_FLAGS
}
}