From patchwork Thu Aug 17 22:24:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13357050 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A7CAFC71133 for ; Thu, 17 Aug 2023 22:24:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355703AbjHQWY3 (ORCPT ); Thu, 17 Aug 2023 18:24:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49968 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355704AbjHQWYU (ORCPT ); Thu, 17 Aug 2023 18:24:20 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 493A630DC for ; Thu, 17 Aug 2023 15:24:18 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id CB9686677E for ; Thu, 17 Aug 2023 22:24:17 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2C2E0C433CA; Thu, 17 Aug 2023 22:24:17 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.96) (envelope-from ) id 1qWlPj-000UsH-2C; Thu, 17 Aug 2023 18:24:23 -0400 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: Ross Zwisler , Stevie Alvarez , "Steven Rostedt (Google)" Subject: [PATCH 1/9] libtraceeval: Add check for updates to know to recreate iter array Date: Thu, 17 Aug 2023 18:24:14 -0400 Message-Id: <20230817222422.118568-2-rostedt@goodmis.org> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230817222422.118568-1-rostedt@goodmis.org> References: <20230817222422.118568-1-rostedt@goodmis.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (Google)" When an iterator is created, it creates an array of pointers to point to all the elements in the traceeval. This is used to index through the entities in an nice order. But if an event is added or removed from the traceeval, the size and count of this array will be off in the iterator. Add an "update_counter" that gets incremented every time an item is added or removed (doesn't need to keep track of updates to existing entries). If the counter is different from the last time the iterator created the sort array, it will need to delete and recreate the list again before it can do a sort. Note: It is safe to use the iterator to remove times, so a removal (or even insert) should not affect the traceeval_iterator_next(). But it should be explained in the man pages (soon to be written) that doing so must be done with care. And maybe a helper function should be used instead! Signed-off-by: Steven Rostedt (Google) Reviewed-by: Ross Zwisler --- src/eval-local.h | 2 ++ src/histograms.c | 91 ++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 74 insertions(+), 19 deletions(-) diff --git a/src/eval-local.h b/src/eval-local.h index 5c3918f17cc1..73f52efdf0da 100644 --- a/src/eval-local.h +++ b/src/eval-local.h @@ -68,6 +68,7 @@ struct traceeval { struct hash_table *hist; size_t nr_key_types; size_t nr_val_types; + size_t update_counter; }; struct traceeval_iterator { @@ -75,6 +76,7 @@ struct traceeval_iterator { struct entry **entries; struct traceeval_type **sort; bool *direction; + size_t update_counter; size_t nr_entries; size_t nr_sort; size_t next; diff --git a/src/histograms.c b/src/histograms.c index 96f0926f062c..66bdc1769985 100644 --- a/src/histograms.c +++ b/src/histograms.c @@ -757,6 +757,8 @@ static int create_entry(struct traceeval *teval, entry->keys = new_keys; entry->vals = new_vals; + teval->update_counter++; + return 0; fail: @@ -960,6 +962,9 @@ int traceeval_remove(struct traceeval *teval, return check; hash_remove(hist, &entry->hash); + + teval->update_counter++; + return 1; } @@ -981,6 +986,37 @@ void traceeval_iterator_put(struct traceeval_iterator *iter) free(iter); } +static int create_iter_array(struct traceeval_iterator *iter) +{ + struct traceeval *teval = iter->teval; + struct hash_table *hist = teval->hist; + struct hash_iter *hiter; + struct hash_item *item; + int i; + + iter->nr_entries = hash_nr_items(hist); + iter->entries = calloc(iter->nr_entries, sizeof(*iter->entries)); + if (!iter->entries) + return -1; + + for (i = 0, hiter = hash_iter_start(hist); (item = hash_iter_next(hiter)); i++) { + struct entry *entry = container_of(item, struct entry, hash); + + iter->entries[i] = entry; + } + + /* Loop must match entries */ + if (i != iter->nr_entries) { + free(iter->entries); + iter->entries = NULL; + return -1; + } + + iter->update_counter = teval->update_counter; + + return 0; +} + /** * traceeval_iterator_get - get a handle to iterate over a given traceeval * @teval: The traceeval handle to iterate over @@ -997,33 +1033,19 @@ void traceeval_iterator_put(struct traceeval_iterator *iter) struct traceeval_iterator *traceeval_iterator_get(struct traceeval *teval) { struct traceeval_iterator *iter; - struct hash_table *hist = teval->hist; - struct hash_iter *hiter; - struct hash_item *item; - int i; + int ret; iter = calloc(1, sizeof(*iter)); if (!iter) return NULL; iter->teval = teval; - iter->nr_entries = hash_nr_items(hist); - iter->entries = calloc(iter->nr_entries, sizeof(*iter->entries)); - if (!iter->entries) { - free(iter); - return NULL; - } - - for (i = 0, hiter = hash_iter_start(hist); (item = hash_iter_next(hiter)); i++) { - struct entry *entry = container_of(item, struct entry, hash); - iter->entries[i] = entry; - } + ret = create_iter_array(iter); - /* Loop must match entries */ - if (i != iter->nr_entries) { - traceeval_iterator_put(iter); - return NULL; + if (ret < 0) { + free(iter); + iter = NULL; } return iter; @@ -1168,6 +1190,31 @@ static int iter_cmp(const void *A, const void *B, void *data) return 0; } +static int check_update(struct traceeval_iterator *iter) +{ + struct entry **entries; + size_t nr_entries; + int ret; + + /* Was something added or removed from the teval? */ + if (iter->teval->update_counter == iter->update_counter) + return 0; + + entries = iter->entries; + nr_entries = iter->nr_entries; + + /* Something changed, need to recreate the array */ + ret = create_iter_array(iter); + if (ret < 0) { + iter->entries = entries; + iter->nr_entries = nr_entries; + return -1; + } + free(entries); + + return 0; +} + static int sort_iter(struct traceeval_iterator *iter) { int i; @@ -1178,6 +1225,9 @@ static int sort_iter(struct traceeval_iterator *iter) return -1; } + if (check_update(iter) < 0) + return -1; + qsort_r(iter->entries, iter->nr_entries, sizeof(*iter->entries), iter_cmp, iter); @@ -1214,6 +1264,9 @@ int traceeval_iterator_sort_custom(struct traceeval_iterator *iter, .data = data }; + if (check_update(iter) < 0) + return -1; + qsort_r(iter->entries, iter->nr_entries, sizeof(*iter->entries), iter_custom_cmp, &cust_data); From patchwork Thu Aug 17 22:24:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13357043 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EFDBCC6FD22 for ; Thu, 17 Aug 2023 22:24:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355677AbjHQWY0 (ORCPT ); Thu, 17 Aug 2023 18:24:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38944 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355702AbjHQWYT (ORCPT ); Thu, 17 Aug 2023 18:24:19 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3A1C630DA for ; Thu, 17 Aug 2023 15:24:18 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id C00F064FD0 for ; Thu, 17 Aug 2023 22:24:17 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2843DC433C9; Thu, 17 Aug 2023 22:24:17 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.96) (envelope-from ) id 1qWlPj-000UsK-2H; Thu, 17 Aug 2023 18:24:23 -0400 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: Ross Zwisler , Stevie Alvarez , "Steven Rostedt (Google)" Subject: [PATCH 2/9] libtraceeval: Add traceeval_iterator_query() Date: Thu, 17 Aug 2023 18:24:15 -0400 Message-Id: <20230817222422.118568-3-rostedt@goodmis.org> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230817222422.118568-1-rostedt@goodmis.org> References: <20230817222422.118568-1-rostedt@goodmis.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (Google)" Add a query to the iterator that will return the values of the last entry that matches the keys returned by the last call of traceeval_iterator_next(). Signed-off-by: Steven Rostedt (Google) Reviewed-by: Ross Zwisler --- include/traceeval-hist.h | 2 ++ samples/task-eval.c | 2 +- src/histograms.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/include/traceeval-hist.h b/include/traceeval-hist.h index 0cee9bcbeb83..837a74f61a66 100644 --- a/include/traceeval-hist.h +++ b/include/traceeval-hist.h @@ -186,5 +186,7 @@ int traceeval_iterator_sort_custom(struct traceeval_iterator *iter, traceeval_cmp_fn sort_fn, void *data); int traceeval_iterator_next(struct traceeval_iterator *iter, const union traceeval_data **keys); +int traceeval_iterator_query(struct traceeval_iterator *iter, + const union traceeval_data **results); #endif /* __LIBTRACEEVAL_HIST_H__ */ diff --git a/samples/task-eval.c b/samples/task-eval.c index 66d0c40dc0c8..18e07f44e11e 100644 --- a/samples/task-eval.c +++ b/samples/task-eval.c @@ -836,7 +836,7 @@ static void display_processes(struct traceeval *teval, struct process_data *pdata = NULL; const char *comm = keys[0].cstring; - ret = traceeval_query(teval_data, keys, &results); + ret = traceeval_iterator_query(iter, &results); if (ret < 0) pdie("Could not query iterator"); if (ret < 1) diff --git a/src/histograms.c b/src/histograms.c index 66bdc1769985..4f603ce36c8c 100644 --- a/src/histograms.c +++ b/src/histograms.c @@ -1306,3 +1306,33 @@ int traceeval_iterator_next(struct traceeval_iterator *iter, *keys = entry->keys; return 1; } + +/** + * traceeval_iterator_query - return the results of the last entry in the iterator + * @iter: The iterator to retrieve the entry results from + * @results: The returned results of the last entry (if exists) + * + * This returns the @results of the values from the last instance of + * traceeval_iterator_next(). It is equivalent of calling: + * + * traceeval_query_size() with the keys returned by traceeval_iterator_next(). + * + * Except that it will always quickly return the last entry, whereas the + * traceeval_query_size() will reset the cached next_entry and do a full + * lookup again. + * + * Returns 1 if another entry is returned, or 0 if not (or negative on error) + */ +int traceeval_iterator_query(struct traceeval_iterator *iter, + const union traceeval_data **results) +{ + struct entry *entry; + + if (iter->next < 1 || iter->next > iter->nr_entries) + return 0; + + entry = iter->entries[iter->next - 1]; + *results = entry->vals; + + return 1; +} From patchwork Thu Aug 17 22:24:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13357042 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DE732C64EDA for ; Thu, 17 Aug 2023 22:24:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355702AbjHQWY1 (ORCPT ); Thu, 17 Aug 2023 18:24:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38930 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355698AbjHQWYT (ORCPT ); Thu, 17 Aug 2023 18:24:19 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2B14B30C5 for ; Thu, 17 Aug 2023 15:24:18 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id B3BAD6644D for ; Thu, 17 Aug 2023 22:24:17 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1EE5DC433C7; Thu, 17 Aug 2023 22:24:17 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.96) (envelope-from ) id 1qWlPj-000UsN-2M; Thu, 17 Aug 2023 18:24:23 -0400 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: Ross Zwisler , Stevie Alvarez , "Steven Rostedt (Google)" Subject: [PATCH 3/9] libtraceeval: Add traceeval_iterator_stat() Date: Thu, 17 Aug 2023 18:24:16 -0400 Message-Id: <20230817222422.118568-4-rostedt@goodmis.org> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230817222422.118568-1-rostedt@goodmis.org> References: <20230817222422.118568-1-rostedt@goodmis.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (Google)" Add traceeval_iterator_stat() that will return a stat of a value of the current entry from a traceeval_iterator_next() loop. Signed-off-by: Steven Rostedt (Google) Reviewed-by: Ross Zwisler --- include/traceeval-hist.h | 2 ++ samples/task-eval.c | 6 ++--- src/histograms.c | 47 ++++++++++++++++++++++++++++++++-------- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/include/traceeval-hist.h b/include/traceeval-hist.h index 837a74f61a66..d511c9c5f14c 100644 --- a/include/traceeval-hist.h +++ b/include/traceeval-hist.h @@ -188,5 +188,7 @@ int traceeval_iterator_next(struct traceeval_iterator *iter, const union traceeval_data **keys); int traceeval_iterator_query(struct traceeval_iterator *iter, const union traceeval_data **results); +struct traceeval_stat *traceeval_iterator_stat(struct traceeval_iterator *iter, + struct traceeval_type *type); #endif /* __LIBTRACEEVAL_HIST_H__ */ diff --git a/samples/task-eval.c b/samples/task-eval.c index 18e07f44e11e..bde167d1219b 100644 --- a/samples/task-eval.c +++ b/samples/task-eval.c @@ -706,7 +706,7 @@ static void display_cpus(struct traceeval *teval) int state = keys[1].number; int cpu = keys[0].number; - stat = traceeval_stat(teval, keys, &delta_vals[0]); + stat = traceeval_iterator_stat(iter, &delta_vals[0]); if (!stat) continue; // die? @@ -773,7 +773,7 @@ static void display_threads(struct traceeval *teval) int state = keys[1].number; int tid = keys[0].number; - stat = traceeval_stat(teval, keys, &delta_vals[0]); + stat = traceeval_iterator_stat(iter, &delta_vals[0]); if (!stat) continue; // die? @@ -875,7 +875,7 @@ static void display(struct task_data *tdata) while (traceeval_iterator_next(iter, &keys) > 0) { int state = keys[1].number; - stat = traceeval_stat(teval, keys, &delta_vals[0]); + stat = traceeval_iterator_stat(iter, &delta_vals[0]); if (!stat) continue; diff --git a/src/histograms.c b/src/histograms.c index 4f603ce36c8c..fddd0f3587e2 100644 --- a/src/histograms.c +++ b/src/histograms.c @@ -812,16 +812,11 @@ static int update_entry(struct traceeval *teval, struct entry *entry, return -1; } -struct traceeval_stat *traceeval_stat(struct traceeval *teval, - const union traceeval_data *keys, - struct traceeval_type *type) +static bool is_stat_type(struct traceeval_type *type) { - struct entry *entry; - int ret; - /* Only value numbers have stats */ if (!(type->flags & TRACEEVAL_FL_VALUE)) - return NULL; + return false; switch (type->type) { case TRACEEVAL_TYPE_NUMBER: @@ -829,10 +824,21 @@ struct traceeval_stat *traceeval_stat(struct traceeval *teval, case TRACEEVAL_TYPE_NUMBER_32: case TRACEEVAL_TYPE_NUMBER_16: case TRACEEVAL_TYPE_NUMBER_8: - break; + return true; default: - return NULL; + return false; } +} + +struct traceeval_stat *traceeval_stat(struct traceeval *teval, + const union traceeval_data *keys, + struct traceeval_type *type) +{ + struct entry *entry; + int ret; + + if (!is_stat_type(type)) + return NULL; ret = get_entry(teval, keys, &entry); if (ret <= 0) @@ -1336,3 +1342,26 @@ int traceeval_iterator_query(struct traceeval_iterator *iter, return 1; } + +/** + * traceeval_iterator_stat - return the stats from the last iterator entry + * @iter: The iterator to retrieve the stats from + * @type: The value type to get the stat from + * + * Returns the stats of the @type for the current iterator entry on success, + * or NULL if not found or an error occurred. + */ +struct traceeval_stat *traceeval_iterator_stat(struct traceeval_iterator *iter, + struct traceeval_type *type) +{ + struct entry *entry; + + if (!is_stat_type(type)) + return NULL; + + if (iter->next < 1 || iter->next > iter->nr_entries) + return NULL; + + entry = iter->entries[iter->next - 1]; + return &entry->val_stats[type->index]; +} From patchwork Thu Aug 17 22:24:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13357046 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2111BC7112F for ; Thu, 17 Aug 2023 22:24:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355695AbjHQWY1 (ORCPT ); Thu, 17 Aug 2023 18:24:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50014 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355708AbjHQWYU (ORCPT ); Thu, 17 Aug 2023 18:24:20 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 560AF30E6 for ; Thu, 17 Aug 2023 15:24:19 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 5259A66D1D for ; Thu, 17 Aug 2023 22:24:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2EDF8C433CC; Thu, 17 Aug 2023 22:24:17 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.96) (envelope-from ) id 1qWlPj-000UsQ-2Q; Thu, 17 Aug 2023 18:24:23 -0400 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: Ross Zwisler , Stevie Alvarez , "Steven Rostedt (Google)" Subject: [PATCH 4/9] libtraceeval: Add traceeval_iterator_remove() Date: Thu, 17 Aug 2023 18:24:17 -0400 Message-Id: <20230817222422.118568-5-rostedt@goodmis.org> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230817222422.118568-1-rostedt@goodmis.org> References: <20230817222422.118568-1-rostedt@goodmis.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (Google)" Add an API traceeval_iterator_remove() that is safe to call in the traceeval_iterator_next() loop. Currently, traceeval_remove() can also be called "safely", but that may change in the future. The main difference between traceeval_remove() and traceeval_iterator_remove() is that that traceeval_iterator_remove() will NULL out the entry in the sort array, and use this in the other iterator functions. If the entry is NULL, it will not be returned. Signed-off-by: Steven Rostedt (Google) --- include/traceeval-hist.h | 1 + src/histograms.c | 48 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/include/traceeval-hist.h b/include/traceeval-hist.h index d511c9c5f14c..7d67673ce7e5 100644 --- a/include/traceeval-hist.h +++ b/include/traceeval-hist.h @@ -190,5 +190,6 @@ int traceeval_iterator_query(struct traceeval_iterator *iter, const union traceeval_data **results); struct traceeval_stat *traceeval_iterator_stat(struct traceeval_iterator *iter, struct traceeval_type *type); +int traceeval_iterator_remove(struct traceeval_iterator *iter); #endif /* __LIBTRACEEVAL_HIST_H__ */ diff --git a/src/histograms.c b/src/histograms.c index fddd0f3587e2..0fbd9e0a353e 100644 --- a/src/histograms.c +++ b/src/histograms.c @@ -1305,10 +1305,13 @@ int traceeval_iterator_next(struct traceeval_iterator *iter, iter->next = 0; } - if (iter->next >= iter->nr_entries) - return 0; + do { + if (iter->next >= iter->nr_entries) + return 0; + + entry = iter->entries[iter->next++]; + } while (!entry); - entry = iter->entries[iter->next++]; *keys = entry->keys; return 1; } @@ -1338,6 +1341,9 @@ int traceeval_iterator_query(struct traceeval_iterator *iter, return 0; entry = iter->entries[iter->next - 1]; + if (!entry) + return 0; + *results = entry->vals; return 1; @@ -1363,5 +1369,39 @@ struct traceeval_stat *traceeval_iterator_stat(struct traceeval_iterator *iter, return NULL; entry = iter->entries[iter->next - 1]; - return &entry->val_stats[type->index]; + return entry ? &entry->val_stats[type->index] : NULL; +} + +/** + * traceeval_iterator_remove - remove the current iterator entry + * @iter: The iterator to remove the entry from + * + * This will remove the current entry from the histogram. + * This is useful if the current entry should be removed. It will not + * affect the traceeval_iterator_next(). + * + * Returns 1 if it successfully removed the entry, 0 if for some reason + * there was no "current entry" (called before traceeval_iterator_next()). + * or -1 on error. + */ +int traceeval_iterator_remove(struct traceeval_iterator *iter) +{ + struct traceeval *teval = iter->teval; + struct hash_table *hist = teval->hist; + struct entry *entry; + + if (iter->next < 1 || iter->next > iter->nr_entries) + return 0; + + entry = iter->entries[iter->next - 1]; + if (!entry) + return 0; + + hash_remove(hist, &entry->hash); + + /* The entry no longer exists */ + iter->entries[iter->next - 1] = NULL; + teval->update_counter++; + + return 1; } From patchwork Thu Aug 17 22:24:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13357051 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 96C02C71134 for ; Thu, 17 Aug 2023 22:24:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355712AbjHQWYa (ORCPT ); Thu, 17 Aug 2023 18:24:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50042 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355710AbjHQWYW (ORCPT ); Thu, 17 Aug 2023 18:24:22 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EC1C830C5 for ; Thu, 17 Aug 2023 15:24:19 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 5FFB866D7D for ; Thu, 17 Aug 2023 22:24:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 34080C433D9; Thu, 17 Aug 2023 22:24:17 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.96) (envelope-from ) id 1qWlPj-000UsX-2V; Thu, 17 Aug 2023 18:24:23 -0400 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: Ross Zwisler , Stevie Alvarez , "Steven Rostedt (Google)" Subject: [PATCH 5/9] libtraceeval histogram: Add type to traceeval_data and make it a structure Date: Thu, 17 Aug 2023 18:24:18 -0400 Message-Id: <20230817222422.118568-6-rostedt@goodmis.org> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230817222422.118568-1-rostedt@goodmis.org> References: <20230817222422.118568-1-rostedt@goodmis.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (Google)" Having a straight union for passing in the data that must match the types is dangerous and prone for buggy code. If some data doesn't match its type, there's nothing to catch it. Instead of having a union traceeval_data of each type, have it be a structure with a "type" field follow by a union, where the type defines what kind of data it is. Add helper macros to make it easy to define the data when using it. Signed-off-by: Steven Rostedt (Google) Reviewed-by: Ross Zwisler --- include/traceeval-hist.h | 88 ++++++++++++++++--------- samples/task-eval.c | 137 ++++++++++++++++----------------------- src/eval-local.h | 4 +- src/histograms.c | 68 +++++++++---------- 4 files changed, 150 insertions(+), 147 deletions(-) diff --git a/include/traceeval-hist.h b/include/traceeval-hist.h index 7d67673ce7e5..38d5dc878d3b 100644 --- a/include/traceeval-hist.h +++ b/include/traceeval-hist.h @@ -52,45 +52,75 @@ struct traceeval_dynamic { * Trace data entry for a traceeval histogram * Constitutes keys and values. */ -union traceeval_data { - struct traceeval_dynamic dyn_data; - char *string; - const char *cstring; - void *pointer; - unsigned long number; - unsigned long long number_64; - unsigned int number_32; - unsigned short number_16; - unsigned char number_8; +struct traceeval_data { + enum traceeval_data_type type; + union { + struct traceeval_dynamic dyn_data; + char *string; + const char *cstring; + void *pointer; + unsigned long number; + unsigned long long number_64; + unsigned int number_32; + unsigned short number_16; + unsigned char number_8; + }; }; +#define __TRACEEVAL_DATA(data_type, member, data) \ + { .type = TRACEEVAL_TYPE_##data_type, .member = (data) } + +#define DEFINE_TRACEEVAL_NUMBER(data) __TRACEEVAL_DATA(NUMBER, number, data) +#define DEFINE_TRACEEVAL_NUMBER_8(data) __TRACEEVAL_DATA(NUMBER_8, number_8, data) +#define DEFINE_TRACEEVAL_NUMBER_16(data) __TRACEEVAL_DATA(NUMBER_16, number_16, data) +#define DEFINE_TRACEEVAL_NUMBER_32(data) __TRACEEVAL_DATA(NUMBER_32, number_32, data) +#define DEFINE_TRACEEVAL_NUMBER_64(data) __TRACEEVAL_DATA(NUMBER_64, number_64, data) +#define DEFINE_TRACEEVAL_STRING(data) __TRACEEVAL_DATA(STRING, string, data) +#define DEFINE_TRACEEVAL_CSTRING(data) __TRACEEVAL_DATA(STRING, cstring, data) +#define DEFINE_TRACEEVAL_POINTER(data) __TRACEEVAL_DATA(POINTER, pointer, data) + +#define __TRACEEVAL_SET(data, data_type, member, val) \ + do { \ + (data).type = TRACEEVAL_TYPE_##data_type; \ + (data).member = (val); \ + } while (0) + +#define TRACEEVAL_SET_NUMBER(data, val) __TRACEEVAL_SET(data, NUMBER, number, val) +#define TRACEEVAL_SET_NUMBER_8(data, val) __TRACEEVAL_SET(data, NUMBER_8, number_8, val) +#define TRACEEVAL_SET_NUMBER_16(data, val) __TRACEEVAL_SET(data, NUMBER_16, number_16, val) +#define TRACEEVAL_SET_NUMBER_32(data, val) __TRACEEVAL_SET(data, NUMBER_32, number_32, val) +#define TRACEEVAL_SET_NUMBER_64(data, val) __TRACEEVAL_SET(data, NUMBER_64, number_64, val) +#define TRACEEVAL_SET_STRING(data, val) __TRACEEVAL_SET(data, STRING, string, val) +#define TRACEEVAL_SET_CSTRING(data, val) __TRACEEVAL_SET(data, STRING, cstring, val) +#define TRACEEVAL_SET_POINTER(data, val) __TRACEEVAL_SET(data, POINTER, pointer, val) + struct traceeval_type; struct traceeval; /* release function callback on traceeval_data */ typedef void (*traceeval_data_release_fn)(const struct traceeval_type *type, - union traceeval_data *data); + struct traceeval_data *data); /* compare function callback to compare traceeval_data */ typedef int (*traceeval_data_cmp_fn)(struct traceeval *teval, const struct traceeval_type *type, - const union traceeval_data *A, - const union traceeval_data *B); + const struct traceeval_data *A, + const struct traceeval_data *B); /* make a unique value */ typedef int (*traceeval_data_hash_fn)(struct traceeval *teval, const struct traceeval_type *type, - const union traceeval_data *data); + const struct traceeval_data *data); typedef int (*traceeval_data_copy_fn)(const struct traceeval_type *type, - union traceeval_data *dst, - const union traceeval_data *src); + struct traceeval_data *dst, + const struct traceeval_data *src); typedef int (*traceeval_cmp_fn)(struct traceeval *teval, - const union traceeval_data *Akeys, - const union traceeval_data *Avals, - const union traceeval_data *Bkeys, - const union traceeval_data *Bvals, + const struct traceeval_data *Akeys, + const struct traceeval_data *Avals, + const struct traceeval_data *Bkeys, + const struct traceeval_data *Bvals, void *data); /* @@ -157,20 +187,20 @@ struct traceeval *traceeval_init(struct traceeval_type *keys, void traceeval_release(struct traceeval *teval); int traceeval_insert(struct traceeval *teval, - const union traceeval_data *keys, - const union traceeval_data *vals); + const struct traceeval_data *keys, + const struct traceeval_data *vals); int traceeval_remove(struct traceeval *teval, - const union traceeval_data *keys); + const struct traceeval_data *keys); -int traceeval_query(struct traceeval *teval, const union traceeval_data *keys, - const union traceeval_data **results); +int traceeval_query(struct traceeval *teval, const struct traceeval_data *keys, + const struct traceeval_data **results); void traceeval_results_release(struct traceeval *teval, - const union traceeval_data *results); + const struct traceeval_data *results); struct traceeval_stat *traceeval_stat(struct traceeval *teval, - const union traceeval_data *keys, + const struct traceeval_data *keys, struct traceeval_type *type); unsigned long long traceeval_stat_max(struct traceeval_stat *stat); @@ -185,9 +215,9 @@ int traceeval_iterator_sort(struct traceeval_iterator *iter, const char *sort_fi int traceeval_iterator_sort_custom(struct traceeval_iterator *iter, traceeval_cmp_fn sort_fn, void *data); int traceeval_iterator_next(struct traceeval_iterator *iter, - const union traceeval_data **keys); + const struct traceeval_data **keys); int traceeval_iterator_query(struct traceeval_iterator *iter, - const union traceeval_data **results); + const struct traceeval_data **results); struct traceeval_stat *traceeval_iterator_stat(struct traceeval_iterator *iter, struct traceeval_type *type); int traceeval_iterator_remove(struct traceeval_iterator *iter); diff --git a/samples/task-eval.c b/samples/task-eval.c index bde167d1219b..ed3a1a95f097 100644 --- a/samples/task-eval.c +++ b/samples/task-eval.c @@ -190,21 +190,15 @@ static void update_process(struct task_data *tdata, const char *comm, enum sched_state state, enum command cmd, unsigned long long ts) { - union traceeval_data keys[] = { - { - .cstring = comm, - }, - { - .number = state, - }, + struct traceeval_data keys[] = { + DEFINE_TRACEEVAL_CSTRING( comm ), + DEFINE_TRACEEVAL_NUMBER( state ), }; - union traceeval_data vals[] = { - { - .number_64 = ts, - }, + struct traceeval_data vals[] = { + DEFINE_TRACEEVAL_NUMBER_64( ts ), }; - union traceeval_data new_vals[1] = { }; - const union traceeval_data *results; + struct traceeval_data new_vals[1] = { }; + const struct traceeval_data *results; int ret; switch (cmd) { @@ -222,14 +216,15 @@ static void update_process(struct task_data *tdata, const char *comm, if (!results[0].number_64) break; - new_vals[0].number_64 = ts - results[0].number_64; + TRACEEVAL_SET_NUMBER_64(new_vals[0], ts - results[0].number_64); ret = traceeval_insert(tdata->teval_processes.stop, keys, new_vals); if (ret < 0) pdie("Could not stop process"); /* Reset the start */ - new_vals[0].number_64 = 0; + TRACEEVAL_SET_NUMBER_64(new_vals[0], 0); + ret = traceeval_insert(tdata->teval_processes.start, keys, new_vals); if (ret < 0) pdie("Could not start CPU"); @@ -253,15 +248,11 @@ static void stop_process(struct task_data *tdata, const char *comm, static struct process_data * get_process_data(struct task_data *tdata, const char *comm) { - union traceeval_data keys[] = { - { - .cstring = comm, - }, - { - .number = RUNNING, - } + struct traceeval_data keys[] = { + DEFINE_TRACEEVAL_CSTRING( comm ), + DEFINE_TRACEEVAL_NUMBER( RUNNING ), }; - const union traceeval_data *results; + const struct traceeval_data *results; void *data; int ret; @@ -278,16 +269,12 @@ get_process_data(struct task_data *tdata, const char *comm) void set_process_data(struct task_data *tdata, const char *comm, void *data) { - union traceeval_data keys[] = { - { - .cstring = comm, - }, - { - .number = RUNNING, - } + struct traceeval_data keys[] = { + DEFINE_TRACEEVAL_CSTRING( comm ), + DEFINE_TRACEEVAL_NUMBER( RUNNING ), }; - union traceeval_data new_vals[1] = { }; - const union traceeval_data *results; + struct traceeval_data new_vals[1] = { }; + const struct traceeval_data *results; int ret; ret = traceeval_query(tdata->teval_processes_data, keys, &results); @@ -296,7 +283,7 @@ void set_process_data(struct task_data *tdata, const char *comm, void *data) if (ret < 0) pdie("Could not query process data"); - new_vals[0].pointer = data; + TRACEEVAL_SET_POINTER(new_vals[0], data); ret = traceeval_insert(tdata->teval_processes_data, keys, new_vals); if (ret < 0) pdie("Failed to set process data"); @@ -309,21 +296,15 @@ static void update_cpu(struct teval_pair *teval_pair, int cpu, enum sched_state state, enum command cmd, unsigned long long ts) { - const union traceeval_data *results; - union traceeval_data keys[] = { - { - .number = cpu, - }, - { - .number = state, - } + const struct traceeval_data *results; + struct traceeval_data keys[] = { + DEFINE_TRACEEVAL_NUMBER( cpu ), + DEFINE_TRACEEVAL_NUMBER( state ), }; - union traceeval_data vals[] = { - { - .number_64 = ts, - }, + struct traceeval_data vals[] = { + DEFINE_TRACEEVAL_NUMBER_64( ts ), }; - union traceeval_data new_vals[1] = { }; + struct traceeval_data new_vals[1] = { }; int ret; switch (cmd) { @@ -350,14 +331,14 @@ static void update_cpu(struct teval_pair *teval_pair, int cpu, if (!results[0].number_64) break; - new_vals[0].number_64 = ts - results[0].number_64; + TRACEEVAL_SET_NUMBER_64(new_vals[0], ts - results[0].number_64); ret = traceeval_insert(teval_pair->stop, keys, new_vals); if (ret < 0) pdie("Could not stop CPU"); /* Reset the start */ - new_vals[0].number_64 = 0; + TRACEEVAL_SET_NUMBER_64(new_vals[0], 0); ret = traceeval_insert(teval_pair->start, keys, new_vals); if (ret < 0) pdie("Could not start CPU"); @@ -385,21 +366,15 @@ static void update_thread(struct process_data *pdata, int tid, enum sched_state state, enum command cmd, unsigned long long ts) { - const union traceeval_data *results; - union traceeval_data keys[] = { - { - .number = tid, - }, - { - .number = state, - } + const struct traceeval_data *results; + struct traceeval_data keys[] = { + DEFINE_TRACEEVAL_NUMBER( tid ), + DEFINE_TRACEEVAL_NUMBER( state ), }; - union traceeval_data vals[] = { - { - .number_64 = ts, - }, + struct traceeval_data vals[] = { + DEFINE_TRACEEVAL_NUMBER_64( ts ), }; - union traceeval_data new_vals[1] = { }; + struct traceeval_data new_vals[1] = { }; int ret; switch (cmd) { @@ -415,7 +390,7 @@ static void update_thread(struct process_data *pdata, int tid, if (ret == 0) return; - new_vals[0].number_64 = ts - results[0].number_64; + TRACEEVAL_SET_NUMBER_64(new_vals[0], ts - results[0].number_64); ret = traceeval_insert(pdata->teval_threads.stop, keys, new_vals); traceeval_results_release(pdata->teval_threads.start, results); @@ -646,17 +621,19 @@ static void print_microseconds(int idx, unsigned long long nsecs) * If RUNNING is equal, then sort by COMM. */ static int compare_pdata(struct traceeval *teval_data, - const union traceeval_data *Akeys, - const union traceeval_data *Avals, - const union traceeval_data *Bkeys, - const union traceeval_data *Bvals, + const struct traceeval_data *Akeys, + const struct traceeval_data *Avals, + const struct traceeval_data *Bkeys, + const struct traceeval_data *Bvals, void *data) { struct traceeval *teval = data; /* The deltas are here */ - union traceeval_data keysA[] = { - { .cstring = Akeys[0].cstring }, { .number = RUNNING } }; - union traceeval_data keysB[] = { - { .cstring = Bkeys[0].cstring }, { .number = RUNNING } }; + struct traceeval_data keysA[] = { + DEFINE_TRACEEVAL_CSTRING( Akeys[0].cstring ), + DEFINE_TRACEEVAL_NUMBER( RUNNING ), }; + struct traceeval_data keysB[] = { + DEFINE_TRACEEVAL_CSTRING( Bkeys[0].cstring ), + DEFINE_TRACEEVAL_NUMBER( RUNNING ), }; struct traceeval_stat *statA; struct traceeval_stat *statB; unsigned long long totalA = -1; @@ -690,7 +667,7 @@ static int compare_pdata(struct traceeval *teval_data, static void display_cpus(struct traceeval *teval) { struct traceeval_iterator *iter = traceeval_iterator_get(teval); - const union traceeval_data *keys; + const struct traceeval_data *keys; struct traceeval_stat *stat; int last_cpu = -1; @@ -762,7 +739,7 @@ static void display_state_times(int state, unsigned long long total) static void display_threads(struct traceeval *teval) { struct traceeval_iterator *iter = traceeval_iterator_get(teval); - const union traceeval_data *keys; + const struct traceeval_data *keys; struct traceeval_stat *stat; int last_tid = -1; @@ -802,13 +779,9 @@ static void display_process_stats(struct traceeval *teval, { struct traceeval_stat *stat; unsigned long long delta; - union traceeval_data keys[] = { - { - .cstring = comm, - }, - { - .number = RUNNING, - } + struct traceeval_data keys[] = { + DEFINE_TRACEEVAL_CSTRING( comm ), + DEFINE_TRACEEVAL_NUMBER( RUNNING ), }; for (int i = 0; i < OTHER; i++) { @@ -826,13 +799,13 @@ static void display_processes(struct traceeval *teval, struct traceeval *teval_data) { struct traceeval_iterator *iter = traceeval_iterator_get(teval_data); - const union traceeval_data *keys; + const struct traceeval_data *keys; int ret; traceeval_iterator_sort_custom(iter, compare_pdata, teval); while (traceeval_iterator_next(iter, &keys) > 0) { - const union traceeval_data *results; + const struct traceeval_data *results; struct process_data *pdata = NULL; const char *comm = keys[0].cstring; @@ -857,7 +830,7 @@ static void display(struct task_data *tdata) { struct traceeval *teval = tdata->teval_cpus.stop; struct traceeval_iterator *iter = traceeval_iterator_get(teval); - const union traceeval_data *keys; + const struct traceeval_data *keys; struct traceeval_stat *stat; unsigned long long total_time = 0; unsigned long long idle_time = 0; diff --git a/src/eval-local.h b/src/eval-local.h index 73f52efdf0da..26b3c9b29929 100644 --- a/src/eval-local.h +++ b/src/eval-local.h @@ -56,8 +56,8 @@ struct traceeval_stat { /* A key-value pair */ struct entry { struct hash_item hash; - union traceeval_data *keys; - union traceeval_data *vals; + struct traceeval_data *keys; + struct traceeval_data *vals; struct traceeval_stat *val_stats; }; diff --git a/src/histograms.c b/src/histograms.c index 0fbd9e0a353e..7c0eef6cf421 100644 --- a/src/histograms.c +++ b/src/histograms.c @@ -37,8 +37,8 @@ static void print_err(const char *fmt, ...) */ static int compare_traceeval_data(struct traceeval *teval, struct traceeval_type *type, - const union traceeval_data *orig, - const union traceeval_data *copy) + const struct traceeval_data *orig, + const struct traceeval_data *copy) { int i; @@ -86,14 +86,14 @@ static int compare_traceeval_data(struct traceeval *teval, } /* - * Compare arrays of union traceeval_data's with respect to @def. + * Compare arrays of struct traceeval_data's with respect to @def. * * Return 1 if @orig and @copy are the same, 0 if not, and -1 on error. */ static int compare_traceeval_data_set(struct traceeval *teval, struct traceeval_type *defs, - union traceeval_data *orig, - const union traceeval_data *copy, size_t size) + struct traceeval_data *orig, + const struct traceeval_data *copy, size_t size) { int check; size_t i; @@ -335,7 +335,7 @@ fail: /* * Frees dynamic data in @data if @type specifies a dynamic data type. */ -static void clean_data(union traceeval_data *data, struct traceeval_type *type) +static void clean_data(struct traceeval_data *data, struct traceeval_type *type) { if (type->release) type->release(type, data); @@ -352,7 +352,7 @@ static void clean_data(union traceeval_data *data, struct traceeval_type *type) /* * Free any specified dynamic data in @data. */ -static void clean_data_set(union traceeval_data *data, struct traceeval_type *defs, +static void clean_data_set(struct traceeval_data *data, struct traceeval_type *defs, size_t size) { size_t i; @@ -431,7 +431,7 @@ void traceeval_release(struct traceeval *teval) free(teval); } -static unsigned make_hash(struct traceeval *teval, const union traceeval_data *keys, +static unsigned make_hash(struct traceeval *teval, const struct traceeval_data *keys, int bits) { const struct traceeval_type *types = teval->key_types; @@ -470,7 +470,7 @@ static unsigned make_hash(struct traceeval *teval, const union traceeval_data *k * * Returns 1 on success, 0 if no match found, -1 on error. */ -static int get_entry(struct traceeval *teval, const union traceeval_data *keys, +static int get_entry(struct traceeval *teval, const struct traceeval_data *keys, struct entry **result) { struct hash_table *hist = teval->hist; @@ -506,8 +506,8 @@ static int get_entry(struct traceeval *teval, const union traceeval_data *keys, */ static int copy_traceeval_data(struct traceeval_type *type, struct traceeval_stat *stat, - union traceeval_data *dst, - const union traceeval_data *src) + struct traceeval_data *dst, + const struct traceeval_data *src) { unsigned long long val; @@ -597,7 +597,7 @@ static int copy_traceeval_data(struct traceeval_type *type, * * Does not call the release() callback if a copy() exists. */ -static void data_release(size_t size, union traceeval_data *data, +static void data_release(size_t size, struct traceeval_data *data, struct traceeval_type *type) { for (size_t i = 0; i < size; i++) { @@ -610,7 +610,7 @@ static void data_release(size_t size, union traceeval_data *data, } } -static void data_release_and_free(size_t size, union traceeval_data **data, +static void data_release_and_free(size_t size, struct traceeval_data **data, struct traceeval_type *type) { data_release(size, *data, type); @@ -625,8 +625,8 @@ static void data_release_and_free(size_t size, union traceeval_data **data, */ static int dup_traceeval_data_set(size_t size, struct traceeval_type *type, struct traceeval_stat *stats, - const union traceeval_data *orig, - union traceeval_data **copy) + const struct traceeval_data *orig, + struct traceeval_data **copy) { size_t i; @@ -669,8 +669,8 @@ fail: * * Returns 1 if found, 0 if not found, and -1 on error. */ -int traceeval_query(struct traceeval *teval, const union traceeval_data *keys, - const union traceeval_data **results) +int traceeval_query(struct traceeval *teval, const struct traceeval_data *keys, + const struct traceeval_data **results) { struct entry *entry; int check; @@ -698,7 +698,7 @@ int traceeval_query(struct traceeval *teval, const union traceeval_data *keys, * allow traceeval to clean up its references. */ void traceeval_results_release(struct traceeval *teval, - const union traceeval_data *results) + const struct traceeval_data *results) { if (!teval || !results) { if (!teval) @@ -708,7 +708,7 @@ void traceeval_results_release(struct traceeval *teval, } static struct entry *create_hist_entry(struct traceeval *teval, - const union traceeval_data *keys) + const struct traceeval_data *keys) { struct hash_table *hist = teval->hist; unsigned key = make_hash(teval, keys, hist->bits); @@ -729,11 +729,11 @@ static struct entry *create_hist_entry(struct traceeval *teval, * Returns 0 on success, -1 on error. */ static int create_entry(struct traceeval *teval, - const union traceeval_data *keys, - const union traceeval_data *vals) + const struct traceeval_data *keys, + const struct traceeval_data *vals) { - union traceeval_data *new_keys; - union traceeval_data *new_vals; + struct traceeval_data *new_keys; + struct traceeval_data *new_vals; struct entry *entry; entry = create_hist_entry(teval, keys); @@ -780,12 +780,12 @@ fail_entry: * Return 0 on success, -1 on error. */ static int update_entry(struct traceeval *teval, struct entry *entry, - const union traceeval_data *vals) + const struct traceeval_data *vals) { struct traceeval_stat *stats = entry->val_stats; struct traceeval_type *types = teval->val_types; - union traceeval_data *copy = entry->vals; - union traceeval_data old[teval->nr_val_types]; + struct traceeval_data *copy = entry->vals; + struct traceeval_data old[teval->nr_val_types]; size_t size = teval->nr_val_types; size_t i; @@ -831,7 +831,7 @@ static bool is_stat_type(struct traceeval_type *type) } struct traceeval_stat *traceeval_stat(struct traceeval *teval, - const union traceeval_data *keys, + const struct traceeval_data *keys, struct traceeval_type *type) { struct entry *entry; @@ -923,8 +923,8 @@ unsigned long long traceeval_stat_count(struct traceeval_stat *stat) * Returns 0 on success, and -1 on error. */ int traceeval_insert(struct traceeval *teval, - const union traceeval_data *keys, - const union traceeval_data *vals) + const struct traceeval_data *keys, + const struct traceeval_data *vals) { struct entry *entry; int check; @@ -955,7 +955,7 @@ int traceeval_insert(struct traceeval *teval, * -1 if there was an error. */ int traceeval_remove(struct traceeval *teval, - const union traceeval_data *keys) + const struct traceeval_data *keys) { struct hash_table *hist = teval->hist; struct entry *entry; @@ -1174,8 +1174,8 @@ static int iter_cmp(const void *A, const void *B, void *data) for (int i = 0; i < iter->nr_sort; i++) { struct traceeval_type *type; - union traceeval_data *dataA; - union traceeval_data *dataB; + struct traceeval_data *dataA; + struct traceeval_data *dataB; type = iter->sort[i]; @@ -1293,7 +1293,7 @@ int traceeval_iterator_sort_custom(struct traceeval_iterator *iter, * Returns 1 if another entry is returned, or 0 if not (or negative on error) */ int traceeval_iterator_next(struct traceeval_iterator *iter, - const union traceeval_data **keys) + const struct traceeval_data **keys) { struct entry *entry; int ret; @@ -1333,7 +1333,7 @@ int traceeval_iterator_next(struct traceeval_iterator *iter, * Returns 1 if another entry is returned, or 0 if not (or negative on error) */ int traceeval_iterator_query(struct traceeval_iterator *iter, - const union traceeval_data **results) + const struct traceeval_data **results) { struct entry *entry; From patchwork Thu Aug 17 22:24:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13357045 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4529FC71130 for ; Thu, 17 Aug 2023 22:24:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355707AbjHQWY3 (ORCPT ); Thu, 17 Aug 2023 18:24:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49966 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355703AbjHQWYU (ORCPT ); Thu, 17 Aug 2023 18:24:20 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4BE0930E1 for ; Thu, 17 Aug 2023 15:24:19 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 5246B66CCE for ; Thu, 17 Aug 2023 22:24:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 343DBC43391; Thu, 17 Aug 2023 22:24:17 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.96) (envelope-from ) id 1qWlPj-000Usb-2a; Thu, 17 Aug 2023 18:24:23 -0400 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: Ross Zwisler , Stevie Alvarez , "Steven Rostedt (Google)" Subject: [PATCH 6/9] libtraceveal: Add type checks to traceeval_data vals and keys Date: Thu, 17 Aug 2023 18:24:19 -0400 Message-Id: <20230817222422.118568-7-rostedt@goodmis.org> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230817222422.118568-1-rostedt@goodmis.org> References: <20230817222422.118568-1-rostedt@goodmis.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (Google)" Now that the traceeval_data has a type, add checks to traceeval_insert() and traceveal_query() as well as traceeval_stat() to make sure the keys and vals match the types that were for the traceeval. Signed-off-by: Steven Rostedt (Google) --- src/histograms.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/histograms.c b/src/histograms.c index 7c0eef6cf421..560046cc8d96 100644 --- a/src/histograms.c +++ b/src/histograms.c @@ -479,10 +479,16 @@ static int get_entry(struct traceeval *teval, const struct traceeval_data *keys, struct hash_item *item; unsigned key; int check = 0; + int i; if (!teval || !keys) return -1; + for (i = 0; i < teval->nr_key_types; i++) { + if (keys[i].type != teval->key_types[i].type) + return -1; + } + key = make_hash(teval, keys, hist->bits); for (iter = hash_iter_bucket(hist, key); (item = hash_iter_bucket_next(iter)); ) { @@ -928,10 +934,16 @@ int traceeval_insert(struct traceeval *teval, { struct entry *entry; int check; + int i; entry = NULL; check = get_entry(teval, keys, &entry); + for (i = 0; i < teval->nr_val_types; i++) { + if (vals[i].type != teval->val_types[i].type) + return -1; + } + if (check == -1) return check; From patchwork Thu Aug 17 22:24:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13357044 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0F12EC678DF for ; Thu, 17 Aug 2023 22:24:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355698AbjHQWY2 (ORCPT ); Thu, 17 Aug 2023 18:24:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49982 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355706AbjHQWYU (ORCPT ); Thu, 17 Aug 2023 18:24:20 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 50A9530DF for ; Thu, 17 Aug 2023 15:24:18 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id D357866A03 for ; Thu, 17 Aug 2023 22:24:17 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2A161C433CB; Thu, 17 Aug 2023 22:24:17 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.96) (envelope-from ) id 1qWlPj-000Usf-2e; Thu, 17 Aug 2023 18:24:23 -0400 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: Ross Zwisler , Stevie Alvarez , "Steven Rostedt (Google)" Subject: [PATCH 7/9] libtraceeval: Add size checks to insert and query functions Date: Thu, 17 Aug 2023 18:24:20 -0400 Message-Id: <20230817222422.118568-8-rostedt@goodmis.org> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230817222422.118568-1-rostedt@goodmis.org> References: <20230817222422.118568-1-rostedt@goodmis.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (Google)" Currently, there's nothing that checks the size of the keys/values being passed into traceeval_query() and traceeval_insert(). Make functions that take the size of those arrays: traceeval_query_size() traceeval_insert_size() and convert the traceeval_query() and traceeval_insert() into macros that calculate the size of the fields to pass in: #define traceeval_query(teval, keys, results) \ traceeval_query_size(teval, sizeof(keys) / sizeof(keys[0]), results) and this will allow the code to check to make sure the size matches what is expected (note, that currently is not done, but can be added). If the keys or vals is not an array, but instead a pointer, if one of the macros is used, the compiler will complain with: warning: division sizeof (const struct traceeval_data *) / sizeof (const struct traceeval_data) does not compute the number of array elements [-Wsizeof-pointer-div] 190 | sizeof(keys) / sizeof(keys[0]), results); Then the user would need to call the "_size()" function directly (as is done in the sample code, where the keys received by an iterator is used for a query) Signed-off-by: Steven Rostedt (Google) --- include/traceeval-hist.h | 18 +++++++++++++----- src/histograms.c | 10 +++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/include/traceeval-hist.h b/include/traceeval-hist.h index 38d5dc878d3b..81fe805e691d 100644 --- a/include/traceeval-hist.h +++ b/include/traceeval-hist.h @@ -186,15 +186,23 @@ struct traceeval *traceeval_init(struct traceeval_type *keys, void traceeval_release(struct traceeval *teval); -int traceeval_insert(struct traceeval *teval, - const struct traceeval_data *keys, - const struct traceeval_data *vals); +int traceeval_insert_size(struct traceeval *teval, + const struct traceeval_data *keys, size_t nr_keys, + const struct traceeval_data *vals, size_t nr_vals); + +#define traceeval_insert(teval, keys, vals) \ + traceeval_insert_size(teval, keys, sizeof(keys) / sizeof(keys[0]), \ + vals, sizeof(vals) / sizeof(vals[0])) int traceeval_remove(struct traceeval *teval, const struct traceeval_data *keys); -int traceeval_query(struct traceeval *teval, const struct traceeval_data *keys, - const struct traceeval_data **results); +int traceeval_query_size(struct traceeval *teval, const struct traceeval_data *keys, + size_t nr_keys, const struct traceeval_data **results); + +#define traceeval_query(teval, keys, results) \ + traceeval_query_size(teval, keys, \ + sizeof(keys) / sizeof(keys[0]), results); void traceeval_results_release(struct traceeval *teval, const struct traceeval_data *results); diff --git a/src/histograms.c b/src/histograms.c index 560046cc8d96..5e2e9200cbf6 100644 --- a/src/histograms.c +++ b/src/histograms.c @@ -675,8 +675,8 @@ fail: * * Returns 1 if found, 0 if not found, and -1 on error. */ -int traceeval_query(struct traceeval *teval, const struct traceeval_data *keys, - const struct traceeval_data **results) +int traceeval_query_size(struct traceeval *teval, const struct traceeval_data *keys, + size_t nr_keys, const struct traceeval_data **results) { struct entry *entry; int check; @@ -928,9 +928,9 @@ unsigned long long traceeval_stat_count(struct traceeval_stat *stat) * * Returns 0 on success, and -1 on error. */ -int traceeval_insert(struct traceeval *teval, - const struct traceeval_data *keys, - const struct traceeval_data *vals) +int traceeval_insert_size(struct traceeval *teval, + const struct traceeval_data *keys, size_t nr_keys, + const struct traceeval_data *vals, size_t nr_vals) { struct entry *entry; int check; From patchwork Thu Aug 17 22:24:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13357049 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 64A82C71132 for ; Thu, 17 Aug 2023 22:24:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355708AbjHQWY2 (ORCPT ); Thu, 17 Aug 2023 18:24:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49998 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355707AbjHQWYU (ORCPT ); Thu, 17 Aug 2023 18:24:20 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7C00430E9 for ; Thu, 17 Aug 2023 15:24:19 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 56F1C66B63 for ; Thu, 17 Aug 2023 22:24:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 35915C433CD; Thu, 17 Aug 2023 22:24:17 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.96) (envelope-from ) id 1qWlPj-000Usj-2i; Thu, 17 Aug 2023 18:24:23 -0400 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: Ross Zwisler , Stevie Alvarez , "Steven Rostedt (Google)" Subject: [PATCH 8/9] libtraceeval: Add checks to traceeval_insert() and query() Date: Thu, 17 Aug 2023 18:24:21 -0400 Message-Id: <20230817222422.118568-9-rostedt@goodmis.org> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230817222422.118568-1-rostedt@goodmis.org> References: <20230817222422.118568-1-rostedt@goodmis.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (Google)" Now that there are size functions for traceeval_insert() and traceveal_query(), add checks to make sure that the size being passed in is actually the size expected. Signed-off-by: Steven Rostedt (Google) Reviewed-by: Ross Zwisler --- src/histograms.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/histograms.c b/src/histograms.c index 5e2e9200cbf6..973bf3ad279c 100644 --- a/src/histograms.c +++ b/src/histograms.c @@ -684,6 +684,9 @@ int traceeval_query_size(struct traceeval *teval, const struct traceeval_data *k if (!teval || !keys || !results) return -1; + if (nr_keys != teval->nr_key_types) + return -1; + /* find key and copy its corresponding value pair */ if ((check = get_entry(teval, keys, &entry)) < 1) return check; @@ -936,6 +939,9 @@ int traceeval_insert_size(struct traceeval *teval, int check; int i; + if (nr_keys != teval->nr_key_types || nr_vals != teval->nr_val_types) + return -1; + entry = NULL; check = get_entry(teval, keys, &entry); From patchwork Thu Aug 17 22:24:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13357048 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 760ECC71131 for ; Thu, 17 Aug 2023 22:24:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1355710AbjHQWYa (ORCPT ); Thu, 17 Aug 2023 18:24:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50026 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1355709AbjHQWYU (ORCPT ); Thu, 17 Aug 2023 18:24:20 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 85CB930F1 for ; Thu, 17 Aug 2023 15:24:19 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 5E3CA66D8E for ; Thu, 17 Aug 2023 22:24:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 41CB2C43397; Thu, 17 Aug 2023 22:24:17 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.96) (envelope-from ) id 1qWlPj-000Usn-2m; Thu, 17 Aug 2023 18:24:23 -0400 From: Steven Rostedt To: linux-trace-devel@vger.kernel.org Cc: Ross Zwisler , Stevie Alvarez , "Steven Rostedt (Google)" Subject: [PATCH 9/9] libtraceeval: Only do stats on values marked with the STAT flag Date: Thu, 17 Aug 2023 18:24:22 -0400 Message-Id: <20230817222422.118568-10-rostedt@goodmis.org> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230817222422.118568-1-rostedt@goodmis.org> References: <20230817222422.118568-1-rostedt@goodmis.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org From: "Steven Rostedt (Google)" Add TRACEEVAL_FL_STAT to perform stats on the value, otherwise ignore it. Signed-off-by: Steven Rostedt (Google) --- include/traceeval-hist.h | 1 + samples/task-eval.c | 1 + src/histograms.c | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/traceeval-hist.h b/include/traceeval-hist.h index 81fe805e691d..34f01a51a334 100644 --- a/include/traceeval-hist.h +++ b/include/traceeval-hist.h @@ -36,6 +36,7 @@ enum traceeval_flags { TRACEEVAL_FL_VALUE = (1 << 1), TRACEEVAL_FL_SIGNED = (1 << 2), TRACEEVAL_FL_TIMESTAMP = (1 << 3), + TRACEEVAL_FL_STAT = (1 << 3), }; /* diff --git a/samples/task-eval.c b/samples/task-eval.c index ed3a1a95f097..0e3acb7644ef 100644 --- a/samples/task-eval.c +++ b/samples/task-eval.c @@ -147,6 +147,7 @@ static struct traceeval_type delta_vals[] = { { .type = TRACEEVAL_TYPE_NUMBER_64, .name = "delta", + .flags = TRACEEVAL_FL_STAT, }, { .type = TRACEEVAL_TYPE_NONE, diff --git a/src/histograms.c b/src/histograms.c index 973bf3ad279c..8f1cf4187713 100644 --- a/src/histograms.c +++ b/src/histograms.c @@ -571,7 +571,7 @@ static int copy_traceeval_data(struct traceeval_type *type, return 0; } - if (!stat) + if (!stat || !(type->flags & TRACEEVAL_FL_STAT)) return 0; if (!stat->count++) {