• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 /*
21  *  FILE        : sem02.c
22  *
23  *  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.
27  *
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  *
36  *  HISTORY:
37  *    written by Dave Olien (oliend@us.ibm.com)
38  *    03/06/2002 Robbie Williamson (robbiew@us.ibm.com)
39  *      -ported
40  *    07/04/2003 Paul Larson (plars@linuxtestproject.org)
41  *      -ported to LTP
42  *
43  */
44 
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <unistd.h>
48 #include <errno.h>
49 #include <pthread.h>
50 #include <sys/types.h>
51 #include <sys/ipc.h>
52 #include "lapi/sem.h"
53 #include "test.h"
54 
55 #define KEY IPC_PRIVATE
56 
57 #define NUMTHREADS 2
58 
59 void *retval[NUMTHREADS];
60 void *waiter(void *);
61 void *poster(void *);
62 void cleanup(void);
63 
64 char *TCID = "sem02";
65 int TST_TOTAL = 1;
66 
67 struct sembuf Psembuf = { 0, -1, SEM_UNDO };
68 struct sembuf Vsembuf = { 0, 1, SEM_UNDO };
69 
70 int sem_id;
71 int err_ret;			/* This is used to determine PASS/FAIL status */
main(int argc,char ** argv)72 int main(int argc, char **argv)
73 {
74 	int i, rc;
75 	union semun semunion;
76 
77 	pthread_t pt[NUMTHREADS];
78 	pthread_attr_t attr;
79 
80 	tst_parse_opts(argc, argv, NULL, NULL);
81 	/* Create the semaphore set */
82 	sem_id = semget(KEY, 1, 0666 | IPC_CREAT);
83 	if (sem_id < 0) {
84 		printf("semget failed, errno = %d\n", errno);
85 		exit(1);
86 	}
87 	/* initialize data  structure associated to the semaphore */
88 	semunion.val = 1;
89 	semctl(sem_id, 0, SETVAL, semunion);
90 
91 	/* setup the attributes of the thread        */
92 	/* set the scope to be system to make sure the threads compete on a  */
93 	/* global scale for cpu   */
94 	pthread_attr_init(&attr);
95 	pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
96 
97 	err_ret = 1;		/* Set initial error value to 1 */
98 	/* Create the threads */
99 	for (i = 0; i < NUMTHREADS; i++) {
100 		if (i == 0)
101 			rc = pthread_create(&pt[i], &attr, waiter, retval[i]);
102 		else
103 			rc = pthread_create(&pt[i], &attr, poster, retval[i]);
104 	}
105 
106 	/* Sleep long enough to see that the other threads do what they are supposed to do */
107 	sleep(20);
108 	semunion.val = 1;
109 	semctl(sem_id, 0, IPC_RMID, semunion);
110 	if (err_ret == 1)
111 		tst_resm(TFAIL, "failed");
112 	else
113 		tst_resm(TPASS, "passed");
114 	cleanup();
115 
116 	tst_exit();
117 }
118 
119 /* This thread sleeps 10 seconds then waits on the semaphore.  As long
120    as someone has posted on the semaphore, and no undo has taken
121    place, the semop should complete and we'll print "Waiter done
122    waiting." */
waiter(void * foo)123 void *waiter(void *foo)
124 {
125 	int pid;
126 	pid = getpid();
127 
128 	tst_resm(TINFO, "Waiter, pid = %d", pid);
129 	sleep(10);
130 
131 	tst_resm(TINFO, "Waiter waiting, pid = %d", pid);
132 	semop(sem_id, &Psembuf, 1);
133 	tst_resm(TINFO, "Waiter done waiting");
134 	err_ret = 0;		/* If the message above is displayed, the test is a PASS */
135 	pthread_exit(0);
136 }
137 
138 /* This thread immediately posts on the semaphore and then immediately
139    exits.  If the *thread* exits, the undo should not happen, and the
140    waiter thread which will start waiting on it in 10 seconds, should
141    still get it.   */
poster(void * foo)142 void *poster(void *foo)
143 {
144 	int pid;
145 
146 	pid = getpid();
147 	tst_resm(TINFO, "Poster, pid = %d, posting", pid);
148 	semop(sem_id, &Vsembuf, 1);
149 	tst_resm(TINFO, "Poster posted");
150 	tst_resm(TINFO, "Poster exiting");
151 
152 	pthread_exit(0);
153 }
154 
cleanup(void)155 void cleanup(void)
156 {
157 }
158