From nobody Mon Feb 9 14:37:07 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=mit.edu ARC-Seal: i=1; a=rsa-sha256; t=1662067170; cv=none; d=zohomail.com; s=zohoarc; b=TVQJ0Zs5lqm1uw2SR08PmneuZdOJY9Drlg8RL9eWB/Tn2TXREkwEhhOVydGWCOXEwJJPMrGeBxWjMwnNYRbyZQVaARYwG049B+nnXFXcBnNoxASRgsf51KuwB42/VViy0Wk9/BQMNYWTuw9mcjrK6SrbGn86wdLCnjcF6TaCilc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1662067170; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=YEk48QzMX/JqwU4rcwOXSUQf0A3XbfORMVl4Dm6zpIs=; b=d9MIduDulXY1Azad7Mp4il/jEn5eLV/CCvw295M8JUttqWE8f4+Rw5UJZBWH+H6qXwR3go3C7Q4bXxjBmKComg4aXoMS9B6NeA5cQOrTUgm1bVDXjxKLQpJ40a42K0Oz/mSBfC1rq6LQOV0vHHdIcUDmOTrjtRyoLG7UMKF/L60= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1662067170486615.0054685109212; Thu, 1 Sep 2022 14:19:30 -0700 (PDT) Received: from localhost ([::1]:51982 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oTraz-0000Lz-13 for importer@patchew.org; Thu, 01 Sep 2022 17:19:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35184) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oTp0g-0000Sx-Dp for qemu-devel@nongnu.org; Thu, 01 Sep 2022 14:33:50 -0400 Received: from outgoing-auth-1.mit.edu ([18.9.28.11]:49492 helo=outgoing.mit.edu) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oTp0d-0001xq-En for qemu-devel@nongnu.org; Thu, 01 Sep 2022 14:33:50 -0400 Received: from panda194.. ([18.4.85.108]) (authenticated bits=0) (User authenticated as fasano@ATHENA.MIT.EDU) by outgoing.mit.edu (8.14.7/8.12.4) with ESMTP id 281IRv2f010380 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 1 Sep 2022 14:28:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mit.edu; s=outgoing; t=1662056895; bh=YEk48QzMX/JqwU4rcwOXSUQf0A3XbfORMVl4Dm6zpIs=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=pH274Fdf7BzbafYzytRRKWniiXvXiduNPcfq7k+JXVXNZPe/mb2Vnb7f02JNdmrB+ 9ByGs79Fm0NPSyQu6us1aiNst0qfrxd9xmpMPpUq4NfjMQFfheEAFyw8p60QJ14+WM qGebMGy07xqbvbC22QiuAgDTT93VBxY816rWYeijFh7faG3d+rpVDgw8OTfsCaYl7p 3TpGr5K38Uk0/QL/gCCDst63WpL/Uk4IwzhlAMr0psLfVBxA/huZ5V9kw+YiLHlJk3 Dih7FhRueEy7RUUxoAivxyKheIU6CDRmg8+YW8EsZ7YJLPdibphCwa8LQSrPoK3Ckg 5Zys5QllWylYA== From: Andrew Fasano To: qemu-devel@nongnu.org Cc: alex.bennee@linaro.org, erdnaxe@crans.org, ma.mandourr@gmail.com, Andrew Fasano Subject: [RFC 1/4] docs/tcg-plugins: describe QPP API Date: Thu, 1 Sep 2022 14:27:31 -0400 Message-Id: <20220901182734.2987337-2-fasano@mit.edu> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220901182734.2987337-1-fasano@mit.edu> References: <20220901182734.2987337-1-fasano@mit.edu> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=18.9.28.11; envelope-from=fasano@mit.edu; helo=outgoing.mit.edu X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Thu, 01 Sep 2022 17:11:41 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @mit.edu) X-ZM-MESSAGEID: 1662067171295100001 Content-Type: text/plain; charset="utf-8" Describe how multiple TCG plugins can interact using the QEMU Plugin-to-Plugin API (QPP) with both callbacks and direct function calls. Signed-off-by: Andrew Fasano --- docs/devel/tcg-plugins.rst | 76 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst index a7cc44aa20..7985572027 100644 --- a/docs/devel/tcg-plugins.rst +++ b/docs/devel/tcg-plugins.rst @@ -441,3 +441,79 @@ The plugin has a number of arguments, all of them are = optional: associativity of the L2 cache, respectively. Setting any of the L2 configuration arguments implies ``l2=3Don``. (default: N =3D 2097152 (2MB), B =3D 64, A =3D 16) + +Plugin-to-Plugin Interactions +----------------------------- + +Plugins may interact with other plugins through the QEMU Plugin-to-Plugin +("QPP") API by including ``qemu/plugin-qpp.h``. This API supports direct +function calls between plugins as well as an inter-plugin callback system. +This API allows for composition of plugins: plugins can make use of logic = in +other plugins without the need for code duplication. + +Plugin names +~~~~~~~~~~~~ +Plugins are automatically given a name by removing the suffix from their +filename. These plugin names will be used during QPP interactions as +described below. A plugin can access its own name through the preprocessor +variable ``CURRENT_PLUGIN``. + +QPP function calls +~~~~~~~~~~~~~~~~~~ +When a plugin (e.g. ``plugin_a``) wishes to make some of its functions (e.= g. +``func_1``) available to other plugins, it must: + +1. Mark the function definition with the ``QEMU_PLUGIN_EXPORT`` macro. For +example : ``QEMU_PLUGIN_EXPORT int func_1(int x) {...}``. +2. Provide prototypes for exported functions in a header file (e.g. +``plugin_a.h``) using the macro ``QPP_FUN_PROTOTYPE`` with arguments of the +plugin's name, the function's return type, the function's name, and any +arguments the function takes. For example: +``QPP_FUN_PROTOTYPE(plugin_a, int, func_1, int);``. +3. Import this header from the plugin. + +When other plugins wish to use the functions exported by ``plugin_a``, they +must: + +1. Import the header file (e.g. ``plugin_a.h``) with the function prototyp= e(s). +2. Call the function when desired by combining the target plugin name, an + underscore, and the target function name, e.g. ``plugin_a_func_1()``. + +QPP callbacks +~~~~~~~~~~~~~ + +The QPP API also allows a plugin to define callback events and for other p= lugins +to request to be notified whenever these events happens. The plugin that d= efines +the callback is responsible for triggering the callback when it so wishes.= Other +plugins that wish to be notified on these events must define a function of= an +appropriate type and register it to run on this event. + +When a plugin (e.g. ``plugin_a``) wishes to define a callback (an event th= at +other plugins can request to be notified about), it must: + +1. Define the callback using the ``QPP_CREATE_CB`` macro with a single arg= ument + of the callback's name. For example: ``QPP_CREATE_CB(on_some_event);``. +2. In a header file (e.g. ``plugin_a.h``) create a prototype for the callb= ack + type with ``QPP_CB_PROTOTYPE`` with arguments of the callback's return = type + (only ``void`` is currently supported), the name of the callback, and a= ny + arguments the callback function will be called with. For example with a + callback named ``on_some_event`` that returns a void and takes an int a= nd + a bool as an argument, you would use: ``QPP_CB_PROTOTYPE(void, + on_some_event, int, bool)``. +3. Import this header from the plugin. +4. When the plugin wishes to run any registered callback functions, it sho= uld + use the macro ``QPP_RUN_CB`` with the first argument set to the callback + name followed by the arguments as specified in the header. For example: + ``QPP_RUN_CB(on_some_event, 2, true);``. + +When other plugins wish to register a function to run on such an event, th= ey +must: + +1. Import the header file with the callback prototype(s) (e.g. ``plugin_a.= h``) +2. Define a function that matches the callback signature. For example: + ``void plugin_b_callback(int, bool) {...}``. +3. Register this function to be run on the callback using the ``QPP_REG_CB= `` + macro with the first argument being the name of the plugin that provide= s the + callback (as a string), the second being the callback name, and the thi= rd as + the function that should be run. For example: ``QPP_REG_CB("plugin_a", + on_some_event, plugin_b_callback);`` --=20 2.34.1 From nobody Mon Feb 9 14:37:07 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=mit.edu ARC-Seal: i=1; a=rsa-sha256; t=1662066902; cv=none; d=zohomail.com; s=zohoarc; b=f/aaGU0j5EqkLAz4NZUOVLhMAq7z8SN3ouQBt755fvAhjYqg7k0rFzBlqXhQS7SPp9n/lpqNongIZQqJ6rdK200Yzz5Fe8hdiRT0TCZZhADsN+WvM4eYIhykpB2zL6XgkrPcWvnC44dRdCBwhGrvYVFjvzsYQs//Vy+qK6Rm578= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1662066902; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=8t7inFGquta1NGByhzLG9+mJKal1v4Fh4FJB1iWeSEQ=; b=ajJBecqY6QoYwffksZXVtSoJmOubXA1ZElN9TNESo2XKf9UI4P2B45gZtcttJBVO3uz2hDzgwo4ghmJCHP0uWCBwX7mPTn3fKnVVufGjWFLc1ekzkSls9Qv7ygk/Ll6VwqPaOl+4/1oBp+GQpt1jRB3z6mHtVeLrC/884lJh1nw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1662066902507883.17464026337; Thu, 1 Sep 2022 14:15:02 -0700 (PDT) Received: from localhost ([::1]:40492 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oTrWf-0004L0-48 for importer@patchew.org; Thu, 01 Sep 2022 17:15:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50134) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oTp0W-0000Lb-5g for qemu-devel@nongnu.org; Thu, 01 Sep 2022 14:33:41 -0400 Received: from outgoing-auth-1.mit.edu ([18.9.28.11]:49439 helo=outgoing.mit.edu) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oTp0U-0001vp-6y for qemu-devel@nongnu.org; Thu, 01 Sep 2022 14:33:39 -0400 Received: from panda194.. ([18.4.85.108]) (authenticated bits=0) (User authenticated as fasano@ATHENA.MIT.EDU) by outgoing.mit.edu (8.14.7/8.12.4) with ESMTP id 281IRv2g010380 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 1 Sep 2022 14:28:21 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mit.edu; s=outgoing; t=1662056902; bh=8t7inFGquta1NGByhzLG9+mJKal1v4Fh4FJB1iWeSEQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=TSFHPo6Yii1RI/4YJzCXOiD+5LlwUkkTTFFI5n3DsBRZrjflJtTQiDwjqIgjzI32X ZryEVDtepvqj66moU/3WmxX4TBMn8x0YIz+J2odsrOg+5LBgzUQ0wPY36Q9O4DyxKO /g+yJV65ZvdxnQG8q2wuFy3ZEngmGwJwaZDd1Wf9CTCClJPvwe25e2QLK193B69ptZ C9sFXW/uI+cetqg5ssO+YUX1Msmv78p8A2esm45npySguDUu7Qupkf/xUqmqC3qe05 OLN/ZQ2dQPtSpDzSwFGlVdFn7fCpja5QzDdBshgbyBlIhhSi2NR+Ez6SQYiFNzM8hA C7ehC//iWcyBg== From: Andrew Fasano To: qemu-devel@nongnu.org Cc: alex.bennee@linaro.org, erdnaxe@crans.org, ma.mandourr@gmail.com, Andrew Fasano Subject: [RFC 2/4] tcg/plugins: Automatically define CURRENT_PLUGIN Date: Thu, 1 Sep 2022 14:27:32 -0400 Message-Id: <20220901182734.2987337-3-fasano@mit.edu> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220901182734.2987337-1-fasano@mit.edu> References: <20220901182734.2987337-1-fasano@mit.edu> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=18.9.28.11; envelope-from=fasano@mit.edu; helo=outgoing.mit.edu X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Thu, 01 Sep 2022 17:11:38 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @mit.edu) X-ZM-MESSAGEID: 1662066903884100003 Content-Type: text/plain; charset="utf-8" Use plugin filenames to set the preprocessor variable CURRENT_PLUGIN as a string during plugin compilation. Signed-off-by: Andrew Fasano --- contrib/plugins/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/plugins/Makefile b/contrib/plugins/Makefile index df3499f4f2..b7720fea0f 100644 --- a/contrib/plugins/Makefile +++ b/contrib/plugins/Makefile @@ -34,7 +34,7 @@ CFLAGS +=3D -I$(SRC_PATH)/include/qemu all: $(SONAMES) =20 %.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< + $(CC) $(CFLAGS) -DCURRENT_PLUGIN=3D\"$(basename $@)\" -c -o $@ $< =20 lib%.so: %.o $(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDLIBS) --=20 2.34.1 From nobody Mon Feb 9 14:37:07 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=mit.edu ARC-Seal: i=1; a=rsa-sha256; t=1662066906; cv=none; d=zohomail.com; s=zohoarc; b=KK+C9KuOzsj5xylRENA2xoCohWwjTmqxrufElUND/EIZyTBHu+A4u4oTqc0D3+QjQ704RmBPK2i88el0qD0NzTYxSXac0z9n0E+56Bv8r7LIEp3RLd0nn8gxpAYml755LVeoTHlNz+iw1dmeIW67Q/u/xjnyO+QkjAQ5cHY7dEY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1662066906; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=alqlzwQKfFpi3MAZrP2ZJcVCA33Noh+eVOID7rx3Pyo=; b=OlroK4MSVD1Nla29UmqjiZrbtCaPzpYMfZFioq3stH/NvuvNQgTdEADdkT99OjEipsM3bYjZqpBHgBTcz6+AuFbOmGB1V9FUS2ZSm5oZgtYHmj036lOY/p9AAQbYycSdRxJvILPpIv1nltny/VfT9iOqF1A41CUTH9HK8RyGhaM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1662066906428989.4338914835507; Thu, 1 Sep 2022 14:15:06 -0700 (PDT) Received: from localhost ([::1]:40494 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oTrWj-0004O6-9L for importer@patchew.org; Thu, 01 Sep 2022 17:15:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52584) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oTp2j-0002eU-M2 for qemu-devel@nongnu.org; Thu, 01 Sep 2022 14:35:57 -0400 Received: from outgoing-auth-1.mit.edu ([18.9.28.11]:50280 helo=outgoing.mit.edu) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oTp2h-0002R9-BF for qemu-devel@nongnu.org; Thu, 01 Sep 2022 14:35:57 -0400 Received: from panda194.. ([18.4.85.108]) (authenticated bits=0) (User authenticated as fasano@ATHENA.MIT.EDU) by outgoing.mit.edu (8.14.7/8.12.4) with ESMTP id 281IRv2h010380 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 1 Sep 2022 14:28:26 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mit.edu; s=outgoing; t=1662056907; bh=alqlzwQKfFpi3MAZrP2ZJcVCA33Noh+eVOID7rx3Pyo=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=CmqBg+N/Nv4dmMLiBjrWVwYloTz+foilhzF1xbobbDum1p3+k/9Zw3ZsGL2RVrqUu BqYISNlXEJPOSLac0xolOcpZNr0PHPsR5gQ7m5lYfF7tBooqMY9QzoVoZfSeGmBvIU mtqC6LfFzhbYt/3TVFKNZlOPIfj69Xi6p1p2eQv1IrSy9JTdTuCnFvztKRcQbxAGsb yLdAaM1P+rUqJFwMDIKZ6K0l9zirhCc79PYIi9tJ5yI9BpFG8Wf8/smAs59b0myZWm VBZgiEk98k0Mg0j2bnCQ6ThybDZqZ44vWM9GM/S3y0LHl4zi6wGZHnyU3QffhXVZSk il+PkiRGbAY9Q== From: Andrew Fasano To: qemu-devel@nongnu.org Cc: alex.bennee@linaro.org, erdnaxe@crans.org, ma.mandourr@gmail.com, Andrew Fasano Subject: [RFC 3/4] tcg/plugins: Support for inter-plugin interactions Date: Thu, 1 Sep 2022 14:27:33 -0400 Message-Id: <20220901182734.2987337-4-fasano@mit.edu> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220901182734.2987337-1-fasano@mit.edu> References: <20220901182734.2987337-1-fasano@mit.edu> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=18.9.28.11; envelope-from=fasano@mit.edu; helo=outgoing.mit.edu X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Thu, 01 Sep 2022 17:11:41 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @mit.edu) X-ZM-MESSAGEID: 1662066908112100001 Content-Type: text/plain; charset="utf-8" Expand tcg-plugin system to allow for plugins to export functions and callbacks that can be used by other plugins. Exported functions can be called at runtime by other loaded plugins. Loaded plugins can register functions with exported callbacks and have these functions run whenever the callback is triggered. Signed-off-by: Andrew Fasano --- include/qemu/plugin-qpp.h | 252 +++++++++++++++++++++++++++++++++++ plugins/core.c | 11 ++ plugins/loader.c | 24 ++++ plugins/plugin.h | 5 + plugins/qemu-plugins.symbols | 1 + 5 files changed, 293 insertions(+) create mode 100644 include/qemu/plugin-qpp.h diff --git a/include/qemu/plugin-qpp.h b/include/qemu/plugin-qpp.h new file mode 100644 index 0000000000..befa4f9b8b --- /dev/null +++ b/include/qemu/plugin-qpp.h @@ -0,0 +1,252 @@ +#ifndef PLUGIN_QPP_H +#define PLUGIN_QPP_H + +/* + * Facilities for "QEMU plugin to plugin" (QPP) interactions between tcg + * plugins. These allow for an inter-plugin callback system as well + * as direct function calls between loaded plugins. For more details see + * docs/devel/plugin.rst. + */ + +#include +#include +#include +extern GModule * qemu_plugin_name_to_handle(const char *); + +#define PLUGIN_CONCAT(x, y) _PLUGIN_CONCAT(x, y) +#define _PLUGIN_CONCAT(x, y) x##y +#define QPP_NAME(plugin, fn) PLUGIN_CONCAT(plugin, PLUGIN_CONCAT(_, fn)) +#define QPP_MAX_CB 256 +#define _QPP_SETUP_NAME(plugin, fn) PLUGIN_CONCAT(_qpp_setup_, \ + QPP_NAME(plugin, fn)) + +/* + ************************************************************************** + * The QPP_CREATE_CB and QPP_RUN_CB macros are to be used by a plugin that + * wishs to create and later trigger QPP-based callback events. These are + * events that the plugin can detect (i.e., through analysis of guest stat= e) + * that may be of interest to other plugins. + ************************************************************************** + */ + +/* + * QPP_CREATE_CB(name) will create a callback by defining necessary intern= al + * functions and variables based off the provided name. It must be run bef= ore + * triggering the callback event (with QPP_RUN_CB). This macro will create= the + * following variables and functions, based off the provided name: + * + * 1) qpp_[name]_cb is an array of function pointers storing the + * registered callbacks. + * 2) qpp_[name]_num_cb stores the number of functions stored with this + * callback. + * 3) qpp_add_cb_[name] is a function to add a pointer into the qpp_[name]= _cb + * array and increment qpp_[name]_num_cb. + * 4) qpp_remove_cb_[name] finds a registered callback, deletes it, decrem= ents + * _num_cb and shifts the _cb array appropriately to fill the gap. + * + * Important notes: + * + * 1) Multiple callbacks can be registered for the same event, however con= sumers + * can not control the order in which they are called and this order may + * change in the future. + * + * 2) If this macro is incorrectly used multiple times in the same plugin = with + * the same callback name set, it will raise a compilation error since + * these variables would then be defined multiple times. The same callb= ack + * name can, however, be created in distrinct plugins without issue. + */ +#define QPP_CREATE_CB(cb_name) \ +void qpp_add_cb_##cb_name(cb_name##_t fptr); \ +bool qpp_remove_cb_##cb_name(cb_name##_t fptr); \ +cb_name##_t * qpp_##cb_name##_cb[QPP_MAX_CB]; \ +int qpp_##cb_name##_num_cb; \ + \ +void qpp_add_cb_##cb_name(cb_name##_t fptr) \ +{ \ + assert(qpp_##cb_name##_num_cb < QPP_MAX_CB); \ + qpp_##cb_name##_cb[qpp_##cb_name##_num_cb] =3D fptr; \ + qpp_##cb_name##_num_cb +=3D 1; \ +} \ + \ +bool qpp_remove_cb_##cb_name(cb_name##_t fptr) \ +{ \ + int i =3D 0; \ + bool found =3D false; \ + for (; i < MIN(QPP_MAX_CB, qpp_##cb_name##_num_cb); i++) {\ + if (!found && fptr =3D=3D qpp_##cb_name##_cb[i]) { \ + found =3D true; \ + qpp_##cb_name##_num_cb--; \ + } \ + if (found && i < QPP_MAX_CB - 2) { \ + qpp_##cb_name##_cb[i] =3D qpp_##cb_name##_cb[i + 1]; \ + } \ + } \ + return found; \ +} + + +/* + * QPP_RUN_CB(name, args...) should be run by the plugin that created + * a callback whenever it wishes to trigger the callback functions that + * have been registered with its previously-created callback of the provid= ed + * name. If this macro is run with a callback name that was not previously + * created, a compile time error will be raised. + */ +#define QPP_RUN_CB(cb_name, ...) do { \ + int cb_idx; \ + for (cb_idx =3D 0; cb_idx < qpp_##cb_name##_num_cb; cb_idx++) { \ + if (qpp_##cb_name##_cb[cb_idx] !=3D NULL) { \ + qpp_##cb_name##_cb[cb_idx](__VA_ARGS__); \ + } \ + } \ +} while (false) + +/* + * A header file that defines a callback function should use + * the QPP_CB_PROTOTYPE macro to create the necessary types. + */ +#define QPP_CB_PROTOTYPE(fn_ret, name, ...) \ + typedef fn_ret(PLUGIN_CONCAT(name, _t))(__VA_ARGS__); + +/* + *************************************************************************= **** + * The QPP_REG_CB and QPP_REMOVE_CB macros are to be used by plugins that + * wish to run internal logic when another plugin determines that some eve= nt + * has occured. The plugin name, target callback name, and a local function + * are provided to these macros. + *************************************************************************= **** + */ + +/* + * When a plugin wishes to register a function `cb_func` with a callback + * `cb_name` provided `other_plugin`, it must use the QPP_REG_CB. + */ +#define QPP_REG_CB(other_plugin, cb_name, cb_func) \ +{ \ + dlerror(); \ + void *h =3D qemu_plugin_name_to_handle(other_plugin); \ + if (!h) { \ + fprintf(stderr, "In trying to add plugin callback, "\ + "couldn't load %s plugin\n", \ + other_plugin); \ + assert(h); \ + } \ + void (*add_cb)(cb_name##_t fptr); \ + if (g_module_symbol(h, "qpp_add_cb_" #cb_name, \ + (gpointer *) &add_cb)) { \ + add_cb(cb_func); \ + } else { \ + fprintf(stderr, "Could not find symbol " #cb_name \ + " in " #other_plugin "\n"); \ + } \ +} + +/* + * If a plugin wishes to disable a previously-registered `cb_func` it shou= ld + * use the QPP_REMOVE_CB macro. + */ +#define QPP_REMOVE_CB(other_plugin, cb_name, cb_func) \ +{ \ + dlerror(); \ + void *op =3D panda_get_plugin_by_name(other_plugin); \ + if (!op) { \ + fprintf(stderr, "In trying to remove plugin callback, " \ + "couldn't load %s plugin\n", other_plugin); \ + assert(op); \ + } \ + void (*rm_cb)(cb_name##_t fptr) =3D (void (*)(cb_name##_t)) \ + dlsym(op, "qpp_remove_cb_" \ + #cb_name); \ + assert(rm_cb !=3D 0); \ + rm_cb(cb_func); \ +} + +/* + *************************************************************************= **** + * The QPP_FUN_PROTOTYPE enables a plugin to expose a local function to ot= her + * plugins. The macro should be used in a header file that is included + * by both the plugin that defines the function as well as other plugins + * that wish to call the function. + *************************************************************************= **** + */ + +/* + * A header file that defines an exported function should use the + * QPP_FUN_PROTOTYPE to create the necessary types. When other plugins + * include this header, a function pointer named `[plugin_name]_[fn]` will + * be created and available for the plugin to call. + * + * Note that these functions are not callbacks, but instead regular + * functions that are exported by one plugin such that they can be called = by + * others. + * + * In particular, this macro will create a function pointer by combining t= he + * `plugin_name` with an underscore and the name provided in `fn`. It will + * create a function to run on plugin load, that initializes this function + * pointer to the function named `fn` inside the plugin named `plugin_name= `. + * If this fails, an error will be printed and the plugin will abort. + * + * There are three distinct cases this macro must handle: + * 1) When the header is loaded by the plugin that defines the function. + * In this case, we do not need to find the symbol externally. + * qemu_plugin_name_to_handle will return NULL, we see that the + * target plugin matches CURRENT_PLUGIN and do nothing. + * 2) When the header is loaded by another plugin but the function + * is not available (i.e., the target plugin isn't loaded or the + * target plugin does not export the requested function). In this case = we + * raise a fatal error. + * 3) When the header is loaded by another plugin. In this case + * we need to get a handle to the target plugin and then use + * g_module_symbol to resolve the symbol and store it as the fn_name. + * If we get the handle, but can't resolve the symbol, raise a fatal er= ror. + * + * This plugin creates the following local variables and functions: + * + * 1) `fn`: A prototype for the provided function, with the specified argu= ments. + * This is necessary for case 1 above and irrelevant for the others. + * 2) A function pointer typedef for `[fn]_t` set to a pointer of the type= of + * `fn`. + * 3) A function pointer (of type `[fn]_t`) named `[plugin_name]_[fn]` + * 4) A constructor function named "_qpp_setup_[plugin_name]_[fn]" that wi= ll + * run when the plugin is loaded. In case 1 above, it will do nothing. = In + * case 2 it will print an error to stderr and abort. In case 3 it will + * update the function pointer "[plugin_name]_[fn]" to point to the tar= get + * function. + * + * After this constructor runs, the plugin can directly call the target fu= nction + * using `[plugin_name]_[fn]()`. + * + * For example, consider a plugin named "my_plugin" that wishes to export a + * function named "my_func" that returns void and takes a single integer = arg. + * This would work as follows: + * 1) The header file for the plugin, my_plugin.h, should include + * QPP_FUN_PROTOTYPE(my_plugin, void, my_func, int) which will define t= he + * function prototype and necessary internal state. + * 2) This header should be included by my_plugin.c which should also incl= ude + * QEMU_PLUGIN_EXPORT void my_func(int) {...} with the function definit= ion. + * 3) Other plugins can get access to this function by including my_plugin= .h + * which will set up the function pointer `my_plugin_my_func` automatic= ally + * using the internal state here. + * + */ +#define QPP_FUN_PROTOTYPE(plugin_name, fn_ret, fn, args) = \ + fn_ret fn(args); = \ + typedef fn_ret(*PLUGIN_CONCAT(fn, _t))(args); = \ + fn##_t QPP_NAME(plugin_name, fn); = \ + void _QPP_SETUP_NAME(plugin_name, fn) (void); = \ + = \ + void __attribute__ ((constructor)) _QPP_SETUP_NAME(plugin_name, fn) (voi= d) {\ + GModule *h =3D qemu_plugin_name_to_handle(#plugin_name); = \ + if (!h && strcmp(CURRENT_PLUGIN, #plugin_name) !=3D 0) { \ + fprintf(stderr, "Error plugin %s cannot access %s. Is it loaded?\n",= \ + CURRENT_PLUGIN, #plugin_name); \ + abort(); = \ + } else if (h && !g_module_symbol(h, #fn, = \ + (gpointer *)&QPP_NAME(plugin_name, fn))) { = \ + fprintf(stderr, "Error loading symbol " # fn " from plugin " = \ + # plugin_name "\n"); = \ + abort(); = \ + } = \ + } + +#endif /* PLUGIN_QPP_H */ diff --git a/plugins/core.c b/plugins/core.c index 792262da08..81c714bbf4 100644 --- a/plugins/core.c +++ b/plugins/core.c @@ -236,6 +236,17 @@ void qemu_plugin_vcpu_exit_hook(CPUState *cpu) qemu_rec_mutex_unlock(&plugin.lock); } =20 +GModule *qemu_plugin_name_to_handle(const char* name) +{ + struct qemu_plugin_ctx *ctx; + QTAILQ_FOREACH(ctx, &plugin.ctxs, entry) { + if (is_plugin_named(*ctx, name)) { + return plugin_id_to_ctx_locked(ctx->id)->handle; + } + } + return NULL; +} + struct plugin_for_each_args { struct qemu_plugin_ctx *ctx; qemu_plugin_vcpu_simple_cb_t cb; diff --git a/plugins/loader.c b/plugins/loader.c index 88c30bde2d..26d3c14661 100644 --- a/plugins/loader.c +++ b/plugins/loader.c @@ -265,6 +265,30 @@ static int plugin_load(struct qemu_plugin_desc *desc, = const qemu_info_t *info, E return 1; } =20 +/** + * is_plugin_named - compare a plugins's name to a provided name + * @ctx: the ctx for the plugin in question + * @name: the name that should be used in the comparison + * + * Returns true if the names match. + */ + +bool is_plugin_named(struct qemu_plugin_ctx ctx, const char *name) +{ + char *plugin_basename =3D basename(ctx.desc->path); + /* + * First resolve the name of the shared object for the current plugin, + * then check if it could possibly be of the form libNAME.so + * where NAME is the provided name. If so, compare the strings. + */ + if (plugin_basename =3D=3D NULL || strlen(plugin_basename) !=3D strlen(n= ame) + 6) { + return false; + } + + return strncmp(plugin_basename + 3, name, + strlen(plugin_basename) - 6) =3D=3D 0; +} + /* call after having removed @desc from the list */ static void plugin_desc_free(struct qemu_plugin_desc *desc) { diff --git a/plugins/plugin.h b/plugins/plugin.h index 5eb2fdbc85..69d9b09d4c 100644 --- a/plugins/plugin.h +++ b/plugins/plugin.h @@ -97,4 +97,9 @@ void plugin_register_vcpu_mem_cb(GArray **arr, =20 void exec_inline_op(struct qemu_plugin_dyn_cb *cb); =20 +GModule *qemu_plugin_name_to_handle(const char* name); + +/* loader.c */ +bool is_plugin_named(struct qemu_plugin_ctx ctx, const char *name); + #endif /* PLUGIN_H */ diff --git a/plugins/qemu-plugins.symbols b/plugins/qemu-plugins.symbols index 71f6c90549..d98c0bc38a 100644 --- a/plugins/qemu-plugins.symbols +++ b/plugins/qemu-plugins.symbols @@ -18,6 +18,7 @@ qemu_plugin_mem_size_shift; qemu_plugin_n_max_vcpus; qemu_plugin_n_vcpus; + qemu_plugin_name_to_handle; qemu_plugin_outs; qemu_plugin_path_to_binary; qemu_plugin_register_atexit_cb; --=20 2.34.1 From nobody Mon Feb 9 14:37:07 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=mit.edu ARC-Seal: i=1; a=rsa-sha256; t=1662066901; cv=none; d=zohomail.com; s=zohoarc; b=iKcvX17PkqSWlgRmvWovtNBUnYVVNqHk7tjGgPo6HbnssH9a7LazDidN6I9dtR2MP4VKgSwXtTSMHeYi/O580gL/UmIPYwpdIbtom6o9FDIapC1FQrxRORGHvAv++wE3y+0RE8cVPfJWWCXxl+c029557icTrWxzy0zB9rv7GfM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1662066901; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=knzxQ+knlh1GCYMrF32LK9BHiAKUl5jfg5+Wc9gLQxQ=; b=OGPZ+Upcpa58+Xi0h21QB2lwJ4AjBw+Ds7zpG0eqC1939XbhEjkvjpJV4+XFmmaDYgiN/Dh+Va36fGrDAnASBO0yqo9Vf8SJ+ijaNBWSxjp6SpjGkE0RridHugmeVHcCxmVqMDzdHtnd8bQe3Vm/fkbOTKhOngGfvf6jjRtdjVo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1662066901666995.4806245975446; Thu, 1 Sep 2022 14:15:01 -0700 (PDT) Received: from localhost ([::1]:40488 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1oTrWd-0004Jq-Q3 for importer@patchew.org; Thu, 01 Sep 2022 17:14:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:49146) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oTp2h-0002bf-6b for qemu-devel@nongnu.org; Thu, 01 Sep 2022 14:35:56 -0400 Received: from outgoing-auth-1.mit.edu ([18.9.28.11]:50280 helo=outgoing.mit.edu) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oTp2f-0002R9-Eq for qemu-devel@nongnu.org; Thu, 01 Sep 2022 14:35:54 -0400 Received: from panda194.. ([18.4.85.108]) (authenticated bits=0) (User authenticated as fasano@ATHENA.MIT.EDU) by outgoing.mit.edu (8.14.7/8.12.4) with ESMTP id 281IRv2i010380 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 1 Sep 2022 14:28:29 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mit.edu; s=outgoing; t=1662056910; bh=knzxQ+knlh1GCYMrF32LK9BHiAKUl5jfg5+Wc9gLQxQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=AYWpdFWaEIvPulHw7rxuSHvrQ9RTKy57x+KI8GTkC5nEPddg5ZyxPvH+9s7ls5ISI coRblqutkYDVlamSRAIQ/8N1MZSXKQNg7p/yRPbqXsMgV3gcRHGbfS69/22yFd9rWf 0EU9Di1L9JQcNat+hIPuwwuHbxwR6EJ4Loq+K/yYVwiCD6teUt+kCFzcO5PBeiJzh5 GVlfOzzdjn7Gzh7IFqE0jf5PBhhXHWbWP6uJWfMvsWkUL7EFC6kaT+KNQpiUlKZYBT qoievv0T/A/Axm3IwCie1WIACzUEZbV45BRSIzHwEDwG5Lr/iz61NzhomXhUnxg4aJ tTfc7ACpZj7fQ== From: Andrew Fasano To: qemu-devel@nongnu.org Cc: alex.bennee@linaro.org, erdnaxe@crans.org, ma.mandourr@gmail.com, Andrew Fasano Subject: [RFC 4/4] tcg/plugins: Add example pair of QPP plugins Date: Thu, 1 Sep 2022 14:27:34 -0400 Message-Id: <20220901182734.2987337-5-fasano@mit.edu> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220901182734.2987337-1-fasano@mit.edu> References: <20220901182734.2987337-1-fasano@mit.edu> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=18.9.28.11; envelope-from=fasano@mit.edu; helo=outgoing.mit.edu X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Thu, 01 Sep 2022 17:11:41 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @mit.edu) X-ZM-MESSAGEID: 1662066902375100001 Content-Type: text/plain; charset="utf-8" The first plugin, qpp_srv exposes two functions and one callback that other plugins can leverage. These functions are described in the corresponding header file. The second plugin, qpp_client, imports this header file, registers its own function to run on a qpp_srv-provided callback, and directly calls into the two exposed functions in qpp_srv. Signed-off-by: Andrew Fasano --- contrib/plugins/Makefile | 2 ++ contrib/plugins/qpp_client.c | 42 ++++++++++++++++++++++++++++++++++++ contrib/plugins/qpp_client.h | 1 + contrib/plugins/qpp_srv.c | 33 ++++++++++++++++++++++++++++ contrib/plugins/qpp_srv.h | 17 +++++++++++++++ 5 files changed, 95 insertions(+) create mode 100644 contrib/plugins/qpp_client.c create mode 100644 contrib/plugins/qpp_client.h create mode 100644 contrib/plugins/qpp_srv.c create mode 100644 contrib/plugins/qpp_srv.h diff --git a/contrib/plugins/Makefile b/contrib/plugins/Makefile index b7720fea0f..b7510de89c 100644 --- a/contrib/plugins/Makefile +++ b/contrib/plugins/Makefile @@ -21,6 +21,8 @@ NAMES +=3D lockstep NAMES +=3D hwprofile NAMES +=3D cache NAMES +=3D drcov +NAMES +=3D qpp_srv +NAMES +=3D qpp_client =20 SONAMES :=3D $(addsuffix .so,$(addprefix lib,$(NAMES))) =20 diff --git a/contrib/plugins/qpp_client.c b/contrib/plugins/qpp_client.c new file mode 100644 index 0000000000..de3335e167 --- /dev/null +++ b/contrib/plugins/qpp_client.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include "qpp_srv.h" + +QEMU_PLUGIN_EXPORT int qemu_plugin_version =3D QEMU_PLUGIN_VERSION; + +void my_on_exit(int x, bool b) +{ + g_autoptr(GString) report =3D g_string_new("Client: on_exit runs with ar= gs: "); + g_string_append_printf(report, "%d, %d\n", x, b); + qemu_plugin_outs(report->str); + + g_string_printf(report, "Client: calls qpp_srv's do_add(1): %d\n", + qpp_srv_do_add(1)); + qemu_plugin_outs(report->str); + + g_string_printf(report, "Client: calls qpp_srv's do_sub(1): %d\n", + qpp_srv_do_sub(1)); + qemu_plugin_outs(report->str); +} + + +QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, + const qemu_info_t *info, int argc, char **argv) { + + /* + * Register our "my_on_exit" function to run on the on_exit QPP-callba= ck + * exported by qpp_srv + */ + QPP_REG_CB("qpp_srv", on_exit, my_on_exit); + + g_autoptr(GString) report =3D g_string_new(CURRENT_PLUGIN ": Call " + "qpp_srv's do_add(0) =3D> "); + g_string_append_printf(report, "%d\n", qpp_srv_do_add(0)); + qemu_plugin_outs(report->str); + + g_string_printf(report, "Client: registered on_exit callback\n"); + return 0; +} + diff --git a/contrib/plugins/qpp_client.h b/contrib/plugins/qpp_client.h new file mode 100644 index 0000000000..573923f580 --- /dev/null +++ b/contrib/plugins/qpp_client.h @@ -0,0 +1 @@ +void my_on_exit(int, bool); diff --git a/contrib/plugins/qpp_srv.c b/contrib/plugins/qpp_srv.c new file mode 100644 index 0000000000..61a6ab38ed --- /dev/null +++ b/contrib/plugins/qpp_srv.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include "qpp_srv.h" + +QEMU_PLUGIN_EXPORT int qemu_plugin_version =3D QEMU_PLUGIN_VERSION; + +QPP_CREATE_CB(on_exit); + +static void plugin_exit(qemu_plugin_id_t id, void *p) +{ + qemu_plugin_outs(CURRENT_PLUGIN "exit triggered, running all registered" + " QPP callbacks\n"); + QPP_RUN_CB(on_exit, 0, true); +} + +QEMU_PLUGIN_EXPORT int do_add(int x) +{ + return x + 1; +} + +QEMU_PLUGIN_EXPORT int do_sub(int x) +{ + return x - 1; +} + +QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, + const qemu_info_t *info, int argc, char **argv) { + qemu_plugin_outs("qpp_srv loaded\n"); + qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); + return 0; +} diff --git a/contrib/plugins/qpp_srv.h b/contrib/plugins/qpp_srv.h new file mode 100644 index 0000000000..ceb26e3d2c --- /dev/null +++ b/contrib/plugins/qpp_srv.h @@ -0,0 +1,17 @@ +#ifndef QPP_SRV_H +#define QPP_SRV_H + +/* + * Prototype for the on_exit callback: callback functions should be + * of type `void f(int, bool)` + */ +QPP_CB_PROTOTYPE(void, on_exit, int, bool); + +/* + * Prototypes for the do_add and do_sub functions. Both return an int and + * take an int as an argument. + */ +QPP_FUN_PROTOTYPE(qpp_srv, int, do_add, int); +QPP_FUN_PROTOTYPE(qpp_srv, int, do_sub, int); + +#endif /* QPP_SRV_H */ --=20 2.34.1