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