1*fb2ab7ceSKonstantin Belousov /*- 2*fb2ab7ceSKonstantin Belousov * SPDX-License-Identifier: BSD-2-Clause 3*fb2ab7ceSKonstantin Belousov * 4*fb2ab7ceSKonstantin Belousov * Copyright 2024 The FreeBSD Foundation 5*fb2ab7ceSKonstantin Belousov * 6*fb2ab7ceSKonstantin Belousov * This software was developed by Konstantin Belousov <kib@FreeBSD.org> 7*fb2ab7ceSKonstantin Belousov * under sponsorship from the FreeBSD Foundation. 8*fb2ab7ceSKonstantin Belousov * 9*fb2ab7ceSKonstantin Belousov * Redistribution and use in source and binary forms, with or without 10*fb2ab7ceSKonstantin Belousov * modification, are permitted provided that the following conditions 11*fb2ab7ceSKonstantin Belousov * are met: 12*fb2ab7ceSKonstantin Belousov * 1. Redistributions of source code must retain the above copyright 13*fb2ab7ceSKonstantin Belousov * notice, this list of conditions and the following disclaimer. 14*fb2ab7ceSKonstantin Belousov * 2. Redistributions in binary form must reproduce the above copyright 15*fb2ab7ceSKonstantin Belousov * notice, this list of conditions and the following disclaimer in the 16*fb2ab7ceSKonstantin Belousov * documentation and/or other materials provided with the distribution. 17*fb2ab7ceSKonstantin Belousov * 18*fb2ab7ceSKonstantin Belousov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19*fb2ab7ceSKonstantin Belousov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*fb2ab7ceSKonstantin Belousov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*fb2ab7ceSKonstantin Belousov * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22*fb2ab7ceSKonstantin Belousov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23*fb2ab7ceSKonstantin Belousov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24*fb2ab7ceSKonstantin Belousov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25*fb2ab7ceSKonstantin Belousov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26*fb2ab7ceSKonstantin Belousov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27*fb2ab7ceSKonstantin Belousov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28*fb2ab7ceSKonstantin Belousov * SUCH DAMAGE. 29*fb2ab7ceSKonstantin Belousov */ 30*fb2ab7ceSKonstantin Belousov 31*fb2ab7ceSKonstantin Belousov #include <atf-c.h> 32*fb2ab7ceSKonstantin Belousov #include <err.h> 33*fb2ab7ceSKonstantin Belousov #include <errno.h> 34*fb2ab7ceSKonstantin Belousov #include <signal.h> 35*fb2ab7ceSKonstantin Belousov #include <stdio.h> 36*fb2ab7ceSKonstantin Belousov #include <stdlib.h> 37*fb2ab7ceSKonstantin Belousov #include <pthread.h> 38*fb2ab7ceSKonstantin Belousov #include <unistd.h> 39*fb2ab7ceSKonstantin Belousov 40*fb2ab7ceSKonstantin Belousov #define NTHREADS 330 41*fb2ab7ceSKonstantin Belousov static int value[NTHREADS]; 42*fb2ab7ceSKonstantin Belousov static pthread_t thr[NTHREADS]; 43*fb2ab7ceSKonstantin Belousov static pthread_barrier_t barrier; 44*fb2ab7ceSKonstantin Belousov 45*fb2ab7ceSKonstantin Belousov static void 46*fb2ab7ceSKonstantin Belousov handler(int signo __unused, siginfo_t *info, void *data __unused) 47*fb2ab7ceSKonstantin Belousov { 48*fb2ab7ceSKonstantin Belousov pthread_t self; 49*fb2ab7ceSKonstantin Belousov int i; 50*fb2ab7ceSKonstantin Belousov 51*fb2ab7ceSKonstantin Belousov /* 52*fb2ab7ceSKonstantin Belousov * Formally this is thread-unsafe but we know context from 53*fb2ab7ceSKonstantin Belousov * where the signal is sent. 54*fb2ab7ceSKonstantin Belousov */ 55*fb2ab7ceSKonstantin Belousov self = pthread_self(); 56*fb2ab7ceSKonstantin Belousov for (i = 0; i < NTHREADS; i++) { 57*fb2ab7ceSKonstantin Belousov if (pthread_equal(self, thr[i])) { 58*fb2ab7ceSKonstantin Belousov value[i] = info->si_value.sival_int; 59*fb2ab7ceSKonstantin Belousov pthread_exit(NULL); 60*fb2ab7ceSKonstantin Belousov } 61*fb2ab7ceSKonstantin Belousov } 62*fb2ab7ceSKonstantin Belousov } 63*fb2ab7ceSKonstantin Belousov 64*fb2ab7ceSKonstantin Belousov static void * 65*fb2ab7ceSKonstantin Belousov threadfunc(void *arg __unused) 66*fb2ab7ceSKonstantin Belousov { 67*fb2ab7ceSKonstantin Belousov pthread_barrier_wait(&barrier); 68*fb2ab7ceSKonstantin Belousov for (;;) 69*fb2ab7ceSKonstantin Belousov pause(); 70*fb2ab7ceSKonstantin Belousov } 71*fb2ab7ceSKonstantin Belousov 72*fb2ab7ceSKonstantin Belousov ATF_TC(pthread_sigqueue); 73*fb2ab7ceSKonstantin Belousov ATF_TC_HEAD(pthread_sigqueue, tc) 74*fb2ab7ceSKonstantin Belousov { 75*fb2ab7ceSKonstantin Belousov atf_tc_set_md_var(tc, "descr", 76*fb2ab7ceSKonstantin Belousov "Checks pthread_sigqueue(3) sigval delivery"); 77*fb2ab7ceSKonstantin Belousov } 78*fb2ab7ceSKonstantin Belousov 79*fb2ab7ceSKonstantin Belousov ATF_TC_BODY(pthread_sigqueue, tc) 80*fb2ab7ceSKonstantin Belousov { 81*fb2ab7ceSKonstantin Belousov struct sigaction sa; 82*fb2ab7ceSKonstantin Belousov union sigval sv; 83*fb2ab7ceSKonstantin Belousov int error, i; 84*fb2ab7ceSKonstantin Belousov 85*fb2ab7ceSKonstantin Belousov error = pthread_barrier_init(&barrier, NULL, NTHREADS + 1); 86*fb2ab7ceSKonstantin Belousov ATF_REQUIRE_EQ(0, error); 87*fb2ab7ceSKonstantin Belousov 88*fb2ab7ceSKonstantin Belousov memset(&sa, 0, sizeof(sa)); 89*fb2ab7ceSKonstantin Belousov sa.sa_sigaction = handler; 90*fb2ab7ceSKonstantin Belousov sigemptyset(&sa.sa_mask); 91*fb2ab7ceSKonstantin Belousov sa.sa_flags = SA_SIGINFO; 92*fb2ab7ceSKonstantin Belousov 93*fb2ab7ceSKonstantin Belousov if (sigaction(SIGUSR1, &sa, NULL) != 0) 94*fb2ab7ceSKonstantin Belousov atf_tc_fail("sigaction failed"); 95*fb2ab7ceSKonstantin Belousov 96*fb2ab7ceSKonstantin Belousov memset(&sv, 0, sizeof(sv)); 97*fb2ab7ceSKonstantin Belousov 98*fb2ab7ceSKonstantin Belousov for (i = 0; i < NTHREADS; i++) { 99*fb2ab7ceSKonstantin Belousov error = pthread_create(&thr[i], NULL, threadfunc, NULL); 100*fb2ab7ceSKonstantin Belousov ATF_REQUIRE_EQ(0, error); 101*fb2ab7ceSKonstantin Belousov } 102*fb2ab7ceSKonstantin Belousov error = pthread_barrier_wait(&barrier); 103*fb2ab7ceSKonstantin Belousov ATF_REQUIRE(error == 0 || error == PTHREAD_BARRIER_SERIAL_THREAD); 104*fb2ab7ceSKonstantin Belousov 105*fb2ab7ceSKonstantin Belousov for (i = 0; i < NTHREADS; i++) { 106*fb2ab7ceSKonstantin Belousov sv.sival_int = i + 1000; 107*fb2ab7ceSKonstantin Belousov error = pthread_sigqueue(thr[i], SIGUSR1, sv); 108*fb2ab7ceSKonstantin Belousov ATF_REQUIRE_EQ(0, error); 109*fb2ab7ceSKonstantin Belousov error = pthread_join(thr[i], NULL); 110*fb2ab7ceSKonstantin Belousov ATF_REQUIRE_EQ(0, error); 111*fb2ab7ceSKonstantin Belousov } 112*fb2ab7ceSKonstantin Belousov for (i = 0; i < NTHREADS; i++) 113*fb2ab7ceSKonstantin Belousov ATF_REQUIRE_EQ(i + 1000, value[i]); 114*fb2ab7ceSKonstantin Belousov } 115*fb2ab7ceSKonstantin Belousov 116*fb2ab7ceSKonstantin Belousov ATF_TP_ADD_TCS(tp) 117*fb2ab7ceSKonstantin Belousov { 118*fb2ab7ceSKonstantin Belousov ATF_TP_ADD_TC(tp, pthread_sigqueue); 119*fb2ab7ceSKonstantin Belousov return atf_no_error(); 120*fb2ab7ceSKonstantin Belousov } 121