All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: Mahmoud Mandour <ma.mandourr@gmail.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [PATCH v2] plugins/syscall: Added a table-like summary output
Date: Mon, 19 Apr 2021 11:23:30 +0100	[thread overview]
Message-ID: <87czuqa7be.fsf@linaro.org> (raw)
In-Reply-To: <20210416071740.3393-1-ma.mandourr@gmail.com>


Mahmoud Mandour <ma.mandourr@gmail.com> writes:

> Added a table-like output which contains the total number of calls
> for each used syscall along with the number of errors that occurred.
>
> Per-call tracing is still available through supplying the argument
> ``print`` to the plugin.
>
> Signed-off-by: Mahmoud Mandour <ma.mandourr@gmail.com>
> ---
> v1: https://lists.gnu.org/archive/html/qemu-devel/2021-04/msg02623.html
> v1 -> v2: Removed debugging code in the on-return from syscall callback 
>           that was silently existent.
>
>  tests/plugin/syscall.c | 91 +++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 85 insertions(+), 6 deletions(-)
>
> diff --git a/tests/plugin/syscall.c b/tests/plugin/syscall.c
> index 53ee2ab6c4..b66a930635 100644
> --- a/tests/plugin/syscall.c
> +++ b/tests/plugin/syscall.c
> @@ -16,32 +16,111 @@
>  
>  QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
>  
> +typedef struct {
> +    int64_t calls;
> +    int64_t errors;
> +} SyscallStats;
> +
> +static GHashTable *syscalls_statistics;
> +
> +static bool percall_print;
> +
>  static void vcpu_syscall(qemu_plugin_id_t id, unsigned int vcpu_index,
>                           int64_t num, uint64_t a1, uint64_t a2,
>                           uint64_t a3, uint64_t a4, uint64_t a5,
>                           uint64_t a6, uint64_t a7, uint64_t a8)
>  {
> -    g_autofree gchar *out = g_strdup_printf("syscall #%" PRIi64 "\n", num);
> -    qemu_plugin_outs(out);
> +    if (!percall_print) {

I think you could eliminate the percall_print global and just invert the
test and have if (syscall_statisitics)

> +        SyscallStats *syscall_entry;
> +
> +        syscall_entry =
> +            (SyscallStats *) g_hash_table_lookup(syscalls_statistics,
> +                                                  GINT_TO_POINTER(num));
> +
> +        if (!syscall_entry) {
> +            syscall_entry = g_new(SyscallStats, 1);
> +            syscall_entry->calls = 1;
> +            syscall_entry->errors = 0;
> +
> +            g_hash_table_insert(syscalls_statistics, GINT_TO_POINTER(num),
> +                                (gpointer) syscall_entry);

You you wrap up the entry creation into a helper it would make the code
less cluttered here, e.g.:

     syscall_entry = get_or_create_entry();
     syscall_entry->calls++;

> +        } else {
> +            syscall_entry->calls++;
> +        }
> +    } else {
> +        g_autofree gchar *out = g_strdup_printf("syscall #%" PRIi64 "\n", num);
> +        qemu_plugin_outs(out);
> +    }
>  }
>  
>  static void vcpu_syscall_ret(qemu_plugin_id_t id, unsigned int vcpu_idx,
>                               int64_t num, int64_t ret)
> +{
> +    if (!percall_print) {
> +        SyscallStats *syscall_entry;
> +
> +        syscall_entry =
> +            (SyscallStats *) g_hash_table_lookup(syscalls_statistics,
> +                                                  GINT_TO_POINTER(num));
> +        if (ret < 0) {
> +            syscall_entry->errors++;
> +        }
> +    } else {
> +        g_autofree gchar *out;
> +        out = g_strdup_printf("syscall #%" PRIi64 " returned -> %" PRIi64 "\n",
> +                num, ret);
> +        qemu_plugin_outs(out);
> +    }

ditto.

> +}
> +
> +/* ************************************************************************* */
> +
> +void print_entry(gpointer key, gpointer val, gpointer user_data)
>  {
>      g_autofree gchar *out;
> -    out = g_strdup_printf("syscall #%" PRIi64 " returned -> %" PRIi64 "\n",
> -            num, ret);
> +    int64_t syscall_num = (int64_t) key;
> +    SyscallStats *syscall_entry = (SyscallStats *) val;
> +    out = g_strdup_printf(
> +        "%-13" PRIi64 "%-6" PRIi64 " %" PRIi64 "\n",
> +        syscall_num, syscall_entry->calls, syscall_entry->errors);
>      qemu_plugin_outs(out);
>  }
>  
> -/* ************************************************************************* */
> +static void plugin_exit(qemu_plugin_id_t id, void *p)
> +{
> +    if (!percall_print) {
> +        qemu_plugin_outs("syscall no.  calls  errors\n");
> +        g_hash_table_foreach(syscalls_statistics, &print_entry,
> NULL);

Sorting the hash list by calls would be a nice improvement - see howvec
for an example of how to use g_hash_table_get_values/g_list_sort.

For cleanliness you should also clean-up the syscall_statisitics hash
table and deallocation although in practice it doesn't really matter as
use space is about to exit anyway.

> +    }
> +}
>  
> -static void plugin_exit(qemu_plugin_id_t id, void *p) {}
> +void free_entry(gpointer entry)
> +{
> +    g_free(entry);
> +}
>  
>  QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
>                                             const qemu_info_t *info,
>                                             int argc, char **argv)
>  {
> +    int i;
> +
> +    for (i = 0; i < argc; i++) {
> +        char *opt = argv[i];
> +        if (g_strcmp0(opt, "print") == 0) {
> +            percall_print = true;

So this would be a local now and or even:

  if (argc == 0) {
      syscalls_statistics = g_hash_table_new_full(g_direct_hash, g_direct_equal,  NULL, &free_entry);
  } else {
      for (i = 0; i < argc; i++) {
          ...

> +        } else {
> +            fprintf(stderr, "unsupported argument: %s\n", opt);
> +            return -1;
> +        }
> +    }
> +
> +    if (!percall_print) {
> +        syscalls_statistics =
> +            g_hash_table_new_full(g_direct_hash, g_direct_equal,
> +                    NULL, &free_entry);

For a simple non-nested structure you might even get away with a plain g_hash_table_new()

> +    }
> +
>      qemu_plugin_register_vcpu_syscall_cb(id, vcpu_syscall);
>      qemu_plugin_register_vcpu_syscall_ret_cb(id, vcpu_syscall_ret);
>      qemu_plugin_register_atexit_cb(id, plugin_exit, NULL);


-- 
Alex Bennée


      reply	other threads:[~2021-04-19 10:53 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-16  7:17 [PATCH v2] plugins/syscall: Added a table-like summary output Mahmoud Mandour
2021-04-19 10:23 ` Alex Bennée [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=87czuqa7be.fsf@linaro.org \
    --to=alex.bennee@linaro.org \
    --cc=ma.mandourr@gmail.com \
    --cc=qemu-devel@nongnu.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 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.