completion.h revision 271127
161981Sbrian/*- 261981Sbrian * Copyright (c) 2010 Isilon Systems, Inc. 361981Sbrian * Copyright (c) 2010 iX Systems, Inc. 461981Sbrian * Copyright (c) 2010 Panasas, Inc. 561981Sbrian * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd. 661981Sbrian * All rights reserved. 761981Sbrian * 861981Sbrian * Redistribution and use in source and binary forms, with or without 961981Sbrian * modification, are permitted provided that the following conditions 1061981Sbrian * are met: 1161981Sbrian * 1. Redistributions of source code must retain the above copyright 1261981Sbrian * notice unmodified, this list of conditions, and the following 1361981Sbrian * disclaimer. 1461981Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1561981Sbrian * notice, this list of conditions and the following disclaimer in the 1661981Sbrian * documentation and/or other materials provided with the distribution. 1761981Sbrian * 1861981Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1961981Sbrian * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2061981Sbrian * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2161981Sbrian * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2261981Sbrian * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2361981Sbrian * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2461981Sbrian * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2565843Sbrian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2665843Sbrian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2765843Sbrian * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2865843Sbrian */ 2965843Sbrian 3065843Sbrian#ifndef _FBSD_COMPLETION_H_ 3165843Sbrian#define _FBSD_COMPLETION_H_ 3265843Sbrian 3365843Sbrian#include <linux/errno.h> 3465843Sbrian 3561981Sbrian#include <sys/param.h> 3661981Sbrian#include <sys/systm.h> 3761981Sbrian#include <sys/sleepqueue.h> 3861981Sbrian#include <sys/kernel.h> 3961981Sbrian#include <sys/proc.h> 4061981Sbrian 4161981Sbrianstruct completion { 4261981Sbrian unsigned int done; 4361981Sbrian}; 4461981Sbrian 4561981Sbrian#define INIT_COMPLETION(c) ((c).done = 0) 4661981Sbrian#define init_completion(c) ((c)->done = 0) 4761981Sbrian 4861981Sbrianstatic inline void 4961981Sbrian_complete_common(struct completion *c, int all) 5061981Sbrian{ 5161981Sbrian int wakeup_swapper; 5261981Sbrian 5361981Sbrian sleepq_lock(c); 5461981Sbrian c->done++; 5561981Sbrian if (all) 5661981Sbrian wakeup_swapper = sleepq_broadcast(c, SLEEPQ_SLEEP, 0, 0); 5761981Sbrian else 5861981Sbrian wakeup_swapper = sleepq_signal(c, SLEEPQ_SLEEP, 0, 0); 5961981Sbrian sleepq_release(c); 6061981Sbrian if (wakeup_swapper) 6161981Sbrian kick_proc0(); 6261981Sbrian} 6361981Sbrian 6461981Sbrian#define complete(c) _complete_common(c, 0) 6561981Sbrian#define complete_all(c) _complete_common(c, 1) 6661981Sbrian 6761981Sbrian/* 6861981Sbrian * Indefinite wait for done != 0 with or without signals. 6961981Sbrian */ 7061981Sbrianstatic inline long 7161981Sbrian_wait_for_common(struct completion *c, int flags) 7261981Sbrian{ 7361981Sbrian 7474314Sbrian flags |= SLEEPQ_SLEEP; 7561981Sbrian for (;;) { 7661981Sbrian sleepq_lock(c); 7761981Sbrian if (c->done) 7861981Sbrian break; 7961981Sbrian sleepq_add(c, NULL, "completion", flags, 0); 8061981Sbrian if (flags & SLEEPQ_INTERRUPTIBLE) { 8162054Sbrian if (sleepq_wait_sig(c, 0) != 0) 8277496Sbrian return (-ERESTARTSYS); 8377492Sbrian } else 8461981Sbrian sleepq_wait(c, 0); 8561981Sbrian } 8661981Sbrian c->done--; 8761981Sbrian sleepq_release(c); 8861981Sbrian 8961981Sbrian return (0); 9061981Sbrian} 9161981Sbrian 9261981Sbrian#define wait_for_completion(c) _wait_for_common(c, 0) 9362644Ssheldonh#define wait_for_completion_interuptible(c) \ 9461981Sbrian _wait_for_common(c, SLEEPQ_INTERRUPTIBLE) 9561981Sbrian 9661981Sbrianstatic inline long 9761981Sbrian_wait_for_timeout_common(struct completion *c, long timeout, int flags) 9861981Sbrian{ 9961981Sbrian long end; 10061981Sbrian 10161981Sbrian end = ticks + timeout; 10261981Sbrian flags |= SLEEPQ_SLEEP; 10361981Sbrian for (;;) { 10461981Sbrian sleepq_lock(c); 10594342Sgshapiro if (c->done) 10661981Sbrian break; 10761981Sbrian sleepq_add(c, NULL, "completion", flags, 0); 10861981Sbrian sleepq_set_timeout(c, end - ticks); 10987514Scjc if (flags & SLEEPQ_INTERRUPTIBLE) { 11061981Sbrian if (sleepq_timedwait_sig(c, 0) != 0) 11161981Sbrian return (-ERESTARTSYS); 11261981Sbrian } else 11362274Sbrian sleepq_timedwait(c, 0); 11461981Sbrian } 11575809Sdirk c->done--; 11675809Sdirk sleepq_release(c); 11775809Sdirk timeout = end - ticks; 11875809Sdirk 11972677Speter return (timeout > 0 ? timeout : 1); 12072677Speter} 12194342Sgshapiro 12272677Speter#define wait_for_completion_timeout(c, timeout) \ 12361981Sbrian _wait_for_timeout_common(c, timeout, 0) 12461981Sbrian#define wait_for_completion_interruptible_timeout(c, timeout) \ 12561981Sbrian _wait_for_timeout_common(c, timeout, SLEEPQ_INTERRUPTIBLE) 12661981Sbrian 12787514Scjcstatic inline int 12887514Scjctry_wait_for_completion(struct completion *c) 129101607Sfanf{ 13087514Scjc int isdone; 13187514Scjc 13287514Scjc isdone = 1; 13387514Scjc sleepq_lock(c); 13487514Scjc if (c->done) 13587514Scjc c->done--; 13687514Scjc else 13787514Scjc isdone = 0; 13887514Scjc sleepq_release(c); 13987514Scjc return (isdone); 14087514Scjc} 14187514Scjc 14287514Scjcstatic inline int 14387514Scjccompletion_done(struct completion *c) 14487514Scjc{ 14587514Scjc int isdone; 14687514Scjc 14787514Scjc isdone = 1; 14887514Scjc sleepq_lock(c); 14987514Scjc if (c->done == 0) 15087514Scjc isdone = 0; 15187514Scjc sleepq_release(c); 15287514Scjc return (isdone); 15387514Scjc} 15487514Scjc 15587514Scjc#endif /* _LINUX_COMPLETION_H_ */ 15687514Scjc