mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-09 00:51:29 +00:00
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:
committed by
Gerrit
parent
9f0bfd4609
commit
03d4ed278d
1
Makefile
1
Makefile
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
9
util/lock/build.mk
Normal 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
279
util/lock/csem.c
Normal 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
154
util/lock/csem.h
Normal 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
45
util/lock/gec_lock.c
Normal 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
51
util/lock/gec_lock.h
Normal 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
106
util/lock/ipc_lock.c
Normal 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
71
util/lock/ipc_lock.h
Normal 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
47
util/lock/locks.h
Normal 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__ */
|
||||
Reference in New Issue
Block a user