diff options
| author | Khem Raj <raj.khem@gmail.com> | 2013-01-23 22:04:02 -0800 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2013-01-28 12:25:36 +0000 |
| commit | af17e816dd4ee0c2a7401f26a148129ad8f8e1fa (patch) | |
| tree | cc9dd18f5436270a417f421d12f21dac2e5b01c9 | |
| parent | 8fb1e3b74b01095cbc626497f1a7c71145343af3 (diff) | |
| download | openembedded-core-af17e816dd4ee0c2a7401f26a148129ad8f8e1fa.tar.gz openembedded-core-af17e816dd4ee0c2a7401f26a148129ad8f8e1fa.tar.bz2 openembedded-core-af17e816dd4ee0c2a7401f26a148129ad8f8e1fa.zip | |
systemd: Upgrade to 197
LGPL-2.1 licensce is updated to reflect the new FSF address
Drop patches to disable argparse and dbus-python
analyser has been implemented in C lets use that patch
and get rid of the python version
disable hostname detection for uclibc bases systems
since uclibc lacks NSS
Signed-off-by: Khem Raj <raj.khem@gmail.com>
Signed-off-by: Saul Wold <sgw@linux.intel.com>
Conflicts:
meta/recipes-core/systemd/systemd_197.bb
| -rw-r--r-- | meta/recipes-core/systemd/systemd/0001-Revert-systemd-analyze-use-argparse-instead-of-getop.patch | 106 | ||||
| -rw-r--r-- | meta/recipes-core/systemd/systemd/0001-systemd-analyze-rewrite-in-C.patch | 1087 | ||||
| -rw-r--r-- | meta/recipes-core/systemd/systemd/0002-Revert-analyze-use-GDBus-instead-of-dbus-python.patch | 94 | ||||
| -rw-r--r-- | meta/recipes-core/systemd/systemd_197.bb (renamed from meta/recipes-core/systemd/systemd_196.bb) | 12 |
4 files changed, 1094 insertions, 205 deletions
diff --git a/meta/recipes-core/systemd/systemd/0001-Revert-systemd-analyze-use-argparse-instead-of-getop.patch b/meta/recipes-core/systemd/systemd/0001-Revert-systemd-analyze-use-argparse-instead-of-getop.patch deleted file mode 100644 index 1e208a244f..0000000000 --- a/meta/recipes-core/systemd/systemd/0001-Revert-systemd-analyze-use-argparse-instead-of-getop.patch +++ /dev/null @@ -1,106 +0,0 @@ -Upstream-Status: Backport [revert] -Signed-off-by: Koen Kooi <koen@dominion.thruhere.net> - -From 2003e63f48cee2f497de7b90b66284f98c1c9919 Mon Sep 17 00:00:00 2001 -From: Koen Kooi <koen@dominion.thruhere.net> -Date: Mon, 10 Dec 2012 12:24:32 +0100 -Subject: [PATCH 1/2] Revert "systemd-analyze: use argparse instead of getopt" - -This reverts commit 0c0271841ab45595f71528c50bcf1904d4b841d5. - -Argparse is broken in current OE python ---- - src/analyze/systemd-analyze | 60 ++++++++++++++++++++++++++++--------------- - 1 files changed, 39 insertions(+), 21 deletions(-) - -diff --git a/src/analyze/systemd-analyze b/src/analyze/systemd-analyze -index 88699d6..87a83dd 100755 ---- a/src/analyze/systemd-analyze -+++ b/src/analyze/systemd-analyze -@@ -1,7 +1,6 @@ - #!/usr/bin/python - --import sys, os --import argparse -+import getopt, sys, os - from gi.repository import Gio - try: - import cairo -@@ -76,6 +75,20 @@ def draw_text(context, x, y, text, size = 12, r = 0, g = 0, b = 0, vcenter = 0.5 - - context.restore() - -+def usage(): -+ sys.stdout.write("""systemd-analyze [--user] time -+systemd-analyze [--user] blame -+systemd-analyze [--user] plot -+ -+Process systemd profiling information -+ -+ -h --help Show this help -+""") -+ -+def help(): -+ usage() -+ sys.exit() -+ - def time(): - - initrd_time, start_time, finish_time = acquire_start_time() -@@ -266,29 +279,34 @@ def plot(): - - surface.finish() - --parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, -- description='Process systemd profiling information', -- epilog='''\ --time - print time spent in the kernel before reaching userspace --blame - print list of running units ordered by time to init --plot - output SVG graphic showing service initialization --''') -- --parser.add_argument('action', choices=('time', 'blame', 'plot'), -- default='time', nargs='?', -- help='action to perform (default: time)') --parser.add_argument('--user', action='store_true', -- help='use the session bus') -+def unknown_verb(): -+ sys.stderr.write("Unknown verb '%s'.\n" % args[0]) -+ usage() -+ sys.exit(1) - --args = parser.parse_args() -+bus = Gio.BusType.SYSTEM - --if args.user: -- bus = Gio.BusType.SESSION --else: -- bus = Gio.BusType.SYSTEM -+try: -+ opts, args = getopt.gnu_getopt(sys.argv[1:], "h", ["help", "user"]) -+except getopt.GetoptError as err: -+ sys.stdout.write(str(err) + "\n") -+ usage() -+ sys.exit(2) -+for o, a in opts: -+ if o in ("-h", "--help"): -+ help() -+ elif o == '--user': -+ bus = Gio.BusType.SESSION -+ else: -+ assert False, "unhandled option" - - verb = {'time' : time, - 'blame': blame, - 'plot' : plot, -+ 'help' : help, - } --verb.get(args.action)() -+ -+if len(args) == 0: -+ time() -+else: -+ verb.get(args[0], unknown_verb)() --- -1.7.7.6 - diff --git a/meta/recipes-core/systemd/systemd/0001-systemd-analyze-rewrite-in-C.patch b/meta/recipes-core/systemd/systemd/0001-systemd-analyze-rewrite-in-C.patch new file mode 100644 index 0000000000..b278390fef --- /dev/null +++ b/meta/recipes-core/systemd/systemd/0001-systemd-analyze-rewrite-in-C.patch @@ -0,0 +1,1087 @@ +Upstream-Status: Pending + +From 523f304facdf3dbc09dbcdcff500ddce60274987 Mon Sep 17 00:00:00 2001 +From: Peeters Simon <peeters.simon@gmail.com> +Date: Thu, 17 Jan 2013 14:34:25 -0800 +Subject: [PATCH] systemd-analyze: rewrite in C. + +Written by Peeters Simon <peeters.simon@gmail.com>. Makefile stuff +and cleaned up a bit by Auke Kok <auke-jan.h.kok@intel.com>. +--- + Makefile.am | 21 +- + src/analyze/systemd-analyze.c | 684 +++++++++++++++++++++++++++++++++++++++++ + src/analyze/systemd-analyze.in | 328 -------------------- + 3 files changed, 694 insertions(+), 339 deletions(-) + create mode 100644 src/analyze/systemd-analyze.c + delete mode 100755 src/analyze/systemd-analyze.in + +Index: systemd-197/Makefile.am +=================================================================== +--- systemd-197.orig/Makefile.am 2013-01-07 17:37:15.391966148 -0800 ++++ systemd-197/Makefile.am 2013-01-24 10:06:11.219490786 -0800 +@@ -185,7 +185,8 @@ + systemd-ask-password \ + systemd-tty-ask-password-agent \ + systemd-tmpfiles \ +- systemd-machine-id-setup ++ systemd-machine-id-setup \ ++ systemd-analyze + + bin_PROGRAMS = \ + systemd-cgls \ +@@ -220,14 +221,16 @@ + systemd-fstab-generator \ + systemd-system-update-generator + +-dist_bin_SCRIPTS = \ +- src/analyze/systemd-analyze ++systemd_analyze_SOURCES = \ ++ src/analyze/systemd-analyze.c + +-EXTRA_DIST += \ +- src/analyze/systemd-analyze.in ++systemd_analyze_CFLAGS = \ ++ $(AM_CFLAGS) \ ++ $(DBUS_CFLAGS) + +-CLEANFILES += \ +- src/analyze/systemd-analyze ++systemd_analyze_LDADD = \ ++ libsystemd-shared.la \ ++ libsystemd-dbus.la + + dist_bashcompletion_DATA = \ + shell-completion/systemd-bash-completion.sh +@@ -3839,10 +3842,6 @@ + $(SED_PROCESS) + $(AM_V_GEN)chmod +x $@ + +-src/analyze/systemd-analyze: %: %.in Makefile +- $(SED_PROCESS) +- $(AM_V_GEN)chmod +x $@ +- + src/%.c: src/%.gperf + $(AM_V_at)$(MKDIR_P) $(dir $@) + $(AM_V_GEN)$(GPERF) < $< > $@ +Index: systemd-197/src/analyze/systemd-analyze.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ systemd-197/src/analyze/systemd-analyze.c 2013-01-24 10:06:11.219490786 -0800 +@@ -0,0 +1,684 @@ ++#include <stdio.h> ++#include <stdlib.h> ++#include <getopt.h> ++#include <locale.h> ++ ++#include "install.h" ++#include "log.h" ++#include "dbus-common.h" ++#include "build.h" ++#include "util.h" ++ ++#define svg(...) printf(__VA_ARGS__) ++ ++static UnitFileScope arg_scope = UNIT_FILE_SYSTEM; ++ ++struct unit_times { ++ char *name; ++ unsigned long long int ixt; ++ unsigned long long int iet; ++ unsigned long long int axt; ++ unsigned long long int aet; ++}; ++ ++ ++unsigned long long int property_getull( ++ DBusConnection *bus, ++ const char *dest, ++ const char *path, ++ const char *interface, ++ const char *property) ++{ ++ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; ++ DBusMessageIter iter, sub; ++ unsigned long long int result = 0; ++ union { ++ char byte; ++ dbus_int16_t i16; ++ dbus_uint16_t u16; ++ dbus_int32_t i32; ++ dbus_uint32_t u32; ++ dbus_int64_t i64; ++ dbus_uint64_t u64; ++ } dbus_result; ++ ++ int r = bus_method_call_with_reply ( ++ bus, ++ dest, ++ path, ++ "org.freedesktop.DBus.Properties", ++ "Get", ++ &reply, ++ NULL, ++ DBUS_TYPE_STRING, &interface, ++ DBUS_TYPE_STRING, &property, ++ DBUS_TYPE_INVALID); ++ if (r) ++ goto finish; ++ ++ if (!dbus_message_iter_init(reply, &iter) || ++ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) ++ goto finish; ++ ++ dbus_message_iter_recurse(&iter, &sub); ++ ++ switch(dbus_message_iter_get_arg_type(&sub)) { ++ case DBUS_TYPE_BYTE: ++ dbus_message_iter_get_basic(&sub, &dbus_result.byte); ++ result = dbus_result.byte; ++ break; ++ case DBUS_TYPE_INT16: ++ dbus_message_iter_get_basic(&sub, &dbus_result.i16); ++ result = dbus_result.i16; ++ break; ++ case DBUS_TYPE_UINT16: ++ dbus_message_iter_get_basic(&sub, &dbus_result.u16); ++ result = dbus_result.u16; ++ break; ++ case DBUS_TYPE_INT32: ++ dbus_message_iter_get_basic(&sub, &dbus_result.i32); ++ result = dbus_result.i32; ++ break; ++ case DBUS_TYPE_UINT32: ++ dbus_message_iter_get_basic(&sub, &dbus_result.u32); ++ result = dbus_result.u32; ++ break; ++ case DBUS_TYPE_INT64: ++ dbus_message_iter_get_basic(&sub, &dbus_result.i64); ++ result = dbus_result.i64; ++ break; ++ case DBUS_TYPE_UINT64: ++ dbus_message_iter_get_basic(&sub, &dbus_result.u64); ++ result = dbus_result.u64; ++ break; ++ default: ++ goto finish; ++ } ++finish: ++ return result; ++} ++ ++static int compare_unit_times1(const void *a, const void *b) { ++ const struct unit_times *u = a, *v = b; ++ ++ return (int)(v->aet - v->ixt) - (int)(u->aet - u->ixt); ++} ++ ++static int compare_unit_times2(const void *a, const void *b) { ++ const struct unit_times *u = a, *v = b; ++ ++ return (long long int)(u->ixt) - (long long int)(v->ixt); ++} ++ ++int acquire_time_data(DBusConnection *bus, struct unit_times **out) ++{ ++ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; ++ DBusMessageIter iter, sub, sub2; ++ unsigned int c = 0, n_units = 0; ++ struct unit_times *unit_times = NULL; ++ int r = bus_method_call_with_reply ( ++ bus, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "ListUnits", ++ &reply, ++ NULL, ++ DBUS_TYPE_INVALID); ++ if (r) ++ goto finish; ++ ++ if (!dbus_message_iter_init(reply, &iter) || ++ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY || ++ dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) { ++ log_error("Failed to parse reply."); ++ r = -EIO; ++ goto finish; ++ } ++ ++ dbus_message_iter_recurse(&iter, &sub); ++ ++ while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) { ++ struct unit_times *u; ++ char *path; ++ ++ if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) { ++ log_error("Failed to parse reply."); ++ r = -EIO; ++ goto finish; ++ } ++ ++ if (c >= n_units) { ++ struct unit_times *w; ++ ++ n_units = MAX(2*c, 16); ++ w = realloc(unit_times, sizeof(struct unit_times) * n_units); ++ ++ if (!w) { ++ log_error("Failed to allocate unit array."); ++ r = -ENOMEM; ++ goto finish; ++ } ++ ++ unit_times = w; ++ } ++ u = unit_times+c; ++ ++ dbus_message_iter_recurse(&sub, &sub2); ++ ++ if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &u->name, true) < 0 || ++ dbus_message_iter_next(&sub2), dbus_message_iter_next(&sub2), dbus_message_iter_next(&sub2), ++ dbus_message_iter_next(&sub2), dbus_message_iter_next(&sub2), ++ bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &path, true) < 0) { ++ log_error("Failed to parse reply."); ++ r = -EIO; ++ goto finish; ++ } ++ u->name = strdup(u->name); ++ u->ixt = property_getull(bus, ++ "org.freedesktop.systemd1", ++ path, ++ "org.freedesktop.systemd1.Unit", ++ "InactiveExitTimestampMonotonic"); ++ u->iet = property_getull(bus, ++ "org.freedesktop.systemd1", ++ path, ++ "org.freedesktop.systemd1.Unit", ++ "InactiveEnterTimestampMonotonic"); ++ u->axt = property_getull(bus, ++ "org.freedesktop.systemd1", ++ path, ++ "org.freedesktop.systemd1.Unit", ++ "ActiveExitTimestampMonotonic"); ++ u->aet = property_getull(bus, ++ "org.freedesktop.systemd1", ++ path, ++ "org.freedesktop.systemd1.Unit", ++ "ActiveEnterTimestampMonotonic"); ++ dbus_message_iter_next(&sub); ++ if (u->ixt == 0) ++ continue; ++ c++; ++ } ++ ++ *out = unit_times; ++ return c; ++finish: ++ free(unit_times); ++ return r; ++} ++ ++static void svg_graph_box(int height, long long int begin, long long int end, float scale_x, float scale_y) ++{ ++ double d = 0.0; ++ int i = 0; ++ ++ /* outside box, fill */ ++ svg("<rect class=\"box\" x=\"%.03f\" y=\"0\" width=\"%.03f\" height=\"%.03f\" />\n", ++ 0, ++ scale_x * (end - begin), ++ scale_y * height); ++ ++ for (d = 0.000001 * begin; d <= 0.000001 * end; ++ d += 0.1) { ++ /* lines for each second */ ++ if (i % 50 == 0) ++ svg(" <line class=\"sec5\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n", ++ scale_x * d, ++ scale_x * d, ++ scale_y * height); ++ else if (i % 10 == 0) ++ svg(" <line class=\"sec1\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n", ++ scale_x * d, ++ scale_x * d, ++ scale_y * height); ++ else ++ svg(" <line class=\"sec01\" x1=\"%.03f\" y1=\"0\" x2=\"%.03f\" y2=\"%.03f\" />\n", ++ scale_x * d, ++ scale_x * d, ++ scale_y * height); ++ ++ /* time label */ ++ if (i % 10 == 0) ++ svg(" <text class=\"sec\" x=\"%.03f\" y=\"%.03f\" >%.01fs</text>\n", ++ scale_x * d, -5.0, d); ++ ++ i++; ++ } ++} ++ ++int analyze_plot(DBusConnection *bus) ++{ ++ struct unit_times *times; ++ int n = acquire_time_data(bus, ×); ++ int m = n + 1; ++ unsigned long long int firmware_time, loader_time, kernel_time, initrd_time, userspace_time, finish_time; ++ long long int starttime = 0; ++ ++ float scale_x = 100.0; ++ float scale_y = 20.0; ++ ++ if (n<=0) ++ return -n; ++ ++ qsort(times, n, sizeof(struct unit_times), compare_unit_times2); ++ ++ firmware_time = property_getull(bus, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "FirmwareTimestampMonotonic"); ++ loader_time = property_getull(bus, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "LoaderTimestampMonotonic"); ++ kernel_time = property_getull(bus, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "KernelTimestamp"); ++ initrd_time = property_getull(bus, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "InitRDTimestampMonotonic"); ++ userspace_time = property_getull(bus, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "UserspaceTimestampMonotonic"); ++ finish_time = property_getull(bus, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "FinishTimestampMonotonic"); ++ ++ ++ if (firmware_time > 0) { ++ m++; ++ starttime += firmware_time - loader_time; ++ } ++ if (loader_time > 0) { ++ m++; ++ starttime += loader_time; ++ } ++ if (initrd_time > 0) ++ m += 2; ++ else if (kernel_time > 0) ++ m++; ++ ++ float width = 80.0 + (scale_x * (starttime + finish_time) * 0.000001); ++ float height = 150.0 + (m* scale_y); ++ ++ svg("<?xml version=\"1.0\" standalone=\"no\"?>\n"); ++ svg("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" "); ++ svg("\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"); ++ ++ //svg("<g transform=\"translate(10,%d)\">\n", 1000 + 150 + (pcount * 20)); ++ svg("<svg width=\"%.0fpx\" height=\"%.0fpx\" version=\"1.1\" ", width, height); ++ svg("xmlns=\"http://www.w3.org/2000/svg\">\n\n"); ++ ++ /* write some basic info as a comment, including some help */ ++ svg("<!-- This file is a systemd-analyze SVG file. It is best rendered in a -->\n"); ++ svg("<!-- browser such as Chrome/Chromium, firefox. Other applications that -->\n"); ++ svg("<!-- render these files properly but much more slow are ImageMagick, -->\n"); ++ svg("<!-- gimp, inkscape, etc.. To display the files on your system, just -->\n"); ++ svg("<!-- point your browser to file:///var/log/ and click. -->\n\n"); ++ svg("<!-- this plot was generated by systemd-analyze version %-16.16s -->\n\n", VERSION); ++ ++ /* style sheet */ ++ svg("<defs>\n <style type=\"text/css\">\n <![CDATA[\n"); ++ ++ svg(" rect { stroke-width: 1; stroke-opacity: 0; }\n"); ++ svg(" rect.activating { fill: rgb(255,0,0); fill-opacity: 0.7; }\n"); ++ svg(" rect.active { fill: rgb(200,150,150); fill-opacity: 0.7; }\n"); ++ svg(" rect.deactivating { fill: rgb(150,100,100); fill-opacity: 0.7; }\n"); ++ svg(" rect.kernel { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"); ++ svg(" rect.initrd { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"); ++ svg(" rect.firmware { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"); ++ svg(" rect.loader { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"); ++ svg(" rect.userspace { fill: rgb(150,150,150); fill-opacity: 0.7; }\n"); ++ svg(" rect.cpu { fill: rgb(64,64,240); stroke-width: 0; fill-opacity: 0.7; }\n"); ++ svg(" rect.wait { fill: rgb(240,240,0); stroke-width: 0; fill-opacity: 0.7; }\n"); ++ svg(" rect.bi { fill: rgb(240,128,128); stroke-width: 0; fill-opacity: 0.7; }\n"); ++ svg(" rect.bo { fill: rgb(192,64,64); stroke-width: 0; fill-opacity: 0.7; }\n"); ++ svg(" rect.ps { fill: rgb(192,192,192); stroke: rgb(128,128,128); fill-opacity: 0.7; }\n"); ++ svg(" rect.krnl { fill: rgb(240,240,0); stroke: rgb(128,128,128); fill-opacity: 0.7; }\n"); ++ svg(" rect.box { fill: rgb(240,240,240); stroke: rgb(192,192,192); }\n"); ++ svg(" rect.clrw { stroke-width: 0; fill-opacity: 0.7;}\n"); ++ svg(" line { stroke: rgb(64,64,64); stroke-width: 1; }\n"); ++ svg("// line.sec1 { }\n"); ++ svg(" line.sec5 { stroke-width: 2; }\n"); ++ svg(" line.sec01 { stroke: rgb(224,224,224); stroke-width: 1; }\n"); ++ svg(" line.dot { stroke-dasharray: 2 4; }\n"); ++ svg(" line.idle { stroke: rgb(64,64,64); stroke-dasharray: 10 6; stroke-opacity: 0.7; }\n"); ++ ++ svg(" .run { font-size: 8; font-style: italic; }\n"); ++ svg(" text { font-family: Verdana, Helvetica; font-size: 10; }\n"); ++ svg(" text.sec { font-size: 8; }\n"); ++ svg(" text.t1 { font-size: 24; }\n"); ++ svg(" text.t2 { font-size: 12; }\n"); ++ svg(" text.idle { font-size: 18; }\n"); ++ ++ svg(" ]]>\n </style>\n</defs>\n\n"); ++ ++ svg("<text x=\"20\" y=\"40\">Startup finished in "); ++ ++ if (firmware_time > 0) ++ svg("%llums (firmware) + ", (firmware_time - loader_time) / 1000); ++ if (loader_time > 0) ++ svg("%llums (loader) + ", loader_time / 1000); ++ if (initrd_time > 0) ++ svg("%llums (kernel) + %llums (initrd) + ", initrd_time / 1000, (userspace_time - initrd_time) / 1000); ++ else if (kernel_time > 0) ++ svg("%llums (kernel) + ", userspace_time / 1000); ++ svg("%llums (userspace) ", (finish_time - userspace_time) / 1000); ++ if (kernel_time > 0) ++ svg("= %llums\n", (firmware_time + finish_time) / 1000); ++ else ++ svg("= %llums\n", (finish_time - userspace_time) / 1000); ++ svg("</text>"); ++ ++ svg("<g transform=\"translate(20,100)\">\n"); ++ svg_graph_box(m, starttime, finish_time, scale_x, scale_y); ++ ++ float top = 0.0; ++ ++ if (firmware_time > 0) { ++ svg(" <rect class=\"firmware\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", ++ scale_x * (starttime - firmware_time) * 0.000001, ++ top, ++ scale_x * (firmware_time - loader_time) * 0.000001, ++ scale_y - 1.0); ++ svg(" <text x=\"%.03f\" y=\"%.03f\">firmware</text>\n", ++ scale_x * (starttime - firmware_time) * 0.000001 + 5.0, ++ top + 14.0); ++ top += scale_y; ++ } ++ if (loader_time > 0) { ++ svg(" <rect class=\"loader\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", ++ scale_x * (starttime - loader_time) * 0.000001, ++ top, ++ scale_x * (loader_time) * 0.000001, ++ scale_y - 1.0); ++ svg(" <text x=\"%.03f\" y=\"%.03f\">loader</text>\n", ++ scale_x * (starttime - loader_time) * 0.000001 + 5.0, ++ top + 14.0); ++ top += scale_y; ++ } ++ if (initrd_time > 0) { ++ svg(" <rect class=\"kernel\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", ++ scale_x * (starttime) * 0.000001, ++ top, ++ scale_x * (initrd_time) * 0.000001, ++ scale_y - 1.0); ++ svg(" <text x=\"%.03f\" y=\"%.03f\">kernel</text>\n", ++ scale_x * (starttime) * 0.000001 + 5.0, ++ top + 14.0); ++ top += scale_y; ++ svg(" <rect class=\"inird\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", ++ scale_x * (starttime + initrd_time) * 0.000001, ++ top, ++ scale_x * (userspace_time - initrd_time) * 0.000001, ++ scale_y - 1.0); ++ svg(" <text x=\"%.03f\" y=\"%.03f\">initrd</text>\n", ++ scale_x * (starttime + initrd_time) * 0.000001 + 5.0, ++ top + 14.0); ++ top += scale_y; ++ } else if (kernel_time > 0) { ++ svg(" <rect class=\"kernel\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", ++ scale_x * (starttime) * 0.000001, ++ top, ++ scale_x * (userspace_time) * 0.000001, ++ scale_y - 1.0); ++ svg(" <text x=\"%.03f\" y=\"%.03f\">kernel</text>\n", ++ scale_x * (starttime) * 0.000001 + 5.0, ++ top + 14.0); ++ top += scale_y; ++ } ++ ++ svg(" <rect class=\"userspace\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", ++ scale_x * (userspace_time) * 0.000001, ++ top, ++ scale_x * (finish_time - userspace_time) * 0.000001, ++ scale_y - 1.0); ++ svg(" <text x=\"%.03f\" y=\"%.03f\">userspace</text>\n", ++ scale_x * (userspace_time) * 0.000001 + 5.0, ++ top + 14.0); ++ top += scale_y; ++ ++ ++ for (int i=0; i < n; i++) { ++ //draw times[i] ++ ++ bool drawn = false; ++ ++ if (times[i].ixt >= userspace_time && times[i].ixt <= finish_time) { ++ unsigned long long int end = finish_time; ++ if (times[i].aet >= times[i].ixt && times[i].aet < end) ++ end = times[i].aet; ++ if (times[i].axt >= times[i].ixt && times[i].axt < end) ++ end = times[i].axt; ++ if (times[i].iet >= times[i].ixt && times[i].iet < end) ++ end = times[i].iet; ++ svg(" <rect class=\"activating\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", ++ scale_x * (starttime + times[i].ixt) * 0.000001, ++ top + (scale_y * i), ++ scale_x * (end - times[i].ixt) * 0.000001, ++ scale_y - 1.0); ++ } ++ if (times[i].aet >= userspace_time && times[i].aet <= finish_time) { ++ unsigned long long int end = finish_time; ++ if (times[i].axt >= times[i].aet && times[i].axt < end) ++ end = times[i].axt; ++ if (times[i].iet >= times[i].aet && times[i].iet < end) ++ end = times[i].iet; ++ svg(" <rect class=\"active\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", ++ scale_x * (starttime + times[i].aet) * 0.000001, ++ top + (scale_y * i), ++ scale_x * (end - times[i].aet) * 0.000001, ++ scale_y - 1.0); ++ } ++ if (times[i].axt >= userspace_time && times[i].axt <= finish_time) { ++ unsigned long long int end = finish_time; ++ if (times[i].iet >= times[i].axt && times[i].iet < end) ++ end = times[i].iet; ++ svg(" <rect class=\"deactivating\" x=\"%.03f\" y=\"%.03f\" width=\"%.03f\" height=\"%.03f\" />\n", ++ scale_x * (starttime + times[i].axt) * 0.000001, ++ top + (scale_y * i), ++ scale_x * (end - times[i].axt) * 0.000001, ++ scale_y - 1.0); ++ } ++ ++ svg(" <text x=\"%.03f\" y=\"%.03f\">%s</text>\n", ++ (starttime + times[i].ixt) * scale_x * 0.000001 + 5.0, ++ top + (scale_y * i) + 14.0, ++ times[i].name); ++ ++ } ++ svg("</g>\n\n"); ++ ++ svg("</svg>"); ++ return 0; ++} ++ ++int analyze_blame(DBusConnection *bus) ++{ ++ struct unit_times *times; ++ int n = acquire_time_data(bus, ×); ++ if (n<=0) ++ return -n; ++ ++ qsort(times, n, sizeof(struct unit_times), compare_unit_times1); ++ ++ for (int i = 0; i < n; i++) { ++ if (times[i].ixt <= 0 || times[i].aet <= 0) ++ continue; ++ if (times[i].aet <= times[i].ixt) ++ continue; ++ printf("%6llums %s\n", (times[i].aet - times[i].ixt) / 1000, times[i].name); ++ } ++ return 0; ++} ++int analyze_time(DBusConnection *bus) ++{ ++ unsigned long long firmware_time, loader_time, kernel_time, initrd_time, userspace_time, finish_time; ++ ++ firmware_time = property_getull(bus, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "FirmwareTimestampMonotonic"); ++ loader_time = property_getull(bus, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "LoaderTimestampMonotonic"); ++ kernel_time = property_getull(bus, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "KernelTimestamp"); ++ initrd_time = property_getull(bus, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "InitRDTimestampMonotonic"); ++ userspace_time = property_getull(bus, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "UserspaceTimestampMonotonic"); ++ finish_time = property_getull(bus, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "FinishTimestampMonotonic"); ++ ++ printf("Startup finished in "); ++ ++ if (firmware_time > 0) ++ printf("%llums (firmware) + ", (firmware_time - loader_time) / 1000); ++ if (loader_time > 0) ++ printf("%llums (loader) + ", loader_time / 1000); ++ if (initrd_time > 0) ++ printf("%llums (kernel) + %llums (initrd) + ", initrd_time / 1000, (userspace_time - initrd_time) / 1000); ++ else if (kernel_time > 0) ++ printf("%llums (kernel) + ", userspace_time / 1000); ++ ++ printf("%llums (userspace) ", (finish_time - userspace_time) / 1000); ++ ++ if (kernel_time > 0) ++ printf("= %llums\n", (firmware_time + finish_time) / 1000); ++ else ++ printf("= %llums\n", (finish_time - userspace_time) / 1000); ++ ++ return 0; ++} ++ ++void analyze_help() ++{ ++ printf("%s [OPTIONS...] {COMMAND} ...\n\n" ++ " -h --help Show this help\n" ++ " --version Show package version\n" ++ " --system Connect to system manager\n" ++ " --user Connect to user service manager\n\n" ++ "Commands:\n" ++ " time\n" ++ " blame\n", ++ program_invocation_short_name); ++ ++} ++ ++static int parse_argv(int argc, char *argv[]) ++{ ++ enum { ++ ARG_VERSION = 0x100, ++ ARG_USER, ++ ARG_SYSTEM ++ }; ++ ++ static const struct option options[] = { ++ { "help", no_argument, NULL, 'h' }, ++ { "version", no_argument, NULL, ARG_VERSION }, ++ { "user", no_argument, NULL, ARG_USER }, ++ { "system", no_argument, NULL, ARG_SYSTEM }, ++ { NULL, 0, NULL, 0 } ++ }; ++ ++ int c; ++ ++ assert(argc >= 0); ++ assert(argv); ++ ++ while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) { ++ switch (c) { ++ case 'h': ++ analyze_help(); ++ return 0; ++ case ARG_VERSION: ++ puts(PACKAGE_STRING); ++ puts(SYSTEMD_FEATURES); ++ return 0; ++ case ARG_USER: ++ arg_scope = UNIT_FILE_USER; ++ break; ++ case ARG_SYSTEM: ++ arg_scope = UNIT_FILE_SYSTEM; ++ break; ++ ++ case '?': ++ return -EINVAL; ++ ++ default: ++ log_error("Unknown option code '%c'.", c); ++ return -EINVAL; ++ } ++ } ++ return 1; ++} ++ ++ ++int main(int argc, char*argv[]) { ++ int r, retval = EXIT_FAILURE; ++ DBusConnection *bus = NULL; ++ DBusError error; ++ bool private_bus = false; ++ ++ dbus_error_init(&error); ++ ++ setlocale(LC_ALL, ""); ++ log_parse_environment(); ++ log_open(); ++ ++ r = parse_argv(argc, argv); ++ if (r < 0) ++ goto finish; ++ else if (r == 0) { ++ retval = EXIT_SUCCESS; ++ goto finish; ++ } ++ ++ bus_connect(arg_scope == UNIT_FILE_SYSTEM ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, &bus, &private_bus, &error); ++ ++ if (!argv[optind] || streq(argv[optind], "time")) ++ retval = analyze_time(bus); ++ else if (streq(argv[optind], "blame")) ++ retval = analyze_blame(bus); ++ else if (streq(argv[optind], "plot")) ++ retval = analyze_plot(bus); ++ else ++ log_error("Unknown operation '%s'.", argv[optind]); ++ ++finish: ++ if (bus) { ++ dbus_connection_flush(bus |
