svm: allow mq attachments at random offsets
[vpp.git] / src / svm / fifo_segment.c
index 008cca4..0c3a79a 100644 (file)
@@ -52,6 +52,13 @@ fsh_slice_get (fifo_segment_header_t * fsh, u32 slice_index)
   return &fsh->slices[slice_index];
 }
 
+static inline fifo_slice_private_t *
+fs_slice_private_get (fifo_segment_t *fs, u32 slice_index)
+{
+  ASSERT (slice_index < fs->n_slices);
+  return &fs->slices[slice_index];
+}
+
 static char *fifo_segment_mem_status_strings[] = {
 #define _(sym,str) str,
   foreach_segment_mem_status
@@ -194,25 +201,25 @@ fss_chunk_free_list_pop (fifo_segment_header_t *fsh, fifo_segment_slice_t *fss,
 }
 
 static inline void
-fss_fifo_add_active_list (fifo_segment_slice_t * fss, svm_fifo_t * f)
+pfss_fifo_add_active_list (fifo_slice_private_t *pfss, svm_fifo_t *f)
 {
-  if (fss->fifos)
+  if (pfss->active_fifos)
     {
-      fss->fifos->prev = f;
-      f->next = fss->fifos;
+      pfss->active_fifos->prev = f;
+      f->next = pfss->active_fifos;
     }
-  fss->fifos = f;
+  pfss->active_fifos = f;
 }
 
 static inline void
-fss_fifo_del_active_list (fifo_segment_slice_t * fss, svm_fifo_t * f)
+pfss_fifo_del_active_list (fifo_slice_private_t *pfss, svm_fifo_t *f)
 {
   if (f->flags & SVM_FIFO_F_LL_TRACKED)
     {
       if (f->prev)
        f->prev->next = f->next;
       else
-       fss->fifos = f->next;
+       pfss->active_fifos = f->next;
       if (f->next)
        f->next->prev = f->prev;
     }
@@ -757,9 +764,15 @@ void
 fifo_segment_cleanup (fifo_segment_t *fs)
 {
   int slice_index;
+  svm_msg_q_t *mq = 0;
 
   for (slice_index = 0; slice_index < fs->n_slices; slice_index++)
     clib_mem_bulk_destroy (fs->slices[slice_index].fifos);
+
+  vec_foreach (fs->mqs, mq)
+    vec_free (mq->rings);
+
+  vec_free (fs->mqs);
 }
 
 /**
@@ -770,6 +783,7 @@ fifo_segment_alloc_fifo_w_slice (fifo_segment_t * fs, u32 slice_index,
                                 u32 data_bytes, fifo_segment_ftype_t ftype)
 {
   fifo_segment_header_t *fsh = fs->h;
+  fifo_slice_private_t *pfss;
   fifo_segment_slice_t *fss;
   svm_fifo_shared_t *sf;
   svm_fifo_t *f = 0;
@@ -790,6 +804,7 @@ fifo_segment_alloc_fifo_w_slice (fifo_segment_t * fs, u32 slice_index,
   svm_fifo_init (f, data_bytes);
 
   fss = fsh_slice_get (fsh, slice_index);
+  pfss = fs_slice_private_get (fs, slice_index);
 
   /* If rx fifo type add to active fifos list. When cleaning up segment,
    * we need a list of active sessions that should be disconnected. Since
@@ -797,7 +812,7 @@ fifo_segment_alloc_fifo_w_slice (fifo_segment_t * fs, u32 slice_index,
    * only one. */
   if (ftype == FIFO_SEGMENT_RX_FIFO)
     {
-      fss_fifo_add_active_list (fss, f);
+      pfss_fifo_add_active_list (pfss, f);
       f->flags |= SVM_FIFO_F_LL_TRACKED;
     }
 
@@ -828,6 +843,7 @@ void
 fifo_segment_free_fifo (fifo_segment_t * fs, svm_fifo_t * f)
 {
   fifo_segment_header_t *fsh = fs->h;
+  fifo_slice_private_t *pfss;
   fifo_segment_slice_t *fss;
   svm_fifo_shared_t *sf;
 
@@ -842,6 +858,7 @@ fifo_segment_free_fifo (fifo_segment_t * fs, svm_fifo_t * f)
 
   sf = f->shr;
   fss = fsh_slice_get (fsh, sf->slice_index);
+  pfss = fs_slice_private_get (fs, sf->slice_index);
 
   /* Free fifo chunks */
   fsh_slice_collect_chunks (fsh, fss, fs_chunk_ptr (fsh, f->shr->start_chunk));
@@ -862,7 +879,7 @@ fifo_segment_free_fifo (fifo_segment_t * fs, svm_fifo_t * f)
   /* Remove from active list. Only rx fifos are tracked */
   if (f->flags & SVM_FIFO_F_LL_TRACKED)
     {
-      fss_fifo_del_active_list (fss, f);
+      pfss_fifo_del_active_list (pfss, f);
       f->flags &= ~SVM_FIFO_F_LL_TRACKED;
     }
 
@@ -886,6 +903,7 @@ fifo_segment_free_fifo (fifo_segment_t * fs, svm_fifo_t * f)
 void
 fifo_segment_detach_fifo (fifo_segment_t * fs, svm_fifo_t * f)
 {
+  fifo_slice_private_t *pfss;
   fifo_segment_slice_t *fss;
   svm_fifo_chunk_t *c;
   u32 fl_index;
@@ -893,9 +911,10 @@ fifo_segment_detach_fifo (fifo_segment_t * fs, svm_fifo_t * f)
   ASSERT (f->refcnt == 1);
 
   fss = fsh_slice_get (fs->h, f->shr->slice_index);
+  pfss = fs_slice_private_get (fs, f->shr->slice_index);
   fss->virtual_mem -= svm_fifo_size (f);
   if (f->flags & SVM_FIFO_F_LL_TRACKED)
-    fss_fifo_del_active_list (fss, f);
+    pfss_fifo_del_active_list (pfss, f);
 
   c = fs_chunk_ptr (fs->h, f->shr->start_chunk);
   while (c)
@@ -910,15 +929,17 @@ void
 fifo_segment_attach_fifo (fifo_segment_t * fs, svm_fifo_t * f,
                          u32 slice_index)
 {
+  fifo_slice_private_t *pfss;
   fifo_segment_slice_t *fss;
   svm_fifo_chunk_t *c;
   u32 fl_index;
 
   f->shr->slice_index = slice_index;
   fss = fsh_slice_get (fs->h, f->shr->slice_index);
+  pfss = fs_slice_private_get (fs, f->shr->slice_index);
   fss->virtual_mem += svm_fifo_size (f);
   if (f->flags & SVM_FIFO_F_LL_TRACKED)
-    fss_fifo_add_active_list (fss, f);
+    pfss_fifo_add_active_list (pfss, f);
 
   c = fs_chunk_ptr (fs->h, f->shr->start_chunk);
   while (c)
@@ -929,6 +950,69 @@ fifo_segment_attach_fifo (fifo_segment_t * fs, svm_fifo_t * f,
     }
 }
 
+svm_msg_q_t *
+fifo_segment_msg_q_alloc (fifo_segment_t *fs, u32 mq_index,
+                         svm_msg_q_cfg_t *cfg)
+{
+  fifo_segment_header_t *fsh = fs->h;
+  svm_msg_q_shared_t *smq;
+  svm_msg_q_t *mq;
+  void *base;
+  u32 size;
+
+  if (!fs->mqs)
+    {
+      u32 n_mqs = clib_max (fs->h->n_mqs, 1);
+      vec_validate (fs->mqs, n_mqs - 1);
+    }
+
+  size = svm_msg_q_size_to_alloc (cfg);
+  base = fsh_alloc_aligned (fsh, size, 8);
+  fsh->n_reserved_bytes += size;
+
+  smq = svm_msg_q_init (base, cfg);
+  mq = vec_elt_at_index (fs->mqs, mq_index);
+  svm_msg_q_attach (mq, smq);
+
+  return mq;
+}
+
+svm_msg_q_t *
+fifo_segment_msg_q_attach (fifo_segment_t *fs, uword offset, u32 mq_index)
+{
+  svm_msg_q_t *mq;
+
+  if (!fs->mqs)
+    {
+      u32 n_mqs = clib_max (fs->h->n_mqs, 1);
+      vec_validate (fs->mqs, n_mqs - 1);
+    }
+
+  mq = vec_elt_at_index (fs->mqs, mq_index);
+
+  if (!mq->q)
+    {
+      svm_msg_q_shared_t *smq;
+      smq = (svm_msg_q_shared_t *) ((u8 *) fs->h + offset);
+      svm_msg_q_attach (mq, smq);
+    }
+
+  ASSERT (fifo_segment_msg_q_offset (fs, mq_index) == offset);
+
+  return mq;
+}
+
+uword
+fifo_segment_msg_q_offset (fifo_segment_t *fs, u32 mq_index)
+{
+  svm_msg_q_t *mq = vec_elt_at_index (fs->mqs, mq_index);
+
+  if (mq->q == 0)
+    return ~0ULL;
+
+  return (uword) ((u8 *) mq->q - (u8 *) fs->h) - sizeof (svm_msg_q_shared_t);
+}
+
 int
 fifo_segment_prealloc_fifo_hdrs (fifo_segment_t * fs, u32 slice_index,
                                 u32 batch_size)
@@ -1201,11 +1285,10 @@ fifo_segment_has_fifos (fifo_segment_t * fs)
 svm_fifo_t *
 fifo_segment_get_slice_fifo_list (fifo_segment_t * fs, u32 slice_index)
 {
-  fifo_segment_header_t *fsh = fs->h;
-  fifo_segment_slice_t *fss;
+  fifo_slice_private_t *pfss;
 
-  fss = fsh_slice_get (fsh, slice_index);
-  return fss->fifos;
+  pfss = fs_slice_private_get (fs, slice_index);
+  return pfss->active_fifos;
 }
 
 u8