blob: 6377d8bff9efc9687c0d857bad6d539ef7ce2d61 [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
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
robbiew95ae8f62002-03-06 18:24:32 +000018 */
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
subrata_modak4bb656a2009-02-26 12:02:09 +000025 * sempaphore value performed by that semop should be "undone" only when the
robbiew95ae8f62002-03-06 18:24:32 +000026 * 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
plars5c34fa32003-07-05 03:43:44 +000040 * 07/04/2003 Paul Larson (plars@linuxtestproject.org)
41 * -ported to LTP
robbiew95ae8f62002-03-06 18:24:32 +000042 *
43 */
plars5c34fa32003-07-05 03:43:44 +000044#include "test.h"
plars5c34fa32003-07-05 03:43:44 +000045
robbiew95ae8f62002-03-06 18:24:32 +000046#include <stdio.h>
robbiewb59499d2002-03-28 19:21:32 +000047#include <stdlib.h>
robbiew95ae8f62002-03-06 18:24:32 +000048#include <unistd.h>
49#include <sys/sem.h>
50#include <errno.h>
51#include <pthread.h>
robbiewb59499d2002-03-28 19:21:32 +000052#include <sys/types.h>
53#include <sys/ipc.h>
robbiew95ae8f62002-03-06 18:24:32 +000054
55#define KEY IPC_PRIVATE
56
57#define NUMTHREADS 2
58
subrata_modak4bb656a2009-02-26 12:02:09 +000059void *retval[NUMTHREADS];
Wanlong Gao354ebb42012-12-07 10:10:04 +080060void *waiter(void *);
61void *poster(void *);
plars5c34fa32003-07-05 03:43:44 +000062void cleanup(void);
63
64char *TCID = "sem02";
65int TST_TOTAL = 1;
robbiew95ae8f62002-03-06 18:24:32 +000066
Wanlong Gao354ebb42012-12-07 10:10:04 +080067struct sembuf Psembuf = { 0, -1, SEM_UNDO };
68struct sembuf Vsembuf = { 0, 1, SEM_UNDO };
robbiew95ae8f62002-03-06 18:24:32 +000069
robbiewb59499d2002-03-28 19:21:32 +000070union semun {
Wanlong Gao354ebb42012-12-07 10:10:04 +080071 int val; /* value for SETVAL */
72 struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
73 unsigned short *array; /* array for GETALL & SETALL */
74 struct seminfo *ipc_buf; /* buffer for IPC_INFO */
robbiewb59499d2002-03-28 19:21:32 +000075};
76
robbiew95ae8f62002-03-06 18:24:32 +000077int sem_id;
Wanlong Gao354ebb42012-12-07 10:10:04 +080078int err_ret; /* This is used to determine PASS/FAIL status */
plars5c34fa32003-07-05 03:43:44 +000079int main(int argc, char **argv)
robbiew95ae8f62002-03-06 18:24:32 +000080{
Wanlong Gao354ebb42012-12-07 10:10:04 +080081 int i, rc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020082 const char *msg;
Wanlong Gao354ebb42012-12-07 10:10:04 +080083 union semun semunion;
Garrett Cooper2c282152010-12-16 00:55:50 -080084
Wanlong Gao354ebb42012-12-07 10:10:04 +080085 pthread_t pt[NUMTHREADS];
86 pthread_attr_t attr;
robbiew95ae8f62002-03-06 18:24:32 +000087
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020088 if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL)
Wanlong Gao354ebb42012-12-07 10:10:04 +080089 tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg);
Wanlong Gao354ebb42012-12-07 10:10:04 +080090 /* Create the semaphore set */
91 sem_id = semget(KEY, 1, 0666 | IPC_CREAT);
92 if (sem_id < 0) {
93 printf("semget failed, errno = %d\n", errno);
94 exit(1);
95 }
96 /* initialize data structure associated to the semaphore */
97 semunion.val = 1;
98 semctl(sem_id, 0, SETVAL, semunion);
robbiew22452342003-02-27 17:03:52 +000099
Wanlong Gao354ebb42012-12-07 10:10:04 +0800100 /* setup the attributes of the thread */
101 /* set the scope to be system to make sure the threads compete on a */
102 /* global scale for cpu */
103 pthread_attr_init(&attr);
104 pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
robbiew95ae8f62002-03-06 18:24:32 +0000105
Wanlong Gao354ebb42012-12-07 10:10:04 +0800106 err_ret = 1; /* Set initial error value to 1 */
107 /* Create the threads */
108 for (i = 0; i < NUMTHREADS; i++) {
109 if (i == 0)
110 rc = pthread_create(&pt[i], &attr, waiter, retval[i]);
111 else
112 rc = pthread_create(&pt[i], &attr, poster, retval[i]);
113 }
robbiew95ae8f62002-03-06 18:24:32 +0000114
Wanlong Gao354ebb42012-12-07 10:10:04 +0800115 /* Sleep long enough to see that the other threads do what they are supposed to do */
116 sleep(20);
117 semunion.val = 1;
118 semctl(sem_id, 0, IPC_RMID, semunion);
119 if (err_ret == 1)
120 tst_resm(TFAIL, "failed");
121 else
122 tst_resm(TPASS, "passed");
123 cleanup();
Garrett Cooper2c282152010-12-16 00:55:50 -0800124
Wanlong Gao354ebb42012-12-07 10:10:04 +0800125 tst_exit();
robbiew95ae8f62002-03-06 18:24:32 +0000126}
127
robbiew95ae8f62002-03-06 18:24:32 +0000128/* This thread sleeps 10 seconds then waits on the semaphore. As long
129 as someone has posted on the semaphore, and no undo has taken
130 place, the semop should complete and we'll print "Waiter done
131 waiting." */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800132void *waiter(void *foo)
robbiew95ae8f62002-03-06 18:24:32 +0000133{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800134 int pid;
135 pid = getpid();
robbiew95ae8f62002-03-06 18:24:32 +0000136
Wanlong Gao354ebb42012-12-07 10:10:04 +0800137 tst_resm(TINFO, "Waiter, pid = %d", pid);
138 sleep(10);
robbiew95ae8f62002-03-06 18:24:32 +0000139
Wanlong Gao354ebb42012-12-07 10:10:04 +0800140 tst_resm(TINFO, "Waiter waiting, pid = %d", pid);
141 semop(sem_id, &Psembuf, 1);
142 tst_resm(TINFO, "Waiter done waiting");
143 err_ret = 0; /* If the message above is displayed, the test is a PASS */
144 pthread_exit(0);
robbiew95ae8f62002-03-06 18:24:32 +0000145}
146
147/* This thread immediately posts on the semaphore and then immediately
148 exits. If the *thread* exits, the undo should not happen, and the
149 waiter thread which will start waiting on it in 10 seconds, should
150 still get it. */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800151void *poster(void *foo)
robbiew95ae8f62002-03-06 18:24:32 +0000152{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800153 int pid;
Garrett Cooper2c282152010-12-16 00:55:50 -0800154
Wanlong Gao354ebb42012-12-07 10:10:04 +0800155 pid = getpid();
156 tst_resm(TINFO, "Poster, pid = %d, posting", pid);
157 semop(sem_id, &Vsembuf, 1);
158 tst_resm(TINFO, "Poster posted");
159 tst_resm(TINFO, "Poster exiting");
Garrett Cooper2c282152010-12-16 00:55:50 -0800160
Wanlong Gao354ebb42012-12-07 10:10:04 +0800161 pthread_exit(0);
robbiew95ae8f62002-03-06 18:24:32 +0000162}
plars5c34fa32003-07-05 03:43:44 +0000163
164void cleanup(void)
165{
Garrett Cooperb0a973a2011-01-21 01:15:32 -0800166}