Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 11845789 authored by Hector Dearman's avatar Hector Dearman
Browse files

Atrace: Add commandline flags to enable/disable userland tracing

Adds a commandline flag to Atrace for Perfetto: --only_userspace.

When --only_userspace is passed atrace does everything atrace
would normally do to set up/tear down tracing (set various system
properties, poke services etc) but doesn't modify any ftrace
settings, doesn't clear read or otherwise touch the ftrace buffer,
and doesn't start or stop tracing.

Perfetto allows recording and collection of ftrace kernel events
(as systrace/atrace does for local devices). We currently integrate
with atrace to collect non-kernel events using the async_start and
async_stop command line arguments. These cause atrace to poke
binder/hal services and apps then Perfetto scrapes the print ftrace
events from the kernel ring buffer.

There are two downsides:
1. Atrace attempts drain the ftrace buffer after Perfetto has already
   done so.
2. Any time Atrace starts/stops it modifies the global ftrace settings and
   clears the ring buffer.

The second is especially unfortunate as otherwise Perfetto supports
multiplexing multiple simultaneous traces.

This flag would make it much easier to integrate atrace and Perfetto.

To test:

First enable ftrace:
$ adb shell 'echo 2048 > /d/tracing/buffer_size_kb'
$ adb shell 'echo > /d/tracing/trace'
$ adb shell 'echo 1 > /d/tracing/tracing_on'

Next turn on the input category.
$ adb shell atrace --async_start --only_userspace input
Touch the screen a bunch.
$ adb shell cat /d/tracing/trace
Now you should see many events.

Next turn off the input category.
$ adb shell atrace --async_stop --only_userspace
Clear tracing.
$ adb shell 'echo > /d/tracing/trace'
Touch the screen a bunch.
$ adb shell cat /d/tracing/trace
You should see no events.

Ftrace settings should not have been touched:
$ adb shell cat /d/tracing/tracing_on
Should be 1 still.
$ adb shell cat /d/tracing/buffer_size_kb
Should be 2048 still.

Bug: 73625407
Test: see above.
Change-Id: Ia43ab689c4f93280315eb984581187c1582c2b07
parent 405a40c5
Loading
Loading
Loading
Loading
+68 −37
Original line number Original line Diff line number Diff line
@@ -774,22 +774,10 @@ static bool setCategoriesEnableFromFile(const char* categories_file)
    return ok;
    return ok;
}
}


// Set all the kernel tracing settings to the desired state for this trace
static bool setUpUserspaceTracing()
// capture.
static bool setUpTrace()
{
{
    bool ok = true;
    bool ok = true;


    // Set up the tracing options.
    ok &= setCategoriesEnableFromFile(g_categoriesFile);
    ok &= setTraceOverwriteEnable(g_traceOverwrite);
    ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
    // TODO: Re-enable after stabilization
    //ok &= setCmdlineSize();
    ok &= setClock();
    ok &= setPrintTgidEnableIfPresent(true);
    ok &= setKernelTraceFuncs(g_kernelTraceFuncs);

    // Set up the tags property.
    // Set up the tags property.
    uint64_t tags = 0;
    uint64_t tags = 0;
    for (size_t i = 0; i < arraysize(k_categories); i++) {
    for (size_t i = 0; i < arraysize(k_categories); i++) {
@@ -827,6 +815,37 @@ static bool setUpTrace()
        ok &= ServiceUtility::PokeServices();
        ok &= ServiceUtility::PokeServices();
    }
    }


    return ok;
}

static void cleanUpUserspaceTracing()
{
    setTagsProperty(0);
    clearAppProperties();
    pokeBinderServices();

    if (g_tracePdx) {
        ServiceUtility::PokeServices();
    }
}


// Set all the kernel tracing settings to the desired state for this trace
// capture.
static bool setUpKernelTracing()
{
    bool ok = true;

    // Set up the tracing options.
    ok &= setCategoriesEnableFromFile(g_categoriesFile);
    ok &= setTraceOverwriteEnable(g_traceOverwrite);
    ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
    // TODO: Re-enable after stabilization
    //ok &= setCmdlineSize();
    ok &= setClock();
    ok &= setPrintTgidEnableIfPresent(true);
    ok &= setKernelTraceFuncs(g_kernelTraceFuncs);

    // Disable all the sysfs enables.  This is done as a separate loop from
    // Disable all the sysfs enables.  This is done as a separate loop from
    // the enables to allow the same enable to exist in multiple categories.
    // the enables to allow the same enable to exist in multiple categories.
    ok &= disableKernelTraceEvents();
    ok &= disableKernelTraceEvents();
@@ -854,20 +873,11 @@ static bool setUpTrace()
}
}


