From 67f2eebb44e1f27017750eddaf5a5ea513cb9c71 Mon Sep 17 00:00:00 2001 From: mjg Date: Wed, 10 Jun 2015 10:43:59 +0000 Subject: 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. --- sys/kern/kern_thread.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) (limited to 'sys/kern/kern_thread.c') 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. */ } -- cgit v1.1 From d7bc9285a673d676370f95a84ce93ef553c8688c Mon Sep 17 00:00:00 2001 From: mjg Date: Wed, 10 Jun 2015 10:48:12 +0000 Subject: Implement lockless resource limits. Use the same scheme implemented to manage credentials. Code needing to look at process's credentials (as opposed to thred's) is provided with *_proc variants of relevant functions. Places which possibly had to take the proc lock anyway still use the proc pointer to access limits. --- sys/kern/kern_thread.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'sys/kern/kern_thread.c') diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 2e97553..4343b64 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -389,6 +389,7 @@ 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_limit = lim_hold(p->p_limit); newtd->td_cowgen = p->p_cowgen; } @@ -397,6 +398,7 @@ thread_cow_get(struct thread *newtd, struct thread *td) { newtd->td_ucred = crhold(td->td_ucred); + newtd->td_limit = lim_hold(td->td_limit); newtd->td_cowgen = td->td_cowgen; } @@ -406,6 +408,8 @@ thread_cow_free(struct thread *td) if (td->td_ucred) crfree(td->td_ucred); + if (td->td_limit) + lim_free(td->td_limit); } void @@ -417,6 +421,8 @@ thread_cow_update(struct thread *td) PROC_LOCK(p); if (td->td_ucred != p->p_ucred) cred_update_thread(td); + if (td->td_limit != p->p_limit) + lim_update_thread(td); td->td_cowgen = p->p_cowgen; PROC_UNLOCK(p); } -- cgit v1.1