static bool rwsem_optimistic_spin(struct rw_semaphore *sem)
 {
        bool taken = false;
+       int prev_owner_state = OWNER_NULL;
 
        preempt_disable();
 
         *  2) readers own the lock as we can't determine if they are
         *     actively running or not.
         */
-       while (rwsem_spin_on_owner(sem) & OWNER_SPINNABLE) {
+       for (;;) {
+               enum owner_state owner_state = rwsem_spin_on_owner(sem);
+
+               if (!(owner_state & OWNER_SPINNABLE))
+                       break;
+
                /*
                 * Try to acquire the lock
                 */
                }
 
                /*
-                * When there's no owner, we might have preempted between the
-                * owner acquiring the lock and setting the owner field. If
-                * we're an RT task that will live-lock because we won't let
-                * the owner complete.
+                * An RT task cannot do optimistic spinning if it cannot
+                * be sure the lock holder is running or live-lock may
+                * happen if the current task and the lock holder happen
+                * to run in the same CPU. However, aborting optimistic
+                * spinning while a NULL owner is detected may miss some
+                * opportunity where spinning can continue without causing
+                * problem.
+                *
+                * There are 2 possible cases where an RT task may be able
+                * to continue spinning.
+                *
+                * 1) The lock owner is in the process of releasing the
+                *    lock, sem->owner is cleared but the lock has not
+                *    been released yet.
+                * 2) The lock was free and owner cleared, but another
+                *    task just comes in and acquire the lock before
+                *    we try to get it. The new owner may be a spinnable
+                *    writer.
+                *
+                * To take advantage of two scenarios listed agove, the RT
+                * task is made to retry one more time to see if it can
+                * acquire the lock or continue spinning on the new owning
+                * writer. Of course, if the time lag is long enough or the
+                * new owner is not a writer or spinnable, the RT task will
+                * quit spinning.
+                *
+                * If the owner is a writer, the need_resched() check is
+                * done inside rwsem_spin_on_owner(). If the owner is not
+                * a writer, need_resched() check needs to be done here.
                 */
-               if (!sem->owner && (need_resched() || rt_task(current)))
-                       break;
+               if (owner_state != OWNER_WRITER) {
+                       if (need_resched())
+                               break;
+                       if (rt_task(current) &&
+                          (prev_owner_state != OWNER_WRITER))
+                               break;
+               }
+               prev_owner_state = owner_state;
 
                /*
                 * The cpu_relax() call is a compiler barrier which forces