1 /*
2 * locks.c
3 *
4 * Code for abstracting locks in IPMI
5 *
6 * Author: MontaVista Software, Inc.
7 * Corey Minyard <minyard@mvista.com>
8 * source@mvista.com
9 *
10 * Copyright 2004,2005 MontaVista Software Inc.
11 *
12 * This software is available to you under a choice of one of two
13 * licenses. You may choose to be licensed under the terms of the GNU
14 * Lesser General Public License (GPL) Version 2 or the modified BSD
15 * license below. The following disclamer applies to both licenses:
16 *
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
25 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
26 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * GNU Lesser General Public Licence
29 *
30 * This program is free software; you can redistribute it and/or
31 * modify it under the terms of the GNU Lesser General Public License
32 * as published by the Free Software Foundation; either version 2 of
33 * the License, or (at your option) any later version.
34 *
35 * You should have received a copy of the GNU Lesser General Public
36 * License along with this program; if not, write to the Free
37 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38 *
39 * Modified BSD Licence
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 *
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above
48 * copyright notice, this list of conditions and the following
49 * disclaimer in the documentation and/or other materials provided
50 * with the distribution.
51 * 3. The name of the author may not be used to endorse or promote
52 * products derived from this software without specific prior
53 * written permission.
54 */
55
56 #include <stdlib.h>
57 #include <errno.h>
58
59 #include <OpenIPMI/ipmi_debug.h>
60
61 #include <OpenIPMI/internal/ipmi_malloc.h>
62 #include <OpenIPMI/internal/ipmi_locks.h>
63
64 struct ipmi_lock_s
65 {
66 os_hnd_lock_t *ll_lock;
67 os_handler_t *os_hnd;
68 };
69
70 int i__ipmi_debug_locks = 0;
71
72 int
ipmi_create_lock_os_hnd(os_handler_t * os_hnd,ipmi_lock_t ** new_lock)73 ipmi_create_lock_os_hnd(os_handler_t *os_hnd, ipmi_lock_t **new_lock)
74 {
75 ipmi_lock_t *lock;
76 int rv;
77
78 lock = ipmi_mem_alloc(sizeof(*lock));
79 if (!lock)
80 return ENOMEM;
81
82 lock->os_hnd = os_hnd;
83 if (lock->os_hnd && lock->os_hnd->create_lock) {
84 rv = lock->os_hnd->create_lock(lock->os_hnd, &(lock->ll_lock));
85 if (rv) {
86 ipmi_mem_free(lock);
87 return rv;
88 }
89 } else {
90 lock->ll_lock = NULL;
91 }
92
93 *new_lock = lock;
94
95 return 0;
96 }
97
ipmi_destroy_lock(ipmi_lock_t * lock)98 void ipmi_destroy_lock(ipmi_lock_t *lock)
99 {
100 if (lock->ll_lock)
101 lock->os_hnd->destroy_lock(lock->os_hnd, lock->ll_lock);
102 ipmi_mem_free(lock);
103 }
104
ipmi_lock(ipmi_lock_t * lock)105 void ipmi_lock(ipmi_lock_t *lock)
106 {
107 if (lock->ll_lock)
108 lock->os_hnd->lock(lock->os_hnd, lock->ll_lock);
109 }
110
ipmi_unlock(ipmi_lock_t * lock)111 void ipmi_unlock(ipmi_lock_t *lock)
112 {
113 if (lock->ll_lock)
114 lock->os_hnd->unlock(lock->os_hnd, lock->ll_lock);
115 }
116
117 struct ipmi_rwlock_s
118 {
119 os_hnd_rwlock_t *ll_lock;
120 os_handler_t *os_hnd;
121 };
122
123 int
ipmi_create_rwlock_os_hnd(os_handler_t * os_hnd,ipmi_rwlock_t ** new_lock)124 ipmi_create_rwlock_os_hnd(os_handler_t *os_hnd, ipmi_rwlock_t **new_lock)
125 {
126 ipmi_rwlock_t *lock;
127 int rv;
128
129 lock = ipmi_mem_alloc(sizeof(*lock));
130 if (!lock)
131 return ENOMEM;
132
133 lock->os_hnd = os_hnd;
134 if (lock->os_hnd && lock->os_hnd->create_lock) {
135 rv = lock->os_hnd->create_rwlock(lock->os_hnd, &(lock->ll_lock));
136 if (rv) {
137 ipmi_mem_free(lock);
138 return rv;
139 }
140 } else {
141 lock->ll_lock = NULL;
142 }
143
144 *new_lock = lock;
145
146 return 0;
147 }
148
ipmi_destroy_rwlock(ipmi_rwlock_t * lock)149 void ipmi_destroy_rwlock(ipmi_rwlock_t *lock)
150 {
151 if (lock->ll_lock)
152 lock->os_hnd->destroy_rwlock(lock->os_hnd, lock->ll_lock);
153 ipmi_mem_free(lock);
154 }
155
ipmi_rwlock_read_lock(ipmi_rwlock_t * lock)156 void ipmi_rwlock_read_lock(ipmi_rwlock_t *lock)
157 {
158 if (lock->ll_lock)
159 lock->os_hnd->read_lock(lock->os_hnd, lock->ll_lock);
160 }
161
ipmi_rwlock_read_unlock(ipmi_rwlock_t * lock)162 void ipmi_rwlock_read_unlock(ipmi_rwlock_t *lock)
163 {
164 if (lock->ll_lock)
165 lock->os_hnd->read_unlock(lock->os_hnd, lock->ll_lock);
166 }
167
ipmi_rwlock_write_lock(ipmi_rwlock_t * lock)168 void ipmi_rwlock_write_lock(ipmi_rwlock_t *lock)
169 {
170 if (lock->ll_lock)
171 lock->os_hnd->write_lock(lock->os_hnd, lock->ll_lock);
172 }
173
ipmi_rwlock_write_unlock(ipmi_rwlock_t * lock)174 void ipmi_rwlock_write_unlock(ipmi_rwlock_t *lock)
175 {
176 if (lock->ll_lock)
177 lock->os_hnd->write_unlock(lock->os_hnd, lock->ll_lock);
178 }
179
180 #ifdef IPMI_CHECK_LOCKS
181 /* Set a breakpoint here to detect locking errors. */
182 void
ipmi_report_lock_error(os_handler_t * handler,char * str)183 ipmi_report_lock_error(os_handler_t *handler, char *str)
184 {
185 handler->log(handler, IPMI_LOG_WARNING, "%s", str);
186 }
187
188 void
ipmi_check_lock(ipmi_lock_t * lock,char * str)189 ipmi_check_lock(ipmi_lock_t *lock, char *str)
190 {
191 if ((!DEBUG_LOCKS) || (!lock) || (!lock->ll_lock))
192 return;
193
194 if (! lock->os_hnd->is_locked(lock->os_hnd, lock->ll_lock))
195 IPMI_REPORT_LOCK_ERROR(lock->os_hnd, str);
196 }
197 #endif
198