Add config option to use dlmalloc instead of mheap
[vpp.git] / src / svm / svm.c
index c54f973..aa84a2f 100644 (file)
@@ -58,6 +58,43 @@ svm_get_root_rp (void)
 
 #define MUTEX_DEBUG
 
+u64
+svm_get_global_region_base_va ()
+{
+#if __aarch64__
+  /* On AArch64 VA space can have different size, from 36 to 48 bits.
+     Here we are trying to detect VA bits by parsing /proc/self/maps
+     address ranges */
+  int fd;
+  unformat_input_t input;
+  u64 start, end = 0;
+  u8 bits = 0;
+
+  if ((fd = open ("/proc/self/maps", 0)) < 0)
+    clib_unix_error ("open '/proc/self/maps'");
+
+  unformat_init_clib_file (&input, fd);
+  while (unformat_check_input (&input) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (&input, "%llx-%llx", &start, &end))
+       end--;
+      unformat_skip_line (&input);
+    }
+  unformat_free (&input);
+  close (fd);
+
+  bits = count_leading_zeros (end);
+  bits = 64 - bits;
+  if (bits >= 36 && bits <= 48)
+    return ((1ul << bits) / 4) - (2 * SVM_GLOBAL_REGION_SIZE);
+  else
+    clib_unix_error ("unexpected va bits '%u'", bits);
+#endif
+
+  /* default value */
+  return 0x30000000;
+}
+
 static void
 region_lock (svm_region_t * rp, int tag)
 {
@@ -199,6 +236,7 @@ format_svm_region (u8 * s, va_list * args)
                }
            }
        }
+#if USE_DLMALLOC == 0
       s = format (s, "  rgn heap stats: %U", format_mheap,
                  rp->region_heap, 0);
       if ((rp->flags & SVM_FLAGS_MHEAP) && rp->data_heap)
@@ -207,6 +245,7 @@ format_svm_region (u8 * s, va_list * args)
                      rp->data_heap, 1);
        }
       s = format (s, "\n");
+#endif
     }
 
   return (s);
@@ -302,9 +341,19 @@ svm_data_region_create (svm_map_region_args_t * a, svm_region_t * rp)
 
   if (a->flags & SVM_FLAGS_MHEAP)
     {
+#if USE_DLMALLOC == 0
+      mheap_t *heap_header;
       rp->data_heap =
        mheap_alloc_with_flags ((void *) (rp->data_base), map_size,
                                MHEAP_FLAG_DISABLE_VM);
+      heap_header = mheap_header (rp->data_heap);
+      heap_header->flags |= MHEAP_FLAG_THREAD_SAFE;
+#else
+      rp->data_heap = create_mspace_with_base (rp->data_base,
+                                              map_size, 1 /* locked */ );
+      mspace_disable_expand (rp->data_heap);
+#endif
+
       rp->flags |= SVM_FLAGS_MHEAP;
     }
   return 0;
@@ -477,12 +526,22 @@ svm_region_init_mapped_region (svm_map_region_args_t * a, svm_region_t * rp)
   rp->virtual_base = a->baseva;
   rp->virtual_size = a->size;
 
+#if USE_DLMALLOC == 0
   rp->region_heap =
     mheap_alloc_with_flags (uword_to_pointer
                            (a->baseva + MMAP_PAGESIZE, void *),
                            (a->pvt_heap_size !=
                             0) ? a->pvt_heap_size : SVM_PVT_MHEAP_SIZE,
                            MHEAP_FLAG_DISABLE_VM);
+#else
+  rp->region_heap = create_mspace_with_base
+    (uword_to_pointer (a->baseva + MMAP_PAGESIZE, void *),
+     (a->pvt_heap_size !=
+      0) ? a->pvt_heap_size : SVM_PVT_MHEAP_SIZE, 1 /* locked */ );
+
+  mspace_disable_expand (rp->region_heap);
+#endif
+
   oldheap = svm_push_pvt_heap (rp);
 
   rp->region_name = (char *) format (0, "%s%c", a->name, 0);
@@ -615,6 +674,10 @@ svm_map_region (svm_map_region_args_t * a)
          return (0);
        }
 
