blob: babcf7abef795be65ac01bc82d2e7d9ead36e8e7 [file] [log] [blame]
David Hendricks4b832f52011-01-20 14:28:34 -08001/*
2 * Copyright (C) 2010 Google Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include <inttypes.h>
20#include <time.h>
21
22#include "csem.h"
23#include "flash.h"
24#include "ipc_lock.h"
25
26static int lock_init(struct ipc_lock *lock)
27{
28 if (lock->sem < 0) {
29 /* get or create the semaphore, init to 1 if needed */
30 int sem = csem_get_or_create(lock->key, 1);
31 if (sem < 0) {
32 return -1;
33 }
34 lock->sem = sem;
35 }
36 return 0;
37}
38
39static void msecs_to_timespec(int msecs, struct timespec *tmspec)
40{
41 tmspec->tv_sec = msecs / 1000;
42 tmspec->tv_nsec = (msecs % 1000) * 1000 * 1000;
43}
44
45int acquire_lock(struct ipc_lock *lock, int timeout_msecs)
46{
47 int ret;
48 struct timespec timeout;
49 struct timespec *timeout_ptr;
50
51 /* initialize the lock */
52 if (lock_init(lock) < 0) {
53 msg_gdbg("%s(): failed to init lock 0x%08x\n",
54 __func__, (uint32_t)lock->key);
55 return -1;
56 }
57
58 /* check if it is already held */
59 if (lock->is_held) {
60 return 1;
61 }
62
63 /* calculate the timeout */
64 if (timeout_msecs >= 0) {
65 timeout_ptr = &timeout;
66 msecs_to_timespec(timeout_msecs, timeout_ptr);
67 } else {
68 timeout_ptr = NULL;
69 }
70
71 /* try to get the lock */
72 ret = csem_down_timeout_undo(lock->sem, timeout_ptr);
73 if (ret < 0) {
74 msg_gdbg("%s(): failed to acquire lock 0x%08x",
75 __func__, (uint32_t)lock->key);
76 return -1;
77 }
78
79 /* success */
80 lock->is_held = 1;
81 return 0;
82}
83
84int release_lock(struct ipc_lock *lock)
85{
86 if (lock->is_held) {
87 lock->is_held = 0;
88 csem_up_undo(lock->sem);
89 /* NOTE: do not destroy the semaphore, we want it to persist */
90 return 0;
91 }
92 /* did not hold the lock */
93 return -1;
94}