diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_mutex.c | 42 | ||||
-rw-r--r-- | sys/kern/kern_prot.c | 15 | ||||
-rw-r--r-- | sys/kern/subr_turnstile.c | 42 |
3 files changed, 93 insertions, 6 deletions
diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c index ba6efe5..4829e73 100644 --- a/sys/kern/kern_mutex.c +++ b/sys/kern/kern_mutex.c @@ -720,3 +720,45 @@ mtx_destroy(struct mtx *m) WITNESS_DESTROY(&m->mtx_object); } + +/* + * Encapsulated Giant mutex routines. These routines provide encapsulation + * control for the Giant mutex, allowing sysctls to be used to turn on and + * off Giant around certain subsystems. The default value for the sysctls + * are set to what developers believe is stable and working in regards to + * the Giant pushdown. Developers should not turn off Giant via these + * sysctls unless they know what they are doing. + * + * Callers of mtx_lock_giant() are expected to pass the return value to an + * accompanying mtx_unlock_giant() later on. If multiple subsystems are + * effected by a Giant wrap, all related sysctl variables must be zero for + * the subsystem call to operate without Giant (as determined by the caller). + */ + +SYSCTL_NODE(_kern, OID_AUTO, giant, CTLFLAG_RD, NULL, "Giant mutex manipulation"); + +static int kern_giant_all = 0; +SYSCTL_INT(_kern_giant, OID_AUTO, all, CTLFLAG_RW, &kern_giant_all, 0, ""); + +int kern_giant_proc = 1; /* Giant around PROC locks */ +int kern_giant_file = 1; /* Giant around struct file & filedesc */ +SYSCTL_INT(_kern_giant, OID_AUTO, proc, CTLFLAG_RW, &kern_giant_proc, 0, ""); +SYSCTL_INT(_kern_giant, OID_AUTO, file, CTLFLAG_RW, &kern_giant_file, 0, ""); + +int +mtx_lock_giant(int sysctlvar) +{ + if (sysctlvar || kern_giant_all) { + mtx_lock(&Giant); + return(1); + } + return(0); +} + +void +mtx_unlock_giant(int s) +{ + if (s) + mtx_unlock(&Giant); +} + diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index 553b278..894efac 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -86,15 +86,16 @@ getpid(td, uap) struct getpid_args *uap; { struct proc *p = td->td_proc; + int s; - mtx_lock(&Giant); + s = mtx_lock_giant(kern_giant_proc); td->td_retval[0] = p->p_pid; #if defined(COMPAT_43) || defined(COMPAT_SUNOS) PROC_LOCK(p); td->td_retval[1] = p->p_pptr->p_pid; PROC_UNLOCK(p); #endif - mtx_unlock(&Giant); + mtx_unlock_giant(s); return (0); } @@ -117,12 +118,13 @@ getppid(td, uap) struct getppid_args *uap; { struct proc *p = td->td_proc; + int s; - mtx_lock(&Giant); + s = mtx_lock_giant(kern_giant_proc); PROC_LOCK(p); td->td_retval[0] = p->p_pptr->p_pid; PROC_UNLOCK(p); - mtx_unlock(&Giant); + mtx_unlock_giant(s); return (0); } @@ -170,8 +172,9 @@ getpgid(td, uap) struct proc *p = td->td_proc; struct proc *pt; int error = 0; + int s; - mtx_lock(&Giant); + s = mtx_lock_giant(kern_giant_proc); if (uap->pid == 0) td->td_retval[0] = p->p_pgrp->pg_id; else if ((pt = pfind(uap->pid)) == NULL) @@ -182,7 +185,7 @@ getpgid(td, uap) td->td_retval[0] = pt->p_pgrp->pg_id; PROC_UNLOCK(pt); } - mtx_unlock(&Giant); + mtx_unlock_giant(s); return (error); } diff --git a/sys/kern/subr_turnstile.c b/sys/kern/subr_turnstile.c index ba6efe5..4829e73 100644 --- a/sys/kern/subr_turnstile.c +++ b/sys/kern/subr_turnstile.c @@ -720,3 +720,45 @@ mtx_destroy(struct mtx *m) WITNESS_DESTROY(&m->mtx_object); } + +/* + * Encapsulated Giant mutex routines. These routines provide encapsulation + * control for the Giant mutex, allowing sysctls to be used to turn on and + * off Giant around certain subsystems. The default value for the sysctls + * are set to what developers believe is stable and working in regards to + * the Giant pushdown. Developers should not turn off Giant via these + * sysctls unless they know what they are doing. + * + * Callers of mtx_lock_giant() are expected to pass the return value to an + * accompanying mtx_unlock_giant() later on. If multiple subsystems are + * effected by a Giant wrap, all related sysctl variables must be zero for + * the subsystem call to operate without Giant (as determined by the caller). + */ + +SYSCTL_NODE(_kern, OID_AUTO, giant, CTLFLAG_RD, NULL, "Giant mutex manipulation"); + +static int kern_giant_all = 0; +SYSCTL_INT(_kern_giant, OID_AUTO, all, CTLFLAG_RW, &kern_giant_all, 0, ""); + +int kern_giant_proc = 1; /* Giant around PROC locks */ +int kern_giant_file = 1; /* Giant around struct file & filedesc */ +SYSCTL_INT(_kern_giant, OID_AUTO, proc, CTLFLAG_RW, &kern_giant_proc, 0, ""); +SYSCTL_INT(_kern_giant, OID_AUTO, file, CTLFLAG_RW, &kern_giant_file, 0, ""); + +int +mtx_lock_giant(int sysctlvar) +{ + if (sysctlvar || kern_giant_all) { + mtx_lock(&Giant); + return(1); + } + return(0); +} + +void +mtx_unlock_giant(int s) +{ + if (s) + mtx_unlock(&Giant); +} + |