[PATCH V2 4/5] libxfs: add kernel-compatible completion API
From: Chandan Babu R <hidden>
Date: 2021-09-24 14:10:33
Subsystem:
the rest · Maintainer:
Linus Torvalds
From: Dave Chinner <redacted> This is needed for the kernel buffer cache conversion to be able to wait on IO synchrnously. It is implemented with pthread mutexes and conditional variables. Signed-off-by: Dave Chinner <redacted> --- include/Makefile | 1 + include/completion.h | 61 ++++++++++++++++++++++++++++++++++++++++++++ include/libxfs.h | 1 + libxfs/libxfs_priv.h | 1 + 4 files changed, 64 insertions(+) create mode 100644 include/completion.h
diff --git a/include/Makefile b/include/Makefile
index f7c40a5c..98031e70 100644
--- a/include/Makefile
+++ b/include/Makefile@@ -12,6 +12,7 @@ LIBHFILES = libxfs.h \ atomic.h \ bitops.h \ cache.h \ + completion.h \ hlist.h \ kmem.h \ list.h \
diff --git a/include/completion.h b/include/completion.h
new file mode 100644
index 00000000..92194c3f
--- /dev/null
+++ b/include/completion.h@@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 RedHat, Inc. + * All Rights Reserved. + */ +#ifndef __LIBXFS_COMPLETION_H__ +#define __LIBXFS_COMPLETION_H__ + +/* + * This implements kernel compatible completion semantics. This is slightly + * different to the way pthread conditional variables work in that completions + * can be signalled before the waiter tries to wait on the variable. In the + * pthread case, the completion is ignored and the waiter goes to sleep, whilst + * the kernel will see that the completion has already been completed and so + * will not block. This is handled through the addition of the the @signalled + * flag in the struct completion. + */ +struct completion { + pthread_mutex_t lock; + pthread_cond_t cond; + bool signalled; /* for kernel completion behaviour */ + int waiters; +}; + +static inline void +init_completion(struct completion *w) +{ + pthread_mutex_init(&w->lock, NULL); + pthread_cond_init(&w->cond, NULL); + w->signalled = false; +} + +static inline void +complete(struct completion *w) +{ + pthread_mutex_lock(&w->lock); + w->signalled = true; + pthread_cond_broadcast(&w->cond); + pthread_mutex_unlock(&w->lock); +} + +/* + * Support for mulitple waiters requires that we count the number of waiters + * we have and only clear the signalled variable once all those waiters have + * been woken. + */ +static inline void +wait_for_completion(struct completion *w) +{ + pthread_mutex_lock(&w->lock); + if (!w->signalled) { + w->waiters++; + pthread_cond_wait(&w->cond, &w->lock); + w->waiters--; + } + if (!w->waiters) + w->signalled = false; + pthread_mutex_unlock(&w->lock); +} + +#endif /* __LIBXFS_COMPLETION_H__ */
diff --git a/include/libxfs.h b/include/libxfs.h
index a494a1d4..61475347 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h@@ -19,6 +19,7 @@ #include "libfrog/radix-tree.h" #include "atomic.h" #include "spinlock.h" +#include "completion.h" #include "xfs_types.h" #include "xfs_fs.h"
diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h
index e1e90268..9f28fd90 100644
--- a/libxfs/libxfs_priv.h
+++ b/libxfs/libxfs_priv.h@@ -49,6 +49,7 @@ #include "libfrog/radix-tree.h" #include "atomic.h" #include "spinlock.h" +#include "completion.h" #include "xfs_types.h" #include "xfs_arch.h"
--
2.30.2