]> CyberLeo.Net >> Repos - FreeBSD/releng/8.2.git/blob - sys/contrib/octeon-sdk/cvmx-rwlock.h
Copy stable/8 to releng/8.2 in preparation for FreeBSD-8.2 release.
[FreeBSD/releng/8.2.git] / sys / contrib / octeon-sdk / cvmx-rwlock.h
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
62 extern "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  */
73 typedef 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  */
86 static 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  */
102 static 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  */
124 static 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  */
139 static 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  */
156 static 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__ */