FD.io VPP  v18.07-rc0-415-g6c78436
Vector Packet Processing
lock.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef included_clib_lock_h
17 #define included_clib_lock_h
18 
19 #include <vppinfra/clib.h>
20 
21 #if __x86_64__
22 #define CLIB_PAUSE() __builtin_ia32_pause ()
23 #else
24 #define CLIB_PAUSE()
25 #endif
26 
27 #if CLIB_DEBUG > 1
28 #define CLIB_LOCK_DBG(_p) \
29 do { \
30  (*_p)->frame_address = __builtin_frame_address (0); \
31  (*_p)->pid = getpid (); \
32  (*_p)->thread_index = os_get_thread_index (); \
33 } while (0)
34 #define CLIB_LOCK_DBG_CLEAR(_p) \
35 do { \
36  (*_p)->frame_address = 0; \
37  (*_p)->pid = 0; \
38  (*_p)->thread_index = 0; \
39 } while (0)
40 #else
41 #define CLIB_LOCK_DBG(_p)
42 #define CLIB_LOCK_DBG_CLEAR(_p)
43 #endif
44 
45 typedef struct
46 {
47  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
49 #if CLIB_DEBUG > 0
50  pid_t pid;
53 #endif
55 
56 static inline void
58 {
60  memset ((void *) *p, 0, CLIB_CACHE_LINE_BYTES);
61 }
62 
63 static inline void
65 {
66  if (*p)
67  {
68  clib_mem_free ((void *) *p);
69  *p = 0;
70  }
71 }
72 
75 {
76  while (__sync_lock_test_and_set (&(*p)->lock, 1))
77  CLIB_PAUSE ();
78  CLIB_LOCK_DBG (p);
79 }
80 
83 {
84  if (PREDICT_FALSE (*p != 0))
86 }
87 
90 {
92  /* Make sure all writes are complete before releasing the lock */
94  (*p)->lock = 0;
95 }
96 
99 {
100  if (PREDICT_FALSE (*p != 0))
102 }
103 
104 /*
105  * Readers-Writer Lock
106  */
107 
108 typedef struct clib_rw_lock_
109 {
110  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
111  volatile u32 n_readers;
112  volatile u32 n_readers_lock;
113  volatile u32 writer_lock;
114 #if CLIB_DEBUG > 0
115  pid_t pid;
118 #endif
119 } *clib_rwlock_t;
120 
121 always_inline void
123 {
125  memset ((void *) *p, 0, CLIB_CACHE_LINE_BYTES);
126 }
127 
128 always_inline void
130 {
131  if (*p)
132  {
133  clib_mem_free ((void *) *p);
134  *p = 0;
135  }
136 }
137 
138 always_inline void
140 {
141  while (__sync_lock_test_and_set (&(*p)->n_readers_lock, 1))
142  CLIB_PAUSE ();
143 
144  (*p)->n_readers += 1;
145  if ((*p)->n_readers == 1)
146  {
147  while (__sync_lock_test_and_set (&(*p)->writer_lock, 1))
148  CLIB_PAUSE ();
149  }
151  (*p)->n_readers_lock = 0;
152 
153  CLIB_LOCK_DBG (p);
154 }
155 
156 always_inline void
158 {
159  ASSERT ((*p)->n_readers > 0);
161 
162  while (__sync_lock_test_and_set (&(*p)->n_readers_lock, 1))
163  CLIB_PAUSE ();
164 
165  (*p)->n_readers -= 1;
166  if ((*p)->n_readers == 0)
167  {
169  (*p)->writer_lock = 0;
170  }
171 
173  (*p)->n_readers_lock = 0;
174 }
175 
176 always_inline void
178 {
179  while (__sync_lock_test_and_set (&(*p)->writer_lock, 1))
180  CLIB_PAUSE ();
181  CLIB_LOCK_DBG (p);
182 }
183 
184 always_inline void
186 {
189  (*p)->writer_lock = 0;
190 }
191 
192 #endif
193 
194 /*
195  * fd.io coding-style-patch-verification: ON
196  *
197  * Local Variables:
198  * eval: (c-set-style "gnu")
199  * End:
200  */
static void clib_rwlock_reader_lock(clib_rwlock_t *p)
Definition: lock.h:139
uword thread_index
Definition: lock.h:51
volatile u32 n_readers_lock
Definition: lock.h:112
#define CLIB_PAUSE()
Definition: lock.h:22
volatile u32 n_readers
Definition: lock.h:111
#define CLIB_CACHE_LINE_ALIGN_MARK(mark)
Definition: cache.h:63
static_always_inline void clib_spinlock_unlock(clib_spinlock_t *p)
Definition: lock.h:89
static_always_inline void clib_spinlock_lock(clib_spinlock_t *p)
Definition: lock.h:74
static void clib_rwlock_writer_lock(clib_rwlock_t *p)
Definition: lock.h:177
CLIB_CACHE_LINE_ALIGN_MARK(cacheline0)
static void clib_rwlock_free(clib_rwlock_t *p)
Definition: lock.h:129
static_always_inline void clib_spinlock_unlock_if_init(clib_spinlock_t *p)
Definition: lock.h:98
pid_t pid
Definition: lock.h:115
volatile u32 writer_lock
Definition: lock.h:113
void * frame_address
Definition: lock.h:117
static void clib_spinlock_free(clib_spinlock_t *p)
Definition: lock.h:64
#define CLIB_LOCK_DBG_CLEAR(_p)
Definition: lock.h:42
#define static_always_inline
Definition: clib.h:93
#define always_inline
Definition: clib.h:92
unsigned int u32
Definition: types.h:88
uword thread_index
Definition: lock.h:116
u32 lock
Definition: lock.h:48
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:57
static void clib_rwlock_init(clib_rwlock_t *p)
Definition: lock.h:122
static void clib_rwlock_reader_unlock(clib_rwlock_t *p)
Definition: lock.h:157
#define PREDICT_FALSE(x)
Definition: clib.h:105
static void clib_rwlock_writer_unlock(clib_rwlock_t *p)
Definition: lock.h:185
pid_t pid
Definition: lock.h:50
struct clib_rw_lock_ * clib_rwlock_t
#define ASSERT(truth)
static void clib_mem_free(void *p)
Definition: mem.h:179
u64 uword
Definition: types.h:112
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:120
void * frame_address
Definition: lock.h:52
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:109
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:62
static_always_inline void clib_spinlock_lock_if_init(clib_spinlock_t *p)
Definition: lock.h:82
#define CLIB_LOCK_DBG(_p)
Definition: lock.h:41