Cache the value of c_lock as it can change, in the struct,
while the global callout spinlock is not held, and can lead to PF#. Reported by: dougb, Mark Atkinson <atkin901 at yahoo dot com> Tested by: dougb Diagnosed by: jhb
This commit is contained in:
parent
2b0672aa28
commit
5ed5cf01be
@ -216,6 +216,7 @@ softclock(void *dummy)
|
|||||||
void (*c_func)(void *);
|
void (*c_func)(void *);
|
||||||
void *c_arg;
|
void *c_arg;
|
||||||
struct lock_class *class;
|
struct lock_class *class;
|
||||||
|
struct lock_object *c_lock;
|
||||||
int c_flags, sharedlock;
|
int c_flags, sharedlock;
|
||||||
|
|
||||||
nextsoftcheck = TAILQ_NEXT(c, c_links.tqe);
|
nextsoftcheck = TAILQ_NEXT(c, c_links.tqe);
|
||||||
@ -224,6 +225,7 @@ softclock(void *dummy)
|
|||||||
LOCK_CLASS(c->c_lock) : NULL;
|
LOCK_CLASS(c->c_lock) : NULL;
|
||||||
sharedlock = (c->c_flags & CALLOUT_SHAREDLOCK) ?
|
sharedlock = (c->c_flags & CALLOUT_SHAREDLOCK) ?
|
||||||
0 : 1;
|
0 : 1;
|
||||||
|
c_lock = c->c_lock;
|
||||||
c_func = c->c_func;
|
c_func = c->c_func;
|
||||||
c_arg = c->c_arg;
|
c_arg = c->c_arg;
|
||||||
c_flags = c->c_flags;
|
c_flags = c->c_flags;
|
||||||
@ -240,20 +242,20 @@ softclock(void *dummy)
|
|||||||
}
|
}
|
||||||
curr_cancelled = 0;
|
curr_cancelled = 0;
|
||||||
mtx_unlock_spin(&callout_lock);
|
mtx_unlock_spin(&callout_lock);
|
||||||
if (class != NULL) {
|
if (c_lock != NULL) {
|
||||||
class->lc_lock(c->c_lock, sharedlock);
|
class->lc_lock(c_lock, sharedlock);
|
||||||
/*
|
/*
|
||||||
* The callout may have been cancelled
|
* The callout may have been cancelled
|
||||||
* while we switched locks.
|
* while we switched locks.
|
||||||
*/
|
*/
|
||||||
if (curr_cancelled) {
|
if (curr_cancelled) {
|
||||||
class->lc_unlock(c->c_lock);
|
class->lc_unlock(c_lock);
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
/* The callout cannot be stopped now. */
|
/* The callout cannot be stopped now. */
|
||||||
curr_cancelled = 1;
|
curr_cancelled = 1;
|
||||||
|
|
||||||
if (c->c_lock == &Giant.lock_object) {
|
if (c_lock == &Giant.lock_object) {
|
||||||
gcalls++;
|
gcalls++;
|
||||||
CTR3(KTR_CALLOUT,
|
CTR3(KTR_CALLOUT,
|
||||||
"callout %p func %p arg %p",
|
"callout %p func %p arg %p",
|
||||||
@ -294,7 +296,7 @@ softclock(void *dummy)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if ((c_flags & CALLOUT_RETURNUNLOCKED) == 0)
|
if ((c_flags & CALLOUT_RETURNUNLOCKED) == 0)
|
||||||
class->lc_unlock(c->c_lock);
|
class->lc_unlock(c_lock);
|
||||||
skip:
|
skip:
|
||||||
mtx_lock_spin(&callout_lock);
|
mtx_lock_spin(&callout_lock);
|
||||||
curr_callout = NULL;
|
curr_callout = NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user