Re: svn commit: r311346 - in head/sys: kern sys vm

2017-01-05 Thread Mark Johnston
On Thu, Jan 05, 2017 at 09:16:02AM +, Steven Hartland wrote:
> Given the use of the number of CPU's for sizing would this play nice 
> with hot plug CPU's?
> 
>  Regards
>  Steve

Not without some work. I don't think it would be a major obstacle to
adding hot-plug CPU support on at least 64-bit systems though.

> 
> On 05/01/2017 01:44, Mark Johnston wrote:
> > Author: markj
> > Date: Thu Jan  5 01:44:12 2017
> > New Revision: 311346
> > URL: https://svnweb.freebsd.org/changeset/base/311346
> >
> > Log:
> >Add a small allocator for exec_map entries.
> >
> >Upon each execve, we allocate a KVA range for use in copying data to the
> >new image. Pages must be faulted into the range, and when the range is
> >freed, the backing pages are freed and their mappings are destroyed. This
> >is a lot of needless overhead, and the exec_map management becomes a
> >bottleneck when many CPUs are executing execve concurrently. Moreover, 
> > the
> >number of available ranges is fixed at 16, which is insufficient on large
> >systems and potentially excessive on 32-bit systems.
> >
> >The new allocator reduces overhead by making exec_map allocations
> >persistent. When a range is freed, pages backing the range are marked 
> > clean
> >and made easy to reclaim. With this change, the exec_map is sized based 
> > on
> >the number of CPUs.
___
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"


Re: svn commit: r311346 - in head/sys: kern sys vm

2017-01-05 Thread Steven Hartland
Given the use of the number of CPU's for sizing would this play nice 
with hot plug CPU's?


Regards
Steve

On 05/01/2017 01:44, Mark Johnston wrote:

Author: markj
Date: Thu Jan  5 01:44:12 2017
New Revision: 311346
URL: https://svnweb.freebsd.org/changeset/base/311346

Log:
   Add a small allocator for exec_map entries.
   
   Upon each execve, we allocate a KVA range for use in copying data to the

   new image. Pages must be faulted into the range, and when the range is
   freed, the backing pages are freed and their mappings are destroyed. This
   is a lot of needless overhead, and the exec_map management becomes a
   bottleneck when many CPUs are executing execve concurrently. Moreover, the
   number of available ranges is fixed at 16, which is insufficient on large
   systems and potentially excessive on 32-bit systems.
   
   The new allocator reduces overhead by making exec_map allocations

   persistent. When a range is freed, pages backing the range are marked clean
   and made easy to reclaim. With this change, the exec_map is sized based on
   the number of CPUs.
   
   Reviewed by:	kib

   MFC after:   1 month
   Differential Revision:   https://reviews.freebsd.org/D8921

Modified:
   head/sys/kern/kern_exec.c
   head/sys/sys/imgact.h
   head/sys/vm/vm_init.c
   head/sys/vm/vm_kern.c
   head/sys/vm/vm_kern.h

Modified: head/sys/kern/kern_exec.c
==
--- head/sys/kern/kern_exec.c   Thu Jan  5 01:28:08 2017(r311345)
+++ head/sys/kern/kern_exec.c   Thu Jan  5 01:44:12 2017(r311346)
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -59,6 +60,7 @@ __FBSDID("$FreeBSD$");
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -1315,17 +1317,80 @@ err_exit:
return (error);
  }
  
+struct exec_args_kva {

+   vm_offset_t addr;
+   SLIST_ENTRY(exec_args_kva) next;
+};
+
+static DPCPU_DEFINE(struct exec_args_kva *, exec_args_kva);
+
+static SLIST_HEAD(, exec_args_kva) exec_args_kva_freelist;
+static struct mtx exec_args_kva_mtx;
+
+static void
+exec_prealloc_args_kva(void *arg __unused)
+{
+   struct exec_args_kva *argkva;
+   u_int i;
+
+   SLIST_INIT(&exec_args_kva_freelist);
+   mtx_init(&exec_args_kva_mtx, "exec args kva", NULL, MTX_DEF);
+   for (i = 0; i < exec_map_entries; i++) {
+   argkva = malloc(sizeof(*argkva), M_PARGS, M_WAITOK);
+   argkva->addr = kmap_alloc_wait(exec_map, exec_map_entry_size);
+   SLIST_INSERT_HEAD(&exec_args_kva_freelist, argkva, next);
+   }
+}
+SYSINIT(exec_args_kva, SI_SUB_EXEC, SI_ORDER_ANY, exec_prealloc_args_kva, 
NULL);
+
+static vm_offset_t
+exec_alloc_args_kva(void **cookie)
+{
+   struct exec_args_kva *argkva;
+
+   argkva = (void *)atomic_readandclear_ptr(
+   (uintptr_t *)DPCPU_PTR(exec_args_kva));
+   if (argkva == NULL) {
+   mtx_lock(&exec_args_kva_mtx);
+   while ((argkva = SLIST_FIRST(&exec_args_kva_freelist)) == NULL)
+   (void)mtx_sleep(&exec_args_kva_freelist,
+   &exec_args_kva_mtx, 0, "execkva", 0);
+   SLIST_REMOVE_HEAD(&exec_args_kva_freelist, next);
+   mtx_unlock(&exec_args_kva_mtx);
+   }
+   *(struct exec_args_kva **)cookie = argkva;
+   return (argkva->addr);
+}
+
+static void
+exec_free_args_kva(void *cookie)
+{
+   struct exec_args_kva *argkva;
+   vm_offset_t base;
+
+   argkva = cookie;
+   base = argkva->addr;
+
+   vm_map_madvise(exec_map, base, base + exec_map_entry_size, MADV_FREE);
+   if (!atomic_cmpset_ptr((uintptr_t *)DPCPU_PTR(exec_args_kva),
+   (uintptr_t)NULL, (uintptr_t)argkva)) {
+   mtx_lock(&exec_args_kva_mtx);
+   SLIST_INSERT_HEAD(&exec_args_kva_freelist, argkva, next);
+   wakeup_one(&exec_args_kva_freelist);
+   mtx_unlock(&exec_args_kva_mtx);
+   }
+}
+
  /*
   * Allocate temporary demand-paged, zero-filled memory for the file name,
- * argument, and environment strings.  Returns zero if the allocation succeeds
- * and ENOMEM otherwise.
+ * argument, and environment strings.
   */
  int
  exec_alloc_args(struct image_args *args)
  {
  
-	args->buf = (char *)kmap_alloc_wait(exec_map, PATH_MAX + ARG_MAX);

-   return (args->buf != NULL ? 0 : ENOMEM);
+   args->buf = (char *)exec_alloc_args_kva(&args->bufkva);
+   return (0);
  }
  
  void

@@ -1333,8 +1398,7 @@ exec_free_args(struct image_args *args)
  {
  
  	if (args->buf != NULL) {

-   kmap_free_wakeup(exec_map, (vm_offset_t)args->buf,
-   PATH_MAX + ARG_MAX);
+   exec_free_args_kva(args->bufkva);
args->buf = NULL;
}
if (args->fname_buf != NULL) {

Modified: head/sys/sys/imgact.h
===