Add GEC lock mechanism.

Basically re-use the gec lock code from flashrom package.

BUG=chrome-os-partner:12319
TEST=Build and run on link. Only build on snow.
while true; do ectool hello; done &   ; run 10 instances.
                                      ; expect all instances runs okay.

Signed-off-by: Louis Yung-Chieh Lo <yjlou@chromium.org>
Change-Id: I11d5824f46810c6f5a04a564a81387cdea081697
Reviewed-on: https://gerrit.chromium.org/gerrit/29763
Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
Louis Yung-Chieh Lo
2012-08-09 22:55:51 +08:00
committed by Gerrit
parent 9f0bfd4609
commit 03d4ed278d
11 changed files with 782 additions and 4 deletions

View File

@@ -37,6 +37,7 @@ include core/$(CORE)/build.mk
include common/build.mk
include test/build.mk
include util/build.mk
include util/lock/build.mk
includes+=$(includes-y)

View File

@@ -119,7 +119,8 @@ $(out)/ec_version.h: $(filter-out $(out)/common/version.o,$(objs))
$(build-utils): $(out)/%:%.c
$(call quiet,c_to_build,BUILDCC)
$(host-utils): $(out)/%:%.c $(foreach u,$(host-util-common),util/$(u).c)
$(host-utils): $(out)/%:%.c $(foreach u,$(host-util-common),util/$(u).c) \
$(foreach u,$(util-lock-objs),util/lock/$(u).c)
$(call quiet,c_to_host,HOSTCC )
$(out)/util/burn_my_ec: $(out)/$(PROJECT).bin

View File

@@ -14,6 +14,7 @@
#include "battery.h"
#include "comm-host.h"
#include "lightbar.h"
#include "lock/gec_lock.h"
/* Handy tricks */
#define BUILD_ASSERT(cond) ((void)sizeof(char[1 - 2*!(cond)]))
@@ -21,6 +22,7 @@
/* Don't use a macro where an inline will do... */
static inline int MIN(int a, int b) { return a < b ? a : b; }
#define GEC_LOCK_TIMEOUT_SECS 30 /* 30 secs */
const char help_str[] =
"Commands:\n"
@@ -2168,6 +2170,7 @@ const struct command commands[] = {
int main(int argc, char *argv[])
{
const struct command *cmd;
int rv;
BUILD_ASSERT(ARRAY_SIZE(lb_command_paramcount) == LIGHTBAR_NUM_CMDS);
@@ -2177,17 +2180,28 @@ int main(int argc, char *argv[])
return -2;
}
if (acquire_gec_lock(GEC_LOCK_TIMEOUT_SECS) < 0) {
fprintf(stderr, "Could not acquire GEC lock.\n");
return 1;
}
if (comm_init() < 0)
return -3;
/* Handle commands */
for (cmd = commands; cmd->name; cmd++) {
if (!strcasecmp(argv[1], cmd->name))
return cmd->handler(argc - 1, argv + 1);
if (!strcasecmp(argv[1], cmd->name)) {
rv = cmd->handler(argc - 1, argv + 1);
goto out;
}
}
/* If we're still here, command was unknown */
fprintf(stderr, "Unknown command '%s'\n\n", argv[1]);
print_help(argv[0]);
return -2;
rv = -2;
out:
release_gec_lock();
return rv;
}

9
util/lock/build.mk Normal file
View File

@@ -0,0 +1,9 @@
# -*- makefile -*-
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Lock library
#
util-lock-objs=csem ipc_lock gec_lock

279
util/lock/csem.c Normal file
View File

@@ -0,0 +1,279 @@
/*
* 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(__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;
}

154
util/lock/csem.h Normal file
View File

@@ -0,0 +1,154 @@
/*
* 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 CSEM_H__
#define 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 /* CSEM_H__ */

45
util/lock/gec_lock.c Normal file
View File

@@ -0,0 +1,45 @@
/* 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 "gec_lock.h"
#include "ipc_lock.h"
#include "locks.h"
static struct ipc_lock gec_lock = IPC_LOCK_INIT(GECLOCK);
int acquire_gec_lock(int timeout_secs)
{
return acquire_lock(&gec_lock, timeout_secs * 1000);
}
int release_gec_lock(void)
{
return release_lock(&gec_lock);
}

51
util/lock/gec_lock.h Normal file
View File

@@ -0,0 +1,51 @@
/* 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.
*/
#ifndef GEC_LOCK_H__
#define GEC_LOCK_H__
/*
* acquire_gec_lock - acquire global lock
*
* returns 0 to indicate lock acquired
* returns >0 to indicate lock was already held
* returns <0 to indicate failed to acquire lock
*/
extern int acquire_gec_lock(int timeout_secs);
/*
* release_gec_lock - release global lock
*
* returns 0 if lock was released successfully
* returns -1 if lock had not been held before the call
*/
extern int release_gec_lock(void);
#endif /* GEC_LOCK_H__ */

106
util/lock/ipc_lock.c Normal file
View File

@@ -0,0 +1,106 @@
/* 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;
}

71
util/lock/ipc_lock.h Normal file
View File

@@ -0,0 +1,71 @@
/* 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.
*/
#ifndef IPC_LOCK_H__
#define IPC_LOCK_H__
#include <sys/ipc.h>
struct ipc_lock {
key_t key; /* provided by the developer */
int sem; /* internal */
int is_held; /* internal */
};
/* don't use C99 initializers here, so this can be used in C++ code */
#define IPC_LOCK_INIT(key) \
{ \
key, /* name */ \
-1, /* sem */ \
0, /* is_held */ \
}
/*
* acquire_lock: acquire a lock
*
* timeout <0 = no timeout (try forever)
* timeout 0 = do not wait (return immediately)
* timeout >0 = wait up to $timeout milliseconds (subject to kernel scheduling)
*
* return 0 = lock acquired
* return >0 = lock was already held
* return <0 = failed to acquire lock
*/
extern int acquire_lock(struct ipc_lock *lock, int timeout_msecs);
/*
* release_lock: release a lock
*
* returns 0 if lock was released successfully
* returns -1 if lock had not been held before the call
*/
extern int release_lock(struct ipc_lock *lock);
#endif /* IPC_LOCK_H__ */

47
util/lock/locks.h Normal file
View File

@@ -0,0 +1,47 @@
/* 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.
*/
#ifndef LOCKS_H__
#define 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)
#endif /* LOCKS_H__ */