blob: a0e2641a97e28708a71838d42a9ea57fedb7763d [file] [log] [blame]
robbiew95ae8f62002-03-06 18:24:32 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2002
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/*
21 * FILE : sem02.c
robbiewe52c6dc2002-03-06 18:35:27 +000022 *
robbiew95ae8f62002-03-06 18:24:32 +000023 * DESCRIPTION : The application creates several threads using pthread_create().
24 * One thread performs a semop() with the SEM_UNDO flag set. The change in
25 * sempaphore value performed by that semop should be "undone" only when the
26 * last pthread exits.
robbiewe52c6dc2002-03-06 18:35:27 +000027 *
28 * EXPECTED OUTPUT:
29 * Waiter, pid = <pid#>
30 * Poster, pid = <pid#>, posting
31 * Poster posted
32 * Poster exiting
33 * Waiter waiting, pid = <pid#>
34 * Waiter done waiting
35 *
robbiew95ae8f62002-03-06 18:24:32 +000036 * HISTORY:
robbiewded99ee2002-03-20 20:02:56 +000037 * written by Dave Olien (oliend@us.ibm.com)
robbiew95ae8f62002-03-06 18:24:32 +000038 * 03/06/2002 Robbie Williamson (robbiew@us.ibm.com)
39 * -ported
40 *
41 */
42#include <stdio.h>
robbiewb59499d2002-03-28 19:21:32 +000043#include <stdlib.h>
robbiew95ae8f62002-03-06 18:24:32 +000044#include <unistd.h>
45#include <sys/sem.h>
46#include <errno.h>
47#include <pthread.h>
robbiewb59499d2002-03-28 19:21:32 +000048#include <sys/types.h>
49#include <sys/ipc.h>
robbiew95ae8f62002-03-06 18:24:32 +000050
51#define KEY IPC_PRIVATE
52
53#define NUMTHREADS 2
54
55void *retval[NUMTHREADS];
56void * waiter(void *);
57void * poster(void *);
58
59struct sembuf Psembuf = {0, -1, SEM_UNDO};
60struct sembuf Vsembuf = {0, 1, SEM_UNDO};
61
robbiewb59499d2002-03-28 19:21:32 +000062union semun {
63 int val; /* value for SETVAL */
64 struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
65 unsigned short *array; /* array for GETALL & SETALL */
66 struct seminfo *ipc_buf; /* buffer for IPC_INFO */
67};
68
69
robbiew95ae8f62002-03-06 18:24:32 +000070int sem_id;
71int err_ret; /* This is used to determine PASS/FAIL status */
72int main()
73{
74 int i, rc;
robbiewb59499d2002-03-28 19:21:32 +000075 union semun semunion;
76
robbiew95ae8f62002-03-06 18:24:32 +000077 pthread_t pt[NUMTHREADS];
78 pthread_attr_t attr;
79
80 /* Create the semaphore set */
81 sem_id = semget(KEY, 1, 0666 | IPC_CREAT);
82 if (sem_id < 0)
83 {
84 printf ("semget failed, errno = %d\n", errno);
85 exit (1);
86 }
87
88 /* setup the attributes of the thread */
89 /* set the scope to be system to make sure the threads compete on a */
90 /* global scale for cpu */
91 pthread_attr_init(&attr);
92 pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
93
94 err_ret=1; /* Set initial error value to 1 */
95 /* Create the threads */
96 for (i=0; i<NUMTHREADS; i++)
97 {
98 if (i == 0)
99 rc = pthread_create(&pt[i], &attr, waiter, retval[i]);
100 else
101 rc = pthread_create(&pt[i], &attr, poster, retval[i]);
102 }
103
104 /* Sleep long enough to see that the other threads do what they are supposed to do */
105 sleep(20);
robbiewb59499d2002-03-28 19:21:32 +0000106 semunion.val = 1;
107 semctl(sem_id, 0, IPC_RMID, semunion);
robbiewc9d001f2002-03-21 20:46:21 +0000108 if ( err_ret == 1 )
robbiewc9d001f2002-03-21 20:46:21 +0000109 printf("sem02: FAIL\n");
robbiew055425b2002-03-26 22:32:13 +0000110 else
111 printf("sem02: PASS\n");
robbiew95ae8f62002-03-06 18:24:32 +0000112 return(err_ret);
113}
114
115
116/* This thread sleeps 10 seconds then waits on the semaphore. As long
117 as someone has posted on the semaphore, and no undo has taken
118 place, the semop should complete and we'll print "Waiter done
119 waiting." */
120void * waiter(void * foo)
121{
122 int pid;
123 pid = getpid();
124
125 printf ("Waiter, pid = %d\n", pid);
126 sleep(10);
127
128 printf("Waiter waiting, pid = %d\n", pid);
129 semop(sem_id, &Psembuf, 1);
130 printf("Waiter done waiting\n");
131 err_ret=0; /* If the message above is displayed, the test is a PASS */
132 pthread_exit(0);
133}
134
135/* This thread immediately posts on the semaphore and then immediately
136 exits. If the *thread* exits, the undo should not happen, and the
137 waiter thread which will start waiting on it in 10 seconds, should
138 still get it. */
139void * poster(void * foo)
140{
141 int pid;
142
143 pid = getpid();
144 printf ("Poster, pid = %d, posting\n", pid);
145 semop(sem_id, &Vsembuf, 1);
146 printf ("Poster posted\n");
147 printf ("Poster exiting\n");
148
149 pthread_exit(0);
150}