diff options
author | mjg <mjg@FreeBSD.org> | 2015-06-10 10:43:59 +0000 |
---|---|---|
committer | mjg <mjg@FreeBSD.org> | 2015-06-10 10:43:59 +0000 |
commit | 67f2eebb44e1f27017750eddaf5a5ea513cb9c71 (patch) | |
tree | 4be753ea914cbf9f2ee65a2a1cc53e6989224d5d /sys/kern/kern_thread.c | |
parent | ab3ad78145346dc115fb372ccf5f9bf7731075c9 (diff) | |
download | FreeBSD-src-67f2eebb44e1f27017750eddaf5a5ea513cb9c71.zip FreeBSD-src-67f2eebb44e1f27017750eddaf5a5ea513cb9c71.tar.gz |
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.
Diffstat (limited to 'sys/kern/kern_thread.c')
-rw-r--r-- | sys/kern/kern_thread.c | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index dce760c..2e97553 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -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. */ } |