From: "Michael S. Tsirkin" <mst@redhat.com>
To: davidel@xmailserver.org, avi@redhat.com, gleb@redhat.com,
kvm@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 2/2] eventfd: EFD_STATE flag
Date: Thu, 20 Aug 2009 18:57:09 +0300 [thread overview]
Message-ID: <20090820155708.GC8764@redhat.com> (raw)
In-Reply-To: <cover.1250783333.git.mst@redhat.com>
This implements a new EFD_STATE flag for eventfd.
This changes eventfd behaviour in the following way:
- write simply stores the value written, and is always non-blocking
- read unblocks when the value written changes, and
returns the value written
Motivation: we'd like to use eventfd in qemu to pass interrupts from
(emulated or assigned) devices to guest. For level interrupts, the
counter supported currently by eventfd is not a good match: we really
need to set interrupt to a level, typically 0 or 1, and give the guest
ability to see the last value written.
Acked-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
fs/eventfd.c | 41 ++++++++++++++++++++++++++++++++++-------
include/linux/eventfd.h | 3 ++-
2 files changed, 36 insertions(+), 8 deletions(-)
diff --git a/fs/eventfd.c b/fs/eventfd.c
index 347a0e0..7b279e3 100644
--- a/fs/eventfd.c
+++ b/fs/eventfd.c
@@ -31,37 +31,59 @@ struct eventfd_ctx {
* issue a wakeup.
*/
__u64 count;
+ /*
+ * When EF_STATE flag is set, eventfd behaves differently:
+ * value written gets stored in "count", read will copy
+ * "count" to "state".
+ */
+ __u64 state;
unsigned int flags;
};
static inline int eventfd_readable(struct eventfd_ctx *ctx)
{
- return ctx->count > 0;
+ if (ctx->flags & EFD_STATE)
+ return ctx->state != ctx->count;
+ else
+ return ctx->count > 0;
}
static inline int eventfd_writeable(struct eventfd_ctx *ctx, u64 n)
{
- return ULLONG_MAX - n > ctx->count;
+ if (ctx->flags & EFD_STATE)
+ return 1;
+ else
+ return ULLONG_MAX - n > ctx->count;
}
static inline int eventfd_overflow(struct eventfd_ctx *ctx, u64 cnt)
{
- return cnt == ULLONG_MAX;
+ if (ctx->flags & EFD_STATE)
+ return 0;
+ else
+ return cnt == ULLONG_MAX;
}
static inline void eventfd_dowrite(struct eventfd_ctx *ctx, u64 ucnt)
{
- if (eventfd_writeable(ctx, ucnt))
- ucnt = ULLONG_MAX - ctx->count;
+ if (ctx->flags & EFD_STATE)
+ ctx->count = ucnt;
+ else {
+ if (ULLONG_MAX - ctx->count < ucnt)
+ ucnt = ULLONG_MAX - ctx->count;
- ctx->count += ucnt;
+ ctx->count += ucnt;
+ }
}
static inline u64 eventfd_doread(struct eventfd_ctx *ctx)
{
u64 ucnt = (ctx->flags & EFD_SEMAPHORE) ? 1 : ctx->count;
- ctx->count -= ucnt;
+ if (ctx->flags & EFD_STATE)
+ ctx->state = ucnt;
+ else
+ ctx->count -= ucnt;
return ucnt;
}
@@ -337,6 +359,10 @@ SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags)
if (flags & ~EFD_FLAGS_SET)
return -EINVAL;
+ /* State together with semaphore does not make sense. */
+ if ((flags & EFD_STATE) && (flags & EFD_SEMAPHORE))
+ return -EINVAL;
+
ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
@@ -344,6 +370,7 @@ SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags)
kref_init(&ctx->kref);
init_waitqueue_head(&ctx->wqh);
+ ctx->state = count;
ctx->count = count;
ctx->flags = flags;
diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h
index 3b85ba6..78ff649 100644
--- a/include/linux/eventfd.h
+++ b/include/linux/eventfd.h
@@ -19,11 +19,12 @@
* shared O_* flags.
*/
#define EFD_SEMAPHORE (1 << 0)
+#define EFD_STATE (1 << 1)
#define EFD_CLOEXEC O_CLOEXEC
#define EFD_NONBLOCK O_NONBLOCK
#define EFD_SHARED_FCNTL_FLAGS (O_CLOEXEC | O_NONBLOCK)
-#define EFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS | EFD_SEMAPHORE)
+#define EFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS | EFD_SEMAPHORE | EFD_STATE)
#ifdef CONFIG_EVENTFD
--
1.6.2.5
prev parent reply other threads:[~2009-08-20 15:58 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <cover.1250783333.git.mst@redhat.com>
2009-08-20 15:57 ` [PATCH 1/2] eventfd: reorganize the code to simplify new flags Michael S. Tsirkin
2009-08-27 11:48 ` Paolo Bonzini
2009-08-27 11:58 ` Michael S. Tsirkin
2009-08-27 12:02 ` Michael S. Tsirkin
2009-08-20 15:57 ` Michael S. Tsirkin [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090820155708.GC8764@redhat.com \
--to=mst@redhat.com \
--cc=avi@redhat.com \
--cc=davidel@xmailserver.org \
--cc=gleb@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).