• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2019 Linaro Limited. All rights reserved.
4  * Author: Sumit Garg <sumit.garg@linaro.org>
5  */
6 
7 /*
8  * Test rt_tgsigqueueinfo
9  *
10  * This tests the rt_tgsigqueueinfo() syscall. It sends the signal and data
11  * to the single thread specified by the combination of tgid, a thread group
12  * ID, and tid, a thread in that thread group.
13  *
14  * Also this implement 3 tests differing on the basis of signal sender:
15  * - Sender and receiver is the same thread.
16  * - Sender is parent of the thread.
17  * - Sender is different thread.
18  */
19 
20 #define _GNU_SOURCE
21 
22 #include <err.h>
23 #include <pthread.h>
24 #include "tst_safe_pthread.h"
25 #include "tst_test.h"
26 #include "lapi/syscalls.h"
27 
28 #ifndef ANDROID
29 #define SI_SIGVAL si_sigval
30 #else
31 #define SI_SIGVAL _sigval
32 #endif
33 
34 static char sigval_send[] = "rt_tgsigqueueinfo data";
35 static volatile int signum_rcv;
36 static char *sigval_rcv;
37 
sigusr1_handler(int signum,siginfo_t * uinfo,void * p LTP_ATTRIBUTE_UNUSED)38 static void sigusr1_handler(int signum, siginfo_t *uinfo,
39 			    void *p LTP_ATTRIBUTE_UNUSED)
40 {
41 	signum_rcv = signum;
42 	sigval_rcv = uinfo->_sifields._rt.SI_SIGVAL.sival_ptr;
43 }
44 
send_rcv_func(void * arg)45 void *send_rcv_func(void *arg)
46 {
47 	siginfo_t uinfo;
48 
49 	signum_rcv = 0;
50 	sigval_rcv = NULL;
51 
52 	uinfo.si_errno = 0;
53 	uinfo.si_code = SI_QUEUE;
54 	uinfo._sifields._rt.SI_SIGVAL.sival_ptr = sigval_send;
55 
56 	TEST(tst_syscall(__NR_rt_tgsigqueueinfo, getpid(),
57 			 syscall(__NR_gettid), SIGUSR1, &uinfo));
58 	if (TST_RET)
59 		tst_brk(TFAIL | TTERRNO, "rt_tgsigqueueinfo failed");
60 
61 	while (!signum_rcv)
62 		usleep(1000);
63 
64 	if ((signum_rcv == SIGUSR1) && (sigval_rcv == sigval_send))
65 		tst_res(TPASS, "Test signal to self succeeded");
66 	else
67 		tst_res(TFAIL, "Failed to deliver signal/data to self thread");
68 
69 	return arg;
70 }
71 
verify_signal_self(void)72 static void verify_signal_self(void)
73 {
74 	pthread_t pt;
75 
76 	SAFE_PTHREAD_CREATE(&pt, NULL, send_rcv_func, NULL);
77 
78 	SAFE_PTHREAD_JOIN(pt, NULL);
79 }
80 
receiver_func(void * arg)81 void *receiver_func(void *arg)
82 {
83 	pid_t *tid = arg;
84 
85 	*tid = syscall(__NR_gettid);
86 
87 	signum_rcv = 0;
88 	sigval_rcv = NULL;
89 
90 	TST_CHECKPOINT_WAKE(0);
91 
92 	while (!signum_rcv)
93 		usleep(1000);
94 
95 	if ((signum_rcv == SIGUSR1) && (sigval_rcv == sigval_send))
96 		tst_res(TPASS, "Test signal to different thread succeeded");
97 	else
98 		tst_res(TFAIL,
99 			"Failed to deliver signal/data to different thread");
100 
101 	return NULL;
102 }
103 
verify_signal_parent_thread(void)104 static void verify_signal_parent_thread(void)
105 {
106 	pid_t tid = -1;
107 	pthread_t pt;
108 	siginfo_t uinfo;
109 
110 	SAFE_PTHREAD_CREATE(&pt, NULL, receiver_func, &tid);
111 
112 	TST_CHECKPOINT_WAIT(0);
113 
114 	uinfo.si_errno = 0;
115 	uinfo.si_code = SI_QUEUE;
116 	uinfo._sifields._rt.SI_SIGVAL.sival_ptr = sigval_send;
117 
118 	TEST(tst_syscall(__NR_rt_tgsigqueueinfo, getpid(),
119 			 tid, SIGUSR1, &uinfo));
120 	if (TST_RET)
121 		tst_brk(TFAIL | TTERRNO, "rt_tgsigqueueinfo failed");
122 
123 	SAFE_PTHREAD_JOIN(pt, NULL);
124 }
125 
sender_func(void * arg)126 void *sender_func(void *arg)
127 {
128 	pid_t *tid = arg;
129 	siginfo_t uinfo;
130 
131 	uinfo.si_errno = 0;
132 	uinfo.si_code = SI_QUEUE;
133 	uinfo._sifields._rt.SI_SIGVAL.sival_ptr = sigval_send;
134 
135 	TEST(tst_syscall(__NR_rt_tgsigqueueinfo, getpid(),
136 			 *tid, SIGUSR1, &uinfo));
137 	if (TST_RET)
138 		tst_brk(TFAIL | TTERRNO, "rt_tgsigqueueinfo failed");
139 
140 	return NULL;
141 }
142 
verify_signal_inter_thread(void)143 static void verify_signal_inter_thread(void)
144 {
145 	pid_t tid = -1;
146 	pthread_t pt1, pt2;
147 
148 	SAFE_PTHREAD_CREATE(&pt1, NULL, receiver_func, &tid);
149 
150 	TST_CHECKPOINT_WAIT(0);
151 
152 	SAFE_PTHREAD_CREATE(&pt2, NULL, sender_func, &tid);
153 
154 	SAFE_PTHREAD_JOIN(pt2, NULL);
155 
156 	SAFE_PTHREAD_JOIN(pt1, NULL);
157 }
158 
159 static struct tcase {
160 	void (*tfunc)(void);
161 } tcases[] = {
162 	{&verify_signal_self},
163 	{&verify_signal_parent_thread},
164 	{&verify_signal_inter_thread},
165 };
166 
run(unsigned int i)167 static void run(unsigned int i)
168 {
169 	tcases[i].tfunc();
170 }
171 
setup(void)172 static void setup(void)
173 {
174 	struct sigaction sigusr1 = {
175 		.sa_flags = SA_SIGINFO,
176 		.sa_sigaction = sigusr1_handler,
177 	};
178 
179 	SAFE_SIGACTION(SIGUSR1, &sigusr1, NULL);
180 }
181 
182 static struct tst_test test = {
183 	.tcnt = ARRAY_SIZE(tcases),
184 	.needs_checkpoints = 1,
185 	.setup = setup,
186 	.test = run,
187 };
188