Author: hselasky
Date: Fri Mar 27 16:16:23 2015
New Revision: 280764
URL: https://svnweb.freebsd.org/changeset/base/280764

Log:
  Fixes for the LinuxAPI completion wrappers:
  - make sure the timeout computations are always above zero by using
  the existing "linux_timer_jiffies_until()" function. Negative timeouts
  can result in undefined behaviour.
  - declare all completion functions like external symbols and move the
  code to the LinuxAPI kernel module.
  - add a proper prefix to all LinuxAPI kernel functions to avoid
  namespace collision with other parts of the FreeBSD kernel.
  - clean up header file inclusions in the linux/completion.h, linux/in.h
  and linux/fs.h header files.
  
  MFC after:    1 week
  Sponsored by: Mellanox Technologies

Modified:
  head/sys/ofed/include/linux/completion.h
  head/sys/ofed/include/linux/fs.h
  head/sys/ofed/include/linux/in.h
  head/sys/ofed/include/linux/linux_compat.c

Modified: head/sys/ofed/include/linux/completion.h
==============================================================================
--- head/sys/ofed/include/linux/completion.h    Fri Mar 27 15:49:21 2015        
(r280763)
+++ head/sys/ofed/include/linux/completion.h    Fri Mar 27 16:16:23 2015        
(r280764)
@@ -32,124 +32,35 @@
 
 #include <linux/errno.h>
 
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/sleepqueue.h>
-#include <sys/kernel.h>
-#include <sys/proc.h>
-
 struct completion {
        unsigned int done;
 };
 
-#define        INIT_COMPLETION(c)      ((c).done = 0)
-#define        init_completion(c)      ((c)->done = 0)
-
-static inline void
-_complete_common(struct completion *c, int all)
-{
-       int wakeup_swapper;
-
-       sleepq_lock(c);
-       c->done++;
-       if (all)
-               wakeup_swapper = sleepq_broadcast(c, SLEEPQ_SLEEP, 0, 0);
-       else
-               wakeup_swapper = sleepq_signal(c, SLEEPQ_SLEEP, 0, 0);
-       sleepq_release(c);
-       if (wakeup_swapper)
-               kick_proc0();
-}
-
-#define        complete(c)     _complete_common(c, 0)
-#define        complete_all(c) _complete_common(c, 1)
-
-/*
- * Indefinite wait for done != 0 with or without signals.
- */
-static inline long
-_wait_for_common(struct completion *c, int flags)
-{
-
-       flags |= SLEEPQ_SLEEP;
-       for (;;) {
-               sleepq_lock(c);
-               if (c->done)
-                       break;
-               sleepq_add(c, NULL, "completion", flags, 0);
-               if (flags & SLEEPQ_INTERRUPTIBLE) {
-                       if (sleepq_wait_sig(c, 0) != 0)
-                               return (-ERESTARTSYS);
-               } else
-                       sleepq_wait(c, 0);
-       }
-       c->done--;
-       sleepq_release(c);
-
-       return (0);
-}
-
-#define        wait_for_completion(c)  _wait_for_common(c, 0)
-#define        wait_for_completion_interuptible(c)                             
\
-       _wait_for_common(c, SLEEPQ_INTERRUPTIBLE)
-
-static inline long
-_wait_for_timeout_common(struct completion *c, long timeout, int flags)
-{
-       long end;
-
-       end = ticks + timeout;
-       flags |= SLEEPQ_SLEEP;
-       for (;;) {
-               sleepq_lock(c);
-               if (c->done)
-                       break;
-               sleepq_add(c, NULL, "completion", flags, 0);
-               sleepq_set_timeout(c, end - ticks);
-               if (flags & SLEEPQ_INTERRUPTIBLE) {
-                       if (sleepq_timedwait_sig(c, 0) != 0)
-                               return (-ERESTARTSYS);
-               } else
-                       sleepq_timedwait(c, 0);
-       }
-       c->done--;
-       sleepq_release(c);
-       timeout = end - ticks;
-
-       return (timeout > 0 ? timeout : 1);
-}
-
-#define        wait_for_completion_timeout(c, timeout)                         
\
-       _wait_for_timeout_common(c, timeout, 0)
-#define        wait_for_completion_interruptible_timeout(c, timeout)           
\
-       _wait_for_timeout_common(c, timeout, SLEEPQ_INTERRUPTIBLE)
-
-static inline int
-try_wait_for_completion(struct completion *c)
-{
-       int isdone;
-
-       isdone = 1;
-       sleepq_lock(c);
-       if (c->done)
-               c->done--;
-       else
-               isdone = 0;
-       sleepq_release(c);
-       return (isdone);
-}
-
-static inline int
-completion_done(struct completion *c)
-{
-       int isdone;
-
-       isdone = 1;
-       sleepq_lock(c);
-       if (c->done == 0)
-               isdone = 0;
-       sleepq_release(c);
-       return (isdone);
-}
+#define        INIT_COMPLETION(c) \
+       ((c).done = 0)
+#define        init_completion(c) \
+       ((c)->done = 0)
+#define        complete(c)                             \
+       linux_complete_common((c), 0)
+#define        complete_all(c)                         \
+       linux_complete_common((c), 1)
+#define        wait_for_completion(c)                  \
+       linux_wait_for_common((c), 0)
+#define        wait_for_completion_interuptible(c)     \
+       linux_wait_for_common((c), 1)
+#define        wait_for_completion_timeout(c, timeout) \
+       linux_wait_for_timeout_common((c), (timeout), 0)
+#define        wait_for_completion_interruptible_timeout(c, timeout)   \
+       linux_wait_for_timeout_common((c), (timeout), 1)
+#define        try_wait_for_completion(c) \
+       linux_try_wait_for_completion(c)
+#define        completion_done(c) \
+       linux_completion_done(c)
+
+extern void linux_complete_common(struct completion *, int);
+extern long linux_wait_for_common(struct completion *, int);
+extern long linux_wait_for_timeout_common(struct completion *, long, int);
+extern int linux_try_wait_for_completion(struct completion *);
+extern int linux_completion_done(struct completion *);
 
