remove version in all files
[dpdk.git] / lib / librte_eal / common / include / rte_rwlock.h
1 /*-
2  *   BSD LICENSE
3  * 
4  *   Copyright(c) 2010-2012 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
35 #ifndef _RTE_RWLOCK_H_
36 #define _RTE_RWLOCK_H_
37
38 /**
39  * @file
40  *
41  * RTE Read-Write Locks
42  *
43  * This file defines an API for read-write locks. The lock is used to
44  * protect data that allows multiple readers in parallel, but only
45  * one writer. All readers are blocked until the writer is finished
46  * writing.
47  *
48  */
49
50 #ifdef __cplusplus
51 extern "C" {
52 #endif
53
54 #include <rte_common.h>
55 #include <rte_atomic.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         /* in debug mode, we should check that rwl->cnt is > 0 */
117
118         /* same than atomic32_dec */
119         asm volatile(MPLOCKED
120                      "decl %[cnt]"
121                      : [cnt] "=m" (rwl->cnt) /* output (0) */
122                      : "m" (rwl->cnt)        /* input (1) */
123                      );                      /* no clobber-list */
124 }
125
126 /**
127  * Take a write lock. Loop until the lock is held.
128  *
129  * @param rwl
130  *   A pointer to a rwlock structure.
131  */
132 static inline void
133 rte_rwlock_write_lock(rte_rwlock_t *rwl)
134 {
135         int32_t x;
136         int success = 0;
137
138         while (success == 0) {
139                 x = rwl->cnt;
140                 /* a lock is held */
141                 if (x != 0) {
142                         rte_pause();
143                         continue;
144                 }
145                 success = rte_atomic32_cmpset((volatile uint32_t *)&rwl->cnt,
146                                               0, -1);
147         }
148 }
149
150 /**
151  * Release a write lock.
152  *
153  * @param rwl
154  *   A pointer to a rwlock structure.
155  */
156 static inline void
157 rte_rwlock_write_unlock(rte_rwlock_t *rwl)
158 {
159         /* in debug mode, we should check that rwl->cnt is < 0 */
160
161         /* same than atomic32_inc */
162         asm volatile(MPLOCKED
163                      "incl %[cnt]"
164                      : [cnt] "=m" (rwl->cnt) /* output (0) */
165                      : "m" (rwl->cnt)        /* input (1) */
166                      );                      /* no clobber-list */
167 }
168
169 #ifdef __cplusplus
170 }
171 #endif
172
173 #endif /* _RTE_RWLOCK_H_ */