summaryrefslogtreecommitdiffstats
path: root/sys/kern/sys_generic.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2001-09-21 22:06:22 +0000
committerjhb <jhb@FreeBSD.org>2001-09-21 22:06:22 +0000
commit3f482975e35722efddbdd11fa2141c6552280177 (patch)
tree038d90d97ef78218b4a81007d7e6668e9883759d /sys/kern/sys_generic.c
parent27422e6ae6d8128be14a3cda0c94eb1d3e5d95a7 (diff)
downloadFreeBSD-src-3f482975e35722efddbdd11fa2141c6552280177.zip
FreeBSD-src-3f482975e35722efddbdd11fa2141c6552280177.tar.gz
The P_SELECT flag was moved from p->p_flag to td->td_flags, but p_flag
was locked by the proc lock and td_flags is locked by the sched_lock. The places that read, set, and cleared TDF_SELECT weren't updated, so they read and modified td_flags w/o holding the sched_lock, meaning that they could corrupt the per-thread flags field. As an immediate band-aid, grab sched_lock while reading and manipulating td_flags in relation to TDF_SELECT. This will probably be cleaned up some later on.
Diffstat (limited to 'sys/kern/sys_generic.c')
-rw-r--r--sys/kern/sys_generic.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index a897979..17cee14 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -833,7 +833,9 @@ select(td, uap)
PROC_LOCK(td->td_proc);
retry:
ncoll = nselcoll;
+ mtx_lock_spin(&sched_lock);
td->td_flags |= TDF_SELECT;
+ mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(td->td_proc);
error = selscan(td, ibits, obits, uap->nd);
PROC_LOCK(td->td_proc);
@@ -848,13 +850,16 @@ retry:
* the process, test TDF_SELECT and rescan file descriptors if
* necessary.
*/
+ mtx_lock_spin(&sched_lock);
if ((td->td_flags & TDF_SELECT) == 0 || nselcoll != ncoll) {
ncoll = nselcoll;
td->td_flags |= TDF_SELECT;
+ mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(td->td_proc);
error = selscan(td, ibits, obits, uap->nd);
PROC_LOCK(td->td_proc);
- }
+ } else
+ mtx_unlock_spin(&sched_lock);
goto done;
}
ttv = atv;
@@ -862,7 +867,9 @@ retry:
timo = ttv.tv_sec > 24 * 60 * 60 ?
24 * 60 * 60 * hz : tvtohz(&ttv);
}
+ mtx_lock_spin(&sched_lock);
td->td_flags &= ~TDF_SELECT;
+ mtx_unlock_spin(&sched_lock);
if (timo > 0)
error = cv_timedwait_sig(&selwait, &td->td_proc->p_mtx, timo);
@@ -873,7 +880,9 @@ retry:
goto retry;
done:
+ mtx_lock_spin(&sched_lock);
td->td_flags &= ~TDF_SELECT;
+ mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(td->td_proc);
selholddrop(td, hibits, hobits, uap->nd, 0);
done_noproclock:
@@ -1049,7 +1058,9 @@ poll(td, uap)
PROC_LOCK(td->td_proc);
retry:
ncoll = nselcoll;
+ mtx_lock_spin(&sched_lock);
td->td_flags |= TDF_SELECT;
+ mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(td->td_proc);
error = pollscan(td, (struct pollfd *)bits, nfds);
PROC_LOCK(td->td_proc);
@@ -1064,13 +1075,16 @@ retry:
* the process, test TDF_SELECT and rescan file descriptors if
* necessary.
*/
+ mtx_lock_spin(&sched_lock);
if ((td->td_flags & TDF_SELECT) == 0 || nselcoll != ncoll) {
ncoll = nselcoll;
td->td_flags |= TDF_SELECT;
+ mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(td->td_proc);
error = pollscan(td, (struct pollfd *)bits, nfds);
PROC_LOCK(td->td_proc);
- }
+ } else
+ mtx_unlock_spin(&sched_lock);
goto done;
}
ttv = atv;
@@ -1078,7 +1092,9 @@ retry:
timo = ttv.tv_sec > 24 * 60 * 60 ?
24 * 60 * 60 * hz : tvtohz(&ttv);
}
+ mtx_lock_spin(&sched_lock);
td->td_flags &= ~TDF_SELECT;
+ mtx_unlock_spin(&sched_lock);
if (timo > 0)
error = cv_timedwait_sig(&selwait, &td->td_proc->p_mtx, timo);
else
@@ -1087,7 +1103,9 @@ retry:
goto retry;
done:
+ mtx_lock_spin(&sched_lock);
td->td_flags &= ~TDF_SELECT;
+ mtx_unlock_spin(&sched_lock);
PROC_UNLOCK(td->td_proc);
pollholddrop(td, heldbits, nfds, 0);
done_noproclock:
OpenPOWER on IntegriCloud