Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F177585019
D17817.1794800660.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
10 KB
Referenced Files
None
Subscribers
None
D17817.1794800660.diff
View Options
Index: sys/kern/kern_exit.c
===================================================================
--- sys/kern/kern_exit.c
+++ sys/kern/kern_exit.c
@@ -440,7 +440,6 @@
sx_xlock(&allproc_lock);
LIST_REMOVE(p, p_list);
LIST_INSERT_HEAD(&zombproc, p, p_list);
- LIST_REMOVE(p, p_hash);
sx_xunlock(&allproc_lock);
/*
@@ -883,6 +882,9 @@
sx_xlock(&allproc_lock);
LIST_REMOVE(p, p_list); /* off zombproc */
sx_xunlock(&allproc_lock);
+ sx_xlock(PIDHASHLOCK(p->p_pid));
+ LIST_REMOVE(p, p_hash);
+ sx_xunlock(PIDHASHLOCK(p->p_pid));
LIST_REMOVE(p, p_sibling);
reaper_abandon_children(p, true);
LIST_REMOVE(p, p_reapsibling);
Index: sys/kern/kern_fork.c
===================================================================
--- sys/kern/kern_fork.c
+++ sys/kern/kern_fork.c
@@ -406,7 +406,9 @@
AUDIT_ARG_PID(p2->p_pid);
LIST_INSERT_HEAD(&allproc, p2, p_list);
allproc_gen++;
+ sx_xlock(PIDHASHLOCK(p2->p_pid));
LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash);
+ sx_xunlock(PIDHASHLOCK(p2->p_pid));
PROC_LOCK(p2);
PROC_LOCK(p1);
Index: sys/kern/kern_proc.c
===================================================================
--- sys/kern/kern_proc.c
+++ sys/kern/kern_proc.c
@@ -127,7 +127,9 @@
* Other process lists
*/
struct pidhashhead *pidhashtbl;
+struct sx *pidhashtbl_lock;
u_long pidhash;
+u_long pidhashlock;
struct pgrphashhead *pgrphashtbl;
u_long pgrphash;
struct proclist allproc;
@@ -182,6 +184,7 @@
void
procinit(void)
{
+ u_long i;
sx_init(&allproc_lock, "allproc");
sx_init(&proctree_lock, "proctree");
@@ -189,6 +192,14 @@
LIST_INIT(&allproc);
LIST_INIT(&zombproc);
pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash);
+ pidhashlock = (pidhash + 1) / 64;
+ if (pidhashlock > 0)
+ pidhashlock--;
+ pidhashtbl_lock = malloc(sizeof(*pidhashtbl_lock) * (pidhashlock + 1),
+ M_PROC, M_WAITOK | M_ZERO);
+ for (i = 0; i < pidhashlock + 1; i++)
+ sx_init(&pidhashtbl_lock[i], "pidhash");
+
pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash);
proc_zone = uma_zcreate("PROC", sched_sizeof_proc(),
proc_ctor, proc_dtor, proc_init, proc_fini,
@@ -321,7 +332,7 @@
LIST_FOREACH(p, PIDHASH(pid), p_hash) {
if (p->p_pid == pid) {
PROC_LOCK(p);
- if (p->p_state == PRS_NEW) {
+ if (p->p_state == PRS_NEW || p->p_state == PRS_ZOMBIE) {
PROC_UNLOCK(p);
p = NULL;
}
@@ -1438,13 +1449,145 @@
return (0);
}
+int
+proc_iterate(int (*cb)(struct proc *, void *), void *cbarg)
+{
+ struct proc *p;
+ int i, j, error;
+
+ error = 0;
+ for (i = 0; i < pidhashlock + 1; i++) {
+ sx_slock(&pidhashtbl_lock[i]);
+ for (j = i; j <= pidhash; j += pidhashlock + 1) {
+ LIST_FOREACH(p, &pidhashtbl[j], p_hash) {
+ if (p->p_state == PRS_NEW)
+ continue;
+ error = cb(p, cbarg);
+ PROC_LOCK_ASSERT(p, MA_NOTOWNED);
+ if (error)
+ goto out_err;
+ }
+ }
+ sx_sunlock(&pidhashtbl_lock[i]);
+ }
+ return (0);
+out_err:
+ sx_sunlock(&pidhashtbl_lock[i]);
+ return (error);
+}
+
+struct kern_proc_out_args {
+ struct sysctl_req *req;
+ int flags;
+ int oid_number;
+ int *name;
+};
+
+static int
+sysctl_kern_proc_iterate(struct proc *p, void *origarg)
+{
+ struct kern_proc_out_args *arg = origarg;
+ int *name = arg->name;
+ int oid_number = arg->oid_number;
+ int flags = arg->flags;
+ struct sysctl_req *req = arg->req;
+ int error = 0;
+
+ PROC_LOCK(p);
+
+ KASSERT(p->p_ucred != NULL,
+ ("process credential is NULL for non-NEW proc"));
+ /*
+ * Show a user only appropriate processes.
+ */
+ if (p_cansee(curthread, p)) {
+ goto skip;
+ }
+ /*
+ * TODO - make more efficient (see notes below).
+ * do by session.
+ */
+ switch (oid_number) {
+
+ case KERN_PROC_GID:
+ if (p->p_ucred->cr_gid != (gid_t)name[0]) {
+ goto skip;
+ }
+ break;
+
+ case KERN_PROC_PGRP:
+ /* could do this by traversing pgrp */
+ if (p->p_pgrp == NULL ||
+ p->p_pgrp->pg_id != (pid_t)name[0]) {
+ goto skip;
+ }
+ break;
+
+ case KERN_PROC_RGID:
+ if (p->p_ucred->cr_rgid != (gid_t)name[0]) {
+ goto skip;
+ }
+ break;
+
+ case KERN_PROC_SESSION:
+ if (p->p_session == NULL ||
+ p->p_session->s_sid != (pid_t)name[0]) {
+ goto skip;
+ }
+ break;
+
+ case KERN_PROC_TTY:
+ if ((p->p_flag & P_CONTROLT) == 0 ||
+ p->p_session == NULL) {
+ goto skip;
+ }
+ /* XXX proctree_lock */
+ SESS_LOCK(p->p_session);
+ if (p->p_session->s_ttyp == NULL ||
+ tty_udev(p->p_session->s_ttyp) !=
+ (dev_t)name[0]) {
+ SESS_UNLOCK(p->p_session);
+ goto skip;
+ }
+ SESS_UNLOCK(p->p_session);
+ break;
+
+ case KERN_PROC_UID:
+ if (p->p_ucred->cr_uid != (uid_t)name[0]) {
+ goto skip;
+ }
+ break;
+
+ case KERN_PROC_RUID:
+ if (p->p_ucred->cr_ruid != (uid_t)name[0]) {
+ goto skip;
+ }
+ break;
+
+ case KERN_PROC_PROC:
+ break;
+
+ default:
+ break;
+
+ }
+
+ error = sysctl_out_proc(p, req, flags);
+ PROC_LOCK_ASSERT(p, MA_NOTOWNED);
+ return (error);
+skip:
+ PROC_UNLOCK(p);
+ return (0);
+}
+
static int
sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
{
+ struct kern_proc_out_args iterarg;
int *name = (int *)arg1;
u_int namelen = arg2;
struct proc *p;
- int flags, doingzomb, oid_number;
+ int flags, oid_number;
int error = 0;
oid_number = oidp->oid_number;
@@ -1504,112 +1647,11 @@
*/
sx_slock(&proctree_lock);
}
- sx_slock(&allproc_lock);
- for (doingzomb=0 ; doingzomb < 2 ; doingzomb++) {
- if (!doingzomb)
- p = LIST_FIRST(&allproc);
- else
- p = LIST_FIRST(&zombproc);
- for (; p != NULL; p = LIST_NEXT(p, p_list)) {
- /*
- * Skip embryonic processes.
- */
- if (p->p_state == PRS_NEW)
- continue;
- PROC_LOCK(p);
- KASSERT(p->p_ucred != NULL,
- ("process credential is NULL for non-NEW proc"));
- /*
- * Show a user only appropriate processes.
- */
- if (p_cansee(curthread, p)) {
- PROC_UNLOCK(p);
- continue;
- }
- /*
- * TODO - make more efficient (see notes below).
- * do by session.
- */
- switch (oid_number) {
-
- case KERN_PROC_GID:
- if (p->p_ucred->cr_gid != (gid_t)name[0]) {
- PROC_UNLOCK(p);
- continue;
- }
- break;
-
- case KERN_PROC_PGRP:
- /* could do this by traversing pgrp */
- if (p->p_pgrp == NULL ||
- p->p_pgrp->pg_id != (pid_t)name[0]) {
- PROC_UNLOCK(p);
- continue;
- }
- break;
-
- case KERN_PROC_RGID:
- if (p->p_ucred->cr_rgid != (gid_t)name[0]) {
- PROC_UNLOCK(p);
- continue;
- }
- break;
-
- case KERN_PROC_SESSION:
- if (p->p_session == NULL ||
- p->p_session->s_sid != (pid_t)name[0]) {
- PROC_UNLOCK(p);
- continue;
- }
- break;
-
- case KERN_PROC_TTY:
- if ((p->p_flag & P_CONTROLT) == 0 ||
- p->p_session == NULL) {
- PROC_UNLOCK(p);
- continue;
- }
- /* XXX proctree_lock */
- SESS_LOCK(p->p_session);
- if (p->p_session->s_ttyp == NULL ||
- tty_udev(p->p_session->s_ttyp) !=
- (dev_t)name[0]) {
- SESS_UNLOCK(p->p_session);
- PROC_UNLOCK(p);
- continue;
- }
- SESS_UNLOCK(p->p_session);
- break;
-
- case KERN_PROC_UID:
- if (p->p_ucred->cr_uid != (uid_t)name[0]) {
- PROC_UNLOCK(p);
- continue;
- }
- break;
-
- case KERN_PROC_RUID:
- if (p->p_ucred->cr_ruid != (uid_t)name[0]) {
- PROC_UNLOCK(p);
- continue;
- }
- break;
-
- case KERN_PROC_PROC:
- break;
-
- default:
- break;
-
- }
-
- error = sysctl_out_proc(p, req, flags);
- if (error)
- goto out;
- }
- }
-out:
- sx_sunlock(&allproc_lock);
+ iterarg.flags = flags;
+ iterarg.oid_number = oid_number;
+ iterarg.req = req;
+ iterarg.name = name;
+ error = proc_iterate(sysctl_kern_proc_iterate, &iterarg);
if (req->oldptr != NULL)
sx_sunlock(&proctree_lock);
return (error);
Index: sys/kern/kern_sig.c
===================================================================
--- sys/kern/kern_sig.c
+++ sys/kern/kern_sig.c
@@ -1656,9 +1656,43 @@
* Common code for kill process group/broadcast kill.
* cp is calling process.
*/
+
+struct killpg_iter_arg {
+ int sig;
+ int *ret;
+ ksiginfo_t *ksi;
+ struct thread *td;
+};
+
+static int
+killpg_iter(struct proc *p, void *origarg)
+{
+ struct killpg_iter_arg *arg = origarg;
+ int err;
+
+ if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
+ p == arg->td->td_proc)
+ return (0);
+ PROC_LOCK(p);
+ if (p->p_state == PRS_ZOMBIE)
+ goto out;
+ err = p_cansignal(arg->td, p, arg->sig);
+ if (err == 0) {
+ if (arg->sig)
+ pksignal(p, arg->sig, arg->ksi);
+ *arg->ret = err;
+ }
+ else if (*arg->ret == ESRCH)
+ *arg->ret = err;
+out:
+ PROC_UNLOCK(p);
+ return (0);
+}
+
static int
killpg1(struct thread *td, int sig, int pgid, int all, ksiginfo_t *ksi)
{
+ struct killpg_iter_arg iterarg;
struct proc *p;
struct pgrp *pgrp;
int err;
@@ -1669,24 +1703,11 @@
/*
* broadcast
*/
- sx_slock(&allproc_lock);
- FOREACH_PROC_IN_SYSTEM(p) {
- if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
- p == td->td_proc || p->p_state == PRS_NEW) {
- continue;
- }
- PROC_LOCK(p);
- err = p_cansignal(td, p, sig);
- if (err == 0) {
- if (sig)
- pksignal(p, sig, ksi);
- ret = err;
- }
- else if (ret == ESRCH)
- ret = err;
- PROC_UNLOCK(p);
- }
- sx_sunlock(&allproc_lock);
+ iterarg.sig = sig;
+ iterarg.ret = &ret;
+ iterarg.ksi = ksi;
+ iterarg.td = td;
+ proc_iterate(killpg_iter, &iterarg);
} else {
sx_slock(&proctree_lock);
if (pgid == 0) {
Index: sys/sys/proc.h
===================================================================
--- sys/sys/proc.h
+++ sys/sys/proc.h
@@ -940,8 +940,11 @@
#define THREAD_CAN_SLEEP() ((curthread)->td_no_sleeping == 0)
#define PIDHASH(pid) (&pidhashtbl[(pid) & pidhash])
+#define PIDHASHLOCK(pid) (&pidhashtbl_lock[((pid) & pidhashlock)])
extern LIST_HEAD(pidhashhead, proc) *pidhashtbl;
+extern struct sx *pidhashtbl_lock;
extern u_long pidhash;
+extern u_long pidhashlock;
#define TIDHASH(tid) (&tidhashtbl[(tid) & tidhash])
extern LIST_HEAD(tidhashhead, thread) *tidhashtbl;
extern u_long tidhash;
@@ -1044,6 +1047,7 @@
int proc_getauxv(struct thread *td, struct proc *p, struct sbuf *sb);
int proc_getenvv(struct thread *td, struct proc *p, struct sbuf *sb);
void procinit(void);
+int proc_iterate(int (*cb)(struct proc *, void *), void *cbarg);
void proc_linkup0(struct proc *p, struct thread *td);
void proc_linkup(struct proc *p, struct thread *td);
struct proc *proc_realparent(struct proc *child);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Nov 16, 3:44 AM (21 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41758278
Default Alt Text
D17817.1794800660.diff (10 KB)
Attached To
Mode
D17817: proc: implement pid hash locks and an iterator
Attached
Detach File
Event Timeline