File: stress.cpp

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (102 lines) | stat: -rw-r--r-- 2,805 bytes parent folder | download | duplicates (20)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// This run stresses global reset happenning concurrently with everything else.
// RUN: %clangxx_tsan -O1 %s -o %t && %env_tsan_opts=flush_memory_ms=1:flush_symbolizer_ms=1:memory_limit_mb=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NORACE
// This run stresses race reporting happenning concurrently with everything else.
// RUN: %clangxx_tsan -O1 %s -DRACE=1 -o %t && %env_tsan_opts=suppress_equal_stacks=0 %deflake %run %t | FileCheck %s --check-prefix=CHECK-RACE
#include "test.h"
#include <fcntl.h>
#include <string.h>

volatile long stop;
long atomic, read_only, racy;
int fds[2];

__attribute__((noinline)) void *SecondaryThread(void *x) {
  __atomic_fetch_add(&atomic, 1, __ATOMIC_ACQ_REL);
  return NULL;
}

void *Thread(void *x) {
  const int me = (long)x;
  volatile long sink = 0;
  int fd = -1;
  while (!stop) {
    // If me == 0, we do all of the following,
    // otherwise only 1 type of action.
    if (me == 0 || me == 1) {
      // just read the stop variable
    }
    if (me == 0 || me == 2) {
      __atomic_store_n(&atomic, sink, __ATOMIC_RELEASE);
    }
    if (me == 0 || me == 3) {
      sink += __atomic_fetch_add(&atomic, 1, __ATOMIC_ACQ_REL);
    }
    if (me == 0 || me == 4) {
      SecondaryThread(NULL);
    }
    if (me == 0 || me == 5) {
      write(fds[1], fds, 1);
    }
    if (me == 0 || me == 6) {
      char buf[2];
      read(fds[0], &buf, sizeof(buf));
    }
    if (me == 0 || me == 7) {
      pthread_t th;
      pthread_create(&th, NULL, SecondaryThread, NULL);
      pthread_join(th, NULL);
    }
    if (me == 0 || me == 8) {
      long buf;
      memcpy(&buf, &read_only, sizeof(buf));
      sink += buf;
    }
    if (me == 0 || me == 9) {
#if RACE
      sink += racy++;
#else
      sink += racy;
#endif
    }
    if (me == 0 || me == 10) {
      fd = open("/dev/null", O_RDONLY);
      if (fd != -1) {
        close(fd);
        fd = -1;
      }
    }
    // If you add more actions, update kActions in main.
  }
  return NULL;
}

int main() {
  ANNOTATE_BENIGN_RACE(stop);
  if (pipe(fds))
    exit((perror("pipe"), 1));
  if (fcntl(fds[0], F_SETFL, O_NONBLOCK))
    exit((perror("fcntl"), 1));
  if (fcntl(fds[1], F_SETFL, O_NONBLOCK))
    exit((perror("fcntl"), 1));
  const int kActions = 11;
#if RACE
  const int kMultiplier = 1;
#else
  const int kMultiplier = 4;
#endif
  pthread_t t[kActions * kMultiplier];
  for (int i = 0; i < kActions * kMultiplier; i++)
    pthread_create(&t[i], NULL, Thread, (void *)(long)(i % kActions));
  sleep(5);
  stop = 1;
  for (int i = 0; i < kActions * kMultiplier; i++)
    pthread_join(t[i], NULL);
  fprintf(stderr, "DONE\n");
  return 0;
}

// CHECK-NORACE-NOT: ThreadSanitizer:
// CHECK-NORACE: DONE
// CHECK-NORACE-NOT: ThreadSanitizer:
// CHECK-RACE: ThreadSanitizer: data race
// CHECK-RACE: DONE