update Intel copyright years to 2014
[dpdk.git] / lib / librte_eal / common / include / 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
56 /**
57  * The rte_rwlock_t type.
58  *
59  * cnt is -1 when write lock is held, and > 0 when read locks are held.
60  */
61 typedef struct {
62         volatile int32_t cnt; /**< -1 when W lock held, > 0 when R locks held. */
63 } rte_rwlock_t;
64
65 /**
66  * A static rwlock initializer.
67  */
68 #define RTE_RWLOCK_INITIALIZER { 0 }
69
70 /**
71  * Initialize the rwlock to an unlocked state.
72  *
73  * @param rwl
74  *   A pointer to the rwlock structure.
75  */
76 static inline void
77 rte_rwlock_init(rte_rwlock_t *rwl)
78 {
79         rwl->cnt = 0;
80 }
81
82 /**
83  * Take a read lock. Loop until the lock is held.
84  *
85  * @param rwl
86  *   A pointer to a rwlock structure.
87  */
88 static inline void
89 rte_rwlock_read_lock(rte_rwlock_t *rwl)
90 {
91         int32_t x;
92         int success = 0;
93
94         while (success == 0) {
95                 x = rwl->cnt;
96                 /* write lock is held */
97                 if (x < 0) {
98                         rte_pause();
99                         continue;
100                 }
101                 success = rte_atomic32_cmpset((volatile uint32_t *)&rwl->cnt,
102                                               x, x + 1);
103         }
104 }
105
106 /**
107  * Release a read lock.
108  *
109  * @param rwl
110  *   A pointer to the rwlock structure.
111  */
112 static inline void
113 rte_rwlock_read_unlock(rte_rwlock_t *rwl)
114 {
115         rte_atomic32_dec((rte_atomic32_t *)(intptr_t)&rwl->cnt);
116 }
117
118 /**
119  * Take a write lock. Loop until the lock is held.
120  *
121  * @param rwl
122  *   A pointer to a rwlock structure.
123  */
124 static inline void
125 rte_rwlock_write_lock(rte_rwlock_t *rwl)
126 {
127         int32_t x;
128         int success = 0;
129
130         while (success == 0) {
131                 x = rwl->cnt;
132                 /* a lock is held */
133                 if (x != 0) {
134                         rte_pause();
135                         continue;
136                 }
137                 success = rte_atomic32_cmpset((volatile uint32_t *)&rwl->cnt,
138                                               0, -1);
139         }
140 }
141
142 /**
143  * Release a write lock.
144  *
145  * @param rwl
146  *   A pointer to a rwlock structure.
147  */
148 static inline void
149 rte_rwlock_write_unlock(rte_rwlock_t *rwl)
150 {
151         rte_atomic32_inc((rte_atomic32_t *)(intptr_t)&rwl->cnt);
152 }
153
154 #ifdef __cplusplus
155 }
156 #endif
157
158 #endif /* _RTE_RWLOCK_H_ */