Home | History | Annotate | Download | only in sigwait
      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.,
     15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     16 
     17 * This sample test aims to check the following assertion:
     18 *
     19 * If several threads are waiting for a signal and this signal is generated
     20 * for a specific thread, only this thread is unblocked.
     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 
     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 /******************************************************************************/
     51 #include "../testfrmw/testfrmw.h"
     52 #include "../testfrmw/testfrmw.c"
     53 /* This header is responsible for defining the following macros:
     54  * UNRESOLVED(ret, descr);
     55  *    where descr is a description of the error and ret is an int
     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.
     61  *
     62  * Both three macros shall terminate the calling process.
     63  * The testcase shall not terminate in any other maneer.
     64  *
     65  * The other file defines the functions
     66  * void output_init()
     67  * void output(char * string, ...)
     68  *
     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 */
     90 void *threaded(void *arg)
     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 */
     98 	ret = sigwait(&setusr, &sig);
     99 
    100 	if (ret != 0) {
    101 		UNRESOLVED(ret, "failed to wait for signal in thread");
    102 	}
    103 
    104 	n_awaken++;
    105 
    106 	last_awaken = pthread_self();
    107 
    108 	/* quit */
    109 	return NULL;
    110 }
    111 
    112 /* The main test function. */
    113 int main(void)
    114 {
    115 	int ret, i;
    116 	pthread_t ch[NTHREADS];
    117 
    118 	/* Initialize output */
    119 	output_init();
    120 
    121 	/* Set the signal mask */
    122 	ret = sigemptyset(&setusr);
    123 
    124 	if (ret != 0) {
    125 		UNRESOLVED(ret, "Failed to empty signal set");
    126 	}
    127 
    128 	ret = sigaddset(&setusr, SIGUSR1);
    129 
    130 	if (ret != 0) {
    131 		UNRESOLVED(ret, "failed to add SIGUSR1 to signal set");
    132 	}
    133 
    134 	ret = pthread_sigmask(SIG_BLOCK, &setusr, NULL);
    135 
    136 	if (ret != 0) {
    137 		UNRESOLVED(ret, "Failed to block SIGUSR1");
    138 	}
    139 
    140 	/* Create the children */
    141 
    142 	for (i = 0; i < NTHREADS; i++) {
    143 		ret = pthread_create(&ch[i], NULL, threaded, NULL);
    144 
    145 		if (ret != 0) {
    146 			UNRESOLVED(ret, "Failed to create a thread");
    147 		}
    148 	}
    149 
    150 	/* raise the signal */
    151 	ret = pthread_kill(ch[0], SIGUSR1);
    152 
    153 	if (ret != 0) {
    154 		UNRESOLVED(ret, "Failed to raise the signal");
    155 	}
    156 
    157 	sleep(1);
    158 
    159 	if (n_awaken != 1) {
    160 		output("%d threads were awaken\n", n_awaken);
    161 		FAILED("Unexpected number of threads awaken");
    162 	}
    163 
    164 	if (!pthread_equal(last_awaken, ch[0])) {
    165 		FAILED("The awaken thread is not the signal target one.");
    166 	}
    167 
    168 	/* Wake other threads */
    169 	for (i = 1; i < NTHREADS; i++) {
    170 		ret = pthread_kill(ch[i], SIGUSR1);
    171 
    172 		if (ret != 0) {
    173 			UNRESOLVED(ret, "Failed to raise the signal");
    174 		}
    175 	}
    176 
    177 	/* Wait for child thread termination */
    178 	for (i = 0; i < NTHREADS; i++) {
    179 		ret = pthread_join(ch[i], NULL);
    180 
    181 		if (ret != 0) {
    182 			UNRESOLVED(ret, "Failed to join the thread");
    183 		}
    184 	}
    185 
    186 	/* Test passed */
    187 #if VERBOSE > 0
    188 
    189 	output("Test passed\n");
    190 
    191 #endif
    192 
    193 	PASSED;
    194 }
    195