// Reset all the kernel tracing settings to their default state.
// Reset all the kernel tracing settings to their default state.
static void cleanUpTrace()
static void cleanUpKernelTracing()
{
{
    // Disable all tracing that we're able to.
    // Disable all tracing that we're able to.
    disableKernelTraceEvents();
    disableKernelTraceEvents();


    // Reset the system properties.
    setTagsProperty(0);
    clearAppProperties();
    pokeBinderServices();

    if (g_tracePdx) {
        ServiceUtility::PokeServices();
    }

    // Set the options back to their defaults.
    // Set the options back to their defaults.
    setTraceOverwriteEnable(true);
    setTraceOverwriteEnable(true);
    setTraceBufferSizeKB(1);
    setTraceBufferSizeKB(1);
@@ -875,7 +885,6 @@ static void cleanUpTrace()
    setKernelTraceFuncs(NULL);
    setKernelTraceFuncs(NULL);
}
}



// Enable tracing in the kernel.
// Enable tracing in the kernel.
static bool startTrace()
static bool startTrace()
{
{
@@ -1107,6 +1116,7 @@ int main(int argc, char **argv)
    bool traceStop = true;
    bool traceStop = true;
    bool traceDump = true;
    bool traceDump = true;
    bool traceStream = false;
    bool traceStream = false;
    bool onlyUserspace = false;


    if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
    if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
        showHelp(argv[0]);
        showHelp(argv[0]);
@@ -1125,6 +1135,7 @@ int main(int argc, char **argv)
            {"async_start",       no_argument, 0,  0 },
            {"async_start",       no_argument, 0,  0 },
            {"async_stop",        no_argument, 0,  0 },
            {"async_stop",        no_argument, 0,  0 },
            {"async_dump",        no_argument, 0,  0 },
            {"async_dump",        no_argument, 0,  0 },
            {"only_userspace",    no_argument, 0,  0 },
            {"list_categories",   no_argument, 0,  0 },
            {"list_categories",   no_argument, 0,  0 },
            {"stream",            no_argument, 0,  0 },
            {"stream",            no_argument, 0,  0 },
            {           0,                  0, 0,  0 }
            {           0,                  0, 0,  0 }
@@ -1197,6 +1208,8 @@ int main(int argc, char **argv)
                    async = true;
                    async = true;
                    traceStart = false;
                    traceStart = false;
                    traceStop = false;
                    traceStop = false;
                } else if (!strcmp(long_options[option_index].name, "only_userspace")) {
                    onlyUserspace = true;
                } else if (!strcmp(long_options[option_index].name, "stream")) {
                } else if (!strcmp(long_options[option_index].name, "stream")) {
                    traceStream = true;
                    traceStream = true;
                    traceDump = false;
                    traceDump = false;
@@ -1214,6 +1227,14 @@ int main(int argc, char **argv)
        }
        }
    }
    }


    if (onlyUserspace) {
        if (!async || !(traceStart || traceStop)) {
            fprintf(stderr, "--only_userspace can only be used with "
                    "--async_start or --async_stop\n");
            exit(1);
        }
    }

    registerSigHandler();
    registerSigHandler();


    if (g_initialSleepSecs > 0) {
    if (g_initialSleepSecs > 0) {
@@ -1221,13 +1242,19 @@ int main(int argc, char **argv)
    }
    }


    bool ok = true;
    bool ok = true;

    if (traceStart) {
    if (traceStart) {
        ok &= setUpTrace();
        ok &= setUpUserspaceTracing();
    }

    if (ok && traceStart && !onlyUserspace) {
        ok &= setUpKernelTracing();
        ok &= startTrace();
        ok &= startTrace();
    }
    }


    if (ok && traceStart) {
    if (ok && traceStart) {
        if (!traceStream) {

        if (!traceStream && !onlyUserspace) {
            printf("capturing trace...");
            printf("capturing trace...");
            fflush(stdout);
            fflush(stdout);
        }
        }
@@ -1237,6 +1264,7 @@ int main(int argc, char **argv)
        // contain entries from only one CPU can cause "begin" entries without a
        // contain entries from only one CPU can cause "begin" entries without a
        // matching "end" entry to show up if a task gets migrated from one CPU to
        // matching "end" entry to show up if a task gets migrated from one CPU to
        // another.
        // another.
        if (!onlyUserspace)
            ok = clearTrace();
            ok = clearTrace();


        writeClockSyncMarker();
        writeClockSyncMarker();
@@ -1258,10 +1286,10 @@ int main(int argc, char **argv)
    }
    }


    // Stop the trace and restore the default settings.
    // Stop the trace and restore the default settings.
    if (traceStop)
    if (traceStop && !onlyUserspace)
        stopTrace();
        stopTrace();


    if (ok && traceDump) {
    if (ok && traceDump && !onlyUserspace) {
        if (!g_traceAborted) {
        if (!g_traceAborted) {
            printf(" done\n");
            printf(" done\n");
            fflush(stdout);
            fflush(stdout);
@@ -1288,8 +1316,11 @@ int main(int argc, char **argv)
    }
    }


    // Reset the trace buffer size to 1.
    // Reset the trace buffer size to 1.
    if (traceStop)
    if (traceStop) {
        cleanUpTrace();
        cleanUpUserspaceTracing();
        if (!onlyUserspace)
            cleanUpKernelTracing();
    }


    return g_traceAborted ? 1 : 0;
    return g_traceAborted ? 1 : 0;
}
}