-#endif /* _LINUX_COMPLETION_H_ */
+#endif                                 /* _LINUX_COMPLETION_H_ */

Modified: head/sys/ofed/include/linux/fs.h
==============================================================================
--- head/sys/ofed/include/linux/fs.h    Fri Mar 27 15:49:21 2015        
(r280763)
+++ head/sys/ofed/include/linux/fs.h    Fri Mar 27 16:16:23 2015        
(r280764)
@@ -29,6 +29,8 @@
 #ifndef        _LINUX_FS_H_
 #define        _LINUX_FS_H_
 
+#include <sys/cdefs.h>
+#include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/conf.h>
 #include <sys/vnode.h>

Modified: head/sys/ofed/include/linux/in.h
==============================================================================
--- head/sys/ofed/include/linux/in.h    Fri Mar 27 15:49:21 2015        
(r280763)
+++ head/sys/ofed/include/linux/in.h    Fri Mar 27 16:16:23 2015        
(r280764)
@@ -31,6 +31,9 @@
 
 #include "opt_inet.h"
 
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
 #include <netinet/in.h>
 #include <asm/byteorder.h>
 

Modified: head/sys/ofed/include/linux/linux_compat.c
==============================================================================
--- head/sys/ofed/include/linux/linux_compat.c  Fri Mar 27 15:49:21 2015        
(r280763)
+++ head/sys/ofed/include/linux/linux_compat.c  Fri Mar 27 16:16:23 2015        
(r280764)
@@ -32,6 +32,8 @@
 #include <sys/malloc.h>
 #include <sys/kernel.h>
 #include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/sleepqueue.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
 #include <sys/bus.h>
@@ -781,6 +783,117 @@ linux_timer_init(void *arg)
 }
 SYSINIT(linux_timer, SI_SUB_DRIVERS, SI_ORDER_FIRST, linux_timer_init, NULL);
 
+void
+linux_complete_common(struct completion *c, int all)
+{
+       int wakeup_swapper;
+
+       sleepq_lock(c);
+       c->done++;
+       if (all)
+               wakeup_swapper = sleepq_broadcast(c, SLEEPQ_SLEEP, 0, 0);
+       else
+               wakeup_swapper = sleepq_signal(c, SLEEPQ_SLEEP, 0, 0);
+       sleepq_release(c);
+       if (wakeup_swapper)
+               kick_proc0();
+}
+
+/*
+ * Indefinite wait for done != 0 with or without signals.
+ */
+long
+linux_wait_for_common(struct completion *c, int flags)
+{
+
+       if (flags != 0)
+               flags = SLEEPQ_INTERRUPTIBLE | SLEEPQ_SLEEP;
+       else
+               flags = SLEEPQ_SLEEP;
+       for (;;) {
+               sleepq_lock(c);
+               if (c->done)
+                       break;
+               sleepq_add(c, NULL, "completion", flags, 0);
+               if (flags & SLEEPQ_INTERRUPTIBLE) {
+                       if (sleepq_wait_sig(c, 0) != 0)
+                               return (-ERESTARTSYS);
+               } else
+                       sleepq_wait(c, 0);
+       }
+       c->done--;
+       sleepq_release(c);
+
+       return (0);
+}
+
+/*
+ * Time limited wait for done != 0 with or without signals.
+ */
+long
+linux_wait_for_timeout_common(struct completion *c, long timeout, int flags)
+{
+       long end = jiffies + timeout;
+
+       if (flags != 0)
+               flags = SLEEPQ_INTERRUPTIBLE | SLEEPQ_SLEEP;
+       else
+               flags = SLEEPQ_SLEEP;
+       for (;;) {
+               int ret;
+
+               sleepq_lock(c);
+               if (c->done)
+                       break;
+               sleepq_add(c, NULL, "completion", flags, 0);
+               sleepq_set_timeout(c, linux_timer_jiffies_until(end));
+               if (flags & SLEEPQ_INTERRUPTIBLE)
+                       ret = sleepq_timedwait_sig(c, 0);
+               else
+                       ret = sleepq_timedwait(c, 0);
+               if (ret != 0) {
+                       /* check for timeout or signal */
+                       if (ret == EWOULDBLOCK)
+                               return (0);
+                       else
+                               return (-ERESTARTSYS);
+               }
+       }
+       c->done--;
+       sleepq_release(c);
+
+       /* return how many jiffies are left */
+       return (linux_timer_jiffies_until(end));
+}
+
+int
+linux_try_wait_for_completion(struct completion *c)
+{
+       int isdone;
+
+       isdone = 1;
+       sleepq_lock(c);
+       if (c->done)
+               c->done--;
+       else
+               isdone = 0;
+       sleepq_release(c);
+       return (isdone);
+}
+
+int
+linux_completion_done(struct completion *c)
+{
+       int isdone;
+
+       isdone = 1;
+       sleepq_lock(c);
+       if (c->done == 0)
+               isdone = 0;
+       sleepq_release(c);
+       return (isdone);
+}
+
 static void
 linux_compat_init(void *arg)
 {
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to