Author: hselasky
Date: Tue Mar 13 16:33:41 2018
New Revision: 330865
URL: https://svnweb.freebsd.org/changeset/base/330865

Log:
  MFC r330689:
  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>
  Sponsored by: Mellanox Technologies
  Sponsored by: Limelight Networks

Modified:
  stable/11/sys/compat/linuxkpi/common/src/linux_compat.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/compat/linuxkpi/common/src/linux_compat.c
==============================================================================
--- stable/11/sys/compat/linuxkpi/common/src/linux_compat.c     Tue Mar 13 
16:33:00 2018        (r330864)
+++ stable/11/sys/compat/linuxkpi/common/src/linux_compat.c     Tue Mar 13 
16:33:41 2018        (r330865)
@@ -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-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to