#ifndef _LINUX_COMPLETION_H
#define _LINUX_COMPLETION_H
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mutex.h>
#include <linux/wait.h>
struct completion {
u_int done;
struct mutex lock;
};
#define DECLARE_COMPLETION_ONSTACK(name) \
struct completion name = { 0, MUTEX_INITIALIZER(IPL_TTY) }
static inline void
init_completion(struct completion *x)
{
x->done = 0;
mtx_init(&x->lock, IPL_TTY);
}
static inline void
reinit_completion(struct completion *x)
{
x->done = 0;
}
static inline u_long
wait_for_completion_timeout(struct completion *x, u_long timo)
{
int ret;
KASSERT(!cold);
mtx_enter(&x->lock);
while (x->done == 0) {
ret = msleep(x, &x->lock, 0, "wfct", timo);
if (ret) {
mtx_leave(&x->lock);
return 0;
}
}
if (x->done != UINT_MAX)
x->done--;
mtx_leave(&x->lock);
return 1;
}
static inline void
wait_for_completion(struct completion *x)
{
KASSERT(!cold);
mtx_enter(&x->lock);
while (x->done == 0) {
msleep_nsec(x, &x->lock, 0, "wfcom", INFSLP);
}
if (x->done != UINT_MAX)
x->done--;
mtx_leave(&x->lock);
}
static inline u_long
wait_for_completion_interruptible(struct completion *x)
{
int ret;
KASSERT(!cold);
mtx_enter(&x->lock);
while (x->done == 0) {
ret = msleep_nsec(x, &x->lock, PCATCH, "wfci", INFSLP);
if (ret) {
mtx_leave(&x->lock);
if (ret == EWOULDBLOCK)
return 0;
return -ERESTARTSYS;
}
}
if (x->done != UINT_MAX)
x->done--;
mtx_leave(&x->lock);
return 0;
}
static inline u_long
wait_for_completion_interruptible_timeout(struct completion *x, u_long timo)
{
int ret;
KASSERT(!cold);
mtx_enter(&x->lock);
while (x->done == 0) {
ret = msleep(x, &x->lock, PCATCH, "wfcit", timo);
if (ret) {
mtx_leave(&x->lock);
if (ret == EWOULDBLOCK)
return 0;
return -ERESTARTSYS;
}
}
if (x->done != UINT_MAX)
x->done--;
mtx_leave(&x->lock);
return 1;
}
static inline void
complete(struct completion *x)
{
mtx_enter(&x->lock);
if (x->done != UINT_MAX)
x->done++;
mtx_leave(&x->lock);
wakeup_one(x);
}
static inline void
complete_all(struct completion *x)
{
mtx_enter(&x->lock);
x->done = UINT_MAX;
mtx_leave(&x->lock);
wakeup(x);
}
static inline bool
try_wait_for_completion(struct completion *x)
{
mtx_enter(&x->lock);
if (x->done == 0) {
mtx_leave(&x->lock);
return false;
}
if (x->done != UINT_MAX)
x->done--;
mtx_leave(&x->lock);
return true;
}
#endif