All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alberto Faria <afaria@redhat.com>
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	qemu-block@nongnu.org, "Denis V. Lunev" <den@openvz.org>,
	Emanuele Giuseppe Esposito <eesposit@redhat.com>,
	Stefan Hajnoczi <stefanha@redhat.com>,
	Ronnie Sahlberg <ronniesahlberg@gmail.com>,
	Hanna Reitz <hreitz@redhat.com>,
	Stefano Garzarella <sgarzare@redhat.com>,
	Kevin Wolf <kwolf@redhat.com>, Peter Xu <peterx@redhat.com>,
	Alberto Garcia <berto@igalia.com>, John Snow <jsnow@redhat.com>,
	Eric Blake <eblake@redhat.com>, Fam Zheng <fam@euphon.net>,
	Markus Armbruster <armbru@redhat.com>,
	Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>,
	Peter Lieven <pl@kamp.de>, Alberto Faria <afaria@redhat.com>
Subject: [RFC 7/8] block: Add no_coroutine_fn marker
Date: Sat,  2 Jul 2022 12:33:30 +0100	[thread overview]
Message-ID: <20220702113331.2003820-8-afaria@redhat.com> (raw)
In-Reply-To: <20220702113331.2003820-1-afaria@redhat.com>

When applied to a function, it advertises that it should not be called
from coroutine_fn functions.

Make generated_co_wrapper evaluate to no_coroutine_fn, as coroutine_fn
functions should instead directly call the coroutine_fn that backs the
generated_co_wrapper.

Extend static-analyzer.py's "coroutine-annotation-validity" and
"coroutine-calls" checks to enforce no_coroutine_fn rules.

Signed-off-by: Alberto Faria <afaria@redhat.com>
---
 include/block/block-common.h |  2 +-
 include/qemu/coroutine.h     | 12 ++++++++++++
 static-analyzer.py           | 35 +++++++++++++++++++++++++++++++++++
 3 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/include/block/block-common.h b/include/block/block-common.h
index fdb7306e78..4b60c8c6f2 100644
--- a/include/block/block-common.h
+++ b/include/block/block-common.h
@@ -42,7 +42,7 @@
  *
  * Read more in docs/devel/block-coroutine-wrapper.rst
  */
-#define generated_co_wrapper
+#define generated_co_wrapper no_coroutine_fn
 
 /* block.c */
 typedef struct BlockDriver BlockDriver;
diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h
index 40a4037525..11eea8cc79 100644
--- a/include/qemu/coroutine.h
+++ b/include/qemu/coroutine.h
@@ -48,6 +48,18 @@
 #define coroutine_fn
 #endif
 
