update copyright date to 2013
[dpdk.git] / lib / librte_eal / common / include / rte_rwlock.h
1 /*-
2  *   BSD LICENSE
3  * 
4  *   Copyright(c) 2010-2013 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         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 #ifdef __cplusplus
156 }
157 #endif
158
159 #endif /* _RTE_RWLOCK_H_ */