Re: [PATCH v7 8/9] trace-cmd: Implemented new option in trace.dat file: TRACECMD_OPTION_TIME_SHIFT

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Mar 19, 2019 at 5:56 PM Tzvetomir Stoyanov <tstoyanov@xxxxxxxxxx> wrote:
> +static unsigned long long timestamp_correct(unsigned long long ts,
> +                                           struct tracecmd_input *handle)
> +{
> +       int min, mid, max;
> +
> +       if (handle->ts_offset)
> +               return ts + handle->ts_offset;
> +       if (!handle->ts_corr_count || !handle->ts_corr)
> +               return ts;
> +
> +       /* We have one sample, nothing to calc here */
> +       if (handle->ts_corr_count == 1)
> +               return ts + handle->ts_corr[0].offset;
> +
> +       /* We have two samples, nothing to search here */
> +       if (handle->ts_corr_count == 2)
> +               return timestamp_correction_calc(ts, &handle->ts_corr[0],
> +                                                &handle->ts_corr[1]);
> +
> +       /* We have more than two samples */
> +       min = 0;
> +       max = handle->ts_corr_count-1;
> +       mid = (min + max)/2;
> +       while (min <= max) {
> +               if (ts >= handle->ts_corr[mid].time &&
> +                   (mid == handle->ts_corr_count-1 ||
> +                    ts < handle->ts_corr[mid+1].time))
> +                       break;
> +               if (ts < handle->ts_corr[mid].time) {
> +                       if (mid == 0)
> +                               break;
> +                       min = mid-1;
> +               } else if (ts >= handle->ts_corr[mid+1].time)
> +                       max = mid + 1;
> +               mid = (min + max)/2;
> +       }
> +
> +       if (mid >= handle->ts_corr_count-2)
> +               return timestamp_correction_calc(ts, &handle->ts_corr[handle->ts_corr_count-2],
> +                                                &handle->ts_corr[handle->ts_corr_count-1]);
> +
> +       return timestamp_correction_calc(ts, &handle->ts_corr[mid],
> +                                        &handle->ts_corr[mid+1]);

We can handle the edge cases first (ts is out of range) which would
simplify the search. Something like (untested):

    if (ts <= handle->ts_corr[0]) {
                   return timestamp_correction_calc(ts,
&handle->ts_corr[0], &handle->ts_corr[1]);
    } else if (ts >= handle->ts_corr[handle->ts_corr_count-1]) {
                   return timestamp_correction_calc(ts,
&handle->ts_corr[handle->ts_corr_count-2],
&handle->ts_corr[handle->ts_corr_count-1]);
    }

    min = 0;
    max = handle->ts_corr_count-1;
    mid = (min + max) / 2;
    while (min <= max) {
             if (ts < handle->ts_corr[mid].time)
                    min = mid - 1;
             else if (ts > handle->ts_corr[mid].time)
                   max = mid + 1;
             else
                   break;
             mid = (min + max) / 2;
      }
      return timestamp_correction_calc(ts, &handle->ts_corr[mid],
&handle->ts_corr[mid+1]);

Too bad there's no lower_bound() in libc and bsearch() doesn't quite
cut it here.

> +}
> +
>  /*
>   * Page is mapped, now read in the page header info.
>   */
> @@ -1049,7 +1116,7 @@ static int update_page_info(struct tracecmd_input *handle, int cpu)
>                     kbuffer_subbuffer_size(kbuf));
>                 return -1;
>         }
> -       handle->cpu_data[cpu].timestamp = kbuffer_timestamp(kbuf) + handle->ts_offset;
> +       handle->cpu_data[cpu].timestamp = timestamp_correct(kbuffer_timestamp(kbuf), handle);
>
>         if (handle->ts2secs)
>                 handle->cpu_data[cpu].timestamp *= handle->ts2secs;
> @@ -1776,7 +1843,7 @@ read_again:
>                 goto read_again;
>         }
>
> -       handle->cpu_data[cpu].timestamp = ts + handle->ts_offset;
> +       handle->cpu_data[cpu].timestamp = timestamp_correct(ts, handle);
>
>         if (handle->ts2secs) {
>                 handle->cpu_data[cpu].timestamp *= handle->ts2secs;
> @@ -2101,6 +2168,42 @@ void tracecmd_set_ts2secs(struct tracecmd_input *handle,
>         handle->use_trace_clock = false;
>  }
>
> +static int tsync_offset_cmp(const void *a, const void *b)
> +{
> +       struct ts_offset_sample *ts_a = (struct ts_offset_sample *)a;
> +       struct ts_offset_sample *ts_b = (struct ts_offset_sample *)b;
> +
> +       if (ts_a->time > ts_b->time)
> +               return 1;
> +       if (ts_a->time < ts_b->time)
> +               return -1;
> +       return 0;
> +}
> +
> +static void tsync_offset_load(struct tracecmd_input *handle, char *buf)
> +{
> +       int i, j;
> +       long long *buf8 = (long long *)buf;
> +
> +       for (i = 0; i < handle->ts_corr_count; i++) {
> +               handle->ts_corr[i].time = tep_read_number(handle->pevent,
> +                                                         buf8+i, 8);
> +               handle->ts_corr[i].offset = tep_read_number(handle->pevent,
> +                                               buf8+handle->ts_corr_count+i, 8);
> +       }
> +       qsort(handle->ts_corr,
> +             handle->ts_corr_count, sizeof(struct ts_offset_sample),
> +             tsync_offset_cmp);
> +       /* Filter possible samples with equal time */
> +       for (i = 0, j = 0; i < handle->ts_corr_count; i++) {
> +               if (i == 0 ||
> +                   handle->ts_corr[i].time != handle->ts_corr[i-1].time) {
> +                       handle->ts_corr[j++].time = handle->ts_corr[i].time;
> +                       handle->ts_corr[j++].offset = handle->ts_corr[i].offset;

`j` needs to be increment only once here. How about:

              if (i == 0 || handle->ts_corr[i].time !=
handle->ts_corr[i-1].time)
                    handle->ts_corr[j++] = handle->ts_corr[i];

Thanks!

-- Slavi




[Index of Archives]     [Linux USB Development]     [Linux USB Development]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux