9 #include <sys/syscall.h>
12 static int loops
= 15; // each thread+main will do this amount of loop
13 static int sleepms
= 1000; // in each loop, will sleep "sleepms" milliseconds
14 static int burn
= 0; // after each sleep, will burn cpu in a tight 'burn' loop
15 static void setup_sigusr_handler(void); // sigusr1 and 2 sigaction setup.
20 return syscall(__NR_gettid
);
25 // will be invoked from gdb.
26 static void whoami(char *msg
) __attribute__((unused
));
27 static void whoami(char *msg
)
29 fprintf(stderr
, "pid %d Thread %d %s\n", getpid(), gettid(), msg
);
34 static void do_burn ()
38 // one single line for the below, to ensure interrupt on this line.
39 for (i
= 0; i
< burn
; i
++) loopnr
++;
42 static int thread_ready
= 0;
43 static pthread_cond_t ready
= PTHREAD_COND_INITIALIZER
;
44 static pthread_mutex_t ready_mutex
= PTHREAD_MUTEX_INITIALIZER
;
45 static void signal_ready (void)
48 rc
= pthread_mutex_lock(&ready_mutex
);
50 fprintf(stderr
, "signal_ready lock error %d_n", rc
);
52 rc
= pthread_cond_signal(&ready
);
54 fprintf(stderr
, "signal_ready signal error %d_n", rc
);
55 rc
= pthread_mutex_unlock(&ready_mutex
);
57 fprintf(stderr
, "signal_ready unlock error %d_n", rc
);
66 static struct timeval t
[4];
67 static int nr_sleeper_or_burner
= 0;
68 static volatile int report_finished
= 1;
69 // set to 0 to have no finish msg (as order is non-deterministic)
70 static void *sleeper_or_burner(void *v
)
73 struct spec
* s
= (struct spec
*)v
;
75 fprintf(stderr
, "%s ready to sleep and/or burn\n", s
->name
);
78 nr_sleeper_or_burner
++;
80 for (i
= 0; i
< loops
; i
++) {
81 if (sleepms
> 0 && s
->sleep
) {
82 t
[s
->t
].tv_sec
= sleepms
/ 1000;
83 t
[s
->t
].tv_usec
= (sleepms
% 1000) * 1000;
84 ret
= select (0, NULL
, NULL
, NULL
, &t
[s
->t
]);
85 /* We only expect a timeout result from the above. */
87 perror("unexpected result from select");
89 if (burn
> 0 && s
->burn
)
92 if (report_finished
) {
93 fprintf(stderr
, "%s finished to sleep and/or burn\n", s
->name
);
99 // wait till a thread signals it is ready
100 static void wait_ready(void)
103 rc
= pthread_mutex_lock(&ready_mutex
);
105 fprintf(stderr
, "wait_ready lock error %d_n", rc
);
106 while (! thread_ready
&& rc
== 0) {
107 rc
= pthread_cond_wait(&ready
, &ready_mutex
);
109 fprintf(stderr
, "wait_ready wait error %d_n", rc
);
112 rc
= pthread_mutex_unlock(&ready_mutex
);
114 fprintf(stderr
, "wait_ready unlock error %d_n", rc
);
117 // We will lock ourselves on one single cpu.
118 // This bypasses the unfairness of the Valgrind scheduler
119 // when a multi-cpu machine has enough cpu to run all the
120 // threads wanting to burn cpu.
121 static void setaffinity(void)
124 cpu_set_t single_cpu
;
125 CPU_ZERO(&single_cpu
);
126 CPU_SET(1, &single_cpu
);
127 (void) sched_setaffinity(0, sizeof(single_cpu
), &single_cpu
);
129 // GDBTD: equivalent for Darwin ?
132 int main (int argc
, char *argv
[])
135 pthread_t ebbr
, egll
, zzzz
;
136 struct spec b
, l
, p
, m
;
137 char *some_mem
__attribute__((unused
)) = malloc(100);
139 setup_sigusr_handler();
141 loops
= atoi(argv
[1]);
144 sleepms
= atoi(argv
[2]);
147 burn
= atoll(argv
[3]);
150 threads_spec
= argv
[4];
152 threads_spec
= "BSBSBSBS";
154 fprintf(stderr
, "loops/sleep_ms/burn/threads_spec: %d %d %d %s\n",
155 loops
, sleepms
, burn
, threads_spec
);
159 b
.burn
= *threads_spec
++ == 'B';
160 b
.sleep
= *threads_spec
++ == 'S';
162 if (b
.burn
|| b
.sleep
) {
164 pthread_create(&ebbr
, NULL
, sleeper_or_burner
, &b
);
169 l
.burn
= *threads_spec
++ == 'B';
170 l
.sleep
= *threads_spec
++ == 'S';
172 if (l
.burn
|| l
.sleep
) {
174 pthread_create(&egll
, NULL
, sleeper_or_burner
, &l
);
178 p
.name
= "Petaouchnok";
179 p
.burn
= *threads_spec
++ == 'B';
180 p
.sleep
= *threads_spec
++ == 'S';
182 if (p
.burn
|| p
.sleep
) {
184 pthread_create(&zzzz
, NULL
, sleeper_or_burner
, &p
);
189 m
.burn
= *threads_spec
++ == 'B';
190 m
.sleep
= *threads_spec
++ == 'S';
192 sleeper_or_burner(&m
);
194 if (b
.t
!= -1) pthread_join(ebbr
, NULL
);
195 if (l
.t
!= -1) pthread_join(egll
, NULL
);
196 if (p
.t
!= -1) pthread_join(zzzz
, NULL
);
201 static int sigusr1_received
= 0;
202 static void sigusr1_handler(int signr
)
206 static void setup_sigusr_handler(void)
209 sa
.sa_handler
= sigusr1_handler
;
210 sigemptyset(&sa
.sa_mask
);
213 if (sigaction (SIGUSR1
, &sa
, NULL
) != 0)
214 perror("sigaction SIGUSR1");
216 sa
.sa_handler
= SIG_IGN
;
217 if (sigaction (SIGUSR2
, &sa
, NULL
) != 0)
218 perror("sigaction SIGUSR2");