+/**
+ * Mark a function that should never be called from a coroutine context
+ *
+ * This typically means that there is an analogous, coroutine_fn function that
+ * should be used instead.
+ */
+#ifdef __clang__
+#define no_coroutine_fn __attribute__((__annotate__("no_coroutine_fn")))
+#else
+#define no_coroutine_fn
+#endif
+
 /**
  * This can wrap a call to a coroutine_fn from a non-coroutine_fn function and
  * suppress the static analyzer's complaints.
diff --git a/static-analyzer.py b/static-analyzer.py
index 485d054052..ad7ee1ccf5 100755
--- a/static-analyzer.py
+++ b/static-analyzer.py
@@ -459,6 +459,12 @@ def check_coroutine_annotation_validity(
         ):
             log(node, "invalid coroutine_fn usage")
 
+        if is_annotation(node, "no_coroutine_fn") and (
+            ancestors[-1] is None
+            or not is_valid_no_coroutine_fn_usage(ancestors[-1])
+        ):
+            log(node, "invalid no_coroutine_fn usage")
+
         if is_comma_wrapper(
             node, "__allow_coroutine_fn_call"
         ) and not is_valid_allow_coroutine_fn_call_usage(node):
@@ -478,6 +484,9 @@ def log_annotation_disagreement(annotation: str) -> None:
             if is_coroutine_fn(node) != is_coroutine_fn(node.canonical):
                 log_annotation_disagreement("coroutine_fn")
 
+            if is_no_coroutine_fn(node) != is_no_coroutine_fn(node.canonical):
+                log_annotation_disagreement("no_coroutine_fn")
+
 
 @check("coroutine-calls")
 def check_coroutine_calls(
@@ -516,6 +525,11 @@ def check_coroutine_calls(
             ):
                 log(call, "non-coroutine_fn function calls coroutine_fn")
 
+            # reject calls from coroutine_fn to no_coroutine_fn
+
+            if caller_is_coroutine and is_no_coroutine_fn(callee):
+                log(call, f"coroutine_fn calls no_coroutine_fn function")
+
 
 @check("coroutine-pointers")
 def check_coroutine_pointers(
@@ -704,6 +718,16 @@ def parent_type_is_function_pointer() -> bool:
     return False
 
 
+def is_valid_no_coroutine_fn_usage(parent: Cursor) -> bool:
+    """
+    Checks if an occurrence of `no_coroutine_fn` represented by a node with
+    parent `parent` appears at a valid point in the AST. This is the case if the
+    parent is a function declaration/definition.
+    """
+
+    return parent.kind == CursorKind.FUNCTION_DECL
+
+
 def is_valid_allow_coroutine_fn_call_usage(node: Cursor) -> bool:
     """
     Check if an occurrence of `__allow_coroutine_fn_call()` represented by node
@@ -771,6 +795,17 @@ def is_coroutine_fn(node: Cursor) -> bool:
     return False
 
 
+def is_no_coroutine_fn(node: Cursor) -> bool:
+    """
+    Checks whether the given `node` should be considered to be
+    `no_coroutine_fn`.
+
+    This assumes valid usage of `no_coroutine_fn`.
+    """
+
+    return is_annotated_with(node, "no_coroutine_fn")
+
+
 def is_annotated_with(node: Cursor, annotation: str) -> bool:
     return any(is_annotation(c, annotation) for c in node.get_children())
 
-- 
2.36.1



  parent reply	other threads:[~2022-07-02 11:47 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-02 11:33 [RFC 0/8] Introduce an extensible static analyzer Alberto Faria
2022-07-02 11:33 ` [RFC 1/8] Add " Alberto Faria
2022-07-02 11:33 ` [RFC 2/8] Drop some unused static function return values Alberto Faria
2022-07-02 11:33 ` [RFC 3/8] static-analyzer: Enforce coroutine_fn restrictions for direct calls Alberto Faria
2022-07-02 11:33 ` [RFC 4/8] Fix some direct calls from non-coroutine_fn to coroutine_fn Alberto Faria
2022-07-02 14:13   ` Paolo Bonzini
2022-07-03 22:20     ` Alberto Faria
2022-07-02 11:33 ` [RFC 5/8] static-analyzer: Enforce coroutine_fn restrictions on function pointers Alberto Faria
2022-07-04 14:16   ` Víctor Colombo
2022-07-04 16:57     ` Alberto Faria
2022-07-04 17:46       ` Víctor Colombo
2022-07-04 18:04         ` Alberto Faria
2022-07-04 19:06           ` Víctor Colombo
2022-07-02 11:33 ` [RFC 6/8] Fix some coroutine_fn indirect calls and pointer assignments Alberto Faria
2022-07-02 11:33 ` Alberto Faria [this message]
2022-07-02 11:33 ` [RFC 8/8] Avoid calls from coroutine_fn to no_coroutine_fn Alberto Faria
2022-07-02 14:17 ` [RFC 0/8] Introduce an extensible static analyzer Paolo Bonzini
2022-07-04 16:28 ` Daniel P. Berrangé
2022-07-04 19:30   ` Alberto Faria
2022-07-05  7:16     ` Daniel P. Berrangé
2022-07-05 11:28       ` Alberto Faria
2022-07-05 16:12         ` Daniel P. Berrangé
2022-07-06  9:54           ` Alberto Faria
2022-07-06 10:15             ` Daniel P. Berrangé
2022-07-08 17:18               ` Alberto Faria
2022-07-05 16:13 ` Daniel P. Berrangé
2022-07-06  9:56   ` Alberto Faria

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=20220702113331.2003820-8-afaria@redhat.com \
    --to=afaria@redhat.com \
    --cc=armbru@redhat.com \
    --cc=berto@igalia.com \
    --cc=den@openvz.org \
    --cc=eblake@redhat.com \
    --cc=eesposit@redhat.com \
    --cc=fam@euphon.net \
    --cc=hreitz@redhat.com \
    --cc=jsnow@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peterx@redhat.com \
    --cc=pl@kamp.de \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=ronniesahlberg@gmail.com \
    --cc=sgarzare@redhat.com \
    --cc=stefanha@redhat.com \
    --cc=vsementsov@yandex-team.ru \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.