robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2005, Bull S.A.. All rights reserved. |
| 3 | * Created by: Sebastien Decugis |
| 4 | |
| 5 | * This program is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of version 2 of the GNU General Public License as |
| 7 | * published by the Free Software Foundation. |
| 8 | * |
| 9 | * This program is distributed in the hope that it would be useful, but |
| 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| 12 | * |
| 13 | * You should have received a copy of the GNU General Public License along |
| 14 | * with this program; if not, write the Free Software Foundation, Inc., 59 |
| 15 | * Temple Place - Suite 330, Boston MA 02111-1307, USA. |
| 16 | |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 17 | * This sample test aims to check the following assertion: |
| 18 | * |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 19 | * If several threads are waiting for a signal and this signal is generated |
| 20 | * for a specific thread, only this thread is unblocked. |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 21 | |
| 22 | * The steps are: |
| 23 | * -> mask SIGUSR1 |
| 24 | * -> create several threads which sigwait for SIGUSR1 |
| 25 | * -> pthread_kill one of the threads |
| 26 | * -> Check than this thread has been awaken. |
| 27 | |
| 28 | * The test fails if the thread is not awaken. |
| 29 | |
| 30 | */ |
| 31 | |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 32 | /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ |
| 33 | #define _POSIX_C_SOURCE 200112L |
| 34 | |
| 35 | /******************************************************************************/ |
| 36 | /*************************** standard includes ********************************/ |
| 37 | /******************************************************************************/ |
| 38 | #include <pthread.h> |
| 39 | #include <stdarg.h> |
| 40 | #include <stdio.h> |
| 41 | #include <stdlib.h> |
| 42 | #include <string.h> |
| 43 | #include <unistd.h> |
| 44 | |
| 45 | #include <signal.h> |
| 46 | #include <errno.h> |
| 47 | |
| 48 | /******************************************************************************/ |
| 49 | /*************************** Test framework *******************************/ |
| 50 | /******************************************************************************/ |
Wanlong Gao | 8d9c084 | 2012-03-09 15:52:19 +0800 | [diff] [blame] | 51 | #include "../testfrmw/testfrmw.h" |
| 52 | #include "../testfrmw/testfrmw.c" |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 53 | /* This header is responsible for defining the following macros: |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 54 | * UNRESOLVED(ret, descr); |
| 55 | * where descr is a description of the error and ret is an int |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 56 | * (error code for example) |
| 57 | * FAILED(descr); |
| 58 | * where descr is a short text saying why the test has failed. |
| 59 | * PASSED(); |
| 60 | * No parameter. |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 61 | * |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 62 | * Both three macros shall terminate the calling process. |
| 63 | * The testcase shall not terminate in any other maneer. |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 64 | * |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 65 | * The other file defines the functions |
| 66 | * void output_init() |
| 67 | * void output(char * string, ...) |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 68 | * |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 69 | * Those may be used to output information. |
| 70 | */ |
| 71 | |
| 72 | /******************************************************************************/ |
| 73 | /**************************** Configuration ***********************************/ |
| 74 | /******************************************************************************/ |
| 75 | #ifndef VERBOSE |
| 76 | #define VERBOSE 1 |
| 77 | #endif |
| 78 | |
| 79 | #define NTHREADS 5 |
| 80 | |
| 81 | /******************************************************************************/ |
| 82 | /*************************** Test case ***********************************/ |
| 83 | /******************************************************************************/ |
| 84 | |
| 85 | int n_awaken = 0; |
| 86 | pthread_t last_awaken; |
| 87 | sigset_t setusr; |
| 88 | |
| 89 | /* Thread function */ |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 90 | void * threaded(void * arg) |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 91 | { |
| 92 | int ret; |
| 93 | int sig; |
| 94 | |
| 95 | /* The signal is already masked, because inherited from the parent */ |
| 96 | |
| 97 | /* wait for the signal */ |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 98 | ret = sigwait(&setusr, &sig); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 99 | |
Garrett Cooper | 8fb1cdb | 2010-11-28 22:56:35 -0800 | [diff] [blame] | 100 | if (ret != 0) |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 101 | { |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 102 | UNRESOLVED(ret, "failed to wait for signal in thread"); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 103 | } |
| 104 | |
| 105 | n_awaken++; |
| 106 | |
| 107 | last_awaken = pthread_self(); |
| 108 | |
| 109 | /* quit */ |
| 110 | return NULL; |
| 111 | } |
| 112 | |
| 113 | /* The main test function. */ |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 114 | int main(int argc, char * argv[]) |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 115 | { |
| 116 | int ret, i; |
| 117 | pthread_t ch[ NTHREADS ]; |
| 118 | |
| 119 | /* Initialize output */ |
| 120 | output_init(); |
| 121 | |
| 122 | /* Set the signal mask */ |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 123 | ret = sigemptyset(&setusr); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 124 | |
Garrett Cooper | 8fb1cdb | 2010-11-28 22:56:35 -0800 | [diff] [blame] | 125 | if (ret != 0) |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 126 | { |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 127 | UNRESOLVED(ret, "Failed to empty signal set"); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 128 | } |
| 129 | |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 130 | ret = sigaddset(&setusr, SIGUSR1); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 131 | |
Garrett Cooper | 8fb1cdb | 2010-11-28 22:56:35 -0800 | [diff] [blame] | 132 | if (ret != 0) |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 133 | { |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 134 | UNRESOLVED(ret, "failed to add SIGUSR1 to signal set"); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 135 | } |
| 136 | |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 137 | ret = pthread_sigmask(SIG_BLOCK, &setusr, NULL); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 138 | |
Garrett Cooper | 8fb1cdb | 2010-11-28 22:56:35 -0800 | [diff] [blame] | 139 | if (ret != 0) |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 140 | { |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 141 | UNRESOLVED(ret, "Failed to block SIGUSR1"); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 142 | } |
| 143 | |
| 144 | /* Create the children */ |
| 145 | |
Garrett Cooper | 8fb1cdb | 2010-11-28 22:56:35 -0800 | [diff] [blame] | 146 | for (i = 0; i < NTHREADS; i++) |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 147 | { |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 148 | ret = pthread_create(&ch[ i ], NULL, threaded, NULL); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 149 | |
Garrett Cooper | 8fb1cdb | 2010-11-28 22:56:35 -0800 | [diff] [blame] | 150 | if (ret != 0) |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 151 | { |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 152 | UNRESOLVED(ret, "Failed to create a thread"); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 153 | } |
| 154 | } |
| 155 | |
| 156 | /* raise the signal */ |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 157 | ret = pthread_kill(ch[ 0 ], SIGUSR1); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 158 | |
Garrett Cooper | 8fb1cdb | 2010-11-28 22:56:35 -0800 | [diff] [blame] | 159 | if (ret != 0) |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 160 | { |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 161 | UNRESOLVED(ret, "Failed to raise the signal"); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 162 | } |
| 163 | |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 164 | sleep(1); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 165 | |
Garrett Cooper | 8fb1cdb | 2010-11-28 22:56:35 -0800 | [diff] [blame] | 166 | if (n_awaken != 1) |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 167 | { |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 168 | output("%d threads were awaken\n", n_awaken); |
| 169 | FAILED("Unexpected number of threads awaken"); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 170 | } |
| 171 | |
Garrett Cooper | 3b4d3ce | 2010-11-24 00:03:17 -0800 | [diff] [blame] | 172 | if (!pthread_equal(last_awaken, ch[0])) |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 173 | { |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 174 | FAILED("The awaken thread is not the signal target one."); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 175 | } |
| 176 | |
| 177 | /* Wake other threads */ |
Garrett Cooper | 8fb1cdb | 2010-11-28 22:56:35 -0800 | [diff] [blame] | 178 | for (i = 1; i < NTHREADS ; i++) |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 179 | { |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 180 | ret = pthread_kill(ch[ i ], SIGUSR1); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 181 | |
Garrett Cooper | 8fb1cdb | 2010-11-28 22:56:35 -0800 | [diff] [blame] | 182 | if (ret != 0) |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 183 | { |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 184 | UNRESOLVED(ret, "Failed to raise the signal"); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 185 | } |
| 186 | } |
| 187 | |
| 188 | /* Wait for child thread termination */ |
Garrett Cooper | 8fb1cdb | 2010-11-28 22:56:35 -0800 | [diff] [blame] | 189 | for (i = 0; i < NTHREADS; i++) |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 190 | { |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 191 | ret = pthread_join(ch[ i ], NULL); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 192 | |
Garrett Cooper | 8fb1cdb | 2010-11-28 22:56:35 -0800 | [diff] [blame] | 193 | if (ret != 0) |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 194 | { |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 195 | UNRESOLVED(ret, "Failed to join the thread"); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 196 | } |
| 197 | } |
| 198 | |
| 199 | /* Test passed */ |
| 200 | #if VERBOSE > 0 |
| 201 | |
Garrett Cooper | e9410df | 2010-12-08 08:43:16 -0800 | [diff] [blame] | 202 | output("Test passed\n"); |
robbiew | 0dc0765 | 2005-06-03 16:29:48 +0000 | [diff] [blame] | 203 | |
| 204 | #endif |
| 205 | |
| 206 | PASSED; |
Chris Dearman | ec6edca | 2012-10-17 19:54:01 -0700 | [diff] [blame^] | 207 | } |