Date: Fri, 27 Mar 2015 16:16:24 +0000 (UTC) From: Hans Petter Selasky <hselasky@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r280764 - head/sys/ofed/include/linux Message-ID: <201503271616.t2RGGOKJ039030@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201503271616.t2RGGOKJ039030>