cvmx-rwlock.h revision 210284
1/***********************license start***************
2 *  Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
3 *  reserved.
4 *
5 *
6 *  Redistribution and use in source and binary forms, with or without
7 *  modification, are permitted provided that the following conditions are
8 *  met:
9 *
10 *      * Redistributions of source code must retain the above copyright
11 *        notice, this list of conditions and the following disclaimer.
12 *
13 *      * Redistributions in binary form must reproduce the above
14 *        copyright notice, this list of conditions and the following
15 *        disclaimer in the documentation and/or other materials provided
16 *        with the distribution.
17 *
18 *      * Neither the name of Cavium Networks nor the names of
19 *        its contributors may be used to endorse or promote products
20 *        derived from this software without specific prior written
21 *        permission.
22 *
23 *  TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
24 *  AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
25 *  OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
26 *  RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
27 *  REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
28 *  DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
29 *  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
30 *  PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
31 *  POSSESSION OR CORRESPONDENCE TO DESCRIPTION.  THE ENTIRE RISK ARISING OUT
32 *  OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
33 *
34 *
35 *  For any questions regarding licensing please contact marketing@caviumnetworks.com
36 *
37 ***********************license end**************************************/
38
39
40
41
42
43
44/**
45 * @file
46 *
47 * This file provides reader/writer locks.
48 *
49 * <hr>$Revision: 41586 $<hr>
50 *
51 *
52 */
53
54
55#ifndef __CVMX_RWLOCK_H__
56#define __CVMX_RWLOCK_H__
57
58/* include to get atomic compare and store */
59#include "cvmx-atomic.h"
60
61#ifdef	__cplusplus
62extern "C" {
63#endif
64
65/* Flags for lock value in rw lock structure */
66#define CVMX_RWLOCK_WRITE_FLAG     0x1
67#define CVMX_RWLOCK_READ_INC       0x2
68
69
70/* Writer preference locks (wp).  Can be starved by writers.  When a writer
71 * is waiting, no readers are given the lock until all writers are done.
72 */
73typedef struct
74{
75    volatile uint32_t lock;
76    volatile uint32_t write_req;
77    volatile uint32_t write_comp;
78} cvmx_rwlock_wp_lock_t;
79
80/**
81 * Initialize a reader/writer lock.  This must be done
82 * by a single core before used.
83 *
84 * @param lock   pointer to rwlock structure
85 */
86static inline void cvmx_rwlock_wp_init(cvmx_rwlock_wp_lock_t *lock)
87{
88    lock->lock = 0;
89    lock->write_req = 0;
90    lock->write_comp = 0;
91}
92
93/**
94 * Perform a reader lock.  If a writer is pending, this
95 * will wait for that writer to complete before locking.
96 *
97 * NOTE: Each thread/process must only lock any rwlock
98 * once, or else a deadlock may result.
99 *
100 * @param lock   pointer to rwlock structure
101 */
102static inline void cvmx_rwlock_wp_read_lock(cvmx_rwlock_wp_lock_t *lock)
103{
104
105    /* Wait for outstanding write requests to be serviced */
106    while (lock->write_req != lock->write_comp)
107        ;
108    /* Add ourselves to interested reader count */
109    cvmx_atomic_add32_nosync((int32_t *)&(lock->lock), CVMX_RWLOCK_READ_INC);
110    /* Wait for writer to finish.  No writer will start again
111    ** until after we are done since we have already incremented
112    ** the reader count
113    */
114    while (lock->lock & CVMX_RWLOCK_WRITE_FLAG)
115        ;
116
117}
118
119/**
120 * Perform a reader unlock.
121 *
122 * @param lock   pointer to rwlock structure
123 */
124static inline void cvmx_rwlock_wp_read_unlock(cvmx_rwlock_wp_lock_t *lock)
125{
126    /* Remove ourselves to reader count */
127    cvmx_atomic_add32_nosync((int32_t *)&(lock->lock), -CVMX_RWLOCK_READ_INC);
128}
129
130/**
131 * Perform a writer lock.  Any readers that attempt
132 * to get a lock while there are any pending write locks
133 * will wait until all writers have completed.  Starvation
134 * of readers by writers is possible and must be avoided
135 * by the application.
136 *
137 * @param lock   pointer to rwlock structure
138 */
139static inline void cvmx_rwlock_wp_write_lock(cvmx_rwlock_wp_lock_t *lock)
140{
141    /* Get previous value of write requests */
142    uint32_t prev_writers = ((uint32_t)cvmx_atomic_fetch_and_add32((int32_t *)&(lock->write_req), 1));
143    /* Spin until our turn */
144    while (prev_writers != lock->write_comp)
145        ;
146    /* Spin until no other readers or writers, then set write flag */
147    while (!cvmx_atomic_compare_and_store32((uint32_t *)&(lock->lock), 0, CVMX_RWLOCK_WRITE_FLAG))
148        ;
149
150}
151/**
152 * Perform a writer unlock.
153 *
154 * @param lock   pointer to rwlock structure
155 */
156static inline void cvmx_rwlock_wp_write_unlock(cvmx_rwlock_wp_lock_t *lock)
157{
158    /* Remove our writer flag */
159    CVMX_SYNCWS;  /* Make sure all writes in protected region are visible before unlock */
160    cvmx_atomic_add32_nosync((int32_t *)&(lock->lock), -CVMX_RWLOCK_WRITE_FLAG);
161    cvmx_atomic_add32_nosync((int32_t *)&(lock->write_comp), 1);
162    CVMX_SYNCWS;  /* push unlock writes out, but don't stall */
163}
164
165#ifdef	__cplusplus
166}
167#endif
168
169#endif /* __CVMX_RWLOCK_H__ */
170