Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F159760841
D43488.id132906.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D43488.id132906.diff
View Options
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -40,7 +40,7 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/bitstring.h>
+#include <sys/bitset.h>
#include <sys/sysproto.h>
#include <sys/eventhandler.h>
#include <sys/fcntl.h>
@@ -238,10 +238,7 @@
sysctl_kern_randompid, "I",
"Random PID modulus. Special values: 0: disable, 1: choose random value");
-extern bitstr_t proc_id_pidmap;
-extern bitstr_t proc_id_grpidmap;
-extern bitstr_t proc_id_sessidmap;
-extern bitstr_t proc_id_reapmap;
+extern struct proc_id_map proc_id_pidmap;
/*
* Find an unused process ID
@@ -253,18 +250,14 @@
fork_findpid(int flags)
{
pid_t result;
- int trypid, random;
+ int _lastpid, random, trypid;
- /*
- * Avoid calling arc4random with procid_lock held.
- */
random = 0;
if (__predict_false(randompid))
random = arc4random() % randompid;
- mtx_lock(&procid_lock);
-
- trypid = lastpid + 1;
+ _lastpid = lastpid;
+ trypid = _lastpid;
if (flags & RFHIGHPID) {
if (trypid < 10)
trypid = 10;
@@ -275,27 +268,37 @@
if (trypid >= pid_max)
trypid = 2;
- bit_ffc_at(&proc_id_pidmap, trypid, pid_max, &result);
+ result = BIT_FFC_AT(pid_max, &proc_id_pidmap, trypid + 1) - 1;
if (result == -1) {
KASSERT(trypid != 2, ("unexpectedly ran out of IDs"));
trypid = 2;
goto retry;
- }
- if (bit_test(&proc_id_grpidmap, result) ||
- bit_test(&proc_id_sessidmap, result) ||
- bit_test(&proc_id_reapmap, result)) {
- trypid = result + 1;
- goto retry;
+ } else {
+ /*
+ * We try to reserve the PID first. If we were able to do that,
+ * we still need to check if the PID is not set on the other
+ * bitmaps. We assume that because we were able reserve the PID,
+ * this bit cannot be set in the other bitmaps anymore.
+ * It was either set before or it is not set.
+ */
+ if (proc_id_set_cond(PROC_ID_PID, result)) {
+ /* Lost the race. */
+ trypid = result + 1;
+ goto retry;
+ } else if (proc_id_test(PROC_ID_GROUP, result) ||
+ proc_id_test(PROC_ID_SESSION, result) ||
+ proc_id_test(PROC_ID_REAP, result)) {
+ proc_id_clear(PROC_ID_PID, result);
+ trypid = result + 1;
+ goto retry;
+ }
}
/*
* RFHIGHPID does not mess with the lastpid counter during boot.
*/
if ((flags & RFHIGHPID) == 0)
- lastpid = result;
-
- bit_set(&proc_id_pidmap, result);
- mtx_unlock(&procid_lock);
+ atomic_cmpset_acq_int(&lastpid, _lastpid, result);
return (result);
}
@@ -652,7 +655,7 @@
LIST_INSERT_HEAD(&p2->p_reaper->p_reaplist, p2, p_reapsibling);
if (p2->p_reaper == p1 && p1 != initproc) {
p2->p_reapsubtree = p2->p_pid;
- proc_id_set_cond(PROC_ID_REAP, p2->p_pid);
+ (void)proc_id_set_cond(PROC_ID_REAP, p2->p_pid);
}
sx_xunlock(&proctree_lock);
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -37,7 +37,7 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/bitstring.h>
+#include <sys/bitset.h>
#include <sys/elf.h>
#include <sys/eventhandler.h>
#include <sys/exec.h>
@@ -130,7 +130,6 @@
struct sx __exclusive_cache_line allproc_lock;
struct sx __exclusive_cache_line proctree_lock;
struct mtx __exclusive_cache_line ppeers_lock;
-struct mtx __exclusive_cache_line procid_lock;
uma_zone_t proc_zone;
uma_zone_t pgrp_zone;
@@ -183,7 +182,6 @@
sx_init(&allproc_lock, "allproc");
sx_init(&proctree_lock, "proctree");
mtx_init(&ppeers_lock, "p_peers", NULL, MTX_DEF);
- mtx_init(&procid_lock, "procid", NULL, MTX_DEF);
pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash);
pidhashlock = (pidhash + 1) / 64;
if (pidhashlock > 0)
@@ -317,16 +315,16 @@
*
* These bitmaps are used by fork_findpid.
*/
-bitstr_t bit_decl(proc_id_pidmap, PID_MAX);
-bitstr_t bit_decl(proc_id_grpidmap, PID_MAX);
-bitstr_t bit_decl(proc_id_sessidmap, PID_MAX);
-bitstr_t bit_decl(proc_id_reapmap, PID_MAX);
-
-static bitstr_t *proc_id_array[] = {
- proc_id_pidmap,
- proc_id_grpidmap,
- proc_id_sessidmap,
- proc_id_reapmap,
+struct proc_id_map proc_id_pidmap;
+struct proc_id_map proc_id_grpidmap;
+struct proc_id_map proc_id_sessidmap;
+struct proc_id_map proc_id_reapmap;
+
+static struct proc_id_map *proc_id_array[] = {
+ &proc_id_pidmap,
+ &proc_id_grpidmap,
+ &proc_id_sessidmap,
+ &proc_id_reapmap,
};
void
@@ -335,24 +333,18 @@
KASSERT(type >= 0 && type < nitems(proc_id_array),
("invalid type %d\n", type));
- mtx_lock(&procid_lock);
- KASSERT(bit_test(proc_id_array[type], id) == 0,
- ("bit %d already set in %d\n", id, type));
- bit_set(proc_id_array[type], id);
- mtx_unlock(&procid_lock);
+ if (__predict_false(BIT_TEST_SET_ATOMIC(PID_MAX, id, proc_id_array[type]))) {
+ panic("%s: bit %d already set in %d", __func__, id, type);
+ }
}
-void
+bool
proc_id_set_cond(int type, pid_t id)
{
KASSERT(type >= 0 && type < nitems(proc_id_array),
("invalid type %d\n", type));
- if (bit_test(proc_id_array[type], id))
- return;
- mtx_lock(&procid_lock);
- bit_set(proc_id_array[type], id);
- mtx_unlock(&procid_lock);
+ return (BIT_TEST_SET_ATOMIC(PID_MAX, id, proc_id_array[type]));
}
void
@@ -361,11 +353,18 @@
KASSERT(type >= 0 && type < nitems(proc_id_array),
("invalid type %d\n", type));
- mtx_lock(&procid_lock);
- KASSERT(bit_test(proc_id_array[type], id) != 0,
- ("bit %d not set in %d\n", id, type));
- bit_clear(proc_id_array[type], id);
- mtx_unlock(&procid_lock);
+ if (__predict_false(!BIT_TEST_CLR_ATOMIC(PID_MAX, id, proc_id_array[type]))) {
+ panic("%s: bit %d not set in %d", __func__, id, type);
+ }
+}
+
+bool
+proc_id_test(int type, pid_t id)
+{
+
+ KASSERT(type >= 0 && type < nitems(proc_id_array),
+ ("invalid type %d\n", type));
+ return (BIT_ISSET_ATOMIC(PID_MAX, id, proc_id_array[type]));
}
/*
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -37,6 +37,7 @@
#ifndef _SYS_PROC_H_
#define _SYS_PROC_H_
+#include <sys/bitset.h>
#include <sys/callout.h> /* For struct callout. */
#include <sys/event.h> /* For struct klist. */
#ifdef _KERNEL
@@ -1098,7 +1099,6 @@
extern int allproc_gen;
extern struct sx proctree_lock;
extern struct mtx ppeers_lock;
-extern struct mtx procid_lock;
extern struct proc proc0; /* Process slot for swapper. */
extern struct thread0_storage thread0_st; /* Primary thread in proc0. */
#define thread0 (thread0_st.t0st_thread)
@@ -1351,9 +1351,12 @@
#define PROC_ID_SESSION 2
#define PROC_ID_REAP 3
+BITSET_DEFINE(proc_id_map, PID_MAX);
+
void proc_id_set(int type, pid_t id);
-void proc_id_set_cond(int type, pid_t id);
+bool proc_id_set_cond(int type, pid_t id);
void proc_id_clear(int type, pid_t id);
+bool proc_id_test(int type, pid_t id);
EVENTHANDLER_LIST_DECLARE(process_ctor);
EVENTHANDLER_LIST_DECLARE(process_dtor);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jun 18, 10:55 PM (11 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34061110
Default Alt Text
D43488.id132906.diff (6 KB)
Attached To
Mode
D43488: kern: Implement lockless method for obtaining new PID.
Attached
Detach File
Event Timeline
Log In to Comment