1*2810ac1bSKiyoung Kim #ifndef _DEFAULT_SOURCE
2*2810ac1bSKiyoung Kim #define _DEFAULT_SOURCE
3*2810ac1bSKiyoung Kim #endif
4*2810ac1bSKiyoung Kim
5*2810ac1bSKiyoung Kim #include <pthread.h>
6*2810ac1bSKiyoung Kim #include <stdlib.h>
7*2810ac1bSKiyoung Kim #include <stdio.h>
8*2810ac1bSKiyoung Kim #include <string.h>
9*2810ac1bSKiyoung Kim #include <sys/prctl.h>
10*2810ac1bSKiyoung Kim #include <sys/psx_syscall.h>
11*2810ac1bSKiyoung Kim #include <sys/syscall.h>
12*2810ac1bSKiyoung Kim #include <sys/types.h>
13*2810ac1bSKiyoung Kim #include <sys/wait.h>
14*2810ac1bSKiyoung Kim #include <time.h>
15*2810ac1bSKiyoung Kim #include <unistd.h>
16*2810ac1bSKiyoung Kim
17*2810ac1bSKiyoung Kim typedef union tp {
18*2810ac1bSKiyoung Kim long long unsigned raw;
19*2810ac1bSKiyoung Kim pthread_t pt;
20*2810ac1bSKiyoung Kim } thread_ptr;
21*2810ac1bSKiyoung Kim
say_hello_expecting(const char * title,int n,int kept)22*2810ac1bSKiyoung Kim static void say_hello_expecting(const char *title, int n, int kept) {
23*2810ac1bSKiyoung Kim int keeper = prctl(PR_GET_KEEPCAPS);
24*2810ac1bSKiyoung Kim thread_ptr tp;
25*2810ac1bSKiyoung Kim tp.pt = pthread_self();
26*2810ac1bSKiyoung Kim
27*2810ac1bSKiyoung Kim printf("hello [%d], %s<%d> %llx (keepcaps=%d vs. want=%d)\n",
28*2810ac1bSKiyoung Kim getpid(), title, n, tp.raw, keeper, kept);
29*2810ac1bSKiyoung Kim if (keeper != kept) {
30*2810ac1bSKiyoung Kim printf("--> FAILURE %s thread=%llx has wrong keepcaps: got=%d want=%d\n",
31*2810ac1bSKiyoung Kim title, tp.raw, keeper, kept);
32*2810ac1bSKiyoung Kim exit(1);
33*2810ac1bSKiyoung Kim }
34*2810ac1bSKiyoung Kim }
35*2810ac1bSKiyoung Kim
36*2810ac1bSKiyoung Kim pthread_mutex_t mu;
37*2810ac1bSKiyoung Kim pthread_cond_t cond;
38*2810ac1bSKiyoung Kim
39*2810ac1bSKiyoung Kim int global_kept = 0;
40*2810ac1bSKiyoung Kim int step = 0;
41*2810ac1bSKiyoung Kim int replies = 0;
42*2810ac1bSKiyoung Kim int launched = 0;
43*2810ac1bSKiyoung Kim int started = 0;
44*2810ac1bSKiyoung Kim
say_hello(void * args)45*2810ac1bSKiyoung Kim static void *say_hello(void *args) {
46*2810ac1bSKiyoung Kim int count = 0;
47*2810ac1bSKiyoung Kim
48*2810ac1bSKiyoung Kim pthread_mutex_lock(&mu);
49*2810ac1bSKiyoung Kim started++;
50*2810ac1bSKiyoung Kim int this_step = step+1;
51*2810ac1bSKiyoung Kim pthread_cond_broadcast(&cond);
52*2810ac1bSKiyoung Kim pthread_mutex_unlock(&mu);
53*2810ac1bSKiyoung Kim
54*2810ac1bSKiyoung Kim pthread_mutex_lock(&mu);
55*2810ac1bSKiyoung Kim do {
56*2810ac1bSKiyoung Kim while (this_step > step) {
57*2810ac1bSKiyoung Kim pthread_cond_wait(&cond, &mu);
58*2810ac1bSKiyoung Kim }
59*2810ac1bSKiyoung Kim say_hello_expecting("thread", count, global_kept);
60*2810ac1bSKiyoung Kim
61*2810ac1bSKiyoung Kim replies++;
62*2810ac1bSKiyoung Kim pthread_cond_broadcast(&cond);
63*2810ac1bSKiyoung Kim pthread_mutex_unlock(&mu);
64*2810ac1bSKiyoung Kim
65*2810ac1bSKiyoung Kim this_step++;
66*2810ac1bSKiyoung Kim pthread_mutex_lock(&mu);
67*2810ac1bSKiyoung Kim } while (++count != 3);
68*2810ac1bSKiyoung Kim pthread_mutex_unlock(&mu);
69*2810ac1bSKiyoung Kim
70*2810ac1bSKiyoung Kim return NULL;
71*2810ac1bSKiyoung Kim }
72*2810ac1bSKiyoung Kim
main(int argc,char ** argv)73*2810ac1bSKiyoung Kim int main(int argc, char **argv) {
74*2810ac1bSKiyoung Kim pthread_t tid[3];
75*2810ac1bSKiyoung Kim int i;
76*2810ac1bSKiyoung Kim pid_t child = 0;
77*2810ac1bSKiyoung Kim char * const stop_argv[3] = { argv[0], strdup("stop"), NULL };
78*2810ac1bSKiyoung Kim
79*2810ac1bSKiyoung Kim if (argc != 1) {
80*2810ac1bSKiyoung Kim printf("child %d starting\n", getpid());
81*2810ac1bSKiyoung Kim usleep(2000);
82*2810ac1bSKiyoung Kim printf("child %d exiting\n", getpid());
83*2810ac1bSKiyoung Kim exit(0);
84*2810ac1bSKiyoung Kim }
85*2810ac1bSKiyoung Kim
86*2810ac1bSKiyoung Kim for (i = 0; i<10; i++) {
87*2810ac1bSKiyoung Kim printf("iteration [%d]: %d\n", getpid(), i);
88*2810ac1bSKiyoung Kim
89*2810ac1bSKiyoung Kim pthread_mutex_lock(&mu);
90*2810ac1bSKiyoung Kim global_kept = !global_kept;
91*2810ac1bSKiyoung Kim replies = 0;
92*2810ac1bSKiyoung Kim step = i;
93*2810ac1bSKiyoung Kim pthread_mutex_unlock(&mu);
94*2810ac1bSKiyoung Kim
95*2810ac1bSKiyoung Kim psx_syscall(SYS_prctl, PR_SET_KEEPCAPS, global_kept);
96*2810ac1bSKiyoung Kim
97*2810ac1bSKiyoung Kim pthread_mutex_lock(&mu);
98*2810ac1bSKiyoung Kim step++;
99*2810ac1bSKiyoung Kim pthread_cond_broadcast(&cond);
100*2810ac1bSKiyoung Kim pthread_mutex_unlock(&mu);
101*2810ac1bSKiyoung Kim
102*2810ac1bSKiyoung Kim say_hello_expecting("main", i, global_kept);
103*2810ac1bSKiyoung Kim
104*2810ac1bSKiyoung Kim pthread_mutex_lock(&mu);
105*2810ac1bSKiyoung Kim while (replies < launched) {
106*2810ac1bSKiyoung Kim pthread_cond_wait(&cond, &mu);
107*2810ac1bSKiyoung Kim }
108*2810ac1bSKiyoung Kim pthread_mutex_unlock(&mu);
109*2810ac1bSKiyoung Kim
110*2810ac1bSKiyoung Kim if (i < 3) {
111*2810ac1bSKiyoung Kim if (!child) {
112*2810ac1bSKiyoung Kim child = fork();
113*2810ac1bSKiyoung Kim if (!child) {
114*2810ac1bSKiyoung Kim usleep(2000);
115*2810ac1bSKiyoung Kim execve(argv[0], stop_argv, NULL);
116*2810ac1bSKiyoung Kim perror("failed to exec");
117*2810ac1bSKiyoung Kim exit(1);
118*2810ac1bSKiyoung Kim } else {
119*2810ac1bSKiyoung Kim printf("pid=%d forked -> %d\n", getpid(), child);
120*2810ac1bSKiyoung Kim }
121*2810ac1bSKiyoung Kim }
122*2810ac1bSKiyoung Kim launched++;
123*2810ac1bSKiyoung Kim pthread_create(&tid[i], NULL, say_hello, NULL);
124*2810ac1bSKiyoung Kim /* Confirm that the thread is started. */
125*2810ac1bSKiyoung Kim pthread_mutex_lock(&mu);
126*2810ac1bSKiyoung Kim while (started < launched) {
127*2810ac1bSKiyoung Kim printf("[%d] started=%d vs %d\n", getpid(), started, launched);
128*2810ac1bSKiyoung Kim pthread_cond_wait(&cond, &mu);
129*2810ac1bSKiyoung Kim }
130*2810ac1bSKiyoung Kim printf("[%d] started=%d vs %d\n", getpid(), started, launched);
131*2810ac1bSKiyoung Kim pthread_cond_broadcast(&cond);
132*2810ac1bSKiyoung Kim pthread_mutex_unlock(&mu);
133*2810ac1bSKiyoung Kim } else if (i < 6) {
134*2810ac1bSKiyoung Kim /* Confirm one thread has finished. */
135*2810ac1bSKiyoung Kim pthread_join(tid[i-3], NULL);
136*2810ac1bSKiyoung Kim launched--;
137*2810ac1bSKiyoung Kim }
138*2810ac1bSKiyoung Kim }
139*2810ac1bSKiyoung Kim
140*2810ac1bSKiyoung Kim if (child) {
141*2810ac1bSKiyoung Kim int status;
142*2810ac1bSKiyoung Kim waitpid(child, &status, 0);
143*2810ac1bSKiyoung Kim if (status) {
144*2810ac1bSKiyoung Kim printf("child %d FAILED: %d\n", child, status);
145*2810ac1bSKiyoung Kim exit(1);
146*2810ac1bSKiyoung Kim }
147*2810ac1bSKiyoung Kim }
148*2810ac1bSKiyoung Kim printf("%s PASSED\n", argv[0]);
149*2810ac1bSKiyoung Kim exit(0);
150*2810ac1bSKiyoung Kim }
151