- Fix the last of the threading bugs that were introduced as far back as
1.38 in 2001. Break out of the FOREACH_THREAD_IN_PROC loop when we've discovered a new proc in the chain. - Increment i and check for maxlockdepth once per matching process not once per thread. This didn't properly terminate the loop before. - Fix a bug which has existed potentially since rev 1.1. waitblock->lf_next can be NULL when a thread has been woken-up but not yet scheduled. Check for this condition rather than blindly dereferencing. Found by: libMicro
This commit is contained in:
parent
86a06c6000
commit
fbd762f197
@ -286,28 +286,34 @@ lf_setlock(lock, vp, clean)
|
||||
PROC_LOCK(wproc);
|
||||
FOREACH_THREAD_IN_PROC(wproc, td) {
|
||||
thread_lock(td);
|
||||
while (td->td_wchan &&
|
||||
(td->td_wmesg == lockstr) &&
|
||||
(i++ < maxlockdepth)) {
|
||||
for (;;) {
|
||||
if (!TD_ON_SLEEPQ(td) ||
|
||||
td->td_wmesg != lockstr)
|
||||
break;
|
||||
waitblock = (struct lockf *)td->td_wchan;
|
||||
/* Get the owner of the blocking lock */
|
||||
if (waitblock->lf_next == NULL)
|
||||
break;
|
||||
waitblock = waitblock->lf_next;
|
||||
if ((waitblock->lf_flags & F_POSIX) == 0)
|
||||
break;
|
||||
nproc = (struct proc *)waitblock->lf_id;
|
||||
if (nproc == (struct proc *)lock->lf_id) {
|
||||
if (waitblock->lf_id == lock->lf_id) {
|
||||
thread_unlock(td);
|
||||
PROC_UNLOCK(wproc);
|
||||
lock->lf_next = *clean;
|
||||
*clean = lock;
|
||||
return (EDEADLK);
|
||||
}
|
||||
nproc = (struct proc *)waitblock->lf_id;
|
||||
break;
|
||||
}
|
||||
thread_unlock(td);
|
||||
if (nproc)
|
||||
break;
|
||||
}
|
||||
PROC_UNLOCK(wproc);
|
||||
wproc = nproc;
|
||||
if (wproc)
|
||||
if (++i < maxlockdepth && wproc)
|
||||
goto restart;
|
||||
}
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user