blob: 825804b1ce8e2ed8e3b45b84819712b210e1e9f1 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lam1ed83fc2014-02-19 01:15:45 -08002 * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080020 */
Kiet Lam1ed83fc2014-02-19 01:15:45 -080021
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
Jeff Johnson295189b2012-06-20 16:38:30 -070028/*============================================================================
29 FILE: vos_lock.c
30
31 OVERVIEW: This source file contains definitions for vOS lock APIs
32 The four APIs mentioned in this file are used for
33 initializing , acquiring, releasing and destroying a lock.
34 the lock are implemented using critical sections
35
36 DEPENDENCIES:
37
Jeff Johnson295189b2012-06-20 16:38:30 -070038============================================================================*/
39
40/*============================================================================
41 EDIT HISTORY FOR MODULE
42
43============================================================================*/
44
45/*----------------------------------------------------------------------------
46 * Include Files
47 * -------------------------------------------------------------------------*/
48
49#include "vos_lock.h"
50#include "vos_memory.h"
51#include "vos_trace.h"
52
53
54/*----------------------------------------------------------------------------
55 * Preprocessor Definitions and Constants
56 * -------------------------------------------------------------------------*/
57
58/*----------------------------------------------------------------------------
59 * Type Declarations
60 * -------------------------------------------------------------------------*/
61
62#define LINUX_LOCK_COOKIE 0x12345678
63enum
64{
65 LOCK_RELEASED = 0x11223344,
66 LOCK_ACQUIRED,
67 LOCK_DESTROYED
68};
69
70/*----------------------------------------------------------------------------
71 * Global Data Definitions
72 * -------------------------------------------------------------------------*/
73
74/*----------------------------------------------------------------------------
75 * Static Variable Definitions
76 * -------------------------------------------------------------------------*/
77
78/*----------------------------------------------------------------------------
79 Function Definitions and Documentation
80 * -------------------------------------------------------------------------*/
81
82/*--------------------------------------------------------------------------
83
84 \brief vos_lock_init() - initializes a vOSS lock
85
86 The vos_lock_init() function initializes the specified lock. Upon
87 successful initialization, the state of the lock becomes initialized
88 and unlocked.
89
90 A lock must be initialized by calling vos_lock_init() before it
91 may be used in any other lock functions.
92
93 Attempting to initialize an already initialized lock results in
94 a failure.
95
96 \param lock - pointer to the opaque lock object to initialize
97
98 \return VOS_STATUS_SUCCESS - lock was successfully initialized and
99 is ready to be used.
100
101 VOS_STATUS_E_NOMEM - insufficient memory exists to initialize
102 the lock
103
104 VOS_STATUS_E_BUSY - The implementation has detected an attempt
105 to reinitialize the object referenced by lock, a previously
106 initialized, but not yet destroyed, lock.
107
108 VOS_STATUS_E_FAULT - lock is an invalid pointer.
109
110 VOS_STATUS_E_FAILURE - default return value if it fails due to
111 unknown reasons
112
113 ***VOS_STATUS_E_RESOURCES - System resources (other than memory)
114 are unavailable to initilize the lock
115 \sa
116
117 ( *** return value not considered yet )
118 --------------------------------------------------------------------------*/
119VOS_STATUS vos_lock_init ( vos_lock_t *lock )
120{
121
122 //check for invalid pointer
123 if ( lock == NULL)
124 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700125 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: NULL pointer passed in",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700126 return VOS_STATUS_E_FAULT;
127 }
128 // check for 'already initialized' lock
129 if ( LINUX_LOCK_COOKIE == lock->cookie )
130 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700131 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: already initialized lock",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700132 return VOS_STATUS_E_BUSY;
133 }
134
135 if (in_interrupt())
136 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700137 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s cannot be called from interrupt context!!!", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700138 return VOS_STATUS_E_FAULT;
139 }
140
141 // initialize new lock
142 mutex_init( &lock->m_lock );
143 lock->cookie = LINUX_LOCK_COOKIE;
144 lock->state = LOCK_RELEASED;
145 lock->processID = 0;
146 lock->refcount = 0;
147
148 return VOS_STATUS_SUCCESS;
149}
150
151/*--------------------------------------------------------------------------
152
153 \brief vos_lock_acquire() - acquires a lock
154
155 A lock object is acquired by calling \a vos_lock_acquire(). If the lock
156 is already locked, the calling thread shall block until the lock becomes
157 available. This operation shall return with the lock object referenced by
158 lock in the locked state with the calling thread as its owner.
159
160 \param lock - the lock object to acquire
161
162 \return VOS_STATUS_SUCCESS - the lock was successfully acquired by
163 the calling thread.
164
165 VOS_STATUS_E_INVAL - The value specified by lock does not refer
166 to an initialized lock object.
167
168 VOS_STATUS_E_FAULT - lock is an invalid pointer.
169
170 VOS_STATUS_E_FAILURE - default return value if it fails due to
171 unknown reasons
172
173 \sa
174 ------------------------------------------------------------------------*/
175VOS_STATUS vos_lock_acquire ( vos_lock_t* lock )
176{
177 int rc;
178 //Check for invalid pointer
179 if ( lock == NULL )
180 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700181 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: NULL pointer passed in",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700182 return VOS_STATUS_E_FAULT;
183 }
184 // check if lock refers to an initialized object
185 if ( LINUX_LOCK_COOKIE != lock->cookie )
186 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700187 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: uninitialized lock",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700188 return VOS_STATUS_E_INVAL;
189 }
190
191 if (in_interrupt())
192 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700193 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s cannot be called from interrupt context!!!", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700194 return VOS_STATUS_E_FAULT;
195 }
196 if ((lock->processID == current->pid) &&
197 (lock->state == LOCK_ACQUIRED))
198 {
199 lock->refcount++;
200#ifdef VOS_NESTED_LOCK_DEBUG
201 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,"%s: %x %d %d", __func__, lock, current->pid, lock->refcount);
202#endif
203 return VOS_STATUS_SUCCESS;
204 }
205 // Acquire a Lock
Madan Mohan Koyyalamudi88a770f2012-09-28 15:44:59 -0700206 mutex_lock( &lock->m_lock );
207 rc = mutex_is_locked( &lock->m_lock );
208 if (rc == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700209 {
210 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700211 "%s: unable to lock mutex (rc = %d)", __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -0700212 return VOS_STATUS_E_FAILURE;
213 }
214
215
216#ifdef VOS_NESTED_LOCK_DEBUG
217 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,"%s: %x %d", __func__, lock, current->pid);
218#endif
219 if ( LOCK_DESTROYED != lock->state )
220 {
221 lock->processID = current->pid;
222 lock->refcount++;
223 lock->state = LOCK_ACQUIRED;
224 return VOS_STATUS_SUCCESS;
225 }
226 else
227 {
228 // lock is already destroyed
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700229 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: Lock is already destroyed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700230 mutex_unlock(&lock->m_lock);
231 return VOS_STATUS_E_FAILURE;
232 }
233}
234
235
236/*--------------------------------------------------------------------------
237
238 \brief vos_lock_release() - releases a lock
239
240 The \a vos_lock_release() function shall release the lock object
241 referenced by 'lock'.
242
243 If a thread attempts to release a lock that it unlocked or is not
244 initialized, an error is returned.
245
246 \param lock - the lock to release
247
248 \return VOS_STATUS_SUCCESS - the lock was successfully released
249
250 VOS_STATUS_E_INVAL - The value specified by lock does not refer
251 to an initialized lock object.
252
253 VOS_STATUS_E_FAULT - The value specified by lock does not refer
254 to an initialized lock object.
255
256 VOS_STATUS_E_PERM - Operation is not permitted. The calling
257 thread does not own the lock.
258
259 VOS_STATUS_E_FAILURE - default return value if it fails due to
260 unknown reasons
261
262 \sa
263 ------------------------------------------------------------------------*/
264VOS_STATUS vos_lock_release ( vos_lock_t *lock )
265{
266 //Check for invalid pointer
267 if ( lock == NULL )
268 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700269 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: NULL pointer passed in",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700270 return VOS_STATUS_E_FAULT;
271 }
272
273 // check if lock refers to an uninitialized object
274 if ( LINUX_LOCK_COOKIE != lock->cookie )
275 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700276 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: uninitialized lock",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700277 return VOS_STATUS_E_INVAL;
278 }
279
280 if (in_interrupt())
281 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700282 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s cannot be called from interrupt context!!!", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700283 return VOS_STATUS_E_FAULT;
284 }
285
286 // CurrentThread = GetCurrentThreadId();
287 // Check thread ID of caller against thread ID
288 // of the thread which acquire the lock
289 if ( lock->processID != current->pid )
290 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700291 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: current task pid does not match original task pid!!",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700292#ifdef VOS_NESTED_LOCK_DEBUG
293 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,"%s: Lock held by=%d being released by=%d", __func__, lock->processID, current->pid);
294#endif
295
296 return VOS_STATUS_E_PERM;
297 }
298 if ((lock->processID == current->pid) &&
299 (lock->state == LOCK_ACQUIRED))
300 {
301 if (lock->refcount > 0) lock->refcount--;
302 }
303#ifdef VOS_NESTED_LOCK_DEBUG
304 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,"%s: %x %d %d", __func__, lock, lock->processID, lock->refcount);
305#endif
306 if (lock->refcount) return VOS_STATUS_SUCCESS;
307
308 lock->processID = 0;
309 lock->refcount = 0;
310 lock->state = LOCK_RELEASED;
311 // Release a Lock
312 mutex_unlock( &lock->m_lock );
313#ifdef VOS_NESTED_LOCK_DEBUG
314 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO,"%s: Freeing lock %x %d %d", lock, lock->processID, lock->refcount);
315#endif
316 return VOS_STATUS_SUCCESS;
317}
318
319/*--------------------------------------------------------------------------
320
321 \brief vos_lock_destroy() - Destroys a vOSS Lock - probably not required
322 for Linux. It may not be required for the caller to destroy a lock after
323 usage.
324
325 The \a vos_lock_destroy() function shall destroy the lock object
326 referenced by lock. After a successful return from \a vos_lock_destroy()
327 the lock object becomes, in effect, uninitialized.
328
329 A destroyed lock object can be reinitialized using vos_lock_init();
330 the results of otherwise referencing the object after it has been destroyed
331 are undefined. Calls to vOSS lock functions to manipulate the lock such
332 as vos_lock_acquire() will fail if the lock is destroyed. Therefore,
333 don't use the lock after it has been destroyed until it has
334 been re-initialized.
335
336 \param lock - the lock object to be destroyed.
337
338 \return VOS_STATUS_SUCCESS - lock was successfully destroyed.
339
340 VOS_STATUS_E_BUSY - The implementation has detected an attempt
341 to destroy the object referenced by lock while it is locked
342 or still referenced.
343
344 VOS_STATUS_E_INVAL - The value specified by lock is invalid.
345
346 VOS_STATUS_E_FAULT - lock is an invalid pointer.
347
348 VOS_STATUS_E_FAILURE - default return value if it fails due to
349 unknown reasons
350 \sa
351 ------------------------------------------------------------------------*/
352VOS_STATUS vos_lock_destroy( vos_lock_t *lock )
353{
354 //Check for invalid pointer
355 if ( NULL == lock )
356 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700357 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: NULL pointer passed in", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700358 return VOS_STATUS_E_FAULT;
359 }
360
361 if ( LINUX_LOCK_COOKIE != lock->cookie )
362 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700363 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: uninitialized lock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700364 return VOS_STATUS_E_INVAL;
365 }
366
367 if (in_interrupt())
368 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700369 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s cannot be called from interrupt context!!!", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700370 return VOS_STATUS_E_FAULT;
371 }
372
373 // check if lock is released
374 if (!mutex_trylock(&lock->m_lock))
375 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700376 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, "%s: lock is not released", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700377 return VOS_STATUS_E_BUSY;
378 }
379 lock->cookie = 0;
380 lock->state = LOCK_DESTROYED;
381 lock->processID = 0;
382 lock->refcount = 0;
383
384 mutex_unlock(&lock->m_lock);
385
386
387 return VOS_STATUS_SUCCESS;
388}
389
390
391/*--------------------------------------------------------------------------
392
393 \brief vos_spin_lock_init() - initializes a vOSS spin lock
394
395 The vos_spin_lock_init() function initializes the specified spin lock. Upon
396 successful initialization, the state of the lock becomes initialized
397 and unlocked.
398
399 A lock must be initialized by calling vos_spin_lock_init() before it
400 may be used in any other lock functions.
401
402 Attempting to initialize an already initialized lock results in
403 a failure.
404
405 \param pLock - pointer to the opaque lock object to initialize
406
407 \return VOS_STATUS_SUCCESS - spin lock was successfully initialized and
408 is ready to be used.
409 --------------------------------------------------------------------------*/
410
411VOS_STATUS vos_spin_lock_init(vos_spin_lock_t *pLock)
412{
413 spin_lock_init(pLock);
414
415 return VOS_STATUS_SUCCESS;
416}
417
418/*--------------------------------------------------------------------------
419
420 \brief vos_spin_lock_acquire() - acquires a spin lock
421
422 A lock object is acquired by calling \a vos_spin_lock_acquire(). If the lock
423 is already locked, the calling thread shall spin until the lock becomes
424 available. This operation shall return with the lock object referenced by
425 lock in the locked state with the calling thread as its owner.
426
427 \param pLock - the lock object to acquire
428
429 \return VOS_STATUS_SUCCESS - the lock was successfully acquired by
430 the calling thread.
431
432 \sa
433 ------------------------------------------------------------------------*/
434VOS_STATUS vos_spin_lock_acquire(vos_spin_lock_t *pLock)
435{
436 spin_lock(pLock);
437 return VOS_STATUS_SUCCESS;
438}
439/*--------------------------------------------------------------------------
440
441 \brief vos_spin_lock_release() - releases a lock
442
443 The \a vos_lock_release() function shall release the spin lock object
444 referenced by 'lock'.
445
446 If a thread attempts to release a lock that it unlocked or is not
447 initialized, an error is returned.
448
449 \param pLock - the lock to release
450
451 \return VOS_STATUS_SUCCESS - the lock was successfully released
452
453 \sa
454 ------------------------------------------------------------------------*/
455VOS_STATUS vos_spin_lock_release(vos_spin_lock_t *pLock)
456{
457 spin_unlock(pLock);
458 return VOS_STATUS_SUCCESS;
459}
460
461
462/*--------------------------------------------------------------------------
463
464 \brief vos_spin_lock_destroy() - releases resource of a lock
465
466 \param pLock - the pointer to a lock to release
467
468 \return VOS_STATUS_SUCCESS - the lock was successfully released
469
470 \sa
471 ------------------------------------------------------------------------*/
472VOS_STATUS vos_spin_lock_destroy(vos_spin_lock_t *pLock)
473{
474
475 return VOS_STATUS_SUCCESS;
476}