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