diff options
-rw-r--r-- | util/lock/build.mk | 2 | ||||
-rw-r--r-- | util/lock/csem.c | 275 | ||||
-rw-r--r-- | util/lock/csem.h | 154 | ||||
-rw-r--r-- | util/lock/file_lock.c | 251 | ||||
-rw-r--r-- | util/lock/gec_lock.c | 2 | ||||
-rw-r--r-- | util/lock/ipc_lock.c | 105 | ||||
-rw-r--r-- | util/lock/ipc_lock.h | 16 | ||||
-rw-r--r-- | util/lock/locks.h | 15 |
8 files changed, 263 insertions, 557 deletions
diff --git a/util/lock/build.mk b/util/lock/build.mk index 6cf595b995..48c152d830 100644 --- a/util/lock/build.mk +++ b/util/lock/build.mk @@ -6,5 +6,5 @@ # Lock library # -util-lock-objs=csem.o ipc_lock.o gec_lock.o +util-lock-objs=file_lock.o gec_lock.o util-lock-objs+=android.o diff --git a/util/lock/csem.c b/util/lock/csem.c deleted file mode 100644 index 2ad3d5d873..0000000000 --- a/util/lock/csem.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright 2003 Sun Microsystems, Inc. - * Copyright 2010 Google, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Developer's note: This was open sourced by Sun Microsystems, which got it - * via Cobalt Networks. It has been fairly extensively modified since then. - */ - -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif -#include <sys/types.h> -#include <sys/ipc.h> -#include <sys/sem.h> -#include <sys/stat.h> -#include <time.h> -#include <errno.h> -#include <sched.h> - -#include "csem.h" - -#if (defined(__BIONIC__) || defined(__GNU_LIBRARY__)) && !defined(_SEM_SEMUN_UNDEFINED) -/* union semun is defined by including <sys/sem.h> */ -#else -/* according to X/OPEN we have to define it ourselves */ -union semun { - int val; /* value for SETVAL */ - struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ - unsigned short int *array; /* array for GETALL, SETALL */ - struct seminfo *__buf; /* buffer for IPC_INFO */ -}; -#endif - -/* - * On some platforms semctl(SETVAL) sets sem_otime, on other platforms it - * does not. Figure out what this platform does. - * - * Returns 0 if semctl(SETVAL) does not set sem_otime - * Returns 1 if semctl(SETVAL) does set sem_otime - * Returns -1 on error - */ -static int does_semctl_set_otime(void) -{ - int sem_id; - int ret; - - /* create a test semaphore */ - sem_id = semget(IPC_PRIVATE, 1, S_IRUSR|S_IWUSR); - if (sem_id < 0) - return -1; - - /* set the value */ - if (csem_setval(sem_id, 1) < 0) { - csem_destroy(sem_id); - return -1; - } - - /* read sem_otime */ - ret = (csem_get_otime(sem_id) > 0) ? 1 : 0; - - /* clean up */ - csem_destroy(sem_id); - - return ret; -} - -int csem_create(key_t key, unsigned val) -{ - static int need_otime_hack = -1; - int sem_id; - - /* see if we need to trigger a semop to set sem_otime */ - if (need_otime_hack < 0) { - int ret = does_semctl_set_otime(); - if (ret < 0) - return -1; - - need_otime_hack = !ret; - } - - /* create it or fail */ - sem_id = semget(key, 1, IPC_CREAT|IPC_EXCL | S_IRUSR|S_IWUSR); - if (sem_id < 0) - return -1; - - /* initalize the value */ - if (need_otime_hack) - val++; - - if (csem_setval(sem_id, val) < 0) { - csem_destroy(sem_id); - return -1; - } - - if (need_otime_hack) { - /* force sem_otime to change */ - csem_down(sem_id); - } - - return sem_id; -} - -/* how many times to loop, waiting for sem_otime */ -#define MAX_OTIME_LOOPS 1000 - -int csem_get(key_t key) -{ - int sem_id; - int i; - - /* CSEM_PRIVATE needs to go through csem_create() to get an - * initial value */ - if (key == CSEM_PRIVATE) { - errno = EINVAL; - return -1; - } - - /* get the (assumed existing) semaphore */ - sem_id = semget(key, 1, S_IRUSR|S_IWUSR); - if (sem_id < 0) - return -1; - - /* loop until sem_otime != 0, which means it has been initialized */ - for (i = 0; i < MAX_OTIME_LOOPS; i++) { - time_t otime = csem_get_otime(sem_id); - if (otime < 0) { - /* error */ - return -1; - } - if (otime > 0) { - /* success */ - return sem_id; - } - /* retry */ - sched_yield(); - } - - /* fell through - error */ - return -1; -} - -int csem_get_or_create(key_t key, unsigned val) -{ - int sem_id; - - /* try to create the semaphore */ - sem_id = csem_create(key, val); - if (sem_id >= 0 || errno != EEXIST) { - /* it either succeeded or got an error */ - return sem_id; - } - - /* it must exist already - get it */ - sem_id = csem_get(key); - if (sem_id < 0) - return -1; - - return sem_id; -} - -int csem_destroy(int sem_id) -{ - return semctl(sem_id, 0, IPC_RMID); -} - -int csem_getval(int sem_id) -{ - return semctl(sem_id, 0, GETVAL); -} - -int csem_setval(int sem_id, unsigned val) -{ - union semun arg; - arg.val = val; - if (semctl(sem_id, 0, SETVAL, arg) < 0) - return -1; - - return 0; -} - -static int csem_up_undoflag(int sem_id, int undoflag) -{ - struct sembuf sops; - sops.sem_num = 0; - sops.sem_op = 1; - sops.sem_flg = undoflag; - return semop(sem_id, &sops, 1); -} - -int csem_up(int sem_id) -{ - return csem_up_undoflag(sem_id, 0); -} - -int csem_up_undo(int sem_id) -{ - return csem_up_undoflag(sem_id, SEM_UNDO); -} - -static int csem_down_undoflag(int sem_id, int undoflag) -{ - struct sembuf sops; - sops.sem_num = 0; - sops.sem_op = -1; - sops.sem_flg = undoflag; - return semop(sem_id, &sops, 1); -} - -int csem_down(int sem_id) -{ - return csem_down_undoflag(sem_id, 0); -} - -int csem_down_undo(int sem_id) -{ - return csem_down_undoflag(sem_id, SEM_UNDO); -} - -static int csem_down_timeout_undoflag(int sem_id, - struct timespec *timeout, - int undoflag) -{ - struct sembuf sops; - sops.sem_num = 0; - sops.sem_op = -1; - sops.sem_flg = undoflag; - return semtimedop(sem_id, &sops, 1, timeout); -} - -int csem_down_timeout(int sem_id, struct timespec *timeout) -{ - return csem_down_timeout_undoflag(sem_id, timeout, 0); -} - -int csem_down_timeout_undo(int sem_id, struct timespec *timeout) -{ - return csem_down_timeout_undoflag(sem_id, timeout, SEM_UNDO); -} - -time_t csem_get_otime(int sem_id) -{ - union semun arg; - struct semid_ds ds; - arg.buf = &ds; - if (semctl(sem_id, 0, IPC_STAT, arg) < 0) - return -1; - - return ds.sem_otime; -} diff --git a/util/lock/csem.h b/util/lock/csem.h deleted file mode 100644 index 469a824259..0000000000 --- a/util/lock/csem.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2003 Sun Microsystems, Inc. - * Copyright 2010 Google, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Developer's note: This was open sourced by Sun Microsystems, which got it - * via Cobalt Networks. It has been fairly extensively modified since then. - */ - -#ifndef __UTIL_CSEM_H -#define __UTIL_CSEM_H - -#include <sys/ipc.h> -#include <time.h> - -/* create a private key */ -#define CSEM_PRIVATE IPC_PRIVATE - -/* - * Create a new semaphore with the specified key, initialized to the - * specified value. If the key is CSEM_PRIVATE, a new private semaphore - * is allocated. - * - * Returns the sempahore ID (>= 0) on success. - * Returns < 0 on error, or if the key already exists. - */ -extern int csem_create(key_t key, unsigned val); - -/* - * Fetch an existing semaphore with the specified key. - * - * Returns the sempahore ID (>= 0) on success. - * Returns < 0 on error, or if the key does not exist. - */ -extern int csem_get(key_t key); - -/* - * Fetch or create a semaphore with the specified key. If the semaphore - * did not exist, it will be created with the specified value. - * - * Returns the sempahore ID (>= 0) on success. - * Returns < 0 on error. - */ -extern int csem_get_or_create(key_t key, unsigned val); - -/* - * Destroy the semaphore. - * - * Returns 0 on success. - * Returns < 0 on error. - */ -extern int csem_destroy(int sem_id); - -/* - * Get the value of the semaphore. - * - * Returns the value (>= 0) on success. - * Returns < 0 on error. - */ -extern int csem_getval(int sem_id); - -/* - * Set the value of the semaphore. - * - * Returns 0 on success. - * Returns < 0 on error. - */ -extern int csem_setval(int sem_id, unsigned val); - -/* - * Increment the semaphore. - * - * Returns 0 on success. - * Returns < 0 on error. - */ -extern int csem_up(int sem_id); - -/* - * Increment the semaphore. This operation will be undone when the - * process terminates. - * - * Returns 0 on success. - * Returns < 0 on error. - */ -extern int csem_up_undo(int sem_id); - -/* - * Decrement the semaphore, or block if sem == 0. - * - * Returns 0 on success. - * Returns < 0 on error. - */ -extern int csem_down(int sem_id); - -/* - * Decrement the semaphore, or block if sem == 0. This operation will be - * undone when the process terminates. - * - * Returns 0 on success. - * Returns < 0 on error. - */ -extern int csem_down_undo(int sem_id); - -/* - * Decrement the semaphore, or block with a timeout if sem == 0. - * - * Returns 0 on success. - * Returns < 0 on error. - */ -extern int csem_down_timeout(int sem_id, struct timespec *timeout); - -/* - * Decrement the semaphore, or block with a timeout if sem == 0. This - * operation will be undone when the process terminates. - * - * Returns 0 on success. - * Returns < 0 on error. - */ -extern int csem_down_timeout_undo(int sem_id, struct timespec *timeout); - -/* - * Get the timestamp of the last csem_up()/csem_down() call. - * - * Returns sem_otime on success. - * Returns < 0 on error - */ -extern time_t csem_get_otime(int sem_id); - -#endif /* __UTIL_CSEM_H */ diff --git a/util/lock/file_lock.c b/util/lock/file_lock.c new file mode 100644 index 0000000000..94f5991172 --- /dev/null +++ b/util/lock/file_lock.c @@ -0,0 +1,251 @@ +/* Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * file_lock.c: Implementation for a binary semaphore using a file lock. + * + * Warning: This relies on flock() which is known to be broken on NFS. + * + * The file will remain persistent once the lock has been used. Unfortunately, + * unlinking the file can introduce a race condition so we leave the file + * in place. + * + * The current process's PID will be written to the file for debug purposes. + */ + +#include <errno.h> +#include <fcntl.h> +#include <inttypes.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/file.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "android.h" +#include "ipc_lock.h" +#include "locks.h" + +#define SLEEP_INTERVAL_MS 50 + +static void msecs_to_timespec(int msecs, struct timespec *tmspec) +{ + tmspec->tv_sec = msecs / 1000; + tmspec->tv_nsec = (msecs % 1000) * 1000 * 1000; +} + +static int lock_is_held(struct ipc_lock *lock) +{ + return lock->is_held; +} + +static int file_lock_open_or_create(struct ipc_lock *lock) +{ + struct stat s; + char path[PATH_MAX]; + + if (in_android()) { + char *tmpdir; + + tmpdir = android_tmpdir_path(); + if (!tmpdir) + return -1; + + if (snprintf(path, sizeof(path), "%s/%s", + tmpdir, lock->filename) < 0) { + return -1; + } + } else { + if (snprintf(path, sizeof(path), "%s", SYSTEM_LOCKFILE_DIR) < 0) + return -1; + + if (lstat(path, &s) < 0) { + fprintf(stderr, "Cannot stat %s", path); + return -1; + } + + if (!S_ISDIR(s.st_mode)) { + fprintf(stderr, "%s is not a directory.\n", path); + return -1; + } + + if (strlen(path) + strlen(lock->filename) + 2 > PATH_MAX) { + fprintf(stderr, "Lockfile path too long.\n"); + return -1; + } + strcat(path, "/"); + strcat(path, lock->filename); + } + + lock->fd = open(path, O_RDWR | O_CREAT, 0600); + if (lock->fd < 0) { + fprintf(stderr, "Cannot open lockfile %s", path); + return -1; + } + + return 0; +} + +static int file_lock_get(struct ipc_lock *lock, int timeout_msecs) +{ + int msecs_remaining = timeout_msecs; + struct timespec sleep_interval, rem; + int ret = -1; + + if (timeout_msecs == 0) + return flock(lock->fd, LOCK_EX | LOCK_NB); + + msecs_to_timespec(SLEEP_INTERVAL_MS, &sleep_interval); + + while ((ret = flock(lock->fd, LOCK_EX | LOCK_NB)) != 0) { + if (errno != EWOULDBLOCK) { + fprintf(stderr, "Error obtaining lock"); + return -1; + } + + if (msecs_remaining < SLEEP_INTERVAL_MS) + msecs_to_timespec(msecs_remaining, &sleep_interval); + + while (nanosleep(&sleep_interval, &rem) != 0) { + if (errno == EINTR) { + sleep_interval = rem; + continue; + } else { + fprintf(stderr, "nanosleep() failed"); + return ret; + } + } + + if (timeout_msecs < 0) + continue; + + msecs_remaining -= SLEEP_INTERVAL_MS; + if (msecs_remaining < 0) + break; + } + + if (ret != 0) { + fprintf(stderr, "Timed out waiting for file lock.\n"); + return -1; + } + + return 0; +} + +static int file_lock_write_pid(struct ipc_lock *lock) +{ + ssize_t len; + /* + * PIDs are usually 5 digits, but we'll reserve enough room for + * a value of 2^32 (10 digits) out of paranoia. + */ + char pid_str[11]; + + if (ftruncate(lock->fd, 0) < 0) { + fprintf(stderr, "Cannot truncate lockfile"); + return -1; + } + + snprintf(pid_str, sizeof(pid_str), "%lu", (unsigned long)getpid()); + len = write(lock->fd, pid_str, strlen(pid_str)); + if (len < 0) { + fprintf(stderr, "Cannot write PID to lockfile"); + return -1; + } + + return 0; +} + +static void file_lock_release(struct ipc_lock *lock) +{ + if (flock(lock->fd, LOCK_UN) < 0) + fprintf(stderr, "Cannot release lock"); + + if (close(lock->fd) < 0) + fprintf(stderr, "Cannot close lockfile"); +} + +/* + * timeout <0 = no timeout (try forever) + * timeout 0 = do not wait (return immediately) + * timeout >0 = wait up to $timeout milliseconds + * + * returns 0 to indicate lock acquired + * returns >0 to indicate lock was already held + * returns <0 to indicate failed to acquire lock + */ +int acquire_lock(struct ipc_lock *lock, int timeout_msecs) +{ + /* check if it is already held */ + if (lock_is_held(lock)) + return 1; + + if (file_lock_open_or_create(lock)) + return -1; + + if (file_lock_get(lock, timeout_msecs)) { + lock->is_held = 0; + close(lock->fd); + return -1; + } else { + lock->is_held = 1; + } + + /* + * Write PID to lockfile for debug purposes. Failure to write to + * the file should not be considered fatal. There might be something + * bad happening with the filesystem, but the lock has already been + * obtained and we may need our tools for diagnostics and repairs + * so we should continue anyway. + */ + file_lock_write_pid(lock); + return 0; +} + +/* + * returns 0 if lock was released successfully + * returns -1 if lock had not been held before the call + */ +int release_lock(struct ipc_lock *lock) +{ + if (lock_is_held(lock)) { + file_lock_release(lock); + lock->is_held = 0; + return 0; + } + + return -1; +} diff --git a/util/lock/gec_lock.c b/util/lock/gec_lock.c index 4df231af3e..d354ea08f3 100644 --- a/util/lock/gec_lock.c +++ b/util/lock/gec_lock.c @@ -32,7 +32,7 @@ #include "ipc_lock.h" #include "locks.h" -static struct ipc_lock gec_lock = IPC_LOCK_INIT(GECLOCK); +static struct ipc_lock gec_lock = LOCKFILE_INIT(CROS_EC_LOCKFILE_NAME); int acquire_gec_lock(int timeout_secs) { diff --git a/util/lock/ipc_lock.c b/util/lock/ipc_lock.c deleted file mode 100644 index 790014e67b..0000000000 --- a/util/lock/ipc_lock.c +++ /dev/null @@ -1,105 +0,0 @@ -/* Copyright 2012, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <inttypes.h> -#include <stdio.h> -#include <time.h> - -#include "csem.h" -#include "ipc_lock.h" - -static int lock_init(struct ipc_lock *lock) -{ - if (lock->sem < 0) { - /* get or create the semaphore, init to 1 if needed */ - int sem = csem_get_or_create(lock->key, 1); - if (sem < 0) - return -1; - - lock->sem = sem; - } - return 0; -} - -static void msecs_to_timespec(int msecs, struct timespec *tmspec) -{ - tmspec->tv_sec = msecs / 1000; - tmspec->tv_nsec = (msecs % 1000) * 1000 * 1000; -} - -int acquire_lock(struct ipc_lock *lock, int timeout_msecs) -{ - int ret; - struct timespec timeout; - struct timespec *timeout_ptr; - - /* initialize the lock */ - if (lock_init(lock) < 0) { - fprintf(stderr, "%s(): failed to init lock 0x%08x\n", - __func__, (uint32_t)lock->key); - return -1; - } - - /* check if it is already held */ - if (lock->is_held) - return 1; - - /* calculate the timeout */ - if (timeout_msecs >= 0) { - timeout_ptr = &timeout; - msecs_to_timespec(timeout_msecs, timeout_ptr); - } else { - timeout_ptr = NULL; - } - - /* try to get the lock */ - ret = csem_down_timeout_undo(lock->sem, timeout_ptr); - if (ret < 0) { - fprintf(stderr, "%s(): failed to acquire lock 0x%08x\n", - __func__, (uint32_t)lock->key); - return -1; - } - - /* success */ - lock->is_held = 1; - return 0; -} - -int release_lock(struct ipc_lock *lock) -{ - if (lock->is_held) { - lock->is_held = 0; - csem_up_undo(lock->sem); - /* NOTE: do not destroy the semaphore, we want it to persist */ - return 0; - } - /* did not hold the lock */ - return -1; -} diff --git a/util/lock/ipc_lock.h b/util/lock/ipc_lock.h index 39ae277a7e..ca739ac04e 100644 --- a/util/lock/ipc_lock.h +++ b/util/lock/ipc_lock.h @@ -31,20 +31,18 @@ #ifndef __UTIL_IPC_LOCK_H #define __UTIL_IPC_LOCK_H -#include <sys/ipc.h> - struct ipc_lock { - key_t key; /* provided by the developer */ - int sem; /* internal */ - int is_held; /* internal */ + int is_held; /* internal */ + char *filename; /* provided by the developer */ + int fd; /* internal */ }; /* don't use C99 initializers here, so this can be used in C++ code */ -#define IPC_LOCK_INIT(key) \ +#define LOCKFILE_INIT(lockfile) \ { \ - key, /* name */ \ - -1, /* sem */ \ - 0, /* is_held */ \ + 0, /* is_held */ \ + lockfile, /* filename */ \ + -1, /* fd */ \ } /* diff --git a/util/lock/locks.h b/util/lock/locks.h index 74360883fd..e87c36d73b 100644 --- a/util/lock/locks.h +++ b/util/lock/locks.h @@ -31,17 +31,8 @@ #ifndef __UTIL_LOCKS_H #define __UTIL_LOCKS_H -/* this is the base key, since we have to pick something global */ -#define IPC_LOCK_KEY (0x67736c00 & 0xfffffc00) /* 22 bits "gsl" */ - -/* The ordering of the following keys matters a lot. We don't want to reorder - * keys and have a new binary dependent on deployed/used because it will break - * atomicity of existing users and binaries. In other words, DO NOT REORDER. */ - -/* this is the "big lock". */ -#define BIGLOCK (IPC_LOCK_KEY + 0) - -/* for Google EC */ -#define GECLOCK (IPC_LOCK_KEY + 1) +#define SYSTEM_LOCKFILE_DIR "/var/run/lock" +#define LOCKFILE_NAME "firmware_utility_lock" +#define CROS_EC_LOCKFILE_NAME "cros_ec_lock" #endif /* __UTIL_LOCKS_H */ |