4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see http://www.gnu.org/licenses
19 * Please visit http://www.xyratex.com/contact if you need additional
20 * information or have any questions.
26 * Copyright 2012 Xyratex Technology Limited
38 #include <sys/types.h>
41 #include <semaphore.h>
48 struct flock flocks[4] = {
69 .l_start = 2 * LOCK_LEN,
73 /* 2nd & 3rd regions */
78 .l_len = 2 * LOCK_LEN,
88 #define flock_call(fd, num, get, label) \
89 flocks[num].l_type = get == FLOCK_GET ? F_WRLCK : F_UNLCK; \
90 printf("%d: %s lock%d [%llu, %llu]\n", pid, \
91 get == FLOCK_GET ? "taking" : "putting", \
92 num, (unsigned long long)flocks[num].l_start, \
93 (unsigned long long)flocks[num].l_start + flocks[num].l_len); \
94 rc = fcntl(fd, F_SETLKW, &flocks[num]); \
97 fprintf(stderr, "%d: failed to %s lock%d, %s\n", \
98 pid, get == FLOCK_GET ? "take" : "put", \
99 num, strerror(errno)); \
102 printf("%d: done\n", pid); \
107 fprintf(stderr, "lock timeout\n");
111 int main(int argc, char* argv[])
113 struct sigaction act;
116 int fd, i, pid, num = 0, rc = 0;
119 fprintf(stderr, "usage: %s <file>\n", argv[0]);
122 fd = open(argv[1], O_RDWR|O_CREAT, (mode_t)0666);
124 fprintf(stderr, "error open file %s\n", argv[1]);
128 for (i = 0; i < 2; i++) {
135 if (pid == 0 && i == 0) {
138 flock_call(fd, num, FLOCK_GET, err_lock0);
140 printf("%d sleeping 1\n", pid);
143 /* First of all, it should get blocked on flocks[1]
144 * 2nd child. Later, should deadlock with flocks[2]
145 * parent, after cancelling flocks[1] 2nd child. */
146 printf("%d: taking lock3 [%llu, %llu]\n", pid,
147 (unsigned long long)flocks[3].l_start,
148 (unsigned long long)flocks[3].l_start +
150 memset(&act, 0, sizeof(act));
151 act.sa_handler = catch_alarm;
152 sigemptyset(&act.sa_mask);
153 sigaddset(&act.sa_mask, SIGALRM);
154 if (sigaction(SIGALRM, &act, NULL) < 0) {
155 fprintf(stderr, "SIGALRM signal setup failed"
156 ", errno: %d", errno);
161 rc = fcntl(fd, F_SETLKW, &flocks[3]);
163 fprintf(stderr, "%d: should not succeed to "
164 "take lock3\n", pid);
166 flock_call(fd, 3, FLOCK_PUT, err_lock1);
170 if (errno != EDEADLK) {
172 fprintf(stderr, "%d: failed to take lock3: "
173 "%s\n", pid, strerror(errno));
177 printf("%d: expected deadlock\n", pid);
179 flock_call(fd, num, FLOCK_PUT, err_lock0);
181 } else if (pid == 0 && i == 1) {
184 flock_call(fd, 1, FLOCK_GET, err_lock0);
186 /* Let flocks[2] 2nd child get granted and
187 * flocks[3] 1st child, flocks[0] parent get blocked.*/
188 printf("%d sleeping 2\n", pid);
191 flock_call(fd, 1, FLOCK_PUT, err_lock0);
193 } else if (pid && i == 1) {
197 /* Let flocks[1] 2nd child get granted first */
198 printf("%d: sleeping 1\n", pid);
201 flock_call(fd, num, FLOCK_GET, err_lock0);
203 /* Should get blocked on flocks[0], 1st shild
204 * and succeed later. */
205 flock_call(fd, 0, FLOCK_GET, err_lock1);
207 flock_call(fd, 0, FLOCK_PUT, err_lock1);
208 flock_call(fd, num, FLOCK_PUT, err_lock0);
216 waitpid(wpid, &status, 0);
217 rc = WEXITSTATUS(status);
219 printf("%d Exit\n", pid);
224 flocks[num].l_type = F_UNLCK;
225 fcntl(fd, F_SETLKW, &flocks[num]);