diff options
Diffstat (limited to 'util/lock/csem.c')
-rw-r--r-- | util/lock/csem.c | 275 |
1 files changed, 0 insertions, 275 deletions
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; -} |