forked from OSchip/llvm-project
76 lines
3.6 KiB
C++
76 lines
3.6 KiB
C++
// Test caller-callee coverage with large number of threads
|
|
// and various numbers of callers and callees.
|
|
|
|
// RUN: %clangxx_asan -fsanitize-coverage=edge,indirect-calls %s -o %t
|
|
// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 10 1 2>&1 | FileCheck %s --check-prefix=CHECK-10-1
|
|
// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 9 2 2>&1 | FileCheck %s --check-prefix=CHECK-9-2
|
|
// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 7 3 2>&1 | FileCheck %s --check-prefix=CHECK-7-3
|
|
// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 17 1 2>&1 | FileCheck %s --check-prefix=CHECK-17-1
|
|
// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 15 2 2>&1 | FileCheck %s --check-prefix=CHECK-15-2
|
|
// RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t 18 3 2>&1 | FileCheck %s --check-prefix=CHECK-18-3
|
|
// RUN: rm -f caller-callee*.sancov
|
|
//
|
|
// REQUIRES: asan-64-bits
|
|
// UNSUPPORTED: android
|
|
//
|
|
// CHECK-10-1: CovDump: 10 caller-callee pairs written
|
|
// CHECK-9-2: CovDump: 18 caller-callee pairs written
|
|
// CHECK-7-3: CovDump: 21 caller-callee pairs written
|
|
// CHECK-17-1: CovDump: 14 caller-callee pairs written
|
|
// CHECK-15-2: CovDump: 28 caller-callee pairs written
|
|
// CHECK-18-3: CovDump: 42 caller-callee pairs written
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <pthread.h>
|
|
int P = 0;
|
|
struct Foo {virtual void f() {if (P) printf("Foo::f()\n");}};
|
|
struct Foo1 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo2 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo3 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo4 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo5 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo6 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo7 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo8 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo9 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo10 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo11 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo12 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo13 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo14 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo15 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo16 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo17 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo18 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
struct Foo19 : Foo {virtual void f() {if (P) printf("%d\n", __LINE__);}};
|
|
|
|
Foo *foo[20] = {
|
|
new Foo, new Foo1, new Foo2, new Foo3, new Foo4, new Foo5, new Foo6,
|
|
new Foo7, new Foo8, new Foo9, new Foo10, new Foo11, new Foo12, new Foo13,
|
|
new Foo14, new Foo15, new Foo16, new Foo17, new Foo18, new Foo19,
|
|
};
|
|
|
|
int n_functions = 10;
|
|
int n_callers = 2;
|
|
|
|
void *Thread(void *arg) {
|
|
if (n_callers >= 1) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
|
|
if (n_callers >= 2) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
|
|
if (n_callers >= 3) for (int i = 0; i < 2000; i++) foo[i % n_functions]->f();
|
|
return arg;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
if (argc >= 2)
|
|
n_functions = atoi(argv[1]);
|
|
if (argc >= 3)
|
|
n_callers = atoi(argv[2]);
|
|
const int kNumThreads = 16;
|
|
pthread_t t[kNumThreads];
|
|
for (int i = 0; i < kNumThreads; i++)
|
|
pthread_create(&t[i], 0, Thread, 0);
|
|
for (int i = 0; i < kNumThreads; i++)
|
|
pthread_join(t[i], 0);
|
|
}
|