xref: /aosp_15_r20/external/libcap/tests/psx_test.c (revision 2810ac1b38eead2603277920c78344c84ddf3aff)
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