summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_timeout.c
diff options
context:
space:
mode:
authordavide <davide@FreeBSD.org>2013-09-20 23:16:15 +0000
committerdavide <davide@FreeBSD.org>2013-09-20 23:16:15 +0000
commitdefa3b8b8514a27c55c8c03cf37f7c8177bb3efe (patch)
tree4594975cace99b3e3d4631da3bd59c4c78a58f58 /sys/kern/kern_timeout.c
parent023fd8bc674b34351ef00a551db9abc16b6151e5 (diff)
downloadFreeBSD-src-defa3b8b8514a27c55c8c03cf37f7c8177bb3efe.zip
FreeBSD-src-defa3b8b8514a27c55c8c03cf37f7c8177bb3efe.tar.gz
Fix callout_init_rm() in the shared case, allocating storage for 'struct
rm_priotracker' directly in the softclock thread. Now consumers can pass CALLOUT_SHAREDLOCK flag to callout initialization routine safely. The choice of the already existing flags instead of special casing shared rmlocks is done to prevent consumer footshooting. Suggested by: jhb Reviewed by: jhb Approved by: re (delphij)
Diffstat (limited to 'sys/kern/kern_timeout.c')
-rw-r--r--sys/kern/kern_timeout.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c
index e3580fc..507e3b0 100644
--- a/sys/kern/kern_timeout.c
+++ b/sys/kern/kern_timeout.c
@@ -597,11 +597,13 @@ softclock_call_cc(struct callout *c, struct callout_cpu *cc,
#endif
int direct)
{
+ struct rm_priotracker tracker;
void (*c_func)(void *);
void *c_arg;
struct lock_class *class;
struct lock_object *c_lock;
- int c_flags, sharedlock;
+ uintptr_t lock_status;
+ int c_flags;
#ifdef SMP
struct callout_cpu *new_cc;
void (*new_func)(void *);
@@ -620,7 +622,13 @@ softclock_call_cc(struct callout *c, struct callout_cpu *cc,
(CALLOUT_PENDING | CALLOUT_ACTIVE),
("softclock_call_cc: pend|act %p %x", c, c->c_flags));
class = (c->c_lock != NULL) ? LOCK_CLASS(c->c_lock) : NULL;
- sharedlock = (c->c_flags & CALLOUT_SHAREDLOCK) ? 0 : 1;
+ lock_status = 0;
+ if (c->c_flags & CALLOUT_SHAREDLOCK) {
+ if (class == &lock_class_rm)
+ lock_status = (uintptr_t)&tracker;
+ else
+ lock_status = 1;
+ }
c_lock = c->c_lock;
c_func = c->c_func;
c_arg = c->c_arg;
@@ -633,7 +641,7 @@ softclock_call_cc(struct callout *c, struct callout_cpu *cc,
cc->cc_exec_entity[direct].cc_cancel = false;
CC_UNLOCK(cc);
if (c_lock != NULL) {
- class->lc_lock(c_lock, sharedlock);
+ class->lc_lock(c_lock, lock_status);
/*
* The callout may have been cancelled
* while we switched locks.
OpenPOWER on IntegriCloud