+      /* Reset ownership in case the client started first */
+      if (fchown (svm_fd, a->uid, a->gid) < 0)
+       clib_unix_warning ("segment chown [ok if client starts first]");
+
       time_left = 20;
       while (1)
        {
@@ -684,6 +747,8 @@ svm_map_region (svm_map_region_args_t * a)
          return (0);
        }
 
+      close (svm_fd);
+
       if ((uword) rp != rp->virtual_base)
        {
          clib_warning ("mmap botch");
@@ -804,7 +869,7 @@ svm_region_init (void)
   memset (a, 0, sizeof (*a));
   a->root_path = 0;
   a->name = SVM_GLOBAL_REGION_NAME;
-  a->baseva = SVM_GLOBAL_REGION_BASEVA;
+  a->baseva = svm_get_global_region_base_va ();
   a->size = SVM_GLOBAL_REGION_SIZE;
   a->flags = SVM_FLAGS_NODATA;
   a->uid = 0;
@@ -821,7 +886,7 @@ svm_region_init_chroot (const char *root_path)
   memset (a, 0, sizeof (*a));
   a->root_path = root_path;
   a->name = SVM_GLOBAL_REGION_NAME;
-  a->baseva = SVM_GLOBAL_REGION_BASEVA;
+  a->baseva = svm_get_global_region_base_va ();
   a->size = SVM_GLOBAL_REGION_SIZE;
   a->flags = SVM_FLAGS_NODATA;
   a->uid = 0;
@@ -838,7 +903,7 @@ svm_region_init_chroot_uid_gid (const char *root_path, int uid, int gid)
   memset (a, 0, sizeof (*a));
   a->root_path = root_path;
   a->name = SVM_GLOBAL_REGION_NAME;
-  a->baseva = SVM_GLOBAL_REGION_BASEVA;
+  a->baseva = svm_get_global_region_base_va ();
   a->size = SVM_GLOBAL_REGION_SIZE;
   a->flags = SVM_FLAGS_NODATA;
   a->uid = uid;
@@ -997,7 +1062,7 @@ svm_region_unlink (svm_region_t * rp)
  * a new region client showing up at the wrong moment.
  */
 void
-svm_region_unmap (void *rp_arg)
+svm_region_unmap_internal (void *rp_arg, u8 is_client)
 {
   int i, mypid = getpid ();
   int nclients_left;
@@ -1097,7 +1162,12 @@ found:
       vec_free (name);
 
       region_unlock (rp);
-      svm_region_unlink (rp);
+
+      /* If a client asks for the cleanup, don't unlink the backing
+       * file since we can't tell if it has been recreated. */
+      if (!is_client)
+       svm_region_unlink (rp);
+
       munmap ((void *) virtual_base, virtual_size);
       region_unlock (root_rp);
       svm_pop_heap (oldheap);
@@ -1110,11 +1180,23 @@ found:
   munmap ((void *) virtual_base, virtual_size);
 }
 
+void
+svm_region_unmap (void *rp_arg)
+{
+  svm_region_unmap_internal (rp_arg, 0 /* is_client */ );
+}
+
+void
+svm_region_unmap_client (void *rp_arg)
+{
+  svm_region_unmap_internal (rp_arg, 1 /* is_client */ );
+}
+
 /*
  * svm_region_exit
  */
-void
-svm_region_exit ()
+static void
+svm_region_exit_internal (u8 is_client)
 {
   void *oldheap;
   int i, mypid = getpid ();
@@ -1154,7 +1236,7 @@ svm_region_exit ()
 
 found:
 
-  if (vec_len (root_rp->client_pids) == 0)
+  if (!is_client && vec_len (root_rp->client_pids) == 0)
     svm_region_unlink (root_rp);
 
   region_unlock (root_rp);
@@ -1164,6 +1246,18 @@ found:
   munmap ((void *) virtual_base, virtual_size);
 }
 
+void
+svm_region_exit (void)
+{
+  svm_region_exit_internal (0 /* is_client */ );
+}
+
+void
+svm_region_exit_client (void)
+{
+  svm_region_exit_internal (1 /* is_client */ );
+}
+
 void
 svm_client_scan_this_region_nolock (svm_region_t * rp)
 {