From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.6 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 31561C43457 for ; Mon, 12 Oct 2020 13:37:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E010C2222E for ; Mon, 12 Oct 2020 13:37:40 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UOHpDeYm" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730992AbgJLNh1 (ORCPT ); Mon, 12 Oct 2020 09:37:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58788 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729934AbgJLNhO (ORCPT ); Mon, 12 Oct 2020 09:37:14 -0400 Received: from mail-wr1-x444.google.com (mail-wr1-x444.google.com [IPv6:2a00:1450:4864:20::444]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E036CC0613DC for ; Mon, 12 Oct 2020 06:36:42 -0700 (PDT) Received: by mail-wr1-x444.google.com with SMTP id x7so10627979wrl.3 for ; Mon, 12 Oct 2020 06:36:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0ZiYvgJmwEaAbc61G30SdrrBhl//EoKenKIaWmqCYPg=; b=UOHpDeYmchR+ZPDTkvzgyy0vSrhEDG1ZfqKT3l7lS4Gq9nvBfYcSwbIrQYBdHT54TI 1HUtc3PS4ZTSocnRU55mFUzzwjaxiyd4E5Y/hwq8vlIuBpbsiYzPLNJkFcf8La+S9W96 AtPoIyU1Eq7B3Cuji9D46pBAnw0SIJchBBQuoDQ4LTafA0cBROy8+CSviuOd6NPntcna laBqdRUFV/OuJJdkN9E5OtT0yq8BpOhIx+meKKk1LYFNh24vZL8KhF0tFT2/4zkYDhAQ ERsMSJafEA/5vd63rgEY25f6P6rnLt9CEeRTw8QBTlw0qugNxhsh7MUnA64yqOa3Sh6c smPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0ZiYvgJmwEaAbc61G30SdrrBhl//EoKenKIaWmqCYPg=; b=Pnrq585Md7hYGaWyVC4DwYuYZLjF5/Gl7euEDo+u34/A+5qb3By88lE3G4P4KSk1pp 9wWb2nqo5S4O+L0InQONocgdgaBqqt7Tgsl/uLuSAFp1vTFmaygAux8fDkTFYSTdo9nE uhUYqcUUVag606TGjqdPj4OmsdfnQcRy+ra0p3LElfCY2dWUkPHZvm09cAls5LaW6o1N Vfrak26myjjy+3z/qu8cgcpOAIRsHZwik4ISj6kapDpvrV2z4ZIb6D84cwS9dnGiwF01 Qf4Pwx2NPnr7xWSrci7mudELRJYWxCjO86t8YNmIUqbcGptk9ILUsHnHfl5UpGmyUXUD yBIQ== X-Gm-Message-State: AOAM530+QeE0z2ACN6KOYEnV1rHXUW8vy6VYLCz0k6Ojg67wF1qFpFx6 VN7hR09s4CEmMzWZHU2nWNu+GmYJjrY= X-Google-Smtp-Source: ABdhPJx4zwhaRhg0Ft5pF5b63b7NUu2oAvY2/ZxsXNbKv/H+mfCzJ9gMFK4W1JhTXF4EWSMCurKYSA== X-Received: by 2002:a5d:5092:: with SMTP id a18mr26328164wrt.323.1602509801592; Mon, 12 Oct 2020 06:36:41 -0700 (PDT) Received: from localhost.localdomain ([84.40.93.41]) by smtp.gmail.com with ESMTPSA id k5sm23145388wmb.19.2020.10.12.06.36.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 12 Oct 2020 06:36:41 -0700 (PDT) From: "Yordan Karadzhov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org, "Yordan Karadzhov (VMware)" Subject: [PATCH v2 19/20] kernel-shark: Add methods for time calibration Date: Mon, 12 Oct 2020 16:35:22 +0300 Message-Id: <20201012133523.469040-20-y.karadz@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20201012133523.469040-1-y.karadz@gmail.com> References: <20201012133523.469040-1-y.karadz@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org We add an infrastructure for correcting the timestamps of the entries. This is needed in order to correlate Data streams that have been recorded using non-synchronized clocks. The infrastructure can handle an arbitrary timestamps correction formula, however for the moment we only provide calibration that adds a constant offset. Signed-off-by: Yordan Karadzhov (VMware) --- src/libkshark-tepdata.c | 13 +++++- src/libkshark.c | 99 +++++++++++++++++++++++++++++++++++++++++ src/libkshark.h | 27 +++++++++++ 3 files changed, 138 insertions(+), 1 deletion(-) diff --git a/src/libkshark-tepdata.c b/src/libkshark-tepdata.c index d9d57843..31cb33d5 100644 --- a/src/libkshark-tepdata.c +++ b/src/libkshark-tepdata.c @@ -296,6 +296,9 @@ static ssize_t get_records(struct kshark_context *kshark_ctx, entry = &temp_rec->entry; missed_events_action(stream, rec, entry); + /* Apply time calibration. */ + kshark_postprocess_entry(stream, rec, entry); + entry->stream_id = stream->stream_id; temp_next = &temp_rec->next; @@ -316,6 +319,12 @@ static ssize_t get_records(struct kshark_context *kshark_ctx, entry->stream_id = stream->stream_id; + /* + * Post-process the content of the entry. This includes + * time calibration and event-specific plugin actions. + */ + kshark_postprocess_entry(stream, rec, entry); + pid = entry->pid; /* Apply Id filtering. */ @@ -481,8 +490,10 @@ static ssize_t tepdata_load_matrix(struct kshark_data_stream *stream, if (cpu_array) (*cpu_array)[count] = e->cpu; - if (ts_array) + if (ts_array) { + kshark_calib_entry(stream, e); (*ts_array)[count] = e->ts; + } if (pid_array) (*pid_array)[count] = e->pid; diff --git a/src/libkshark.c b/src/libkshark.c index 6f99dd6c..33476ed0 100644 --- a/src/libkshark.c +++ b/src/libkshark.c @@ -131,6 +131,7 @@ static void kshark_stream_free(struct kshark_data_stream *stream) kshark_hash_id_free(stream->tasks); + free(stream->calib_array); free(stream->file); free(stream->name); free(stream); @@ -862,6 +863,37 @@ void kshark_plugin_actions(struct kshark_data_stream *stream, } } +/** + * @brief Time calibration of the timestamp of the entry. + * + * @param stream: Input location for a Trace data stream pointer. + * @param entry: Output location for entry. + */ +void kshark_calib_entry(struct kshark_data_stream *stream, + struct kshark_entry *entry) +{ + if (stream->calib && stream->calib_array) { + /* Calibrate the timestamp of the entry. */ + stream->calib(&entry->ts, stream->calib_array); + } +} + +/** + * @brief Post-process the content of the entry. This includes time calibration + * and all registered event-specific plugin actions. + * + * @param stream: Input location for a Trace data stream pointer. + * @param record: Input location for the trace record. + * @param entry: Output location for entry. + */ +void kshark_postprocess_entry(struct kshark_data_stream *stream, + void *record, struct kshark_entry *entry) +{ + kshark_calib_entry(stream, entry); + + kshark_plugin_actions(stream, record, entry); +} + static inline void free_ptr(void *ptr) { if (ptr) @@ -1259,6 +1291,73 @@ kshark_get_entry_back(const struct kshark_entry_request *req, return get_entry(req, data, index, req->first, end, -1); } +static int compare_time(const void* a, const void* b) +{ + const struct kshark_entry *entry_a, *entry_b; + + entry_a = *(const struct kshark_entry **) a; + entry_b = *(const struct kshark_entry **) b; + + if (entry_a->ts > entry_b->ts) + return 1; + + if (entry_a->ts < entry_b->ts) + return -1; + + return 0; +} + +static void kshark_data_qsort(struct kshark_entry **entries, size_t size) +{ + qsort(entries, size, sizeof(struct kshark_entry *), compare_time); +} + +/** + * Add constant offset to the timestamp of the entry. To be used by the sream + * object as a System clock calibration callback function. + */ +void kshark_offset_calib(int64_t *ts, int64_t *argv) +{ + *ts += argv[0]; +} + +/** + * @brief Apply constant offset to the timestamps of all entries from a given + * Data stream. + * + * @param kshark_ctx: Input location for the session context pointer. + * @param entries: Input location for the trace data. + * @param size: The size of the trace data. + * @param sd: Data stream identifier. + * @param offset: The constant offset to be added (in nanosecond). + */ +void kshark_set_clock_offset(struct kshark_context *kshark_ctx, + struct kshark_entry **entries, size_t size, + int sd, int64_t offset) +{ + struct kshark_data_stream *stream; + int64_t correction; + + stream = kshark_get_data_stream(kshark_ctx, sd); + if (!stream) + return; + + if (!stream->calib_array) { + stream->calib = kshark_offset_calib; + stream->calib_array = calloc(1, sizeof(*stream->calib_array)); + stream->calib_array_size = 1; + } + + correction = offset - stream->calib_array[0]; + stream->calib_array[0] = offset; + + for (size_t i = 0; i < size; ++i) + if (entries[i]->stream_id == sd) + entries[i]->ts += correction; + + kshark_data_qsort(entries, size); +} + static int first_in_time_entry(struct kshark_entry_data_set *buffer, int n_buffers, size_t *count) { int64_t t_min = INT64_MAX; diff --git a/src/libkshark.h b/src/libkshark.h index fbe1b2ac..dc30665b 100644 --- a/src/libkshark.h +++ b/src/libkshark.h @@ -115,6 +115,12 @@ void kshark_hash_id_free(struct kshark_hash_id *hash); int *kshark_hash_ids(struct kshark_hash_id *hash); +/** + * Timestamp calibration function type. To be user for system clock + * calibration. + */ +typedef void (*time_calib_func) (int64_t *, int64_t *); + struct kshark_data_stream; /** A function type to be used to initialize the interface of the data stream. */ @@ -315,6 +321,15 @@ struct kshark_data_stream { /** The number of plugins registered for this stream.*/ int n_plugins; + /** System clock calibration function. */ + time_calib_func calib; + + /** An array of time calibration constants. */ + int64_t *calib_array; + + /** The size of the array of time calibration constants. */ + size_t calib_array_size; + /** List of Plugin's Event handlers. */ struct kshark_event_proc_handler *event_handlers; @@ -669,6 +684,12 @@ void kshark_clear_all_filters(struct kshark_context *kshark_ctx, void kshark_plugin_actions(struct kshark_data_stream *stream, void *record, struct kshark_entry *entry); +void kshark_calib_entry(struct kshark_data_stream *stream, + struct kshark_entry *entry); + +void kshark_postprocess_entry(struct kshark_data_stream *stream, + void *record, struct kshark_entry *entry); + /** Search failed identifiers. */ enum kshark_search_failed { /** All entries have greater timestamps. */ @@ -1059,6 +1080,12 @@ struct kshark_config_doc *kshark_open_config_file(const char *file_name, struct kshark_config_doc *kshark_json_to_conf(struct json_object *jobj); +void kshark_offset_calib(int64_t *ts, int64_t *atgv); + +void kshark_set_clock_offset(struct kshark_context *kshark_ctx, + struct kshark_entry **entries, size_t size, + int sd, int64_t offset); + /** Structure representing a data set made of KernelShark entries. */ struct kshark_entry_data_set { /** Array of entries pointers. */ -- 2.25.1