Author: hselasky
Date: Fri Mar  9 12:16:55 2018
New Revision: 330689
URL: https://svnweb.freebsd.org/changeset/base/330689

Log:
  Implement proper support for complete_all() in the LinuxKPI.
  
  When complete_all() is called there might be multiple waiters. The
  current implementation could only handle one waiter. Make sure the
  completion is sticky when complete_all() is called to be compatible
  with Linux.
  
  Found by:     Johannes Lundberg <johal...@gmail.com>
  MFC after:    1 week
  Sponsored by: Mellanox Technologies
  Sponsored by: Limelight Networks

Modified:
  head/sys/compat/linuxkpi/common/src/linux_compat.c

Modified: head/sys/compat/linuxkpi/common/src/linux_compat.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_compat.c  Fri Mar  9 11:33:56 
2018        (r330688)
+++ head/sys/compat/linuxkpi/common/src/linux_compat.c  Fri Mar  9 12:16:55 
2018        (r330689)
@@ -1779,11 +1779,14 @@ linux_complete_common(struct completion *c, int all)
        int wakeup_swapper;
 
        sleepq_lock(c);
-       c->done++;
-       if (all)
+       if (all) {
+               c->done = UINT_MAX;
                wakeup_swapper = sleepq_broadcast(c, SLEEPQ_SLEEP, 0, 0);
-       else
+       } else {
+               if (c->done != UINT_MAX)
+                       c->done++;
                wakeup_swapper = sleepq_signal(c, SLEEPQ_SLEEP, 0, 0);
+       }
        sleepq_release(c);
        if (wakeup_swapper)
                kick_proc0();
@@ -1825,7 +1828,8 @@ linux_wait_for_common(struct completion *c, int flags)
                } else
                        sleepq_wait(c, 0);
        }
-       c->done--;
+       if (c->done != UINT_MAX)
+               c->done--;
        sleepq_release(c);
 
 intr:
@@ -1878,7 +1882,8 @@ linux_wait_for_timeout_common(struct completion *c, in
                        goto done;
                }
        }
-       c->done--;
+       if (c->done != UINT_MAX)
+               c->done--;
        sleepq_release(c);
 
        /* return how many jiffies are left */
@@ -1894,12 +1899,10 @@ linux_try_wait_for_completion(struct completion *c)
 {
        int isdone;
 
-       isdone = 1;
        sleepq_lock(c);
-       if (c->done)
+       isdone = (c->done != 0);
+       if (c->done != 0 && c->done != UINT_MAX)
                c->done--;
-       else
-               isdone = 0;
        sleepq_release(c);
        return (isdone);
 }
@@ -1909,10 +1912,8 @@ linux_completion_done(struct completion *c)
 {
        int isdone;
 
-       isdone = 1;
        sleepq_lock(c);
-       if (c->done == 0)
-               isdone = 0;
+       isdone = (c->done != 0);
        sleepq_release(c);
        return (isdone);
 }
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to