FD.io VPP  v17.04-9-g99c0734
Vector Packet Processing
memory_shared.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * memclnt_shared.c - API message handling, common code for both clients
4  * and the vlib process itself.
5  *
6  *
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>
24 #include <stddef.h>
25 #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>
35 
37 
38 #define vl_typedefs
40 #undef vl_typedefs
41 
42 static inline void *
43 vl_msg_api_alloc_internal (int nbytes, int pool, int may_return_null)
44 {
45  int i;
46  msgbuf_t *rv;
47  ring_alloc_t *ap;
49  void *oldheap;
51  api_main_t *am = &api_main;
52 
53  shmem_hdr = am->shmem_hdr;
54 
55  if (shmem_hdr == 0)
56  {
57  clib_warning ("shared memory header NULL");
58  return 0;
59  }
60 
61  /* account for the msgbuf_t header */
62  nbytes += sizeof (msgbuf_t);
63 
64  if (shmem_hdr->vl_rings == 0)
65  {
66  clib_warning ("vl_rings NULL");
67  ASSERT (0);
68  abort ();
69  }
70 
71  if (shmem_hdr->client_rings == 0)
72  {
73  clib_warning ("client_rings NULL");
74  ASSERT (0);
75  abort ();
76  }
77 
78  ap = pool ? shmem_hdr->vl_rings : shmem_hdr->client_rings;
79  for (i = 0; i < vec_len (ap); i++)
80  {
81  /* Too big? */
82  if (nbytes > ap[i].size)
83  {
84  continue;
85  }
86 
87  q = ap[i].rp;
88  if (pool == 0)
89  {
90  pthread_mutex_lock (&q->mutex);
91  }
92  rv = (msgbuf_t *) (&q->data[0] + q->head * q->elsize);
93  /*
94  * Is this item still in use?
95  */
96  if (rv->q)
97  {
98  u32 now = (u32) time (0);
99 
100  if (PREDICT_TRUE (rv->gc_mark_timestamp == 0))
101  rv->gc_mark_timestamp = now;
102  else
103  {
104  if (now - rv->gc_mark_timestamp > 10)
105  {
106  if (CLIB_DEBUG > 0)
107  clib_warning ("garbage collect pool %d ring %d index %d",
108  pool, i, q->head);
109  shmem_hdr->garbage_collects++;
110  goto collected;
111  }
112  }
113 
114 
115  /* yes, loser; try next larger pool */
116  ap[i].misses++;
117  if (pool == 0)
118  pthread_mutex_unlock (&q->mutex);
119  continue;
120  }
121  collected:
122 
123  /* OK, we have a winner */
124  ap[i].hits++;
125  /*
126  * Remember the source queue, although we
127  * don't need to know the queue to free the item.
128  */
129  rv->q = q;
130  rv->gc_mark_timestamp = 0;
131  q->head++;
132  if (q->head == q->maxsize)
133  q->head = 0;
134 
135  if (pool == 0)
136  pthread_mutex_unlock (&q->mutex);
137  goto out;
138  }
139 
140  /*
141  * Request too big, or head element of all size-compatible rings
142  * still in use. Fall back to shared-memory malloc.
143  */
144  am->ring_misses++;
145 
146  pthread_mutex_lock (&am->vlib_rp->mutex);
147  oldheap = svm_push_data_heap (am->vlib_rp);
148  if (may_return_null)
149  {
150  rv = clib_mem_alloc_or_null (nbytes);
151  if (PREDICT_FALSE (rv == 0))
152  {
153  svm_pop_heap (oldheap);
154  pthread_mutex_unlock (&am->vlib_rp->mutex);
155  return 0;
156  }
157  }
158  else
159  rv = clib_mem_alloc (nbytes);
160 
161  rv->q = 0;
162  svm_pop_heap (oldheap);
163  pthread_mutex_unlock (&am->vlib_rp->mutex);
164 
165 out:
166  rv->data_len = htonl (nbytes - sizeof (msgbuf_t));
167  return (rv->data);
168 }
169 
170 void *
171 vl_msg_api_alloc (int nbytes)
172 {
173  int pool;
174  api_main_t *am = &api_main;
176 
177  /*
178  * Clients use pool-0, vlib proc uses pool 1
179  */
180  pool = (am->our_pid == shmem_hdr->vl_pid);
181  return vl_msg_api_alloc_internal (nbytes, pool, 0 /* may_return_null */ );
182 }
183 
184 void *
186 {
187  int pool;
188  api_main_t *am = &api_main;
190 
191  pool = (am->our_pid == shmem_hdr->vl_pid);
192  return vl_msg_api_alloc_internal (nbytes, pool, 1 /* may_return_null */ );
193 }
194 
195 void *
197 {
198  return vl_msg_api_alloc_internal (nbytes, 0, 0 /* may_return_null */ );
199 }
200 
201 void *
203 {
204  return vl_msg_api_alloc_internal (nbytes, 0, 1 /* may_return_null */ );
205 }
206 
207 void
209 {
210  msgbuf_t *rv;
211  void *oldheap;
212  api_main_t *am = &api_main;
213 
214  rv = (msgbuf_t *) (((u8 *) a) - offsetof (msgbuf_t, data));
215 
216  /*
217  * Here's the beauty of the scheme. Only one proc/thread has
218  * control of a given message buffer. To free a buffer, we just clear the
219  * queue field, and leave. No locks, no hits, no errors...
220  */
221  if (rv->q)
222  {
223  rv->q = 0;
224  rv->gc_mark_timestamp = 0;
225  return;
226  }
227 
228  pthread_mutex_lock (&am->vlib_rp->mutex);
229  oldheap = svm_push_data_heap (am->vlib_rp);
230  clib_mem_free (rv);
231  svm_pop_heap (oldheap);
232  pthread_mutex_unlock (&am->vlib_rp->mutex);
233 }
234 
235 static void
237 {
238  msgbuf_t *rv;
239  void *oldheap;
240  api_main_t *am = &api_main;
241 
242  rv = (msgbuf_t *) (((u8 *) a) - offsetof (msgbuf_t, data));
243  /*
244  * Here's the beauty of the scheme. Only one proc/thread has
245  * control of a given message buffer. To free a buffer, we just clear the
246  * queue field, and leave. No locks, no hits, no errors...
247  */
248  if (rv->q)
249  {
250  rv->q = 0;
251  return;
252  }
253 
254  oldheap = svm_push_data_heap (am->vlib_rp);
255  clib_mem_free (rv);
256  svm_pop_heap (oldheap);
257 }
258 
259 void
261 {
262  api_main_t *am = &api_main;
263 
264  am->root_path = name;
265 }
266 
267 void
269 {
270  api_main_t *am = &api_main;
271 
272  am->api_uid = uid;
273 }
274 
275 void
277 {
278  api_main_t *am = &api_main;
279 
280  am->api_gid = gid;
281 }
282 
283 void
285 {
286  api_main_t *am = &api_main;
287 
288  am->global_baseva = baseva;
289 }
290 
291 void
293 {
294  api_main_t *am = &api_main;
295 
296  am->global_size = size;
297 }
298 
299 void
301 {
302  api_main_t *am = &api_main;
303 
304  am->api_size = size;
305 }
306 
307 void
309 {
310  api_main_t *am = &api_main;
311 
313 }
314 
315 void
317 {
318  api_main_t *am = &api_main;
319 
320  am->api_pvt_heap_size = size;
321 }
322 
323 int
324 vl_map_shmem (char *region_name, int is_vlib)
325 {
326  svm_map_region_args_t _a, *a = &_a;
327  svm_region_t *vlib_rp, *root_rp;
328  void *oldheap;
330  api_main_t *am = &api_main;
331  int i;
332  struct timespec ts, tsrem;
333 
334  if (is_vlib == 0)
336 
337  memset (a, 0, sizeof (*a));
338 
339  a->name = region_name;
340  a->size = am->api_size ? am->api_size : (16 << 20);
341  a->flags = SVM_FLAGS_MHEAP;
342  a->uid = am->api_uid;
343  a->gid = am->api_gid;
345 
346  vlib_rp = svm_region_find_or_create (a);
347 
348  if (vlib_rp == 0)
349  return (-2);
350 
351  pthread_mutex_lock (&vlib_rp->mutex);
352  /* Has someone else set up the shared-memory variable table? */
353  if (vlib_rp->user_ctx)
354  {
355  am->shmem_hdr = (void *) vlib_rp->user_ctx;
356  am->our_pid = getpid ();
357  if (is_vlib)
358  {
360  uword old_msg;
361  /*
362  * application restart. Reset cached pids, API message
363  * rings, list of clients; otherwise, various things
364  * fail. (e.g. queue non-empty notification)
365  */
366 
367  /* ghosts keep the region from disappearing properly */
370  q = am->shmem_hdr->vl_input_queue;
371  am->shmem_hdr->vl_pid = getpid ();
372  q->consumer_pid = am->shmem_hdr->vl_pid;
373  /* Drain the input queue, freeing msgs */
374  for (i = 0; i < 10; i++)
375  {
376  if (pthread_mutex_trylock (&q->mutex) == 0)
377  {
378  pthread_mutex_unlock (&q->mutex);
379  goto mutex_ok;
380  }
381  ts.tv_sec = 0;
382  ts.tv_nsec = 10000 * 1000; /* 10 ms */
383  while (nanosleep (&ts, &tsrem) < 0)
384  ts = tsrem;
385  }
386  /* Mutex buggered, "fix" it */
387  memset (&q->mutex, 0, sizeof (q->mutex));
388  clib_warning ("forcibly release main input queue mutex");
389 
390  mutex_ok:
391  am->vlib_rp = vlib_rp;
393  (u8 *) & old_msg,
394  1 /* nowait */ )
395  != -2 /* queue underflow */ )
396  {
397  vl_msg_api_free_nolock ((void *) old_msg);
399  }
400  pthread_mutex_unlock (&vlib_rp->mutex);
401  root_rp = svm_get_root_rp ();
402  ASSERT (root_rp);
403  /* Clean up the root region client list */
404  pthread_mutex_lock (&root_rp->mutex);
406  pthread_mutex_unlock (&root_rp->mutex);
407  }
408  else
409  {
410  pthread_mutex_unlock (&vlib_rp->mutex);
411  }
412  am->vlib_rp = vlib_rp;
413  vec_add1 (am->mapped_shmem_regions, vlib_rp);
414  return 0;
415  }
416  /* Clients simply have to wait... */
417  if (!is_vlib)
418  {
419  pthread_mutex_unlock (&vlib_rp->mutex);
420 
421  /* Wait up to 100 seconds... */
422  for (i = 0; i < 10000; i++)
423  {
424  ts.tv_sec = 0;
425  ts.tv_nsec = 10000 * 1000; /* 10 ms */
426  while (nanosleep (&ts, &tsrem) < 0)
427  ts = tsrem;
428  if (vlib_rp->user_ctx)
429  goto ready;
430  }
431  /* Clean up and leave... */
432  svm_region_unmap (vlib_rp);
433  clib_warning ("region init fail");
434  return (-2);
435 
436  ready:
437  am->shmem_hdr = (void *) vlib_rp->user_ctx;
438  am->our_pid = getpid ();
439  am->vlib_rp = vlib_rp;
440  vec_add1 (am->mapped_shmem_regions, vlib_rp);
441  return 0;
442  }
443 
444  /* Nope, it's our problem... */
445 
446  oldheap = svm_push_data_heap (vlib_rp);
447 
448  vec_validate (shmem_hdr, 0);
449  shmem_hdr->version = VL_SHM_VERSION;
450 
451  /* vlib main input queue */
452  shmem_hdr->vl_input_queue =
453  unix_shared_memory_queue_init (1024, sizeof (uword), getpid (),
454  am->vlib_signal);
455 
456  /* Set up the msg ring allocator */
457 #define _(sz,n) \
458  do { \
459  ring_alloc_t _rp; \
460  _rp.rp = unix_shared_memory_queue_init ((n), (sz), 0, 0); \
461  _rp.size = (sz); \
462  _rp.nitems = n; \
463  _rp.hits = 0; \
464  _rp.misses = 0; \
465  vec_add1(shmem_hdr->vl_rings, _rp); \
466  } while (0);
467 
469 #undef _
470 
471 #define _(sz,n) \
472  do { \
473  ring_alloc_t _rp; \
474  _rp.rp = unix_shared_memory_queue_init ((n), (sz), 0, 0); \
475  _rp.size = (sz); \
476  _rp.nitems = n; \
477  _rp.hits = 0; \
478  _rp.misses = 0; \
479  vec_add1(shmem_hdr->client_rings, _rp); \
480  } while (0);
481 
483 #undef _
484 
485  am->shmem_hdr = shmem_hdr;
486  am->vlib_rp = vlib_rp;
487  am->our_pid = getpid ();
488  if (is_vlib)
489  am->shmem_hdr->vl_pid = am->our_pid;
490 
491  svm_pop_heap (oldheap);
492 
493  /*
494  * After absolutely everything that a client might see is set up,
495  * declare the shmem region valid
496  */
497  vlib_rp->user_ctx = shmem_hdr;
498 
499  pthread_mutex_unlock (&vlib_rp->mutex);
500  vec_add1 (am->mapped_shmem_regions, vlib_rp);
501  return 0;
502 }
503 
504 void
506 {
507  api_main_t *am = &api_main;
508 
509  vec_add1 (am->mapped_shmem_regions, rp);
510 }
511 
512 void
514 {
515  svm_region_t *rp;
516  int i;
517  api_main_t *am = &api_main;
518 
519  if (!svm_get_root_rp ())
520  return;
521 
522  for (i = 0; i < vec_len (am->mapped_shmem_regions); i++)
523  {
524  rp = am->mapped_shmem_regions[i];
525  svm_region_unmap (rp);
526  }
527 
529  am->shmem_hdr = 0;
530 
531  svm_region_exit ();
532  /* $$$ more careful cleanup, valgrind run... */
533  vec_free (am->msg_handlers);
536 }
537 
538 void
540 {
541  api_main_t *am = &api_main;
542  uword *trace = (uword *) elem;
543 
544  if (am->tx_trace && am->tx_trace->enabled)
545  vl_msg_api_trace (am, am->tx_trace, (void *) trace[0]);
546 
547  (void) unix_shared_memory_queue_add (q, elem, 0 /* nowait */ );
548 }
549 
550 void
552 {
553  api_main_t *am = &api_main;
554  uword *trace = (uword *) elem;
555 
556  if (am->tx_trace && am->tx_trace->enabled)
557  vl_msg_api_trace (am, am->tx_trace, (void *) trace[0]);
558 
559  (void) unix_shared_memory_queue_add_nolock (q, elem);
560 }
561 
562 static void
564 {
565  serialize_main_t _sm, *sm = &_sm;
566  api_main_t *am = &api_main;
567  u8 *tblv;
568  u32 nmsgs;
569  int i;
570  u8 *name_and_crc;
571  u32 msg_index;
572 
573  am->my_client_index = mp->index;
575 
576  /* Clean out any previous hash table (unlikely) */
578  {
579  int i;
580  u8 **keys = 0;
581  hash_pair_t *hp;
582  /* *INDENT-OFF* */
584  ({
585  vec_add1 (keys, (u8 *) hp->key);
586  }));
587  /* *INDENT-ON* */
588  for (i = 0; i < vec_len (keys); i++)
589  vec_free (keys[i]);
590  vec_free (keys);
591  }
592 
594 
595  /* Recreate the vnet-side API message handler table */
596  tblv = (u8 *) mp->message_table;
597  serialize_open_vector (sm, tblv);
598  unserialize_integer (sm, &nmsgs, sizeof (u32));
599 
600  for (i = 0; i < nmsgs; i++)
601  {
603  unserialize_cstring (sm, (char **) &name_and_crc);
604  hash_set_mem (am->msg_index_by_name_and_crc, name_and_crc, msg_index);
605  }
606 }
607 
608 u32
609 vl_api_get_msg_index (u8 * name_and_crc)
610 {
611  api_main_t *am = &api_main;
612  uword *p;
613 
615  {
616  p = hash_get_mem (am->msg_index_by_name_and_crc, name_and_crc);
617  if (p)
618  return p[0];
619  }
620  return ~0;
621 }
622 
623 int
624 vl_client_connect (char *name, int ctx_quota, int input_queue_size)
625 {
626  svm_region_t *svm;
629  unix_shared_memory_queue_t *vl_input_queue;
631  int rv = 0;
632  void *oldheap;
633  api_main_t *am = &api_main;
634 
635  if (am->my_registration)
636  {
637  clib_warning ("client %s already connected...", name);
638  return -1;
639  }
640 
641  if (am->vlib_rp == 0)
642  {
643  clib_warning ("am->vlib_rp NULL");
644  return -1;
645  }
646 
647  svm = am->vlib_rp;
648  shmem_hdr = am->shmem_hdr;
649 
650  if (shmem_hdr == 0 || shmem_hdr->vl_input_queue == 0)
651  {
652  clib_warning ("shmem_hdr / input queue NULL");
653  return -1;
654  }
655 
656  pthread_mutex_lock (&svm->mutex);
657  oldheap = svm_push_data_heap (svm);
658  vl_input_queue =
659  unix_shared_memory_queue_init (input_queue_size, sizeof (uword),
660  getpid (), 0);
661  pthread_mutex_unlock (&svm->mutex);
662  svm_pop_heap (oldheap);
663 
664  am->my_client_index = ~0;
665  am->my_registration = 0;
666  am->vl_input_queue = vl_input_queue;
667 
669  memset (mp, 0, sizeof (*mp));
670  mp->_vl_msg_id = ntohs (VL_API_MEMCLNT_CREATE);
671  mp->ctx_quota = ctx_quota;
672  mp->input_queue = (uword) vl_input_queue;
673  strncpy ((char *) mp->name, name, sizeof (mp->name) - 1);
674 
675  vl_msg_api_send_shmem (shmem_hdr->vl_input_queue, (u8 *) & mp);
676 
677  while (1)
678  {
679  int qstatus;
680  struct timespec ts, tsrem;
681  int i;
682 
683  /* Wait up to 10 seconds */
684  for (i = 0; i < 1000; i++)
685  {
686  qstatus = unix_shared_memory_queue_sub (vl_input_queue, (u8 *) & rp,
687  1 /* nowait */ );
688  if (qstatus == 0)
689  goto read_one_msg;
690  ts.tv_sec = 0;
691  ts.tv_nsec = 10000 * 1000; /* 10 ms */
692  while (nanosleep (&ts, &tsrem) < 0)
693  ts = tsrem;
694  }
695  /* Timeout... */
696  clib_warning ("memclnt_create_reply timeout");
697  return -1;
698 
699  read_one_msg:
700  if (ntohs (rp->_vl_msg_id) != VL_API_MEMCLNT_CREATE_REPLY)
701  {
702  clib_warning ("unexpected reply: id %d", ntohs (rp->_vl_msg_id));
703  continue;
704  }
705  rv = clib_net_to_host_u32 (rp->response);
706 
707  vl_msg_api_handler ((void *) rp);
708  break;
709  }
710  return (rv);
711 }
712 
713 static void
715 {
716  void *oldheap;
717  api_main_t *am = &api_main;
718 
719  pthread_mutex_lock (&am->vlib_rp->mutex);
720  oldheap = svm_push_data_heap (am->vlib_rp);
722  pthread_mutex_unlock (&am->vlib_rp->mutex);
723  svm_pop_heap (oldheap);
724 
725  am->my_client_index = ~0;
726  am->my_registration = 0;
727  am->vl_input_queue = 0;
728 }
729 
730 void
732 {
735  unix_shared_memory_queue_t *vl_input_queue;
737  time_t begin;
738  api_main_t *am = &api_main;
739 
740  ASSERT (am->vlib_rp);
741  shmem_hdr = am->shmem_hdr;
742  ASSERT (shmem_hdr && shmem_hdr->vl_input_queue);
743 
744  vl_input_queue = am->vl_input_queue;
745 
747  memset (mp, 0, sizeof (*mp));
748  mp->_vl_msg_id = ntohs (VL_API_MEMCLNT_DELETE);
749  mp->index = am->my_client_index;
750  mp->handle = (uword) am->my_registration;
751 
752  vl_msg_api_send_shmem (shmem_hdr->vl_input_queue, (u8 *) & mp);
753 
754  /*
755  * Have to be careful here, in case the client is disconnecting
756  * because e.g. the vlib process died, or is unresponsive.
757  */
758 
759  begin = time (0);
760  while (1)
761  {
762  time_t now;
763 
764  now = time (0);
765 
766  if (now >= (begin + 2))
767  {
768  clib_warning ("peer unresponsive, give up");
769  am->my_client_index = ~0;
770  am->my_registration = 0;
771  am->shmem_hdr = 0;
772  break;
773  }
774  if (unix_shared_memory_queue_sub (vl_input_queue, (u8 *) & rp, 1) < 0)
775  continue;
776 
777  /* drain the queue */
778  if (ntohs (rp->_vl_msg_id) != VL_API_MEMCLNT_DELETE_REPLY)
779  {
780  vl_msg_api_handler ((void *) rp);
781  continue;
782  }
783  vl_msg_api_handler ((void *) rp);
784  break;
785  }
786 }
787 
788 static inline vl_api_registration_t *
790 {
791  vl_api_registration_t **regpp;
792  vl_api_registration_t *regp;
793  api_main_t *am = &api_main;
794  u32 index;
795 
796  index = vl_msg_api_handle_get_index (handle);
798  != vl_msg_api_handle_get_epoch (handle))
799  {
801  return 0;
802  }
803 
804  regpp = am->vl_clients + index;
805 
806  if (pool_is_free (am->vl_clients, regpp))
807  {
809  return 0;
810  }
811  regp = *regpp;
812  return (regp);
813 }
814 
817 {
819 }
820 
823 {
824  vl_api_registration_t *regp;
825  api_main_t *am = &api_main;
826 
827  /* Special case: vlib trying to send itself a message */
828  if (index == (u32) ~ 0)
829  return (am->shmem_hdr->vl_input_queue);
830 
832  if (!regp)
833  return 0;
834  return (regp->vl_input_queue);
835 }
836 
837 #define foreach_api_client_msg \
838 _(MEMCLNT_CREATE_REPLY, memclnt_create_reply) \
839 _(MEMCLNT_DELETE_REPLY, memclnt_delete_reply)
840 
841 int
842 vl_client_api_map (char *region_name)
843 {
844  int rv;
845 
846  if ((rv = vl_map_shmem (region_name, 0 /* is_vlib */ )) < 0)
847  {
848  return rv;
849  }
850 
851 #define _(N,n) \
852  vl_msg_api_set_handlers(VL_API_##N, 0 /* name */, \
853  vl_api_##n##_t_handler, \
854  0/* cleanup */, 0/* endian */, 0/* print */, \
855  sizeof(vl_api_##n##_t), 1);
857 #undef _
858  return 0;
859 }
860 
861 void
863 {
864  vl_unmap_shmem ();
865 }
866 
867 /*
868  * fd.io coding-style-patch-verification: ON
869  *
870  * Local Variables:
871  * eval: (c-set-style "gnu")
872  * End:
873  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:436
u64 pvt_heap_size
Definition: svm.h:76
u64 api_pvt_heap_size
Definition: api.h:176
void vl_client_api_unmap(void)
svm_region_t * svm_get_root_rp(void)
Definition: svm.c:54
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
int vl_client_api_map(char *region_name)
static void svm_pop_heap(void *oldheap)
Definition: svm.h:190
static u64 unserialize_likely_small_unsigned_integer(serialize_main_t *m)
Definition: serialize.h:254
a
Definition: bitmap.h:516
void vl_set_global_memory_baseva(u64 baseva)
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: memory_vlib.c:1172
#define foreach_clnt_aring_size
Definition: api.h:60
u64 api_size
Definition: api.h:170
u32 application_restarts
Definition: api.h:84
#define PREDICT_TRUE(x)
Definition: clib.h:98
void vl_set_memory_uid(int uid)
unix_shared_memory_queue_t * vl_input_queue
Definition: api.h:73
int my_client_index
Definition: api.h:185
void unix_shared_memory_queue_free(unix_shared_memory_queue_t *q)
void vl_set_global_pvt_heap_size(u64 size)
void vl_unmap_shmem(void)
int vl_client_connect(char *name, int ctx_quota, int input_queue_size)
u32 gc_mark_timestamp
Definition: api.h:231
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
int api_uid
Definition: api.h:159
#define hash_set_mem(h, key, value)
Definition: hash.h:274
ring_alloc_t * client_rings
Definition: api.h:81
#define pool_is_free(P, E)
Use free bitmap to query whether given element is free.
Definition: pool.h:230
static vl_api_registration_t * vl_api_client_index_to_registration_internal(u32 handle)
void * vl_msg_api_alloc(int nbytes)
int api_gid
Definition: api.h:161
void vl_set_memory_root_path(char *name)
unix_shared_memory_queue_t * vl_input_queue
Definition: api.h:179
void vl_set_global_memory_size(u64 size)
#define SVM_FLAGS_MHEAP
Definition: svm.h:32
u32 vl_api_get_msg_index(u8 *name_and_crc)
api_main_t api_main
Definition: api_shared.c:35
int our_pid
Definition: api.h:141
vl_api_registration_t * my_registration
Definition: api.h:191
static void * svm_push_data_heap(svm_region_t *rp)
Definition: svm.h:182
vl_api_registration_t ** vl_clients
Definition: api.h:145
void * svm_region_find_or_create(svm_map_region_args_t *a)
Definition: svm.c:839
volatile void * user_ctx
Definition: svm.h:52
char * name
Definition: svm.h:73
int vl_map_shmem(char *region_name, int is_vlib)
svm_region_t * vlib_rp
Definition: api.h:142
int unix_shared_memory_queue_add_nolock(unix_shared_memory_queue_t *q, u8 *elem)
unsigned long u64
Definition: types.h:89
struct vl_shmem_hdr_ * shmem_hdr
Definition: api.h:144
#define hash_create_string(elts, value_bytes)
Definition: hash.h:652
vl_shmem_hdr_t * shmem_hdr
int unix_shared_memory_queue_add(unix_shared_memory_queue_t *q, u8 *elem, int nowait)
volatile int vl_pid
Definition: api.h:70
void vl_register_mapped_shmem_region(svm_region_t *rp)
vl_api_registration_t * vl_api_client_index_to_registration(u32 index)
void(** msg_print_handlers)(void *, void *)
Definition: api.h:129
void vl_msg_api_send_shmem_nolock(unix_shared_memory_queue_t *q, u8 *elem)
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
#define PREDICT_FALSE(x)
Definition: clib.h:97
void svm_region_exit()
Definition: svm.c:1078
static u32 vl_msg_api_handle_get_index(u32 index)
Definition: api.h:106
struct msgbuf_ msgbuf_t
void vl_set_api_pvt_heap_size(u64 size)
void unserialize_cstring(serialize_main_t *m, char **s)
Definition: serialize.c:178
u64 global_size
Definition: api.h:167
u8 enabled
Definition: api.h:82
int unix_shared_memory_queue_sub(unix_shared_memory_queue_t *q, u8 *elem, int nowait)
ring_alloc_t * vl_rings
Definition: api.h:78
static void * clib_mem_alloc_or_null(uword size)
Definition: mem.h:125
void serialize_open_vector(serialize_main_t *m, u8 *vector)
Definition: serialize.c:908
u64 global_baseva
Definition: api.h:164
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
unix_shared_memory_queue_t * vl_input_queue
Definition: api.h:53
unix_shared_memory_queue_t * q
Definition: api.h:229
#define clib_warning(format, args...)
Definition: error.h:59
void vl_msg_api_trace(api_main_t *am, vl_api_trace_t *tp, void *msg)
Definition: api_shared.c:66
void vl_set_memory_gid(int gid)
u32 garbage_collects
Definition: api.h:90
static void vl_msg_api_free_nolock(void *a)
static void unserialize_integer(serialize_main_t *m, void *x, u32 n_bytes)
Definition: serialize.h:201
void vl_msg_api_free(void *a)
#define VL_SHM_VERSION
Definition: api.h:94
#define foreach_vl_aring_size
Definition: api.h:55
int version
Definition: api.h:67
vl_api_trace_t * tx_trace
Definition: api.h:138
#define ASSERT(truth)
#define VL_API_EPOCH_MASK
Definition: api.h:96
unsigned int u32
Definition: types.h:88
void svm_region_init_chroot(char *root_path)
Definition: svm.c:799
static void vl_api_memclnt_create_reply_t_handler(vl_api_memclnt_create_reply_t *mp)
Definition: api.h:227
unix_shared_memory_queue_t * unix_shared_memory_queue_init(int nels, int elsize, int consumer_pid, int signal_when_queue_non_empty)
u64 size
Definition: vhost-user.h:77
static void clib_mem_free(void *p)
Definition: mem.h:176
u32 misses
Definition: api.h:47
u64 global_pvt_heap_size
Definition: api.h:173
static void * clib_mem_alloc(uword size)
Definition: mem.h:109
u32 restart_reclaims
Definition: api.h:87
i32 vlib_signal
Definition: api.h:193
u64 uword
Definition: types.h:112
char * root_path
Definition: api.h:199
#define foreach_api_client_msg
void(** msg_endian_handlers)(void *)
Definition: api.h:128
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
#define hash_foreach_pair(p, v, body)
Iterate over hash pairs.
Definition: hash.h:349
void vl_msg_api_handler(void *the_msg)
Definition: api_shared.c:541
void svm_region_unmap(void *rp_arg)
Definition: svm.c:958
void svm_client_scan_this_region_nolock(svm_region_t *rp)
Definition: svm.c:1126
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
static void vl_api_memclnt_delete_reply_t_handler(vl_api_memclnt_delete_reply_t *mp)
static void * vl_msg_api_alloc_internal(int nbytes, int pool, int may_return_null)
Definition: memory_shared.c:43
unix_shared_memory_queue_t * rp
Definition: api.h:43
void * vl_msg_api_alloc_as_if_client_or_null(int nbytes)
#define hash_get_mem(h, key)
Definition: hash.h:268
void vl_msg_api_increment_missing_client_counter(void)
Definition: api_shared.c:44
void(** msg_handlers)(void *)
Definition: api.h:125
void vl_set_api_memory_size(u64 size)
void * vl_msg_api_alloc_as_if_client(int nbytes)
static u32 vl_msg_api_handle_get_epoch(u32 index)
Definition: api.h:100
void * vl_msg_api_alloc_or_null(int nbytes)
svm_region_t ** mapped_shmem_regions
Definition: api.h:143
uword * msg_index_by_name_and_crc
Definition: api.h:196
u32 hits
Definition: api.h:46
void vl_client_disconnect(void)
pthread_mutex_t mutex
Definition: svm.h:42
struct _unix_shared_memory_queue unix_shared_memory_queue_t
static svm_region_t * root_rp
Definition: svm.c:46