46 (
uword) ((1 + m->n_cpus) << m->log2_n_per_cpu_vm_bytes));
52 clib_smp_main_t *m = &clib_smp_main;
54 uword vm_size, stack_size, mheap_flags;
58 vm_size = (
uword) 1 << m->log2_n_per_cpu_vm_bytes;
59 stack_size = (
uword) 1 << m->log2_n_per_cpu_stack_bytes;
65 vm_size - stack_size, mheap_flags);
80 m->per_cpu_mains[cpu].heap = heap;
87 clib_smp_main_t *m = &clib_smp_main;
93 clib_error (
"error allocating virtual memory");
95 for (cpu = 0; cpu < m->n_cpus; cpu++)
97 clib_smp_stack_top_for_cpu (m, cpu));
104 uword i, n_bytes, n_fifo_elts;
108 if (clib_smp_main.n_cpus < 2)
116 n_fifo_elts = clib_smp_main.n_cpus - 1;
118 n_bytes =
sizeof (l[0]) + n_fifo_elts *
sizeof (l->waiting_fifo[0]);
123 memset (l, 0, n_bytes);
124 l->n_waiting_fifo_elts = n_fifo_elts;
126 for (i = 0; i < l->n_waiting_fifo_elts; i++)
127 l->waiting_fifo[i].wait_type = CLIB_SMP_LOCK_WAIT_EMPTY;
143 clib_smp_lock_header_t h0, clib_smp_lock_type_t type)
145 clib_smp_lock_header_t h1, h2, h3;
146 uword is_reader = type == CLIB_SMP_LOCK_TYPE_READER;
147 uword n_fifo_elts = l->n_waiting_fifo_elts;
155 my_tail = h1.waiting_fifo.head_index + h1.waiting_fifo.n_elts;
156 my_tail = my_tail >= n_fifo_elts ? my_tail - n_fifo_elts : my_tail;
157 h1.waiting_fifo.n_elts += 1;
158 h1.request_cpu = my_cpu;
163 h2 = clib_smp_lock_set_header (l, h1, h0);
166 if (clib_smp_lock_header_is_equal (h0, h2))
170 else if (type == CLIB_SMP_LOCK_TYPE_SPIN)
172 while (!h2.writer_has_lock)
176 h1.request_cpu = my_cpu;
177 h1.writer_has_lock = 1;
179 h3 = clib_smp_lock_set_header (l, h1, h2);
182 if (clib_smp_lock_header_is_equal (h2, h3))
194 clib_smp_lock_waiting_fifo_elt_t *w;
196 w = l->waiting_fifo + my_tail;
198 while (w->wait_type != CLIB_SMP_LOCK_WAIT_EMPTY)
201 w->wait_type = (is_reader
202 ? CLIB_SMP_LOCK_WAIT_READER : CLIB_SMP_LOCK_WAIT_WRITER);
205 while (w->wait_type != CLIB_SMP_LOCK_WAIT_DONE)
208 w->wait_type = CLIB_SMP_LOCK_WAIT_EMPTY;
215 clib_smp_lock_header_t h0,
216 clib_smp_lock_type_t type)
218 clib_smp_lock_header_t h1, h2;
219 clib_smp_lock_waiting_fifo_elt_t *head;
220 clib_smp_lock_wait_type_t head_wait_type;
221 uword is_reader = type == CLIB_SMP_LOCK_TYPE_READER;
222 uword n_fifo_elts = l->n_waiting_fifo_elts;
223 uword head_index, must_wait_for_readers;
234 head_index = h1.waiting_fifo.head_index;
235 head = l->waiting_fifo + head_index;
239 h1.n_readers_with_lock -= 1;
247 while ((head_wait_type =
248 head->wait_type) == CLIB_SMP_LOCK_WAIT_EMPTY)
252 must_wait_for_readers =
253 (type != CLIB_SMP_LOCK_TYPE_SPIN
254 && head_wait_type == CLIB_SMP_LOCK_WAIT_WRITER
255 && h1.n_readers_with_lock != 0);
257 if (!must_wait_for_readers)
260 h1.waiting_fifo.n_elts -= 1;
261 if (type != CLIB_SMP_LOCK_TYPE_SPIN)
263 if (head_wait_type == CLIB_SMP_LOCK_WAIT_WRITER)
264 h1.writer_has_lock = h1.n_readers_with_lock == 0;
267 h1.writer_has_lock = 0;
268 h1.n_readers_with_lock += 1;
273 h1.waiting_fifo.head_index =
274 head_index == n_fifo_elts ? 0 : head_index;
275 h1.request_cpu = my_cpu;
278 && h1.waiting_fifo.head_index < n_fifo_elts);
280 && h1.waiting_fifo.n_elts <= n_fifo_elts);
282 h2 = clib_smp_lock_set_header (l, h1, h0);
284 if (clib_smp_lock_header_is_equal (h2, h0))
289 if (h0.waiting_fifo.n_elts == 0)
290 return clib_smp_unlock_inline (l, type);
293 if (must_wait_for_readers)
301 head->wait_type = CLIB_SMP_LOCK_WAIT_DONE;
305 if (head_wait_type == CLIB_SMP_LOCK_WAIT_READER)
307 uword hi = h0.waiting_fifo.head_index;
308 if (h0.waiting_fifo.n_elts != 0
309 && l->waiting_fifo[hi].wait_type == CLIB_SMP_LOCK_WAIT_READER)
sll srl srl sll sra u16x4 i
#define clib_error(format, args...)
void clib_smp_lock_slow_path(clib_smp_lock_t *l, uword my_cpu, clib_smp_lock_header_t h0, clib_smp_lock_type_t type)
#define MHEAP_FLAG_THREAD_SAFE
#define vec_resize(V, N)
Resize a vector (no header, unspecified alignment) Add N elements to end of given vector V...
void clib_smp_lock_free(clib_smp_lock_t **pl)
#define ASSERT_AND_PANIC(truth)
static void * clib_mem_set_heap(void *heap)
void * mheap_alloc_with_flags(void *memory, uword memory_size, uword flags)
static uword allocate_per_cpu_mheap(uword cpu)
static void clib_mem_free(void *p)
#define MHEAP_FLAG_SMALL_OBJECT_CACHE
static void clib_mem_vm_free(void *addr, uword size)
static_always_inline uword os_get_thread_index(void)
void clib_smp_lock_init(clib_smp_lock_t **pl)
static void * clib_mem_alloc_aligned(uword size, uword align)
uword clib_calljmp(uword(*func)(uword func_arg), uword func_arg, void *stack)
void clib_smp_free(clib_smp_main_t *m)
#define CLIB_CACHE_LINE_BYTES
static void * clib_mem_vm_alloc(uword size)
void clib_smp_unlock_slow_path(clib_smp_lock_t *l, uword my_cpu, clib_smp_lock_header_t h0, clib_smp_lock_type_t type)