Author: davide
Date: Fri Sep 20 23:16:15 2013
New Revision: 255747
URL: http://svnweb.freebsd.org/changeset/base/255747

Log:
  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)

Modified:
  head/sys/kern/kern_timeout.c

Modified: head/sys/kern/kern_timeout.c
==============================================================================
--- head/sys/kern/kern_timeout.c        Fri Sep 20 23:10:52 2013        
(r255746)
+++ head/sys/kern/kern_timeout.c        Fri Sep 20 23:16:15 2013        
(r255747)
@@ -597,11 +597,13 @@ softclock_call_cc(struct callout *c, str
 #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, str
            (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, str
        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.
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to