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