blob: 4d1833eee7e6bf4727c1935bff42017509f34291 [file] [log] [blame]
Dave Barach68b0fb02017-02-28 15:15:56 -05001/*
2 * Copyright (c) 2016 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#include <svm/svm_fifo_segment.h>
17
18svm_fifo_segment_main_t svm_fifo_segment_main;
19
Dave Barach10d8cc62017-05-30 09:30:07 -040020static void
Dave Barach818eb542017-08-02 13:56:13 -040021allocate_new_fifo_chunk (svm_fifo_segment_header_t * fsh,
22 u32 data_size_in_bytes, int chunk_size)
23{
24 int freelist_index;
25 u32 size;
26 u8 *fifo_space;
27 u32 rounded_data_size;
28 svm_fifo_t *f;
29 int i;
30
31 rounded_data_size = (1 << (max_log2 (data_size_in_bytes)));
32 freelist_index = max_log2 (rounded_data_size)
33 - max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE);
34
35 /* Calculate space requirement $$$ round-up data_size_in_bytes */
36 size = (sizeof (*f) + rounded_data_size) * chunk_size;
37
38 /* Allocate fifo space. May fail. */
39 fifo_space = clib_mem_alloc_aligned_at_offset
40 (size, CLIB_CACHE_LINE_BYTES, 0 /* align_offset */ ,
41 0 /* os_out_of_memory */ );
42
43 /* Out of space.. */
44 if (fifo_space == 0)
45 return;
46
47 /* Carve fifo space */
48 f = (svm_fifo_t *) fifo_space;
49 for (i = 0; i < chunk_size; i++)
50 {
51 f->freelist_index = freelist_index;
52 f->next = fsh->free_fifos[freelist_index];
53 fsh->free_fifos[freelist_index] = f;
54 fifo_space += sizeof (*f) + rounded_data_size;
55 f = (svm_fifo_t *) fifo_space;
56 }
57}
58
59static void
Florin Coras9d063042017-09-14 03:08:00 -040060preallocate_fifo_pairs (svm_fifo_segment_private_t * s,
Florin Corasb384b542018-01-15 01:08:33 -080061 svm_fifo_segment_create_args_t * a, u32 protect_size)
Dave Barach10d8cc62017-05-30 09:30:07 -040062{
Florin Coras9d063042017-09-14 03:08:00 -040063 svm_fifo_segment_header_t *fsh = s->h;
64 u32 rx_fifo_size, tx_fifo_size, pairs_to_allocate;
65 u32 rx_rounded_data_size, tx_rounded_data_size, pair_size;
Dave Barach10d8cc62017-05-30 09:30:07 -040066 svm_fifo_t *f;
67 u8 *rx_fifo_space, *tx_fifo_space;
Dave Barach818eb542017-08-02 13:56:13 -040068 int rx_freelist_index, tx_freelist_index;
Dave Barach10d8cc62017-05-30 09:30:07 -040069 int i;
70
71 /* Parameter check */
72 if (a->rx_fifo_size == 0 || a->tx_fifo_size == 0
73 || a->preallocated_fifo_pairs == 0)
74 return;
75
Dave Barach818eb542017-08-02 13:56:13 -040076 if (a->rx_fifo_size < FIFO_SEGMENT_MIN_FIFO_SIZE ||
77 a->rx_fifo_size > FIFO_SEGMENT_MAX_FIFO_SIZE)
78 {
79 clib_warning ("rx fifo_size out of range %d", a->rx_fifo_size);
80 return;
81 }
Dave Barach10d8cc62017-05-30 09:30:07 -040082
Dave Barach818eb542017-08-02 13:56:13 -040083 if (a->tx_fifo_size < FIFO_SEGMENT_MIN_FIFO_SIZE ||
84 a->tx_fifo_size > FIFO_SEGMENT_MAX_FIFO_SIZE)
85 {
86 clib_warning ("tx fifo_size out of range %d", a->rx_fifo_size);
87 return;
88 }
89
90 rx_rounded_data_size = (1 << (max_log2 (a->rx_fifo_size)));
91
92 rx_freelist_index = max_log2 (a->rx_fifo_size)
93 - max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE);
94
95 tx_rounded_data_size = (1 << (max_log2 (a->rx_fifo_size)));
96
97 tx_freelist_index = max_log2 (a->tx_fifo_size)
98 - max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE);
99
100 /* Calculate space requirements */
Florin Coras9d063042017-09-14 03:08:00 -0400101 pair_size = 2 * sizeof (*f) + rx_rounded_data_size + tx_rounded_data_size;
Florin Corasb384b542018-01-15 01:08:33 -0800102 if (protect_size)
103 protect_size += mheap_bytes (s->ssvm.sh->heap);
104 pairs_to_allocate =
105 clib_min ((s->ssvm.ssvm_size - protect_size) / pair_size,
106 a->preallocated_fifo_pairs);
Florin Coras9d063042017-09-14 03:08:00 -0400107 rx_fifo_size = (sizeof (*f) + rx_rounded_data_size) * pairs_to_allocate;
108 tx_fifo_size = (sizeof (*f) + tx_rounded_data_size) * pairs_to_allocate;
Dave Barach818eb542017-08-02 13:56:13 -0400109
110 vec_validate_init_empty (fsh->free_fifos,
111 clib_max (rx_freelist_index, tx_freelist_index),
112 0);
Dave Barach2c25a622017-06-26 11:35:07 -0400113
Dave Barach10d8cc62017-05-30 09:30:07 -0400114 /* Allocate rx fifo space. May fail. */
115 rx_fifo_space = clib_mem_alloc_aligned_at_offset
116 (rx_fifo_size, CLIB_CACHE_LINE_BYTES, 0 /* align_offset */ ,
117 0 /* os_out_of_memory */ );
118
119 /* Same for TX */
120 tx_fifo_space = clib_mem_alloc_aligned_at_offset
121 (tx_fifo_size, CLIB_CACHE_LINE_BYTES, 0 /* align_offset */ ,
122 0 /* os_out_of_memory */ );
123
124 /* Make sure it worked. Clean up if it didn't... */
125 if (rx_fifo_space == 0 || tx_fifo_space == 0)
126 {
127 if (rx_fifo_space)
128 clib_mem_free (rx_fifo_space);
129 else
130 clib_warning ("rx fifo preallocation failure: size %d npairs %d",
131 a->rx_fifo_size, a->preallocated_fifo_pairs);
132
133 if (tx_fifo_space)
134 clib_mem_free (tx_fifo_space);
135 else
136 clib_warning ("tx fifo preallocation failure: size %d nfifos %d",
137 a->tx_fifo_size, a->preallocated_fifo_pairs);
138 return;
139 }
140
141 /* Carve rx fifo space */
142 f = (svm_fifo_t *) rx_fifo_space;
Florin Coras9d063042017-09-14 03:08:00 -0400143 for (i = 0; i < pairs_to_allocate; i++)
Dave Barach10d8cc62017-05-30 09:30:07 -0400144 {
Dave Barach818eb542017-08-02 13:56:13 -0400145 f->freelist_index = rx_freelist_index;
146 f->next = fsh->free_fifos[rx_freelist_index];
147 fsh->free_fifos[rx_freelist_index] = f;
148 rx_fifo_space += sizeof (*f) + rx_rounded_data_size;
Dave Barach10d8cc62017-05-30 09:30:07 -0400149 f = (svm_fifo_t *) rx_fifo_space;
150 }
151 /* Carve tx fifo space */
152 f = (svm_fifo_t *) tx_fifo_space;
Florin Coras9d063042017-09-14 03:08:00 -0400153 for (i = 0; i < pairs_to_allocate; i++)
Dave Barach10d8cc62017-05-30 09:30:07 -0400154 {
Dave Barach818eb542017-08-02 13:56:13 -0400155 f->freelist_index = tx_freelist_index;
156 f->next = fsh->free_fifos[tx_freelist_index];
157 fsh->free_fifos[tx_freelist_index] = f;
158 tx_fifo_space += sizeof (*f) + tx_rounded_data_size;
Dave Barach10d8cc62017-05-30 09:30:07 -0400159 f = (svm_fifo_t *) tx_fifo_space;
160 }
Florin Coras9d063042017-09-14 03:08:00 -0400161
162 /* Account for the pairs allocated */
163 a->preallocated_fifo_pairs -= pairs_to_allocate;
Dave Barach10d8cc62017-05-30 09:30:07 -0400164}
165
Florin Corasb384b542018-01-15 01:08:33 -0800166/**
167 * Create an svm fifo segment and initialize as master
168 */
Dave Barach68b0fb02017-02-28 15:15:56 -0500169int
170svm_fifo_segment_create (svm_fifo_segment_create_args_t * a)
171{
Dave Barach68b0fb02017-02-28 15:15:56 -0500172 svm_fifo_segment_main_t *sm = &svm_fifo_segment_main;
Florin Corasb384b542018-01-15 01:08:33 -0800173 svm_fifo_segment_private_t *s;
Dave Barach68b0fb02017-02-28 15:15:56 -0500174 ssvm_shared_header_t *sh;
175 svm_fifo_segment_header_t *fsh;
176 void *oldheap;
Florin Corasb384b542018-01-15 01:08:33 -0800177 int rv;
Dave Barach68b0fb02017-02-28 15:15:56 -0500178
179 /* Allocate a fresh segment */
180 pool_get (sm->segments, s);
181 memset (s, 0, sizeof (*s));
182
183 s->ssvm.ssvm_size = a->segment_size;
184 s->ssvm.i_am_master = 1;
185 s->ssvm.my_pid = getpid ();
Dave Wallaceb8856642017-07-31 13:33:11 -0400186 s->ssvm.name = format (0, "%s%c", a->segment_name, 0);
Dave Barach68b0fb02017-02-28 15:15:56 -0500187 s->ssvm.requested_va = sm->next_baseva;
188
Florin Corasb384b542018-01-15 01:08:33 -0800189 if ((rv = ssvm_master_init (&s->ssvm, a->segment_type)))
Dave Barach68b0fb02017-02-28 15:15:56 -0500190 {
Florin Corasb384b542018-01-15 01:08:33 -0800191 pool_put (sm->segments, s);
Dave Barach68b0fb02017-02-28 15:15:56 -0500192 return (rv);
193 }
194
Florin Corasc87c91d2017-08-16 19:55:49 -0700195 /* Note: requested_va updated due to seg base addr randomization */
Florin Corasb384b542018-01-15 01:08:33 -0800196 sm->next_baseva = s->ssvm.sh->ssvm_va + a->segment_size;
Dave Barach68b0fb02017-02-28 15:15:56 -0500197
198 sh = s->ssvm.sh;
199 oldheap = ssvm_push_heap (sh);
200
201 /* Set up svm_fifo_segment shared header */
202 fsh = clib_mem_alloc (sizeof (*fsh));
203 memset (fsh, 0, sizeof (*fsh));
Florin Corasb384b542018-01-15 01:08:33 -0800204 s->h = sh->opaque[0] = fsh;
205 preallocate_fifo_pairs (s, a, a->seg_protected_space);
Dave Barach68b0fb02017-02-28 15:15:56 -0500206
207 ssvm_pop_heap (oldheap);
208
209 sh->ready = 1;
Dave Barach2c25a622017-06-26 11:35:07 -0400210 vec_add1 (a->new_segment_indices, s - sm->segments);
Dave Barach68b0fb02017-02-28 15:15:56 -0500211 return (0);
212}
213
Florin Corasb384b542018-01-15 01:08:33 -0800214/**
215 * Create an svm fifo segment in process-private memory
216 */
Florin Corasa5464812017-04-19 13:00:05 -0700217int
218svm_fifo_segment_create_process_private (svm_fifo_segment_create_args_t * a)
219{
220 svm_fifo_segment_private_t *s;
221 svm_fifo_segment_main_t *sm = &svm_fifo_segment_main;
222 ssvm_shared_header_t *sh;
223 svm_fifo_segment_header_t *fsh;
Dave Barach2c25a622017-06-26 11:35:07 -0400224 void *oldheap;
225 u8 **heaps = 0;
226 mheap_t *heap_header;
227 int segment_count = 1;
Dave Barach91f3e742017-09-01 19:12:11 -0400228 u32 rnd_size = 0;
Dave Barach2c25a622017-06-26 11:35:07 -0400229 int i;
Florin Corasa5464812017-04-19 13:00:05 -0700230
Florin Corasff6e7692017-12-11 04:59:01 -0800231 if (a->private_segment_count)
Dave Barach2c25a622017-06-26 11:35:07 -0400232 {
Dave Barach2c25a622017-06-26 11:35:07 -0400233 u8 *heap;
234 u32 pagesize = clib_mem_get_page_size ();
Florin Corasff6e7692017-12-11 04:59:01 -0800235 rnd_size = (a->segment_size + (pagesize - 1)) & ~pagesize;
Florin Corasa5464812017-04-19 13:00:05 -0700236
Dave Barach2c25a622017-06-26 11:35:07 -0400237 for (i = 0; i < a->private_segment_count; i++)
238 {
Florin Corasc87c91d2017-08-16 19:55:49 -0700239 heap = mheap_alloc (0, rnd_size);
240 if (heap == 0)
Dave Barach2c25a622017-06-26 11:35:07 -0400241 {
Florin Corasc87c91d2017-08-16 19:55:49 -0700242 clib_unix_warning ("mheap alloc");
Dave Barach2c25a622017-06-26 11:35:07 -0400243 return -1;
244 }
Dave Barach2c25a622017-06-26 11:35:07 -0400245 heap_header = mheap_header (heap);
246 heap_header->flags |= MHEAP_FLAG_THREAD_SAFE;
247 vec_add1 (heaps, heap);
248 }
249 segment_count = a->private_segment_count;
250 }
Florin Corasa5464812017-04-19 13:00:05 -0700251
Dave Barach2c25a622017-06-26 11:35:07 -0400252 /* Allocate segments */
253 for (i = 0; i < segment_count; i++)
254 {
255 pool_get (sm->segments, s);
256 memset (s, 0, sizeof (*s));
Dave Barach10d8cc62017-05-30 09:30:07 -0400257
Dave Barach91f3e742017-09-01 19:12:11 -0400258 s->ssvm.ssvm_size = rnd_size;
Dave Barach2c25a622017-06-26 11:35:07 -0400259 s->ssvm.i_am_master = 1;
260 s->ssvm.my_pid = getpid ();
Dave Wallaceb8856642017-07-31 13:33:11 -0400261 s->ssvm.name = format (0, "%s%c", a->segment_name, 0);
Dave Barach2c25a622017-06-26 11:35:07 -0400262 s->ssvm.requested_va = ~0;
263
264 /* Allocate a [sic] shared memory header, in process memory... */
265 sh = clib_mem_alloc_aligned (sizeof (*sh), CLIB_CACHE_LINE_BYTES);
266 s->ssvm.sh = sh;
267
268 memset (sh, 0, sizeof (*sh));
269 sh->heap = a->private_segment_count ? heaps[i] : clib_mem_get_heap ();
270
271 /* Set up svm_fifo_segment shared header */
272 fsh = clib_mem_alloc (sizeof (*fsh));
273 memset (fsh, 0, sizeof (*fsh));
Florin Corasc87c91d2017-08-16 19:55:49 -0700274 fsh->flags = FIFO_SEGMENT_F_IS_PRIVATE;
Florin Corasb384b542018-01-15 01:08:33 -0800275 s->h = sh->opaque[0] = fsh;
Florin Corasc87c91d2017-08-16 19:55:49 -0700276 if (!a->private_segment_count)
277 fsh->flags |= FIFO_SEGMENT_F_IS_MAIN_HEAP;
Dave Barach2c25a622017-06-26 11:35:07 -0400278
279 if (a->private_segment_count)
280 {
Florin Coras9d063042017-09-14 03:08:00 -0400281 if (i != 0)
282 fsh->flags |= FIFO_SEGMENT_F_IS_PREALLOCATED;
Dave Barach2c25a622017-06-26 11:35:07 -0400283 oldheap = clib_mem_get_heap ();
284 clib_mem_set_heap (sh->heap);
Florin Corasb384b542018-01-15 01:08:33 -0800285 preallocate_fifo_pairs (s, a, i == 0 ? a->seg_protected_space : 0);
Dave Barach2c25a622017-06-26 11:35:07 -0400286 clib_mem_set_heap (oldheap);
287 }
Dave Barach2c25a622017-06-26 11:35:07 -0400288 sh->ready = 1;
289 vec_add1 (a->new_segment_indices, s - sm->segments);
290 }
291 vec_free (heaps);
Florin Corasa5464812017-04-19 13:00:05 -0700292 return (0);
293}
294
Florin Corasb384b542018-01-15 01:08:33 -0800295/**
296 * Attach as slave to an svm fifo segment
297 */
Dave Barach68b0fb02017-02-28 15:15:56 -0500298int
299svm_fifo_segment_attach (svm_fifo_segment_create_args_t * a)
300{
Dave Barach68b0fb02017-02-28 15:15:56 -0500301 svm_fifo_segment_main_t *sm = &svm_fifo_segment_main;
Florin Corasb384b542018-01-15 01:08:33 -0800302 svm_fifo_segment_private_t *s;
303 int rv;
Dave Barach68b0fb02017-02-28 15:15:56 -0500304
305 /* Allocate a fresh segment */
306 pool_get (sm->segments, s);
Dave Barach68b0fb02017-02-28 15:15:56 -0500307 memset (s, 0, sizeof (*s));
308
309 s->ssvm.ssvm_size = a->segment_size;
310 s->ssvm.my_pid = getpid ();
Dave Wallaceb8856642017-07-31 13:33:11 -0400311 s->ssvm.name = format (0, "%s%c", a->segment_name, 0);
Dave Barach68b0fb02017-02-28 15:15:56 -0500312 s->ssvm.requested_va = sm->next_baseva;
Florin Corasb384b542018-01-15 01:08:33 -0800313 if (a->segment_type == SSVM_SEGMENT_MEMFD)
314 s->ssvm.fd = a->memfd_fd;
315 else
316 s->ssvm.attach_timeout = sm->timeout_in_seconds;
Dave Barach68b0fb02017-02-28 15:15:56 -0500317
Florin Corasb384b542018-01-15 01:08:33 -0800318 if ((rv = ssvm_slave_init (&s->ssvm, a->segment_type)))
Dave Barach68b0fb02017-02-28 15:15:56 -0500319 {
320 _vec_len (s) = vec_len (s) - 1;
321 return (rv);
322 }
323
324 /* Fish the segment header */
Florin Corasb384b542018-01-15 01:08:33 -0800325 s->h = s->ssvm.sh->opaque[0];
Dave Barach68b0fb02017-02-28 15:15:56 -0500326
Dave Barach2c25a622017-06-26 11:35:07 -0400327 vec_add1 (a->new_segment_indices, s - sm->segments);
Dave Barach68b0fb02017-02-28 15:15:56 -0500328 return (0);
329}
330
331void
332svm_fifo_segment_delete (svm_fifo_segment_private_t * s)
333{
334 svm_fifo_segment_main_t *sm = &svm_fifo_segment_main;
Florin Corasb384b542018-01-15 01:08:33 -0800335
Florin Corasc87c91d2017-08-16 19:55:49 -0700336 if (s->h->flags & FIFO_SEGMENT_F_IS_PRIVATE)
337 {
338 /* Don't try to free vpp's heap! */
339 if (!(s->h->flags & FIFO_SEGMENT_F_IS_MAIN_HEAP))
340 mheap_free (s->ssvm.sh->heap);
341 clib_mem_free (s->ssvm.sh);
342 clib_mem_free (s->h);
Florin Corasc87c91d2017-08-16 19:55:49 -0700343 }
344 else
345 {
346 ssvm_delete (&s->ssvm);
Florin Corasc87c91d2017-08-16 19:55:49 -0700347 }
Florin Corasb384b542018-01-15 01:08:33 -0800348 memset (s, 0xfe, sizeof (*s));
349 pool_put (sm->segments, s);
Dave Barach68b0fb02017-02-28 15:15:56 -0500350}
351
Florin Corasb384b542018-01-15 01:08:33 -0800352/**
353 * Allocate fifo in svm segment
354 */
Dave Barach68b0fb02017-02-28 15:15:56 -0500355svm_fifo_t *
356svm_fifo_segment_alloc_fifo (svm_fifo_segment_private_t * s,
Dave Barach10d8cc62017-05-30 09:30:07 -0400357 u32 data_size_in_bytes,
358 svm_fifo_segment_freelist_t list_index)
Dave Barach68b0fb02017-02-28 15:15:56 -0500359{
360 ssvm_shared_header_t *sh;
361 svm_fifo_segment_header_t *fsh;
362 svm_fifo_t *f;
363 void *oldheap;
Dave Barach818eb542017-08-02 13:56:13 -0400364 int freelist_index;
365
366 /*
Florin Corasc87c91d2017-08-16 19:55:49 -0700367 * 4K minimum. It's not likely that anything good will happen
368 * with a smaller FIFO.
Dave Barach818eb542017-08-02 13:56:13 -0400369 */
370 if (data_size_in_bytes < FIFO_SEGMENT_MIN_FIFO_SIZE ||
371 data_size_in_bytes > FIFO_SEGMENT_MAX_FIFO_SIZE)
372 {
373 clib_warning ("fifo size out of range %d", data_size_in_bytes);
374 return 0;
375 }
376
377 freelist_index = max_log2 (data_size_in_bytes)
378 - max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE);
Dave Barach68b0fb02017-02-28 15:15:56 -0500379
380 sh = s->ssvm.sh;
381 fsh = (svm_fifo_segment_header_t *) sh->opaque[0];
Florin Corasa5464812017-04-19 13:00:05 -0700382
Dave Barach2c25a622017-06-26 11:35:07 -0400383 ssvm_lock_non_recursive (sh, 1);
Dave Barach68b0fb02017-02-28 15:15:56 -0500384 oldheap = ssvm_push_heap (sh);
385
Dave Barach10d8cc62017-05-30 09:30:07 -0400386 switch (list_index)
387 {
388 case FIFO_SEGMENT_RX_FREELIST:
389 case FIFO_SEGMENT_TX_FREELIST:
Dave Barach818eb542017-08-02 13:56:13 -0400390 vec_validate_init_empty (fsh->free_fifos, freelist_index, 0);
391
392 f = fsh->free_fifos[freelist_index];
393 if (PREDICT_FALSE (f == 0))
Dave Barach10d8cc62017-05-30 09:30:07 -0400394 {
Dave Barach818eb542017-08-02 13:56:13 -0400395 allocate_new_fifo_chunk (fsh, data_size_in_bytes,
396 FIFO_SEGMENT_ALLOC_CHUNK_SIZE);
397 f = fsh->free_fifos[freelist_index];
398 }
399 if (PREDICT_TRUE (f != 0))
400 {
401 fsh->free_fifos[freelist_index] = f->next;
Dave Barach10d8cc62017-05-30 09:30:07 -0400402 /* (re)initialize the fifo, as in svm_fifo_create */
403 memset (f, 0, sizeof (*f));
404 f->nitems = data_size_in_bytes;
405 f->ooos_list_head = OOO_SEGMENT_INVALID_INDEX;
Dave Barach52851e62017-08-07 09:35:25 -0400406 f->refcnt = 1;
Dave Barach818eb542017-08-02 13:56:13 -0400407 f->freelist_index = freelist_index;
Dave Barach10d8cc62017-05-30 09:30:07 -0400408 goto found;
409 }
410 /* FALLTHROUGH */
411 case FIFO_SEGMENT_FREELIST_NONE:
412 break;
413
414 default:
415 clib_warning ("ignore bogus freelist %d", list_index);
416 break;
417 }
418
Dave Barach68b0fb02017-02-28 15:15:56 -0500419 /* Note: this can fail, in which case: create another segment */
420 f = svm_fifo_create (data_size_in_bytes);
Florin Corasa5464812017-04-19 13:00:05 -0700421 if (PREDICT_FALSE (f == 0))
Dave Barach68b0fb02017-02-28 15:15:56 -0500422 {
423 ssvm_pop_heap (oldheap);
Dave Barach2c25a622017-06-26 11:35:07 -0400424 ssvm_unlock_non_recursive (sh);
Dave Barach68b0fb02017-02-28 15:15:56 -0500425 return (0);
426 }
Dave Barach818eb542017-08-02 13:56:13 -0400427 f->freelist_index = freelist_index;
Dave Barach68b0fb02017-02-28 15:15:56 -0500428
Dave Barach10d8cc62017-05-30 09:30:07 -0400429found:
430 /* If rx_freelist add to active fifos list. When cleaning up segment,
431 * we need a list of active sessions that should be disconnected. Since
432 * both rx and tx fifos keep pointers to the session, it's enough to track
433 * only one. */
434 if (list_index == FIFO_SEGMENT_RX_FREELIST)
435 {
436 if (fsh->fifos)
437 {
438 fsh->fifos->prev = f;
439 f->next = fsh->fifos;
440 }
441 fsh->fifos = f;
442 }
Florin Corasc87c91d2017-08-16 19:55:49 -0700443 fsh->n_active_fifos++;
Dave Barach10d8cc62017-05-30 09:30:07 -0400444
Dave Barach68b0fb02017-02-28 15:15:56 -0500445 ssvm_pop_heap (oldheap);
Dave Barach2c25a622017-06-26 11:35:07 -0400446 ssvm_unlock_non_recursive (sh);
Dave Barach68b0fb02017-02-28 15:15:56 -0500447 return (f);
448}
449
450void
Dave Barach10d8cc62017-05-30 09:30:07 -0400451svm_fifo_segment_free_fifo (svm_fifo_segment_private_t * s, svm_fifo_t * f,
452 svm_fifo_segment_freelist_t list_index)
Dave Barach68b0fb02017-02-28 15:15:56 -0500453{
454 ssvm_shared_header_t *sh;
455 svm_fifo_segment_header_t *fsh;
456 void *oldheap;
Dave Barach818eb542017-08-02 13:56:13 -0400457 int freelist_index;
Dave Barach68b0fb02017-02-28 15:15:56 -0500458
Dave Barach52851e62017-08-07 09:35:25 -0400459 ASSERT (f->refcnt > 0);
460
461 if (--f->refcnt > 0)
462 return;
Dave Barach2c25a622017-06-26 11:35:07 -0400463
Dave Barach68b0fb02017-02-28 15:15:56 -0500464 sh = s->ssvm.sh;
465 fsh = (svm_fifo_segment_header_t *) sh->opaque[0];
Dave Barach68b0fb02017-02-28 15:15:56 -0500466
Dave Barach818eb542017-08-02 13:56:13 -0400467 freelist_index = f->freelist_index;
468
Dave Barachb7f1faa2017-08-29 11:43:37 -0400469 ASSERT (freelist_index < vec_len (fsh->free_fifos));
Dave Barach818eb542017-08-02 13:56:13 -0400470
Dave Barach2c25a622017-06-26 11:35:07 -0400471 ssvm_lock_non_recursive (sh, 2);
Florin Corasa5464812017-04-19 13:00:05 -0700472 oldheap = ssvm_push_heap (sh);
Dave Barach68b0fb02017-02-28 15:15:56 -0500473
Dave Barach10d8cc62017-05-30 09:30:07 -0400474 switch (list_index)
475 {
476 case FIFO_SEGMENT_RX_FREELIST:
477 /* Remove from active list */
478 if (f->prev)
479 f->prev->next = f->next;
Florin Corasf03a59a2017-06-09 21:07:32 -0700480 else
481 fsh->fifos = f->next;
Dave Barach10d8cc62017-05-30 09:30:07 -0400482 if (f->next)
483 f->next->prev = f->prev;
Florin Corasf03a59a2017-06-09 21:07:32 -0700484 /* Fall through: we add only rx fifos to active pool */
Dave Barach10d8cc62017-05-30 09:30:07 -0400485 case FIFO_SEGMENT_TX_FREELIST:
486 /* Add to free list */
Dave Barach818eb542017-08-02 13:56:13 -0400487 f->next = fsh->free_fifos[freelist_index];
Florin Corasf03a59a2017-06-09 21:07:32 -0700488 f->prev = 0;
Dave Barach818eb542017-08-02 13:56:13 -0400489 fsh->free_fifos[freelist_index] = f;
Florin Corasf03a59a2017-06-09 21:07:32 -0700490 break;
Dave Barach10d8cc62017-05-30 09:30:07 -0400491 case FIFO_SEGMENT_FREELIST_NONE:
492 break;
493
494 default:
495 clib_warning ("ignore bogus freelist %d", list_index);
496 break;
497 }
498
Florin Coras68810622017-07-24 17:40:28 -0700499 if (CLIB_DEBUG)
500 {
501 f->master_session_index = ~0;
502 f->master_thread_index = ~0;
503 }
504
Florin Corasc87c91d2017-08-16 19:55:49 -0700505 fsh->n_active_fifos--;
Dave Barach68b0fb02017-02-28 15:15:56 -0500506 ssvm_pop_heap (oldheap);
Dave Barach2c25a622017-06-26 11:35:07 -0400507 ssvm_unlock_non_recursive (sh);
Dave Barach68b0fb02017-02-28 15:15:56 -0500508}
509
510void
511svm_fifo_segment_init (u64 baseva, u32 timeout_in_seconds)
512{
513 svm_fifo_segment_main_t *sm = &svm_fifo_segment_main;
514
515 sm->next_baseva = baseva;
516 sm->timeout_in_seconds = timeout_in_seconds;
517}
518
519u32
520svm_fifo_segment_index (svm_fifo_segment_private_t * s)
521{
522 return s - svm_fifo_segment_main.segments;
523}
524
Florin Corasc87c91d2017-08-16 19:55:49 -0700525/**
526 * Retrieve svm segments pool. Used only for debug purposes.
527 */
528svm_fifo_segment_private_t *
529svm_fifo_segment_segments_pool (void)
530{
531 svm_fifo_segment_main_t *sm = &svm_fifo_segment_main;
532 return sm->segments;
533}
534
535/**
536 * Get number of active fifos
537 */
538u32
539svm_fifo_segment_num_fifos (svm_fifo_segment_private_t * fifo_segment)
540{
541 return fifo_segment->h->n_active_fifos;
542}
543
Dave Barach91f3e742017-09-01 19:12:11 -0400544u32
545svm_fifo_segment_num_free_fifos (svm_fifo_segment_private_t * fifo_segment,
546 u32 fifo_size_in_bytes)
547{
548 ssvm_shared_header_t *sh;
549 svm_fifo_segment_header_t *fsh;
550 svm_fifo_t *f;
551 int i;
552 u32 count = 0, rounded_data_size, freelist_index;
553
554 sh = fifo_segment->ssvm.sh;
555 fsh = (svm_fifo_segment_header_t *) sh->opaque[0];
556
557 /* Count all free fifos? */
558 if (fifo_size_in_bytes == ~0)
559 {
560 for (i = 0; i < vec_len (fsh->free_fifos); i++)
561 {
562 f = fsh->free_fifos[i];
563 if (f == 0)
564 continue;
565
566 while (f)
567 {
568 f = f->next;
569 count++;
570 }
571 }
572 return count;
573 }
574
575 rounded_data_size = (1 << (max_log2 (fifo_size_in_bytes)));
576 freelist_index = max_log2 (rounded_data_size)
577 - max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE);
578
579 if (freelist_index > vec_len (fsh->free_fifos))
580 return 0;
581
582 f = fsh->free_fifos[freelist_index];
583 if (f == 0)
584 return 0;
585
586 while (f)
587 {
588 f = f->next;
589 count++;
590 }
591 return count;
592}
593
Florin Corasb384b542018-01-15 01:08:33 -0800594void
595svm_fifo_segment_info (svm_fifo_segment_private_t * seg, uword * address,
596 u64 * size)
597{
598 if (seg->h->flags & FIFO_SEGMENT_F_IS_PRIVATE)
599 {
600 mheap_t *heap_header;
601
602 *address = pointer_to_uword (seg->ssvm.sh->heap);
603 heap_header = mheap_header (seg->ssvm.sh->heap);
604 *size = heap_header->max_size;
605 }
606 else
607 {
608 *address = seg->ssvm.sh->ssvm_va;
609 *size = seg->ssvm.ssvm_size;
610 }
611}
612
613mheap_t *
614svm_fifo_segment_heap (svm_fifo_segment_private_t * seg)
615{
616 return seg->ssvm.sh->heap;
617}
618
619u8 *
620format_svm_fifo_segment_type (u8 * s, va_list * args)
621{
622 svm_fifo_segment_private_t *sp;
623 sp = va_arg (*args, svm_fifo_segment_private_t *);
624 ssvm_segment_type_t st = ssvm_type (&sp->ssvm);
625
626 if ((sp->h->flags & FIFO_SEGMENT_F_IS_PRIVATE)
627 && !(sp->h->flags & FIFO_SEGMENT_F_IS_MAIN_HEAP))
628 s = format (s, "%s", "private-heap");
629 else if ((sp->h->flags & FIFO_SEGMENT_F_IS_PRIVATE)
630 && (sp->h->flags & FIFO_SEGMENT_F_IS_MAIN_HEAP))
631 s = format (s, "%s", "main-heap");
632 else if (st == SSVM_SEGMENT_MEMFD)
633 s = format (s, "%s", "memfd");
634 else if (st == SSVM_SEGMENT_SHM)
635 s = format (s, "%s", "shm");
636 else
637 s = format (s, "%s", "unknown");
638 return s;
639}
640
Dave Barach91f3e742017-09-01 19:12:11 -0400641/**
642 * Segment format function
643 */
644u8 *
645format_svm_fifo_segment (u8 * s, va_list * args)
646{
647 svm_fifo_segment_private_t *sp
648 = va_arg (*args, svm_fifo_segment_private_t *);
649 int verbose = va_arg (*args, int);
Florin Corasb384b542018-01-15 01:08:33 -0800650 svm_fifo_segment_header_t *fsh = sp->h;
651 u32 count, indent;
Dave Barach91f3e742017-09-01 19:12:11 -0400652 svm_fifo_t *f;
653 int i;
Dave Barach91f3e742017-09-01 19:12:11 -0400654
Florin Corasb384b542018-01-15 01:08:33 -0800655 indent = format_get_indent (s) + 2;
656 s = format (s, "%U segment heap: %U\n", format_white_space, indent,
657 format_mheap, svm_fifo_segment_heap (sp), verbose);
Dave Barach91f3e742017-09-01 19:12:11 -0400658 s = format (s, "%U segment has %u active fifos\n",
659 format_white_space, indent, svm_fifo_segment_num_fifos (sp));
660
661 for (i = 0; i < vec_len (fsh->free_fifos); i++)
662 {
663 f = fsh->free_fifos[i];
664 if (f == 0)
665 continue;
666 count = 0;
667 while (f)
668 {
669 f = f->next;
670 count++;
671 }
672
673 s = format (s, "%U%-5u Kb: %u free",
674 format_white_space, indent + 2,
675 1 << (i + max_log2 (FIFO_SEGMENT_MIN_FIFO_SIZE) - 10),
676 count);
677 }
678 return s;
679}
680
Dave Barach68b0fb02017-02-28 15:15:56 -0500681/*
682 * fd.io coding-style-patch-verification: ON
683 *
684 * Local Variables:
685 * eval: (c-set-style "gnu")
686 * End:
687 */