Merge branch 'master' of ssh://crater.dragonflybsd.org/repository/git/dragonfly
[dragonfly.git] / sys / kern / kern_exec.c
index ab883c4..7dba1a7 100644 (file)
@@ -72,6 +72,7 @@
 #include <sys/user.h>
 #include <sys/reg.h>
 
+#include <sys/refcount.h>
 #include <sys/thread2.h>
 #include <sys/mplock2.h>
 
@@ -183,6 +184,7 @@ kern_execve(struct nlookupdata *nd, struct image_args *args)
        struct lwp *lp = td->td_lwp;
        struct proc *p = td->td_proc;
        register_t *stack_base;
+       struct pargs *pa;
        int error, len, i;
        struct image_params image_params, *imgp;
        struct vattr attr;
@@ -194,6 +196,7 @@ kern_execve(struct nlookupdata *nd, struct image_args *args)
        }
 
        KKASSERT(p);
+       lwkt_gettoken(&p->p_token);
        imgp = &image_params;
 
        /*
@@ -485,19 +488,27 @@ interpret:
        /* Set the access time on the vnode */
        vn_mark_atime(imgp->vp, td);
 
-       /* Free any previous argument cache */
-       if (p->p_args && --p->p_args->ar_ref == 0)
-               FREE(p->p_args, M_PARGS);
+       /*
+        * Free any previous argument cache
+        */
+       pa = p->p_args;
        p->p_args = NULL;
+       if (pa && refcount_release(&pa->ar_ref)) {
+               kfree(pa, M_PARGS);
+               pa = NULL;
+       }
 
-       /* Cache arguments if they fit inside our allowance */
+       /*
+        * Cache arguments if they fit inside our allowance
+        */
        i = imgp->args->begin_envv - imgp->args->begin_argv;
-       if (ps_arg_cache_limit >= i + sizeof(struct pargs)) {
-               MALLOC(p->p_args, struct pargs *, sizeof(struct pargs) + i, 
-                   M_PARGS, M_WAITOK);
-               p->p_args->ar_ref = 1;
-               p->p_args->ar_length = i;
-               bcopy(imgp->args->begin_argv, p->p_args->ar_args, i);
+       if (sizeof(struct pargs) + i <= ps_arg_cache_limit) {
+               pa = kmalloc(sizeof(struct pargs) + i, M_PARGS, M_WAITOK);
+               refcount_init(&pa->ar_ref, 1);
+               pa->ar_length = i;
+               bcopy(imgp->args->begin_argv, pa->ar_args, i);
+               KKASSERT(p->p_args == NULL);
+               p->p_args = pa;
        }
 
 exec_fail_dealloc:
@@ -515,6 +526,7 @@ exec_fail_dealloc:
 
        if (error == 0) {
                ++mycpu->gd_cnt.v_exec;
+               lwkt_reltoken(&p->p_token);
                return (0);
        }
 
@@ -527,6 +539,7 @@ exec_fail:
         */
        if (imgp->vmspace_destroyed & 2)
                p->p_flag &= ~P_INEXEC;
+       lwkt_reltoken(&p->p_token);
        if (imgp->vmspace_destroyed) {
                /*
                 * Sorry, no more process anymore. exit gracefully.