2 * Copyright (c) 2017-2020, De Rais <derais@cock.li>
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
30 static int *lock_table
= 0;
31 static size_t lock_table_len
= 0;
32 static int lock_recent
;
35 * Set up the lock files and make sure we can connect to them.
39 * - setup_locks() was not invoked more recently than clean_locks().
41 * Postconditions (success):
43 * - Any other function in this file may be safely called.
46 setup_locks(const struct configuration
*conf
)
56 if (!(lock_table
= calloc(conf
->boards_num
, sizeof *lock_table
))) {
57 PERROR_MESSAGE("malloc");
58 ERROR_MESSAGE("Cannot set up locks");
62 for (size_t j
= 0; j
< conf
->boards_num
; ++j
) {
66 /* Locks for each board */
67 for (size_t j
= 0; j
< conf
->boards_num
; ++j
) {
68 len
= snprintf(0, 0, "%s/lock_board_%s", conf
->work_path
,
69 conf
->boards
[j
].name
);
72 ERROR_MESSAGE("overflow");
76 if (!(path
= malloc(len
+ 1))) {
77 PERROR_MESSAGE("malloc");
81 sprintf(path
, "%s/lock_board_%s", conf
->work_path
,
82 conf
->boards
[j
].name
);
84 if (!(lock_table
[j
] = open(path
, O_RDWR
| O_CREAT
, 0700))) {
85 PERROR_MESSAGE("open");
86 ERROR_MESSAGE("Cannot open or create lock file %s",
95 lock_table_len
= conf
->boards_num
;
97 /* Lock for the recent page */
98 len
= snprintf(0, 0, "%s/lock_recent", conf
->work_path
);
101 ERROR_MESSAGE("overflow");
105 if (!(path
= malloc(len
+ 1))) {
106 PERROR_MESSAGE("malloc");
110 sprintf(path
, "%s/lock_recent", conf
->work_path
);
112 if (!(lock_recent
= open(path
, O_RDWR
| O_CREAT
, 0700))) {
113 PERROR_MESSAGE("open");
114 ERROR_MESSAGE("Cannot open or create lock file %s", path
);
121 /* Now we've got all the locks */
130 * Get a lock for a board
134 * - board_idx represents a board.
136 * - The lock for board_idx is not held in this program.
138 * Postconditions (success):
140 * - The lock for board_idx is now held by this program.
143 lock_acquire(size_t board_idx
)
148 lock_table
[board_idx
] < 0) {
149 ERROR_MESSAGE("lock_table isn't set up yet");
153 if (lockf(lock_table
[board_idx
], F_LOCK
, 0) < 0) {
154 PERROR_MESSAGE("lockf");
155 ERROR_MESSAGE("Cannot lock board %zu", board_idx
);
166 * Get a lock for the recent page
170 * - The lock for the recent page is not held in this program.
172 * Postconditions (success):
174 * - The lock for the recent page is now held by this program.
177 lock_acquire_recent(void)
181 if (lock_recent
< 0) {
182 ERROR_MESSAGE("lock_recent isn't set up yet");
186 if (lockf(lock_recent
, F_LOCK
, 0) < 0) {
187 PERROR_MESSAGE("lockf");
188 ERROR_MESSAGE("Cannot lock recent page");
199 * Release a lock for a board
203 * - board_idx represents a board.
205 * - The lock for board_idx is held in this program.
207 * Postconditions (success):
209 * - The lock for board_idx is now not held by this program.
212 lock_release(size_t board_idx
)
215 lock_table
[board_idx
] < 0) {
219 if (lockf(lock_table
[board_idx
], F_ULOCK
, 0) < 0) {
220 PERROR_MESSAGE("lockf");
221 ERROR_MESSAGE("Cannot release lock for board %zu", board_idx
);
230 * Release a lock for a board
234 * - The lock for the recent page is held in this program.
236 * Postconditions (success):
238 * - The lock for the recent page is now not held by this program.
241 lock_release_recent(void)
243 if (lock_recent
< 0) {
247 if (lockf(lock_recent
, F_ULOCK
, 0) < 0) {
248 PERROR_MESSAGE("lockf");
249 ERROR_MESSAGE("Cannot release lock for recent page");
258 * Clean up any memory from this file
260 * Postconditions (success):
262 * - Valgrind won't report any memory leaks from this file.
264 * - setup_locks() can be safely called again.
273 for (size_t j
= 0; j
< lock_table_len
; ++j
) {
275 close(lock_table
[j
]);
280 lock_release_recent();