10 #include <sys/syscall.h>
13 static int loops
= 15; // each thread+main will do this amount of loop
14 static int sleepms
= 1000; // in each loop, will sleep "sleepms" milliseconds
15 static int burn
= 0; // after each sleep, will burn cpu in a tight 'burn' loop
16 static void setup_sigusr_handler(void); // sigusr1 and 2 sigaction setup.
18 static pid_t
gettid_sys()
21 return syscall(__NR_gettid
);
26 // will be invoked from gdb.
27 void whoami(char *msg
)
29 fprintf(stderr
, "pid %ld Thread %ld %s\n", (long) getpid(), (long) gettid_sys(),
35 static void do_burn ()
39 // one single line for the below, to ensure interrupt on this line.
40 for (i
= 0; i
< burn
; i
++) loopnr
++;
43 static int thread_ready
= 0;
44 static pthread_cond_t ready
= PTHREAD_COND_INITIALIZER
;
45 static pthread_mutex_t ready_mutex
= PTHREAD_MUTEX_INITIALIZER
;
46 static void signal_ready (void)
49 rc
= pthread_mutex_lock(&ready_mutex
);
51 fprintf(stderr
, "signal_ready lock error %d_n", rc
);
53 rc
= pthread_cond_signal(&ready
);
55 fprintf(stderr
, "signal_ready signal error %d_n", rc
);
56 rc
= pthread_mutex_unlock(&ready_mutex
);
58 fprintf(stderr
, "signal_ready unlock error %d_n", rc
);
67 static struct timeval t
[4];
68 static int nr_sleeper_or_burner
= 0;
69 static volatile int report_finished
= 1;
70 // set to 0 to have no finish msg (as order is non-deterministic)
71 static void *sleeper_or_burner(void *v
)
74 struct spec
* s
= (struct spec
*)v
;
76 fprintf(stderr
, "%s ready to sleep and/or burn\n", s
->name
);
79 nr_sleeper_or_burner
++;
81 for (i
= 0; i
< loops
; i
++) {
82 if (sleepms
> 0 && s
->sleep
) {
83 t
[s
->t
].tv_sec
= sleepms
/ 1000;
84 t
[s
->t
].tv_usec
= (sleepms
% 1000) * 1000;
85 ret
= select (0, NULL
, NULL
, NULL
, &t
[s
->t
]);
86 /* We only expect a timeout result or EINTR from the above. */
87 if (ret
!= 0 && errno
!= EINTR
)
88 perror("unexpected result from select");
90 if (burn
> 0 && s
->burn
)
93 if (report_finished
) {
94 fprintf(stderr
, "%s finished to sleep and/or burn\n", s
->name
);
100 // wait till a thread signals it is ready
101 static void wait_ready(void)
104 rc
= pthread_mutex_lock(&ready_mutex
);
106 fprintf(stderr
, "wait_ready lock error %d_n", rc
);
107 while (! thread_ready
&& rc
== 0) {
108 rc
= pthread_cond_wait(&ready
, &ready_mutex
);
110 fprintf(stderr
, "wait_ready wait error %d_n", rc
);
113 rc
= pthread_mutex_unlock(&ready_mutex
);
115 fprintf(stderr
, "wait_ready unlock error %d_n", rc
);
118 // We will lock ourselves on one single cpu.
119 // This bypasses the unfairness of the Valgrind scheduler
120 // when a multi-cpu machine has enough cpu to run all the
121 // threads wanting to burn cpu.
122 static void setaffinity(void)
125 cpu_set_t single_cpu
;
126 CPU_ZERO(&single_cpu
);
127 CPU_SET(1, &single_cpu
);
128 (void) sched_setaffinity(0, sizeof(single_cpu
), &single_cpu
);
130 // GDBTD: equivalent for Darwin ?
133 int main (int argc
, char *argv
[])
136 pthread_t ebbr
, egll
, zzzz
;
137 struct spec b
, l
, p
, m
;
138 char *some_mem
__attribute__((unused
)) = malloc(100);
139 if (argc
> 5 && atoi(argv
[5])) setaffinity();
140 setup_sigusr_handler();
142 loops
= atoi(argv
[1]);
145 sleepms
= atoi(argv
[2]);
148 burn
= atoll(argv
[3]);
151 threads_spec
= argv
[4];
153 threads_spec
= "BSBSBSBS";
155 fprintf(stderr
, "loops/sleep_ms/burn/threads_spec/affinity: %d %d %d %s %d\n",
156 loops
, sleepms
, burn
, threads_spec
, argc
> 5 && atoi(argv
[5]));
160 b
.burn
= *threads_spec
++ == 'B';
161 b
.sleep
= *threads_spec
++ == 'S';
163 if (b
.burn
|| b
.sleep
) {
165 pthread_create(&ebbr
, NULL
, sleeper_or_burner
, &b
);
170 l
.burn
= *threads_spec
++ == 'B';
171 l
.sleep
= *threads_spec
++ == 'S';
173 if (l
.burn
|| l
.sleep
) {
175 pthread_create(&egll
, NULL
, sleeper_or_burner
, &l
);
179 p
.name
= "Petaouchnok";
180 p
.burn
= *threads_spec
++ == 'B';
181 p
.sleep
= *threads_spec
++ == 'S';
183 if (p
.burn
|| p
.sleep
) {
185 pthread_create(&zzzz
, NULL
, sleeper_or_burner
, &p
);
190 m
.burn
= *threads_spec
++ == 'B';
191 m
.sleep
= *threads_spec
++ == 'S';
193 sleeper_or_burner(&m
);
195 if (b
.t
!= -1) pthread_join(ebbr
, NULL
);
196 if (l
.t
!= -1) pthread_join(egll
, NULL
);
197 if (p
.t
!= -1) pthread_join(zzzz
, NULL
);
202 static int sigusr1_received
= 0;
203 static void sigusr1_handler(int signr
)
207 static void setup_sigusr_handler(void)
210 sa
.sa_handler
= sigusr1_handler
;
211 sigemptyset(&sa
.sa_mask
);
214 if (sigaction (SIGUSR1
, &sa
, NULL
) != 0)
215 perror("sigaction SIGUSR1");
217 sa
.sa_handler
= SIG_IGN
;
218 if (sigaction (SIGUSR2
, &sa
, NULL
) != 0)
219 perror("sigaction SIGUSR2");