Date: Wed, 10 Jun 2015 10:44:00 +0000 (UTC) From: Mateusz Guzik <mjg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r284214 - in head/sys: amd64/amd64 arm/arm i386/i386 kern powerpc/powerpc sparc64/sparc64 sys Message-ID: <201506101044.t5AAi0fn028782@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201506101044.t5AAi0fn028782>