summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_mutex.c42
-rw-r--r--sys/kern/kern_prot.c15
-rw-r--r--sys/kern/subr_turnstile.c42
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);
+}
+
OpenPOWER on IntegriCloud