blob: 7af2433b44e3aeb238d73da7340377de9166dfe6 [file] [log] [blame]
Dave Barach371e4e12016-07-08 09:38:52 -04001/*
Ed Warnickecb9cada2015-12-08 15:45:58 -07002 *------------------------------------------------------------------
3 * memclnt_shared.c - API message handling, common code for both clients
4 * and the vlib process itself.
Dave Barach371e4e12016-07-08 09:38:52 -04005 *
Ed Warnickecb9cada2015-12-08 15:45:58 -07006 *
7 * Copyright (c) 2009 Cisco and/or its affiliates.
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at:
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *------------------------------------------------------------------
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
Ole Troan6855f6c2016-04-09 03:16:30 +020024#include <stddef.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070025#include <string.h>
26#include <unistd.h>
27#include <signal.h>
28#include <vppinfra/format.h>
29#include <vppinfra/byte_order.h>
30#include <vppinfra/error.h>
31#include <vlib/vlib.h>
32#include <vlib/unix/unix.h>
33#include <vlibmemory/api.h>
34#include <vlibmemory/unix_shared_memory_queue.h>
35
Dave Barach371e4e12016-07-08 09:38:52 -040036#include <vlibmemory/vl_memory_msg_enum.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070037
Dave Barach371e4e12016-07-08 09:38:52 -040038#define vl_typedefs
Ed Warnickecb9cada2015-12-08 15:45:58 -070039#include <vlibmemory/vl_memory_api_h.h>
40#undef vl_typedefs
41
Dave Barach59b25652017-09-10 15:04:27 -040042socket_main_t socket_main;
43
44#define DEBUG_MESSAGE_BUFFER_OVERRUN 0
45
Dave Barach371e4e12016-07-08 09:38:52 -040046static inline void *
Dave Barach77378332016-10-13 17:35:09 -040047vl_msg_api_alloc_internal (int nbytes, int pool, int may_return_null)
Ed Warnickecb9cada2015-12-08 15:45:58 -070048{
Dave Barach371e4e12016-07-08 09:38:52 -040049 int i;
50 msgbuf_t *rv;
51 ring_alloc_t *ap;
52 unix_shared_memory_queue_t *q;
53 void *oldheap;
54 vl_shmem_hdr_t *shmem_hdr;
55 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -070056
Dave Barach371e4e12016-07-08 09:38:52 -040057 shmem_hdr = am->shmem_hdr;
Ed Warnickecb9cada2015-12-08 15:45:58 -070058
Dave Barach59b25652017-09-10 15:04:27 -040059#if DEBUG_MESSAGE_BUFFER_OVERRUN > 0
60 nbytes += 4;
61#endif
62
Florin Coras7a2e1bd2017-11-30 16:07:39 -050063 ASSERT (pool == 0 || vlib_get_thread_index () == 0);
64
Dave Barach371e4e12016-07-08 09:38:52 -040065 if (shmem_hdr == 0)
66 {
67 clib_warning ("shared memory header NULL");
68 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -070069 }
70
Dave Barach371e4e12016-07-08 09:38:52 -040071 /* account for the msgbuf_t header */
72 nbytes += sizeof (msgbuf_t);
Ed Warnickecb9cada2015-12-08 15:45:58 -070073
Dave Barach371e4e12016-07-08 09:38:52 -040074 if (shmem_hdr->vl_rings == 0)
75 {
76 clib_warning ("vl_rings NULL");
Dave Barach77378332016-10-13 17:35:09 -040077 ASSERT (0);
78 abort ();
Ed Warnickecb9cada2015-12-08 15:45:58 -070079 }
80
Dave Barach371e4e12016-07-08 09:38:52 -040081 if (shmem_hdr->client_rings == 0)
82 {
83 clib_warning ("client_rings NULL");
Dave Barach77378332016-10-13 17:35:09 -040084 ASSERT (0);
85 abort ();
Ed Warnickecb9cada2015-12-08 15:45:58 -070086 }
87
Dave Barach371e4e12016-07-08 09:38:52 -040088 ap = pool ? shmem_hdr->vl_rings : shmem_hdr->client_rings;
89 for (i = 0; i < vec_len (ap); i++)
90 {
91 /* Too big? */
92 if (nbytes > ap[i].size)
93 {
94 continue;
95 }
Ed Warnickecb9cada2015-12-08 15:45:58 -070096
Dave Barach371e4e12016-07-08 09:38:52 -040097 q = ap[i].rp;
98 if (pool == 0)
99 {
100 pthread_mutex_lock (&q->mutex);
101 }
102 rv = (msgbuf_t *) (&q->data[0] + q->head * q->elsize);
103 /*
104 * Is this item still in use?
105 */
106 if (rv->q)
107 {
Dave Barach842b9c52017-01-09 15:54:00 -0500108 u32 now = (u32) time (0);
109
110 if (PREDICT_TRUE (rv->gc_mark_timestamp == 0))
111 rv->gc_mark_timestamp = now;
112 else
113 {
114 if (now - rv->gc_mark_timestamp > 10)
115 {
116 if (CLIB_DEBUG > 0)
Dave Barach10d8cc62017-05-30 09:30:07 -0400117 {
118 u16 *msg_idp, msg_id;
119 clib_warning
120 ("garbage collect pool %d ring %d index %d", pool, i,
121 q->head);
122 msg_idp = (u16 *) (rv->data);
123 msg_id = clib_net_to_host_u16 (*msg_idp);
124 if (msg_id < vec_len (api_main.msg_names))
125 clib_warning ("msg id %d name %s", (u32) msg_id,
126 api_main.msg_names[msg_id]);
127 }
Dave Barach842b9c52017-01-09 15:54:00 -0500128 shmem_hdr->garbage_collects++;
129 goto collected;
130 }
131 }
132
133
Dave Barach371e4e12016-07-08 09:38:52 -0400134 /* yes, loser; try next larger pool */
135 ap[i].misses++;
136 if (pool == 0)
137 pthread_mutex_unlock (&q->mutex);
138 continue;
139 }
Dave Barach842b9c52017-01-09 15:54:00 -0500140 collected:
141
Dave Barach371e4e12016-07-08 09:38:52 -0400142 /* OK, we have a winner */
143 ap[i].hits++;
144 /*
145 * Remember the source queue, although we
146 * don't need to know the queue to free the item.
147 */
148 rv->q = q;
Dave Barach842b9c52017-01-09 15:54:00 -0500149 rv->gc_mark_timestamp = 0;
Dave Barach371e4e12016-07-08 09:38:52 -0400150 q->head++;
151 if (q->head == q->maxsize)
152 q->head = 0;
153
154 if (pool == 0)
155 pthread_mutex_unlock (&q->mutex);
156 goto out;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700157 }
158
Dave Barach371e4e12016-07-08 09:38:52 -0400159 /*
160 * Request too big, or head element of all size-compatible rings
161 * still in use. Fall back to shared-memory malloc.
162 */
163 am->ring_misses++;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700164
Dave Barach371e4e12016-07-08 09:38:52 -0400165 pthread_mutex_lock (&am->vlib_rp->mutex);
166 oldheap = svm_push_data_heap (am->vlib_rp);
Dave Barach77378332016-10-13 17:35:09 -0400167 if (may_return_null)
168 {
169 rv = clib_mem_alloc_or_null (nbytes);
170 if (PREDICT_FALSE (rv == 0))
171 {
172 svm_pop_heap (oldheap);
173 pthread_mutex_unlock (&am->vlib_rp->mutex);
174 return 0;
175 }
176 }
177 else
178 rv = clib_mem_alloc (nbytes);
179
Dave Barach371e4e12016-07-08 09:38:52 -0400180 rv->q = 0;
181 svm_pop_heap (oldheap);
182 pthread_mutex_unlock (&am->vlib_rp->mutex);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700183
Dave Barach371e4e12016-07-08 09:38:52 -0400184out:
Dave Barach59b25652017-09-10 15:04:27 -0400185#if DEBUG_MESSAGE_BUFFER_OVERRUN > 0
186 {
187 nbytes -= 4;
188 u32 *overrun;
189 overrun = (u32 *) (rv->data + nbytes - sizeof (msgbuf_t));
190 *overrun = 0x1badbabe;
191 }
192#endif
Dave Barach371e4e12016-07-08 09:38:52 -0400193 rv->data_len = htonl (nbytes - sizeof (msgbuf_t));
Dave Barach59b25652017-09-10 15:04:27 -0400194
Dave Barach371e4e12016-07-08 09:38:52 -0400195 return (rv->data);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700196}
197
Dave Barach371e4e12016-07-08 09:38:52 -0400198void *
199vl_msg_api_alloc (int nbytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700200{
Dave Barach371e4e12016-07-08 09:38:52 -0400201 int pool;
202 api_main_t *am = &api_main;
203 vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700204
Dave Barach371e4e12016-07-08 09:38:52 -0400205 /*
206 * Clients use pool-0, vlib proc uses pool 1
207 */
208 pool = (am->our_pid == shmem_hdr->vl_pid);
Dave Barach77378332016-10-13 17:35:09 -0400209 return vl_msg_api_alloc_internal (nbytes, pool, 0 /* may_return_null */ );
210}
211
212void *
213vl_msg_api_alloc_or_null (int nbytes)
214{
215 int pool;
216 api_main_t *am = &api_main;
217 vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr;
218
219 pool = (am->our_pid == shmem_hdr->vl_pid);
220 return vl_msg_api_alloc_internal (nbytes, pool, 1 /* may_return_null */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700221}
222
Dave Barach371e4e12016-07-08 09:38:52 -0400223void *
224vl_msg_api_alloc_as_if_client (int nbytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700225{
Dave Barach77378332016-10-13 17:35:09 -0400226 return vl_msg_api_alloc_internal (nbytes, 0, 0 /* may_return_null */ );
227}
228
229void *
230vl_msg_api_alloc_as_if_client_or_null (int nbytes)
231{
232 return vl_msg_api_alloc_internal (nbytes, 0, 1 /* may_return_null */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700233}
234
Dave Barach371e4e12016-07-08 09:38:52 -0400235void
236vl_msg_api_free (void *a)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700237{
Dave Barach371e4e12016-07-08 09:38:52 -0400238 msgbuf_t *rv;
239 void *oldheap;
240 api_main_t *am = &api_main;
Ole Troan6855f6c2016-04-09 03:16:30 +0200241
Dave Barach371e4e12016-07-08 09:38:52 -0400242 rv = (msgbuf_t *) (((u8 *) a) - offsetof (msgbuf_t, data));
243
244 /*
245 * Here's the beauty of the scheme. Only one proc/thread has
246 * control of a given message buffer. To free a buffer, we just clear the
247 * queue field, and leave. No locks, no hits, no errors...
248 */
249 if (rv->q)
250 {
251 rv->q = 0;
Dave Barach842b9c52017-01-09 15:54:00 -0500252 rv->gc_mark_timestamp = 0;
Dave Barach59b25652017-09-10 15:04:27 -0400253#if DEBUG_MESSAGE_BUFFER_OVERRUN > 0
254 {
255 u32 *overrun;
256 overrun = (u32 *) (rv->data + ntohl (rv->data_len));
257 ASSERT (*overrun == 0x1badbabe);
258 }
259#endif
Dave Barach371e4e12016-07-08 09:38:52 -0400260 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700261 }
262
Dave Barach371e4e12016-07-08 09:38:52 -0400263 pthread_mutex_lock (&am->vlib_rp->mutex);
264 oldheap = svm_push_data_heap (am->vlib_rp);
Dave Barach59b25652017-09-10 15:04:27 -0400265
266#if DEBUG_MESSAGE_BUFFER_OVERRUN > 0
267 {
268 u32 *overrun;
269 overrun = (u32 *) (rv->data + ntohl (rv->data_len));
270 ASSERT (*overrun == 0x1badbabe);
271 }
272#endif
273
Dave Barach371e4e12016-07-08 09:38:52 -0400274 clib_mem_free (rv);
275 svm_pop_heap (oldheap);
276 pthread_mutex_unlock (&am->vlib_rp->mutex);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700277}
278
Dave Barach371e4e12016-07-08 09:38:52 -0400279static void
280vl_msg_api_free_nolock (void *a)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700281{
Dave Barach371e4e12016-07-08 09:38:52 -0400282 msgbuf_t *rv;
283 void *oldheap;
284 api_main_t *am = &api_main;
285
286 rv = (msgbuf_t *) (((u8 *) a) - offsetof (msgbuf_t, data));
287 /*
288 * Here's the beauty of the scheme. Only one proc/thread has
289 * control of a given message buffer. To free a buffer, we just clear the
290 * queue field, and leave. No locks, no hits, no errors...
291 */
292 if (rv->q)
293 {
294 rv->q = 0;
295 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700296 }
297
Dave Barach371e4e12016-07-08 09:38:52 -0400298 oldheap = svm_push_data_heap (am->vlib_rp);
299 clib_mem_free (rv);
300 svm_pop_heap (oldheap);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700301}
302
Dave Barach371e4e12016-07-08 09:38:52 -0400303void
Neale Rannse72be392017-04-26 13:59:20 -0700304vl_set_memory_root_path (const char *name)
Dave Barach309bef22016-01-22 16:09:52 -0500305{
Dave Barach371e4e12016-07-08 09:38:52 -0400306 api_main_t *am = &api_main;
Dave Barach309bef22016-01-22 16:09:52 -0500307
Dave Barach371e4e12016-07-08 09:38:52 -0400308 am->root_path = name;
Dave Barach309bef22016-01-22 16:09:52 -0500309}
310
Dave Barach371e4e12016-07-08 09:38:52 -0400311void
312vl_set_memory_uid (int uid)
Dave Barach16c75df2016-05-31 14:05:46 -0400313{
Dave Barach371e4e12016-07-08 09:38:52 -0400314 api_main_t *am = &api_main;
Dave Barach16c75df2016-05-31 14:05:46 -0400315
Dave Barach371e4e12016-07-08 09:38:52 -0400316 am->api_uid = uid;
Dave Barach16c75df2016-05-31 14:05:46 -0400317}
318
Dave Barach371e4e12016-07-08 09:38:52 -0400319void
320vl_set_memory_gid (int gid)
Dave Barach16c75df2016-05-31 14:05:46 -0400321{
Dave Barach371e4e12016-07-08 09:38:52 -0400322 api_main_t *am = &api_main;
Dave Barach16c75df2016-05-31 14:05:46 -0400323
Dave Barach371e4e12016-07-08 09:38:52 -0400324 am->api_gid = gid;
Dave Barach16c75df2016-05-31 14:05:46 -0400325}
326
Dave Barachb3d93da2016-08-03 14:34:38 -0400327void
328vl_set_global_memory_baseva (u64 baseva)
329{
330 api_main_t *am = &api_main;
331
332 am->global_baseva = baseva;
333}
334
335void
336vl_set_global_memory_size (u64 size)
337{
338 api_main_t *am = &api_main;
339
340 am->global_size = size;
341}
342
343void
344vl_set_api_memory_size (u64 size)
345{
346 api_main_t *am = &api_main;
347
348 am->api_size = size;
349}
350
351void
352vl_set_global_pvt_heap_size (u64 size)
353{
354 api_main_t *am = &api_main;
355
356 am->global_pvt_heap_size = size;
357}
358
359void
360vl_set_api_pvt_heap_size (u64 size)
361{
362 api_main_t *am = &api_main;
363
364 am->api_pvt_heap_size = size;
365}
366
Dave Barach59b25652017-09-10 15:04:27 -0400367void
368vl_init_shmem (svm_region_t * vlib_rp, int is_vlib, int is_private_region)
369{
370 api_main_t *am = &api_main;
371 vl_shmem_hdr_t *shmem_hdr = 0;
372 u32 vlib_input_queue_length;
373 void *oldheap;
374 ASSERT (vlib_rp);
375
376 /* $$$$ need private region config parameters */
377
378 oldheap = svm_push_data_heap (vlib_rp);
379
380 vec_validate (shmem_hdr, 0);
381 shmem_hdr->version = VL_SHM_VERSION;
382
383 /* vlib main input queue */
384 vlib_input_queue_length = 1024;
385 if (am->vlib_input_queue_length)
386 vlib_input_queue_length = am->vlib_input_queue_length;
387
388 shmem_hdr->vl_input_queue =
389 unix_shared_memory_queue_init (vlib_input_queue_length, sizeof (uword),
390 getpid (), am->vlib_signal);
391
392 /* Set up the msg ring allocator */
393#define _(sz,n) \
394 do { \
395 ring_alloc_t _rp; \
396 _rp.rp = unix_shared_memory_queue_init ((n), (sz), 0, 0); \
397 _rp.size = (sz); \
398 _rp.nitems = n; \
399 _rp.hits = 0; \
400 _rp.misses = 0; \
401 vec_add1(shmem_hdr->vl_rings, _rp); \
402 } while (0);
403
404 foreach_vl_aring_size;
405#undef _
406
407#define _(sz,n) \
408 do { \
409 ring_alloc_t _rp; \
410 _rp.rp = unix_shared_memory_queue_init ((n), (sz), 0, 0); \
411 _rp.size = (sz); \
412 _rp.nitems = n; \
413 _rp.hits = 0; \
414 _rp.misses = 0; \
415 vec_add1(shmem_hdr->client_rings, _rp); \
416 } while (0);
417
418 foreach_clnt_aring_size;
419#undef _
420
421 if (is_private_region == 0)
422 {
423 am->shmem_hdr = shmem_hdr;
424 am->vlib_rp = vlib_rp;
425 am->our_pid = getpid ();
426 if (is_vlib)
427 am->shmem_hdr->vl_pid = am->our_pid;
428 }
429 else
430 shmem_hdr->vl_pid = am->our_pid;
431
432 svm_pop_heap (oldheap);
433
434 /*
435 * After absolutely everything that a client might see is set up,
436 * declare the shmem region valid
437 */
438 vlib_rp->user_ctx = shmem_hdr;
439
440 pthread_mutex_unlock (&vlib_rp->mutex);
441}
442
443
Dave Barach371e4e12016-07-08 09:38:52 -0400444int
Neale Rannse72be392017-04-26 13:59:20 -0700445vl_map_shmem (const char *region_name, int is_vlib)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700446{
Dave Barach371e4e12016-07-08 09:38:52 -0400447 svm_map_region_args_t _a, *a = &_a;
448 svm_region_t *vlib_rp, *root_rp;
Dave Barach371e4e12016-07-08 09:38:52 -0400449 api_main_t *am = &api_main;
Ole Troan3cdc25f2017-08-17 11:07:33 +0200450 int i, rv;
Dave Barach371e4e12016-07-08 09:38:52 -0400451 struct timespec ts, tsrem;
Dave Wallacecfc997e2017-08-22 18:32:34 -0400452 char *vpe_api_region_suffix = "-vpe-api";
Ed Warnickecb9cada2015-12-08 15:45:58 -0700453
Jan Srnicek5beec812017-03-24 10:18:11 +0100454 memset (a, 0, sizeof (*a));
455
Dave Wallacecfc997e2017-08-22 18:32:34 -0400456 if (strstr (region_name, vpe_api_region_suffix))
Jan Srnicek5beec812017-03-24 10:18:11 +0100457 {
Dave Wallacecfc997e2017-08-22 18:32:34 -0400458 u8 *root_path = format (0, "%s", region_name);
459 _vec_len (root_path) = (vec_len (root_path) -
460 strlen (vpe_api_region_suffix));
461 vec_terminate_c_string (root_path);
462 a->root_path = (const char *) root_path;
463 am->root_path = (const char *) root_path;
Jan Srnicek5beec812017-03-24 10:18:11 +0100464 }
465
Dave Barach371e4e12016-07-08 09:38:52 -0400466 if (is_vlib == 0)
Ole Troan3cdc25f2017-08-17 11:07:33 +0200467 {
468 rv = svm_region_init_chroot (am->root_path);
469 if (rv)
470 return rv;
471 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700472
Jan Srnicek5beec812017-03-24 10:18:11 +0100473 if (a->root_path != NULL)
474 {
475 a->name = "/vpe-api";
476 }
477 else
478 a->name = region_name;
Dave Barachc3799992016-08-15 11:12:27 -0400479 a->size = am->api_size ? am->api_size : (16 << 20);
Dave Barach371e4e12016-07-08 09:38:52 -0400480 a->flags = SVM_FLAGS_MHEAP;
481 a->uid = am->api_uid;
482 a->gid = am->api_gid;
Dave Barachb3d93da2016-08-03 14:34:38 -0400483 a->pvt_heap_size = am->api_pvt_heap_size;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700484
Dave Barach371e4e12016-07-08 09:38:52 -0400485 vlib_rp = svm_region_find_or_create (a);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700486
Dave Barach371e4e12016-07-08 09:38:52 -0400487 if (vlib_rp == 0)
488 return (-2);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700489
Dave Barach371e4e12016-07-08 09:38:52 -0400490 pthread_mutex_lock (&vlib_rp->mutex);
491 /* Has someone else set up the shared-memory variable table? */
492 if (vlib_rp->user_ctx)
493 {
494 am->shmem_hdr = (void *) vlib_rp->user_ctx;
495 am->our_pid = getpid ();
496 if (is_vlib)
497 {
498 unix_shared_memory_queue_t *q;
499 uword old_msg;
500 /*
501 * application restart. Reset cached pids, API message
502 * rings, list of clients; otherwise, various things
503 * fail. (e.g. queue non-empty notification)
504 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700505
Dave Barach371e4e12016-07-08 09:38:52 -0400506 /* ghosts keep the region from disappearing properly */
507 svm_client_scan_this_region_nolock (vlib_rp);
508 am->shmem_hdr->application_restarts++;
509 q = am->shmem_hdr->vl_input_queue;
510 am->shmem_hdr->vl_pid = getpid ();
511 q->consumer_pid = am->shmem_hdr->vl_pid;
512 /* Drain the input queue, freeing msgs */
513 for (i = 0; i < 10; i++)
514 {
515 if (pthread_mutex_trylock (&q->mutex) == 0)
516 {
517 pthread_mutex_unlock (&q->mutex);
518 goto mutex_ok;
519 }
520 ts.tv_sec = 0;
521 ts.tv_nsec = 10000 * 1000; /* 10 ms */
522 while (nanosleep (&ts, &tsrem) < 0)
523 ts = tsrem;
524 }
525 /* Mutex buggered, "fix" it */
526 memset (&q->mutex, 0, sizeof (q->mutex));
527 clib_warning ("forcibly release main input queue mutex");
528
529 mutex_ok:
530 am->vlib_rp = vlib_rp;
531 while (unix_shared_memory_queue_sub (q,
532 (u8 *) & old_msg,
533 1 /* nowait */ )
534 != -2 /* queue underflow */ )
535 {
536 vl_msg_api_free_nolock ((void *) old_msg);
537 am->shmem_hdr->restart_reclaims++;
538 }
539 pthread_mutex_unlock (&vlib_rp->mutex);
540 root_rp = svm_get_root_rp ();
541 ASSERT (root_rp);
542 /* Clean up the root region client list */
543 pthread_mutex_lock (&root_rp->mutex);
544 svm_client_scan_this_region_nolock (root_rp);
545 pthread_mutex_unlock (&root_rp->mutex);
546 }
547 else
548 {
549 pthread_mutex_unlock (&vlib_rp->mutex);
550 }
551 am->vlib_rp = vlib_rp;
552 vec_add1 (am->mapped_shmem_regions, vlib_rp);
553 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700554 }
Dave Barach371e4e12016-07-08 09:38:52 -0400555 /* Clients simply have to wait... */
556 if (!is_vlib)
557 {
558 pthread_mutex_unlock (&vlib_rp->mutex);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700559
Dave Barach371e4e12016-07-08 09:38:52 -0400560 /* Wait up to 100 seconds... */
561 for (i = 0; i < 10000; i++)
562 {
563 ts.tv_sec = 0;
564 ts.tv_nsec = 10000 * 1000; /* 10 ms */
565 while (nanosleep (&ts, &tsrem) < 0)
566 ts = tsrem;
567 if (vlib_rp->user_ctx)
568 goto ready;
569 }
570 /* Clean up and leave... */
571 svm_region_unmap (vlib_rp);
572 clib_warning ("region init fail");
573 return (-2);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700574
575 ready:
Dave Barach371e4e12016-07-08 09:38:52 -0400576 am->shmem_hdr = (void *) vlib_rp->user_ctx;
577 am->our_pid = getpid ();
578 am->vlib_rp = vlib_rp;
579 vec_add1 (am->mapped_shmem_regions, vlib_rp);
580 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700581 }
582
Dave Barach371e4e12016-07-08 09:38:52 -0400583 /* Nope, it's our problem... */
Dave Barach59b25652017-09-10 15:04:27 -0400584 vl_init_shmem (vlib_rp, 1 /* is vlib */ , 0 /* is_private_region */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700585
Dave Barach371e4e12016-07-08 09:38:52 -0400586 vec_add1 (am->mapped_shmem_regions, vlib_rp);
587 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700588}
589
Dave Barach371e4e12016-07-08 09:38:52 -0400590void
591vl_register_mapped_shmem_region (svm_region_t * rp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700592{
Dave Barach371e4e12016-07-08 09:38:52 -0400593 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700594
Dave Barach371e4e12016-07-08 09:38:52 -0400595 vec_add1 (am->mapped_shmem_regions, rp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700596}
597
Dave Barach371e4e12016-07-08 09:38:52 -0400598void
599vl_unmap_shmem (void)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700600{
Dave Barach371e4e12016-07-08 09:38:52 -0400601 svm_region_t *rp;
602 int i;
603 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700604
Dave Barach371e4e12016-07-08 09:38:52 -0400605 if (!svm_get_root_rp ())
606 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700607
Dave Barach371e4e12016-07-08 09:38:52 -0400608 for (i = 0; i < vec_len (am->mapped_shmem_regions); i++)
609 {
610 rp = am->mapped_shmem_regions[i];
611 svm_region_unmap (rp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700612 }
613
Dave Barach371e4e12016-07-08 09:38:52 -0400614 vec_free (am->mapped_shmem_regions);
615 am->shmem_hdr = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700616
Dave Barach371e4e12016-07-08 09:38:52 -0400617 svm_region_exit ();
618 /* $$$ more careful cleanup, valgrind run... */
619 vec_free (am->msg_handlers);
620 vec_free (am->msg_endian_handlers);
621 vec_free (am->msg_print_handlers);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700622}
623
Dave Barach371e4e12016-07-08 09:38:52 -0400624void
625vl_msg_api_send_shmem (unix_shared_memory_queue_t * q, u8 * elem)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700626{
Dave Barach371e4e12016-07-08 09:38:52 -0400627 api_main_t *am = &api_main;
628 uword *trace = (uword *) elem;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700629
Dave Barach371e4e12016-07-08 09:38:52 -0400630 if (am->tx_trace && am->tx_trace->enabled)
631 vl_msg_api_trace (am, am->tx_trace, (void *) trace[0]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700632
Dave Barach371e4e12016-07-08 09:38:52 -0400633 (void) unix_shared_memory_queue_add (q, elem, 0 /* nowait */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700634}
635
Dave Barach371e4e12016-07-08 09:38:52 -0400636void
637vl_msg_api_send_shmem_nolock (unix_shared_memory_queue_t * q, u8 * elem)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700638{
Dave Barach371e4e12016-07-08 09:38:52 -0400639 api_main_t *am = &api_main;
640 uword *trace = (uword *) elem;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700641
Dave Barach371e4e12016-07-08 09:38:52 -0400642 if (am->tx_trace && am->tx_trace->enabled)
643 vl_msg_api_trace (am, am->tx_trace, (void *) trace[0]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700644
Dave Barach371e4e12016-07-08 09:38:52 -0400645 (void) unix_shared_memory_queue_add_nolock (q, elem);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700646}
647
Dave Barach557d1282016-11-10 14:22:49 -0500648u32
649vl_api_get_msg_index (u8 * name_and_crc)
Dave Barach371e4e12016-07-08 09:38:52 -0400650{
Dave Barach557d1282016-11-10 14:22:49 -0500651 api_main_t *am = &api_main;
652 uword *p;
Dave Barach371e4e12016-07-08 09:38:52 -0400653
Dave Barach557d1282016-11-10 14:22:49 -0500654 if (am->msg_index_by_name_and_crc)
655 {
656 p = hash_get_mem (am->msg_index_by_name_and_crc, name_and_crc);
657 if (p)
658 return p[0];
659 }
660 return ~0;
Dave Barach371e4e12016-07-08 09:38:52 -0400661}
662
Dave Barach371e4e12016-07-08 09:38:52 -0400663static inline vl_api_registration_t *
664vl_api_client_index_to_registration_internal (u32 handle)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700665{
Dave Barach371e4e12016-07-08 09:38:52 -0400666 vl_api_registration_t **regpp;
667 vl_api_registration_t *regp;
668 api_main_t *am = &api_main;
669 u32 index;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700670
Dave Barach371e4e12016-07-08 09:38:52 -0400671 index = vl_msg_api_handle_get_index (handle);
672 if ((am->shmem_hdr->application_restarts & VL_API_EPOCH_MASK)
673 != vl_msg_api_handle_get_epoch (handle))
674 {
675 vl_msg_api_increment_missing_client_counter ();
676 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700677 }
678
Dave Barach371e4e12016-07-08 09:38:52 -0400679 regpp = am->vl_clients + index;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700680
Dave Barach371e4e12016-07-08 09:38:52 -0400681 if (pool_is_free (am->vl_clients, regpp))
682 {
683 vl_msg_api_increment_missing_client_counter ();
684 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700685 }
Dave Barach371e4e12016-07-08 09:38:52 -0400686 regp = *regpp;
687 return (regp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700688}
689
Dave Barach371e4e12016-07-08 09:38:52 -0400690vl_api_registration_t *
691vl_api_client_index_to_registration (u32 index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700692{
Dave Barach59b25652017-09-10 15:04:27 -0400693 if (PREDICT_FALSE (socket_main.current_rp != 0))
694 return socket_main.current_rp;
695
Dave Barach371e4e12016-07-08 09:38:52 -0400696 return (vl_api_client_index_to_registration_internal (index));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700697}
698
Dave Barach371e4e12016-07-08 09:38:52 -0400699unix_shared_memory_queue_t *
700vl_api_client_index_to_input_queue (u32 index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700701{
Dave Barach371e4e12016-07-08 09:38:52 -0400702 vl_api_registration_t *regp;
Dave Barachfc262a02016-12-14 14:49:55 -0500703 api_main_t *am = &api_main;
704
705 /* Special case: vlib trying to send itself a message */
706 if (index == (u32) ~ 0)
707 return (am->shmem_hdr->vl_input_queue);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700708
Dave Barach371e4e12016-07-08 09:38:52 -0400709 regp = vl_api_client_index_to_registration_internal (index);
710 if (!regp)
711 return 0;
712 return (regp->vl_input_queue);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700713}
714
Dave Barach371e4e12016-07-08 09:38:52 -0400715/*
716 * fd.io coding-style-patch-verification: ON
717 *
718 * Local Variables:
719 * eval: (c-set-style "gnu")
720 * End:
721 */