Home | History | Annotate | Download | only in sem_wait
      1 /*
      2 * Copyright (c) 2005, Bull S.A..  All rights reserved.
      3 * Created by: Sebastien Decugis
      4 * Copyright (c) 2011 Cyril Hrubis <chrubis (at) suse.cz>
      5 
      6 * This program is free software; you can redistribute it and/or modify it
      7 * under the terms of version 2 of the GNU General Public License as
      8 * published by the Free Software Foundation.
      9 *
     10 * This program is distributed in the hope that it would be useful, but
     11 * WITHOUT ANY WARRANTY; without even the implied warranty of
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     13 *
     14 * You should have received a copy of the GNU General Public License along
     15 * with this program; if not, write the Free Software Foundation, Inc.,
     16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     17 
     18 * This sample test aims to check the following assertion:
     19 *
     20 *  If the semaphore count is 0, the call blocks until the semphore can be
     21 * locked or the operation is interrupted by a signal.
     22 
     23 * The steps are:
     24 * -> Initialize a semaphore to 0 count
     25 * -> Register a signal handler for SIGALRM which post the semaphore
     26 * -> save current time
     27 * -> set an alarm to 1 second
     28 * -> sem_wait
     29 * -> Verify either errno is EINTR or no error occured.
     30 * -> Verify 1 sec has elapsed.
     31 
     32 * The test fails if the call did not block.
     33 
     34 */
     35 
     36 #include <pthread.h>
     37 #include <stdarg.h>
     38 #include <stdio.h>
     39 #include <stdlib.h>
     40 #include <string.h>
     41 #include <unistd.h>
     42 
     43 #include <semaphore.h>
     44 #include <signal.h>
     45 #include <errno.h>
     46 
     47 #include <timespec.h>
     48 
     49 #include "../testfrmw/testfrmw.h"
     50 #include "../testfrmw/testfrmw.c"
     51 
     52 static sem_t sem;
     53 
     54 static void handler(int sig)
     55 {
     56 	int ret;
     57 	ret = sem_post(&sem);
     58 
     59 	if (ret != 0) {
     60 		UNRESOLVED(errno, "Failed to post semaphore");
     61 	}
     62 }
     63 
     64 int main(void)
     65 {
     66 	int ret;
     67 	struct timespec ts_ref, ts_fin;
     68 	struct sigaction sa;
     69 
     70 	output_init();
     71 
     72 	ret = sem_init(&sem, 0, 0);
     73 
     74 	if (ret != 0) {
     75 		UNRESOLVED(errno, "Failed to init semaphore");
     76 	}
     77 
     78 	sa.sa_flags = 0;
     79 	sa.sa_handler = handler;
     80 
     81 	ret = sigemptyset(&sa.sa_mask);
     82 
     83 	if (ret != 0) {
     84 		UNRESOLVED(ret, "Failed to empty signal set");
     85 	}
     86 
     87 	sigaction(SIGALRM, &sa, 0);
     88 
     89 	if (ret != 0) {
     90 		UNRESOLVED(ret, "Failed to set signal handler");
     91 	}
     92 
     93 	ret = clock_gettime(CLOCK_REALTIME, &ts_ref);
     94 
     95 	if (ret != 0) {
     96 		UNRESOLVED(errno, "Unable to read clock");
     97 	}
     98 
     99 	/*
    100 	 * POSIX allows for alarm to quite unprecise, so we ask for 2 seconds
    101 	 * and check for at least one.
    102 	 */
    103 	alarm(2);
    104 
    105 	ret = sem_wait(&sem);
    106 
    107 	if (ret != 0 && errno != EINTR) {
    108 		UNRESOLVED(errno, "Failed to wait for the semaphore");
    109 	}
    110 
    111 	ret = clock_gettime(CLOCK_REALTIME, &ts_fin);
    112 
    113 	if (ret != 0) {
    114 		UNRESOLVED(errno, "Unable to read clock");
    115 	}
    116 
    117 	if (timespec_nsec_diff(&ts_fin, &ts_ref) < NSEC_IN_SEC) {
    118 		output("Ts: %d.%9.9d  ->  %d.%9.9d\n",
    119 		       ts_ref.tv_sec, ts_ref.tv_nsec,
    120 		       ts_fin.tv_sec, ts_fin.tv_nsec);
    121 		FAILED("The sem_wait call did not block");
    122 	}
    123 
    124 	ret = sem_destroy(&sem);
    125 
    126 	if (ret != 0) {
    127 		UNRESOLVED(errno, "Failed to sem_destroy");
    128 	}
    129 
    130 	output("Test passed\n");
    131 
    132 	PASSED;
    133 }
    134