Author: mjg
Date: Wed Jun 10 10:43:59 2015
New Revision: 284214
URL: https://svnweb.freebsd.org/changeset/base/284214

Log:
  Generalised support for copy-on-write structures shared by threads.
  
  Thread credentials are maintained as follows: each thread has a pointer to
  creds and a reference on them. The pointer is compared with proc's creds on
  userspace<->kernel boundary and updated if needed.
  
  This patch introduces a counter which can be compared instead, so that more
  structures can use this scheme without adding more comparisons on the 
boundary.

Modified:
  head/sys/amd64/amd64/trap.c
  head/sys/arm/arm/trap-v6.c
  head/sys/arm/arm/trap.c
  head/sys/i386/i386/trap.c
  head/sys/kern/init_main.c
  head/sys/kern/kern_fork.c
  head/sys/kern/kern_kthread.c
  head/sys/kern/kern_prot.c
  head/sys/kern/kern_syscalls.c
  head/sys/kern/kern_thr.c
  head/sys/kern/kern_thread.c
  head/sys/kern/subr_syscall.c
  head/sys/kern/subr_trap.c
  head/sys/powerpc/powerpc/trap.c
  head/sys/sparc64/sparc64/trap.c
  head/sys/sys/proc.h

Modified: head/sys/amd64/amd64/trap.c
==============================================================================
--- head/sys/amd64/amd64/trap.c Wed Jun 10 09:59:26 2015        (r284213)
+++ head/sys/amd64/amd64/trap.c Wed Jun 10 10:43:59 2015        (r284214)
@@ -257,8 +257,8 @@ trap(struct trapframe *frame)
                td->td_pticks = 0;
                td->td_frame = frame;
                addr = frame->tf_rip;
