2 * Copyright (c) 2017-2018, 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.
45 int setup_locks(const struct configuration
*conf
)
55 if (!(lock_table
= calloc(conf
->boards_num
, sizeof *lock_table
))) {
56 PERROR_MESSAGE("malloc");
57 ERROR_MESSAGE("Cannot set up locks");
61 for (size_t j
= 0; j
< conf
->boards_num
; ++j
) {
65 /* Locks for each board */
66 for (size_t j
= 0; j
< conf
->boards_num
; ++j
) {
67 len
= snprintf(0, 0, "%s/lock_board_%s", conf
->work_path
,
68 conf
->boards
[j
].name
);
71 ERROR_MESSAGE("overflow");
75 if (!(path
= malloc(len
+ 1))) {
76 PERROR_MESSAGE("malloc");
80 sprintf(path
, "%s/lock_board_%s", conf
->work_path
,
81 conf
->boards
[j
].name
);
83 if (!(lock_table
[j
] = open(path
, O_RDWR
| O_CREAT
, 0700))) {
84 PERROR_MESSAGE("open");
85 ERROR_MESSAGE("Cannot open or create lock file %s",
94 lock_table_len
= conf
->boards_num
;
96 /* Lock for the recent page */
97 len
= snprintf(0, 0, "%s/lock_recent", conf
->work_path
);
100 ERROR_MESSAGE("overflow");
104 if (!(path
= malloc(len
+ 1))) {
105 PERROR_MESSAGE("malloc");
109 sprintf(path
, "%s/lock_recent", conf
->work_path
);
111 if (!(lock_recent
= open(path
, O_RDWR
| O_CREAT
, 0700))) {
112 PERROR_MESSAGE("open");
113 ERROR_MESSAGE("Cannot open or create lock file %s", path
);
120 /* Now we've got all the locks */
129 * Get a lock for a board
133 * - board_idx represents a board.
135 * - The lock for board_idx is not held in this program.
137 * Postconditions (success):
139 * - The lock for board_idx is now held by this program.
141 int lock_acquire(size_t board_idx
)
146 lock_table
[board_idx
] < 0) {
147 ERROR_MESSAGE("lock_table isn't set up yet");
151 if (lockf(lock_table
[board_idx
], F_LOCK
, 0) < 0) {
152 PERROR_MESSAGE("lockf");
153 ERROR_MESSAGE("Cannot lock board %zu", board_idx
);
164 * Get a lock for the recent page
168 * - The lock for the recent page is not held in this program.
170 * Postconditions (success):
172 * - The lock for the recent page is now held by this program.
174 int lock_acquire_recent(void)
178 if (lock_recent
< 0) {
179 ERROR_MESSAGE("lock_recent isn't set up yet");
183 if (lockf(lock_recent
, F_LOCK
, 0) < 0) {
184 PERROR_MESSAGE("lockf");
185 ERROR_MESSAGE("Cannot lock recent page");
196 * Release a lock for a board
200 * - board_idx represents a board.
202 * - The lock for board_idx is held in this program.
204 * Postconditions (success):
206 * - The lock for board_idx is now not held by this program.
208 int lock_release(size_t board_idx
)
211 lock_table
[board_idx
] < 0) {
215 if (lockf(lock_table
[board_idx
], F_ULOCK
, 0) < 0) {
216 PERROR_MESSAGE("lockf");
217 ERROR_MESSAGE("Cannot release lock for board %zu", board_idx
);
226 * Release a lock for a board
230 * - The lock for the recent page is held in this program.
232 * Postconditions (success):
234 * - The lock for the recent page is now not held by this program.
236 int lock_release_recent(void)
238 if (lock_recent
< 0) {
242 if (lockf(lock_recent
, F_ULOCK
, 0) < 0) {
243 PERROR_MESSAGE("lockf");
244 ERROR_MESSAGE("Cannot release lock for recent page");
253 * Clean up any memory from this file
255 * Postconditions (success):
257 * - Valgrind won't report any memory leaks from this file.
259 * - setup_locks() can be safely called again.
261 int clean_locks(void)
267 for (size_t j
= 0; j
< lock_table_len
; ++j
) {
269 close(lock_table
[j
]);
274 lock_release_recent();