Add mtx_lock_giant() and mtx_unlock_giant() wrappers for sysctl management
of Giant during the Giant unwinding phase, and start work on instrumenting Giant for the file and proc mutexes. These wrappers allow developers to turn on and off Giant around various subsystems. DEVELOPERS SHOULD NEVER TURN OFF GIANT AROUND A SUBSYSTEM JUST BECAUSE THE SYSCTL EXISTS! General developers should only considering turning on Giant for a subsystem whos default is off (to help track down bugs). Only developers working on particular subsystems who know what they are doing should consider turning off Giant. These wrappers will greatly improve our ability to unwind Giant and test the kernel on a (mostly) subsystem by subsystem basis. They allow Giant unwinding developers (GUDs) to emplace appropriate subsystem and structural mutexes in the main tree and then request that the larger community test the work by turning off Giant around the subsystem(s), without the larger community having to mess around with patches. These wrappers also allow GUDs to boot into a (more likely to be) working system in the midst of their unwinding work and to test that work under more controlled circumstances. There is a master sysctl, kern.giant.all, which defaults to 0 (off). If turned on it overrides *ALL* other kern.giant sysctls and forces Giant to be turned on for all wrapped subsystems. If turned off then Giant around individual subsystems are controlled by various other kern.giant.XXX sysctls. Code which overlaps multiple subsystems must have all related subsystem Giant sysctls turned off in order to run without Giant.
This commit is contained in:
parent
8d5c8e9f04
commit
d23f5958bc
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -114,6 +114,8 @@ void _mtx_unlock_spin_flags(struct mtx *m, int opts, const char *file,
|
||||
#ifdef INVARIANT_SUPPORT
|
||||
void _mtx_assert(struct mtx *m, int what, const char *file, int line);
|
||||
#endif
|
||||
int mtx_lock_giant(int sysctlvar);
|
||||
void mtx_unlock_giant(int s);
|
||||
|
||||
/*
|
||||
* We define our machine-independent (unoptimized) mutex micro-operations
|
||||
@ -275,6 +277,12 @@ void _mtx_assert(struct mtx *m, int what, const char *file, int line);
|
||||
extern struct mtx sched_lock;
|
||||
extern struct mtx Giant;
|
||||
|
||||
/*
|
||||
* Giant lock sysctl variables used by other modules
|
||||
*/
|
||||
extern int kern_giant_proc;
|
||||
extern int kern_giant_file;
|
||||
|
||||
/*
|
||||
* Giant lock manipulation and clean exit macros.
|
||||
* Used to replace return with an exit Giant and return.
|
||||
|
Loading…
x
Reference in New Issue
Block a user