pci: avoid inlining functions
[dpdk.git] / lib / librte_eal / common / include / generic / rte_rwlock.h
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #ifndef _RTE_RWLOCK_H_
35 #define _RTE_RWLOCK_H_
36
37 /**
38  * @file
39  *
40  * RTE Read-Write Locks
41  *
42  * This file defines an API for read-write locks. The lock is used to
43  * protect data that allows multiple readers in parallel, but only
44  * one writer. All readers are blocked until the writer is finished
45  * writing.
46  *
47  */
48
49 #ifdef __cplusplus
50 extern "C" {
51 #endif
52
53 #include <rte_common.h>
54 #include <rte_atomic.h>
55 #include <rte_pause.h>
56
57 /**
58  * The rte_rwlock_t type.
59  *
60  * cnt is -1 when write lock is held, and > 0 when read locks are held.
61  */
62 typedef struct {
63         volatile int32_t cnt; /**< -1 when W lock held, > 0 when R locks held. */
64 } rte_rwlock_t;
65
66 /**
67  * A static rwlock initializer.
68  */
69 #define RTE_RWLOCK_INITIALIZER { 0 }
70
71 /**
72  * Initialize the rwlock to an unlocked state.
73  *
74  * @param rwl
75  *   A pointer to the rwlock structure.
76  */
77 static inline void
78 rte_rwlock_init(rte_rwlock_t *rwl)
79 {
80         rwl->cnt = 0;
81 }
82
83 /**
84  * Take a read lock. Loop until the lock is held.
85  *
86  * @param rwl
87  *   A pointer to a rwlock structure.
88  */
89 static inline void
90 rte_rwlock_read_lock(rte_rwlock_t *rwl)
91 {
92         int32_t x;
93         int success = 0;
94
95         while (success == 0) {
96                 x = rwl->cnt;
97                 /* write lock is held */
98                 if (x < 0) {
99                         rte_pause();
100                         continue;
101                 }
102                 success = rte_atomic32_cmpset((volatile uint32_t *)&rwl->cnt,
103                                               x, x + 1);
104         }
105 }
106
107 /**
108  * Release a read lock.
109  *
110  * @param rwl
111  *   A pointer to the rwlock structure.
112  */
113 static inline void
114 rte_rwlock_read_unlock(rte_rwlock_t *rwl)
115 {
116         rte_atomic32_dec((rte_atomic32_t *)(intptr_t)&rwl->cnt);
117 }
118
119 /**
120  * Take a write lock. Loop until the lock is held.
121  *
122  * @param rwl
123  *   A pointer to a rwlock structure.
124  */
125 static inline void
126 rte_rwlock_write_lock(rte_rwlock_t *rwl)
127 {
128         int32_t x;
129         int success = 0;
130
131         while (success == 0) {
132                 x = rwl->cnt;
133                 /* a lock is held */
134                 if (x != 0) {
135                         rte_pause();
136                         continue;
137                 }
138                 success = rte_atomic32_cmpset((volatile uint32_t *)&rwl->cnt,
139                                               0, -1);
140         }
141 }
142
143 /**
144  * Release a write lock.
145  *
146  * @param rwl
147  *   A pointer to a rwlock structure.
148  */
149 static inline void
150 rte_rwlock_write_unlock(rte_rwlock_t *rwl)
151 {
152         rte_atomic32_inc((rte_atomic32_t *)(intptr_t)&rwl->cnt);
153 }
154
155 /**
156  * Try to execute critical section in a hardware memory transaction, if it
157  * fails or not available take a read lock
158  *
159  * NOTE: An attempt to perform a HW I/O operation inside a hardware memory
160  * transaction always aborts the transaction since the CPU is not able to
161  * roll-back should the transaction fail. Therefore, hardware transactional
162  * locks are not advised to be used around rte_eth_rx_burst() and
163  * rte_eth_tx_burst() calls.
164  *
165  * @param rwl
166  *   A pointer to a rwlock structure.
167  */
168 static inline void
169 rte_rwlock_read_lock_tm(rte_rwlock_t *rwl);
170
171 /**
172  * Commit hardware memory transaction or release the read lock if the lock is used as a fall-back
173  *
174  * @param rwl
175  *   A pointer to the rwlock structure.
176  */
177 static inline void
178 rte_rwlock_read_unlock_tm(rte_rwlock_t *rwl);
179
180 /**
181  * Try to execute critical section in a hardware memory transaction, if it
182  * fails or not available take a write lock
183  *
184  * NOTE: An attempt to perform a HW I/O operation inside a hardware memory
185  * transaction always aborts the transaction since the CPU is not able to
186  * roll-back should the transaction fail. Therefore, hardware transactional
187  * locks are not advised to be used around rte_eth_rx_burst() and
188  * rte_eth_tx_burst() calls.
189  *
190  * @param rwl
191  *   A pointer to a rwlock structure.
192  */
193 static inline void
194 rte_rwlock_write_lock_tm(rte_rwlock_t *rwl);
195
196 /**
197  * Commit hardware memory transaction or release the write lock if the lock is used as a fall-back
198  *
199  * @param rwl
200  *   A pointer to a rwlock structure.
201  */
202 static inline void
203 rte_rwlock_write_unlock_tm(rte_rwlock_t *rwl);
204
205 #ifdef __cplusplus
206 }
207 #endif
208
209 #endif /* _RTE_RWLOCK_H_ */