-               if (td->td_ucred != p->p_ucred) 
-                       cred_update_thread(td);
+               if (td->td_cowgen != p->p_cowgen)
+                       thread_cow_update(td);
 
                switch (type) {
                case T_PRIVINFLT:       /* privileged instruction fault */

Modified: head/sys/arm/arm/trap-v6.c
==============================================================================
--- head/sys/arm/arm/trap-v6.c  Wed Jun 10 09:59:26 2015        (r284213)
+++ head/sys/arm/arm/trap-v6.c  Wed Jun 10 10:43:59 2015        (r284214)
@@ -395,8 +395,8 @@ abort_handler(struct trapframe *tf, int 
        p = td->td_proc;
        if (usermode) {
                td->td_pticks = 0;
-               if (td->td_ucred != p->p_ucred)
-                       cred_update_thread(td);
+               if (td->td_cowgen != p->p_cowgen)
+                       thread_cow_update(td);
        }
 
        /* Invoke the appropriate handler, if necessary. */

Modified: head/sys/arm/arm/trap.c
==============================================================================
--- head/sys/arm/arm/trap.c     Wed Jun 10 09:59:26 2015        (r284213)
+++ head/sys/arm/arm/trap.c     Wed Jun 10 10:43:59 2015        (r284214)
@@ -214,8 +214,8 @@ abort_handler(struct trapframe *tf, int 
        if (user) {
                td->td_pticks = 0;
                td->td_frame = tf;
-               if (td->td_ucred != td->td_proc->p_ucred)
-                       cred_update_thread(td);
+               if (td->td_cowgen != td->td_proc->p_cowgen)
+                       thread_cow_update(td);
 
        }
        /* Grab the current pcb */
@@ -644,8 +644,8 @@ prefetch_abort_handler(struct trapframe 
 
        if (TRAP_USERMODE(tf)) {
                td->td_frame = tf;
-               if (td->td_ucred != td->td_proc->p_ucred)
-                       cred_update_thread(td);
+               if (td->td_cowgen != td->td_proc->p_cowgen)
+                       thread_cow_update(td);
        }
        fault_pc = tf->tf_pc;
        if (td->td_md.md_spinlock_count == 0) {

Modified: head/sys/i386/i386/trap.c
==============================================================================
--- head/sys/i386/i386/trap.c   Wed Jun 10 09:59:26 2015        (r284213)
+++ head/sys/i386/i386/trap.c   Wed Jun 10 10:43:59 2015        (r284214)
@@ -306,8 +306,8 @@ trap(struct trapframe *frame)
                td->td_pticks = 0;
                td->td_frame = frame;
                addr = frame->tf_eip;
-               if (td->td_ucred != p->p_ucred) 
-                       cred_update_thread(td);
+               if (td->td_cowgen != p->p_cowgen)
+                       thread_cow_update(td);
 
                switch (type) {
                case T_PRIVINFLT:       /* privileged instruction fault */

Modified: head/sys/kern/init_main.c
==============================================================================
--- head/sys/kern/init_main.c   Wed Jun 10 09:59:26 2015        (r284213)
+++ head/sys/kern/init_main.c   Wed Jun 10 10:43:59 2015        (r284214)
@@ -523,8 +523,6 @@ proc0_init(void *dummy __unused)
 #ifdef MAC
        mac_cred_create_swapper(newcred);
 #endif
-       td->td_ucred = crhold(newcred);
-
        /* Create sigacts. */
        p->p_sigacts = sigacts_alloc();
 
@@ -556,6 +554,10 @@ proc0_init(void *dummy __unused)
        p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_max = pageablemem;
        p->p_cpulimit = RLIM_INFINITY;
 
+       PROC_LOCK(p);
+       thread_cow_get_proc(td, p);
+       PROC_UNLOCK(p);
+
        /* Initialize resource accounting structures. */
        racct_create(&p->p_racct);
 
@@ -843,10 +845,10 @@ create_init(const void *udata __unused)
        audit_cred_proc1(newcred);
 #endif
        proc_set_cred(initproc, newcred);
+       cred_update_thread(FIRST_THREAD_IN_PROC(initproc));
        PROC_UNLOCK(initproc);
        sx_xunlock(&proctree_lock);
        crfree(oldcred);
-       cred_update_thread(FIRST_THREAD_IN_PROC(initproc));
        cpu_set_fork_handler(FIRST_THREAD_IN_PROC(initproc), start_init, NULL);
 }
 SYSINIT(init, SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL);

Modified: head/sys/kern/kern_fork.c
==============================================================================
--- head/sys/kern/kern_fork.c   Wed Jun 10 09:59:26 2015        (r284213)
+++ head/sys/kern/kern_fork.c   Wed Jun 10 10:43:59 2015        (r284214)
@@ -496,7 +496,6 @@ do_fork(struct thread *td, int flags, st
        p2->p_swtick = ticks;
        if (p1->p_flag & P_PROFIL)
                startprofclock(p2);
-       td2->td_ucred = crhold(p2->p_ucred);
 
        if (flags & RFSIGSHARE) {
                p2->p_sigacts = sigacts_hold(p1->p_sigacts);
@@ -526,6 +525,8 @@ do_fork(struct thread *td, int flags, st
         */
        lim_fork(p1, p2);
 
+       thread_cow_get_proc(td2, p2);
+
        pstats_fork(p1->p_stats, p2->p_stats);
 
        PROC_UNLOCK(p1);

Modified: head/sys/kern/kern_kthread.c
==============================================================================
--- head/sys/kern/kern_kthread.c        Wed Jun 10 09:59:26 2015        
(r284213)
+++ head/sys/kern/kern_kthread.c        Wed Jun 10 10:43:59 2015        
(r284214)
@@ -289,7 +289,7 @@ kthread_add(void (*func)(void *), void *
        cpu_set_fork_handler(newtd, func, arg);
 
        newtd->td_pflags |= TDP_KTHREAD;
-       newtd->td_ucred = crhold(p->p_ucred);
+       thread_cow_get_proc(newtd, p);
 
        /* this code almost the same as create_thread() in kern_thr.c */
        p->p_flag |= P_HADTHREADS;

Modified: head/sys/kern/kern_prot.c
==============================================================================
--- head/sys/kern/kern_prot.c   Wed Jun 10 09:59:26 2015        (r284213)
+++ head/sys/kern/kern_prot.c   Wed Jun 10 10:43:59 2015        (r284214)
@@ -1946,9 +1946,8 @@ cred_update_thread(struct thread *td)
 
        p = td->td_proc;
        cred = td->td_ucred;
-       PROC_LOCK(p);
+       PROC_LOCK_ASSERT(p, MA_OWNED);
        td->td_ucred = crhold(p->p_ucred);
-       PROC_UNLOCK(p);
        if (cred != NULL)
                crfree(cred);
 }
@@ -1987,6 +1986,8 @@ proc_set_cred(struct proc *p, struct ucr
 
        oldcred = p->p_ucred;
        p->p_ucred = newcred;
+       if (newcred != NULL)
+               PROC_UPDATE_COW(p);
        return (oldcred);
 }
 

Modified: head/sys/kern/kern_syscalls.c
==============================================================================
--- head/sys/kern/kern_syscalls.c       Wed Jun 10 09:59:26 2015        
(r284213)
+++ head/sys/kern/kern_syscalls.c       Wed Jun 10 10:43:59 2015        
(r284214)
@@ -31,6 +31,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
 #include <sys/sx.h>
 #include <sys/syscall.h>
 #include <sys/sysent.h>

Modified: head/sys/kern/kern_thr.c
==============================================================================
--- head/sys/kern/kern_thr.c    Wed Jun 10 09:59:26 2015        (r284213)
+++ head/sys/kern/kern_thr.c    Wed Jun 10 10:43:59 2015        (r284214)
@@ -220,13 +220,13 @@ create_thread(struct thread *td, mcontex
        bcopy(&td->td_startcopy, &newtd->td_startcopy,
            __rangeof(struct thread, td_startcopy, td_endcopy));
        newtd->td_proc = td->td_proc;
-       newtd->td_ucred = crhold(td->td_ucred);
+       thread_cow_get(newtd, td);
 
        if (ctx != NULL) { /* old way to set user context */
                error = set_mcontext(newtd, ctx);
                if (error != 0) {
+                       thread_cow_free(newtd);
                        thread_free(newtd);
-                       crfree(td->td_ucred);
                        goto fail;
                }
        } else {
@@ -238,8 +238,8 @@ create_thread(struct thread *td, mcontex
                /* Setup user TLS address and TLS pointer register. */
                error = cpu_set_user_tls(newtd, tls_base);
                if (error != 0) {
+                       thread_cow_free(newtd);
                        thread_free(newtd);
-                       crfree(td->td_ucred);
                        goto fail;
                }
        }

Modified: head/sys/kern/kern_thread.c
==============================================================================
--- head/sys/kern/kern_thread.c Wed Jun 10 09:59:26 2015        (r284213)
+++ head/sys/kern/kern_thread.c Wed Jun 10 10:43:59 2015        (r284214)
@@ -327,8 +327,7 @@ thread_reap(void)
                mtx_unlock_spin(&zombie_lock);
                while (td_first) {
                        td_next = TAILQ_NEXT(td_first, td_slpq);
-                       if (td_first->td_ucred)
-                               crfree(td_first->td_ucred);
+                       thread_cow_free(td_first);
                        thread_free(td_first);
                        td_first = td_next;
                }
@@ -384,6 +383,44 @@ thread_free(struct thread *td)
        uma_zfree(thread_zone, td);
 }
 
+void
+thread_cow_get_proc(struct thread *newtd, struct proc *p)
+{
+
+       PROC_LOCK_ASSERT(p, MA_OWNED);
+       newtd->td_ucred = crhold(p->p_ucred);
+       newtd->td_cowgen = p->p_cowgen;
+}
+
+void
+thread_cow_get(struct thread *newtd, struct thread *td)
+{
+
+       newtd->td_ucred = crhold(td->td_ucred);
+       newtd->td_cowgen = td->td_cowgen;
+}
+
+void
+thread_cow_free(struct thread *td)
+{
+
+       if (td->td_ucred)
+               crfree(td->td_ucred);
+}
+
+void
+thread_cow_update(struct thread *td)
+{
+       struct proc *p;
+
+       p = td->td_proc;
+       PROC_LOCK(p);
+       if (td->td_ucred != p->p_ucred)
+               cred_update_thread(td);
+       td->td_cowgen = p->p_cowgen;
+       PROC_UNLOCK(p);
+}
+
 /*
  * Discard the current thread and exit from its context.
  * Always called with scheduler locked.
@@ -521,7 +558,7 @@ thread_wait(struct proc *p)
        cpuset_rel(td->td_cpuset);
        td->td_cpuset = NULL;
        cpu_thread_clean(td);
-       crfree(td->td_ucred);
+       thread_cow_free(td);
        thread_reap();  /* check for zombie threads etc. */
 }
 

Modified: head/sys/kern/subr_syscall.c
==============================================================================
--- head/sys/kern/subr_syscall.c        Wed Jun 10 09:59:26 2015        
(r284213)
+++ head/sys/kern/subr_syscall.c        Wed Jun 10 10:43:59 2015        
(r284214)
@@ -61,8 +61,8 @@ syscallenter(struct thread *td, struct s
        p = td->td_proc;
 
        td->td_pticks = 0;
-       if (td->td_ucred != p->p_ucred)
-               cred_update_thread(td);
+       if (td->td_cowgen != p->p_cowgen)
+               thread_cow_update(td);
        if (p->p_flag & P_TRACED) {
                traced = 1;
                PROC_LOCK(p);

Modified: head/sys/kern/subr_trap.c
==============================================================================
--- head/sys/kern/subr_trap.c   Wed Jun 10 09:59:26 2015        (r284213)
+++ head/sys/kern/subr_trap.c   Wed Jun 10 10:43:59 2015        (r284214)
@@ -220,8 +220,8 @@ ast(struct trapframe *framep)
        thread_unlock(td);
        PCPU_INC(cnt.v_trap);
 
-       if (td->td_ucred != p->p_ucred) 
-               cred_update_thread(td);
+       if (td->td_cowgen != p->p_cowgen)
+               thread_cow_update(td);
        if (td->td_pflags & TDP_OWEUPC && p->p_flag & P_PROFIL) {
                addupc_task(td, td->td_profil_addr, td->td_profil_ticks);
                td->td_profil_ticks = 0;

Modified: head/sys/powerpc/powerpc/trap.c
==============================================================================
--- head/sys/powerpc/powerpc/trap.c     Wed Jun 10 09:59:26 2015        
(r284213)
+++ head/sys/powerpc/powerpc/trap.c     Wed Jun 10 10:43:59 2015        
(r284214)
@@ -196,8 +196,8 @@ trap(struct trapframe *frame)
        if (user) {
                td->td_pticks = 0;
                td->td_frame = frame;
-               if (td->td_ucred != p->p_ucred)
-                       cred_update_thread(td);
+               if (td->td_cowgen != p->p_cowgen)
+                       thread_cow_update(td);
 
                /* User Mode Traps */
                switch (type) {

Modified: head/sys/sparc64/sparc64/trap.c
==============================================================================
--- head/sys/sparc64/sparc64/trap.c     Wed Jun 10 09:59:26 2015        
(r284213)
+++ head/sys/sparc64/sparc64/trap.c     Wed Jun 10 10:43:59 2015        
(r284214)
@@ -277,8 +277,8 @@ trap(struct trapframe *tf)
                td->td_pticks = 0;
                td->td_frame = tf;
                addr = tf->tf_tpc;
-               if (td->td_ucred != p->p_ucred)
-                       cred_update_thread(td);
+               if (td->td_cowgen != p->p_cowgen)
+                       thread_cow_update(td);
 
                switch (tf->tf_type) {
                case T_DATA_MISS:

Modified: head/sys/sys/proc.h
==============================================================================
--- head/sys/sys/proc.h Wed Jun 10 09:59:26 2015        (r284213)
+++ head/sys/sys/proc.h Wed Jun 10 10:43:59 2015        (r284214)
@@ -308,6 +308,7 @@ struct thread {
                off_t           tdu_off;        
        } td_uretoff;                   /* (k) Syscall aux returns. */
 #define td_retval      td_uretoff.tdu_retval
+       u_int           td_cowgen;      /* (k) Generation of COW pointers. */
        struct callout  td_slpcallout;  /* (h) Callout for sleep. */
        struct trapframe *td_frame;     /* (k) */
        struct vm_object *td_kstack_obj;/* (a) Kstack object. */
@@ -533,6 +534,7 @@ struct proc {
        pid_t           p_oppid;        /* (c + e) Save ppid in ptrace. XXX */
        struct vmspace  *p_vmspace;     /* (b) Address space. */
        u_int           p_swtick;       /* (c) Tick when swapped in or out. */
+       u_int           p_cowgen;       /* (c) Generation of COW pointers. */
        struct itimerval p_realtimer;   /* (c) Alarm timer. */
        struct rusage   p_ru;           /* (a) Exit information. */
        struct rusage_ext p_rux;        /* (cu) Internal resource usage. */
@@ -833,6 +835,11 @@ extern pid_t pid_max;
        KASSERT((p)->p_lock == 0, ("process held"));                    \
 } while (0)
 
+#define        PROC_UPDATE_COW(p) do {                                         
\
+       PROC_LOCK_ASSERT((p), MA_OWNED);                                \
+       (p)->p_cowgen++;                                                \
+} while (0)
+
 /* Check whether a thread is safe to be swapped out. */
 #define        thread_safetoswapout(td)        ((td)->td_flags & TDF_CANSWAP)
 
@@ -977,6 +984,10 @@ void       cpu_thread_swapin(struct thread *);
 void   cpu_thread_swapout(struct thread *);
 struct thread *thread_alloc(int pages);
 int    thread_alloc_stack(struct thread *, int pages);
+void   thread_cow_get_proc(struct thread *newtd, struct proc *p);
+void   thread_cow_get(struct thread *newtd, struct thread *td);
+void   thread_cow_free(struct thread *td);
+void   thread_cow_update(struct thread *td);
 void   thread_exit(void) __dead2;
 void   thread_free(struct thread *td);
 void   thread_link(struct thread *td, struct proc *p);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to