Home | History | Annotate | Download | only in semaphore
      1 /*
      2  *
      3  *   Copyright (c) International Business Machines  Corp., 2001
      4  *
      5  *   This program is free software;  you can redistribute it and/or modify
      6  *   it under the terms of the GNU General Public License as published by
      7  *   the Free Software Foundation; either version 2 of the License, or
      8  *   (at your option) any later version.
      9  *
     10  *   This program is distributed in the hope that it will be useful,
     11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
     12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     13  *   the GNU General Public License for more details.
     14  *
     15  *   You should have received a copy of the GNU General Public License
     16  *   along with this program;  if not, write to the Free Software
     17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     18  */
     19 
     20 /*
     21  *  FILE        : sem01.c
     22  *  DESCRIPTION : Creates a semaphore and two processes.  The processes
     23  *                each go through a loop where they semdown, delay for a
     24  *                random amount of time, and semup, so they will almost
     25  *                always be fighting for control of the semaphore.
     26  *  HISTORY:
     27  *    01/15/2001 Paul Larson (plars (at) us.ibm.com)
     28  *      -written
     29  *    11/09/2001 Manoj Iyer (manjo (at) ausin.ibm.com)
     30  *    Modified.
     31  *    - Removed compiler warnings.
     32  *      added exit to the end of function main()
     33  *
     34  */
     35 
     36 #include <unistd.h>
     37 #include <stdlib.h>
     38 #include <stdio.h>
     39 #include <errno.h>
     40 #include <sys/types.h>
     41 #include <sys/wait.h>
     42 #include <sys/ipc.h>
     43 #include <sys/sem.h>
     44 #include "lapi/semun.h"
     45 
     46 int verbose = 0;
     47 int loops = 100;
     48 int errors = 0;
     49 
     50 int semup(int semid)
     51 {
     52 	struct sembuf semops;
     53 	semops.sem_num = 0;
     54 	semops.sem_op = 1;
     55 	semops.sem_flg = SEM_UNDO;
     56 	if (semop(semid, &semops, 1) == -1) {
     57 		perror("semup");
     58 		errors++;
     59 		return 1;
     60 	}
     61 	return 0;
     62 }
     63 
     64 int semdown(int semid)
     65 {
     66 	struct sembuf semops;
     67 	semops.sem_num = 0;
     68 	semops.sem_op = -1;
     69 	semops.sem_flg = SEM_UNDO;
     70 	if (semop(semid, &semops, 1) == -1) {
     71 		perror("semdown");
     72 		errors++;
     73 		return 1;
     74 	}
     75 	return 0;
     76 }
     77 
     78 void delayloop()
     79 {
     80 	int delay;
     81 	delay = 1 + ((100.0 * rand()) / RAND_MAX);
     82 	if (verbose)
     83 		printf("in delay function for %d microseconds\n", delay);
     84 	usleep(delay);
     85 }
     86 
     87 void mainloop(int semid)
     88 {
     89 	int i;
     90 	for (i = 0; i < loops; i++) {
     91 		if (semdown(semid)) {
     92 			printf("semdown failed\n");
     93 		}
     94 		if (verbose)
     95 			printf("sem is down\n");
     96 		delayloop();
     97 		if (semup(semid)) {
     98 			printf("semup failed\n");
     99 		}
    100 		if (verbose)
    101 			printf("sem is up\n");
    102 	}
    103 }
    104 
    105 int main(int argc, char *argv[])
    106 {
    107 	int semid, opt;
    108 	union semun semunion;
    109 	extern char *optarg;
    110 	pid_t pid;
    111 	int chstat;
    112 
    113 	while ((opt = getopt(argc, argv, "l:vh")) != EOF) {
    114 		switch ((char)opt) {
    115 		case 'l':
    116 			loops = atoi(optarg);
    117 			break;
    118 		case 'v':
    119 			verbose = 1;
    120 			break;
    121 		case 'h':
    122 		default:
    123 			printf("Usage: -l loops [-v]\n");
    124 			exit(1);
    125 		}
    126 	}
    127 
    128 	/* set up the semaphore */
    129 	if ((semid = semget((key_t) 9142, 1, 0666 | IPC_CREAT)) < 0) {
    130 		printf("error in semget()\n");
    131 		exit(-1);
    132 	}
    133 	semunion.val = 1;
    134 	if (semctl(semid, 0, SETVAL, semunion) == -1) {
    135 		printf("error in semctl\n");
    136 	}
    137 
    138 	if ((pid = fork()) < 0) {
    139 		printf("fork error\n");
    140 		exit(-1);
    141 	}
    142 	if (pid) {
    143 		/* parent */
    144 		srand(pid);
    145 		mainloop(semid);
    146 		waitpid(pid, &chstat, 0);
    147 		if (!WIFEXITED(chstat)) {
    148 			printf("child exited with status\n");
    149 			exit(-1);
    150 		}
    151 		if (semctl(semid, 0, IPC_RMID, semunion) == -1) {
    152 			printf("error in semctl\n");
    153 		}
    154 		if (errors) {
    155 			printf("FAIL: there were %d errors\n", errors);
    156 		} else {
    157 			printf("PASS: error count is 0\n");
    158 		}
    159 		exit(errors);
    160 	} else {
    161 		/* child */
    162 		mainloop(semid);
    163 	}
    164 	exit(0);
    165 }
    166