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