svn commit: r280764 - head/sys/ofed/include/linux

Hans Petter Selasky hselasky at FreeBSD.org
Fri Mar 27 16:16:25 UTC 2015


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)
 {


More information about the svn-src-head mailing list