From fc2765595a6bb6e5cd9ee92f2a80648e69619dcb Mon Sep 17 00:00:00 2001 From: Michael 'Mickey' Lauer Date: Tue, 5 Jan 2010 19:11:50 +0100 Subject: [PATCH] dbus-1.3.0: add performance optimization patches from https://bugs.freedesktop.org/show_bug.cgi?id=23117 --- recipes/dbus/dbus-1.3.0/will-1.patch | 25 ++ recipes/dbus/dbus-1.3.0/will-2.patch | 370 ++++++++++++++++++++++++++++ recipes/dbus/dbus-1.3.0/will-3.patch | 119 +++++++++ recipes/dbus/dbus-1.3.0/will-4.patch | 56 +++++ recipes/dbus/dbus-1.3.0/will-5.patch | 116 +++++++++ recipes/dbus/dbus-1.3.0/will-6.patch | 456 +++++++++++++++++++++++++++++++++++ recipes/dbus/dbus_1.3.0.bb | 10 +- 7 files changed, 1151 insertions(+), 1 deletion(-) create mode 100644 recipes/dbus/dbus-1.3.0/will-1.patch create mode 100644 recipes/dbus/dbus-1.3.0/will-2.patch create mode 100644 recipes/dbus/dbus-1.3.0/will-3.patch create mode 100644 recipes/dbus/dbus-1.3.0/will-4.patch create mode 100644 recipes/dbus/dbus-1.3.0/will-5.patch create mode 100644 recipes/dbus/dbus-1.3.0/will-6.patch diff --git a/recipes/dbus/dbus-1.3.0/will-1.patch b/recipes/dbus/dbus-1.3.0/will-1.patch new file mode 100644 index 0000000000..eb3bb9049e --- /dev/null +++ b/recipes/dbus/dbus-1.3.0/will-1.patch @@ -0,0 +1,25 @@ +From aebf924fce126e4eb1409e995edb78f7c02f65b1 Mon Sep 17 00:00:00 2001 +From: Will Thompson +Date: Wed, 29 Jul 2009 17:47:04 +0100 +Subject: [PATCH 1/6] Add a constant for the number of message types + +--- + dbus/dbus-protocol.h | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h +index a2284ee..17798e9 100644 +--- a/dbus/dbus-protocol.h ++++ b/dbus/dbus-protocol.h +@@ -239,6 +239,8 @@ extern "C" { + /** Message type of a signal message, see dbus_message_get_type() */ + #define DBUS_MESSAGE_TYPE_SIGNAL 4 + ++#define DBUS_NUM_MESSAGE_TYPES 5 ++ + /* Header flags */ + + /** If set, this flag means that the sender of a message does not care about getting +-- +1.6.3.3 + diff --git a/recipes/dbus/dbus-1.3.0/will-2.patch b/recipes/dbus/dbus-1.3.0/will-2.patch new file mode 100644 index 0000000000..e1c756bd64 --- /dev/null +++ b/recipes/dbus/dbus-1.3.0/will-2.patch @@ -0,0 +1,370 @@ +From 2d4da5596b34cbd5de2b97971fbb484657a1f485 Mon Sep 17 00:00:00 2001 +From: Will Thompson +Date: Wed, 29 Jul 2009 17:48:21 +0100 +Subject: [PATCH 2/6] Index match rules by message type + +This avoids scanning all the signal matches while dispatching method +calls and returns, which are rarely matched against. +--- + bus/signals.c | 217 ++++++++++++++++++++++++++++++++++++-------------------- + 1 files changed, 139 insertions(+), 78 deletions(-) + +diff --git a/bus/signals.c b/bus/signals.c +index b020a76..10e0b5e 100644 +--- a/bus/signals.c ++++ b/bus/signals.c +@@ -1022,7 +1022,11 @@ struct BusMatchmaker + { + int refcount; + +- DBusList *all_rules; ++ /* lists of rules, grouped by the type of message they match. 0 ++ * (DBUS_MESSAGE_TYPE_INVALID) represents rules that do not specify a message ++ * type. ++ */ ++ DBusList *rules_by_type[DBUS_NUM_MESSAGE_TYPES]; + }; + + BusMatchmaker* +@@ -1039,6 +1043,16 @@ bus_matchmaker_new (void) + return matchmaker; + } + ++static DBusList ** ++bus_matchmaker_get_rules (BusMatchmaker *matchmaker, ++ int message_type) ++{ ++ _dbus_assert (message_type >= 0); ++ _dbus_assert (message_type < DBUS_NUM_MESSAGE_TYPES); ++ ++ return matchmaker->rules_by_type + message_type; ++} ++ + BusMatchmaker * + bus_matchmaker_ref (BusMatchmaker *matchmaker) + { +@@ -1057,14 +1071,20 @@ bus_matchmaker_unref (BusMatchmaker *matchmaker) + matchmaker->refcount -= 1; + if (matchmaker->refcount == 0) + { +- while (matchmaker->all_rules != NULL) ++ int i; ++ ++ for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++) + { +- BusMatchRule *rule; ++ DBusList **rules = bus_matchmaker_get_rules (matchmaker, i); ++ ++ while (*rules != NULL) ++ { ++ BusMatchRule *rule; + +- rule = matchmaker->all_rules->data; +- bus_match_rule_unref (rule); +- _dbus_list_remove_link (&matchmaker->all_rules, +- matchmaker->all_rules); ++ rule = (*rules)->data; ++ bus_match_rule_unref (rule); ++ _dbus_list_remove_link (rules, *rules); ++ } + } + + dbus_free (matchmaker); +@@ -1076,14 +1096,18 @@ dbus_bool_t + bus_matchmaker_add_rule (BusMatchmaker *matchmaker, + BusMatchRule *rule) + { ++ DBusList **rules; ++ + _dbus_assert (bus_connection_is_active (rule->matches_go_to)); + +- if (!_dbus_list_append (&matchmaker->all_rules, rule)) ++ rules = bus_matchmaker_get_rules (matchmaker, rule->message_type); ++ ++ if (!_dbus_list_append (rules, rule)) + return FALSE; + + if (!bus_connection_add_match_rule (rule->matches_go_to, rule)) + { +- _dbus_list_remove_last (&matchmaker->all_rules, rule); ++ _dbus_list_remove_last (rules, rule); + return FALSE; + } + +@@ -1171,13 +1195,13 @@ match_rule_equal (BusMatchRule *a, + } + + static void +-bus_matchmaker_remove_rule_link (BusMatchmaker *matchmaker, ++bus_matchmaker_remove_rule_link (DBusList **rules, + DBusList *link) + { + BusMatchRule *rule = link->data; + + bus_connection_remove_match_rule (rule->matches_go_to, rule); +- _dbus_list_remove_link (&matchmaker->all_rules, link); ++ _dbus_list_remove_link (rules, link); + + #ifdef DBUS_ENABLE_VERBOSE_MODE + { +@@ -1196,8 +1220,12 @@ void + bus_matchmaker_remove_rule (BusMatchmaker *matchmaker, + BusMatchRule *rule) + { ++ DBusList **rules; ++ + bus_connection_remove_match_rule (rule->matches_go_to, rule); +- _dbus_list_remove (&matchmaker->all_rules, rule); ++ ++ rules = bus_matchmaker_get_rules (matchmaker, rule->message_type); ++ _dbus_list_remove (rules, rule); + + #ifdef DBUS_ENABLE_VERBOSE_MODE + { +@@ -1219,24 +1247,26 @@ bus_matchmaker_remove_rule_by_value (BusMatchmaker *matchmaker, + DBusError *error) + { + /* FIXME this is an unoptimized linear scan */ +- ++ DBusList **rules; + DBusList *link; + ++ rules = bus_matchmaker_get_rules (matchmaker, value->message_type); ++ + /* we traverse backward because bus_connection_remove_match_rule() + * removes the most-recently-added rule + */ +- link = _dbus_list_get_last_link (&matchmaker->all_rules); ++ link = _dbus_list_get_last_link (rules); + while (link != NULL) + { + BusMatchRule *rule; + DBusList *prev; + + rule = link->data; +- prev = _dbus_list_get_prev_link (&matchmaker->all_rules, link); ++ prev = _dbus_list_get_prev_link (rules, link); + + if (match_rule_equal (rule, value)) + { +- bus_matchmaker_remove_rule_link (matchmaker, link); ++ bus_matchmaker_remove_rule_link (rules, link); + break; + } + +@@ -1258,6 +1288,7 @@ bus_matchmaker_disconnected (BusMatchmaker *matchmaker, + DBusConnection *disconnected) + { + DBusList *link; ++ int i; + + /* FIXME + * +@@ -1270,41 +1301,46 @@ bus_matchmaker_disconnected (BusMatchmaker *matchmaker, + + _dbus_assert (bus_connection_is_active (disconnected)); + +- link = _dbus_list_get_first_link (&matchmaker->all_rules); +- while (link != NULL) ++ for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++) + { +- BusMatchRule *rule; +- DBusList *next; ++ DBusList **rules = bus_matchmaker_get_rules (matchmaker, i); + +- rule = link->data; +- next = _dbus_list_get_next_link (&matchmaker->all_rules, link); +- +- if (rule->matches_go_to == disconnected) +- { +- bus_matchmaker_remove_rule_link (matchmaker, link); +- } +- else if (((rule->flags & BUS_MATCH_SENDER) && *rule->sender == ':') || +- ((rule->flags & BUS_MATCH_DESTINATION) && *rule->destination == ':')) ++ link = _dbus_list_get_first_link (rules); ++ while (link != NULL) + { +- /* The rule matches to/from a base service, see if it's the +- * one being disconnected, since we know this service name +- * will never be recycled. +- */ +- const char *name; +- +- name = bus_connection_get_name (disconnected); +- _dbus_assert (name != NULL); /* because we're an active connection */ +- +- if (((rule->flags & BUS_MATCH_SENDER) && +- strcmp (rule->sender, name) == 0) || +- ((rule->flags & BUS_MATCH_DESTINATION) && +- strcmp (rule->destination, name) == 0)) ++ BusMatchRule *rule; ++ DBusList *next; ++ ++ rule = link->data; ++ next = _dbus_list_get_next_link (rules, link); ++ ++ if (rule->matches_go_to == disconnected) + { +- bus_matchmaker_remove_rule_link (matchmaker, link); ++ bus_matchmaker_remove_rule_link (rules, link); ++ } ++ else if (((rule->flags & BUS_MATCH_SENDER) && *rule->sender == ':') || ++ ((rule->flags & BUS_MATCH_DESTINATION) && *rule->destination == ':')) ++ { ++ /* The rule matches to/from a base service, see if it's the ++ * one being disconnected, since we know this service name ++ * will never be recycled. ++ */ ++ const char *name; ++ ++ name = bus_connection_get_name (disconnected); ++ _dbus_assert (name != NULL); /* because we're an active connection */ ++ ++ if (((rule->flags & BUS_MATCH_SENDER) && ++ strcmp (rule->sender, name) == 0) || ++ ((rule->flags & BUS_MATCH_DESTINATION) && ++ strcmp (rule->destination, name) == 0)) ++ { ++ bus_matchmaker_remove_rule_link (rules, link); ++ } + } +- } + +- link = next; ++ link = next; ++ } + } + } + +@@ -1504,38 +1540,16 @@ match_rule_matches (BusMatchRule *rule, + return TRUE; + } + +-dbus_bool_t +-bus_matchmaker_get_recipients (BusMatchmaker *matchmaker, +- BusConnections *connections, +- DBusConnection *sender, +- DBusConnection *addressed_recipient, +- DBusMessage *message, +- DBusList **recipients_p) ++static dbus_bool_t ++get_recipients_from_list (DBusList **rules, ++ DBusConnection *sender, ++ DBusConnection *addressed_recipient, ++ DBusMessage *message, ++ DBusList **recipients_p) + { +- /* FIXME for now this is a wholly unoptimized linear search */ +- /* Guessing the important optimization is to skip the signal-related +- * match lists when processing method call and exception messages. +- * So separate match rule lists for signals? +- */ +- + DBusList *link; + +- _dbus_assert (*recipients_p == NULL); +- +- /* This avoids sending same message to the same connection twice. +- * Purpose of the stamp instead of a bool is to avoid iterating over +- * all connections resetting the bool each time. +- */ +- bus_connections_increment_stamp (connections); +- +- /* addressed_recipient is already receiving the message, don't add to list. +- * NULL addressed_recipient means either bus driver, or this is a signal +- * and thus lacks a specific addressed_recipient. +- */ +- if (addressed_recipient != NULL) +- bus_connection_mark_stamp (addressed_recipient); +- +- link = _dbus_list_get_first_link (&matchmaker->all_rules); ++ link = _dbus_list_get_first_link (rules); + while (link != NULL) + { + BusMatchRule *rule; +@@ -1545,7 +1559,7 @@ bus_matchmaker_get_recipients (BusMatchmaker *matchmaker, + #ifdef DBUS_ENABLE_VERBOSE_MODE + { + char *s = match_rule_to_string (rule); +- ++ + _dbus_verbose ("Checking whether message matches rule %s for connection %p\n", + s, rule->matches_go_to); + dbus_free (s); +@@ -1556,12 +1570,12 @@ bus_matchmaker_get_recipients (BusMatchmaker *matchmaker, + sender, addressed_recipient, message)) + { + _dbus_verbose ("Rule matched\n"); +- ++ + /* Append to the list if we haven't already */ + if (bus_connection_mark_stamp (rule->matches_go_to)) + { + if (!_dbus_list_append (recipients_p, rule->matches_go_to)) +- goto nomem; ++ return FALSE; + } + #ifdef DBUS_ENABLE_VERBOSE_MODE + else +@@ -1571,10 +1585,57 @@ bus_matchmaker_get_recipients (BusMatchmaker *matchmaker, + #endif /* DBUS_ENABLE_VERBOSE_MODE */ + } + +- link = _dbus_list_get_next_link (&matchmaker->all_rules, link); ++ link = _dbus_list_get_next_link (rules, link); + } + + return TRUE; ++} ++ ++dbus_bool_t ++bus_matchmaker_get_recipients (BusMatchmaker *matchmaker, ++ BusConnections *connections, ++ DBusConnection *sender, ++ DBusConnection *addressed_recipient, ++ DBusMessage *message, ++ DBusList **recipients_p) ++{ ++ /* FIXME for now this is a wholly unoptimized linear search */ ++ /* Guessing the important optimization is to skip the signal-related ++ * match lists when processing method call and exception messages. ++ * So separate match rule lists for signals? ++ */ ++ int type; ++ ++ _dbus_assert (*recipients_p == NULL); ++ ++ /* This avoids sending same message to the same connection twice. ++ * Purpose of the stamp instead of a bool is to avoid iterating over ++ * all connections resetting the bool each time. ++ */ ++ bus_connections_increment_stamp (connections); ++ ++ /* addressed_recipient is already receiving the message, don't add to list. ++ * NULL addressed_recipient means either bus driver, or this is a signal ++ * and thus lacks a specific addressed_recipient. ++ */ ++ if (addressed_recipient != NULL) ++ bus_connection_mark_stamp (addressed_recipient); ++ ++ /* We always need to try the rules that don't specify a message type */ ++ if (!get_recipients_from_list ( ++ bus_matchmaker_get_rules (matchmaker, DBUS_MESSAGE_TYPE_INVALID), ++ sender, addressed_recipient, message, recipients_p)) ++ goto nomem; ++ ++ /* Also try rules that match the type of this message */ ++ type = dbus_message_get_type (message); ++ if (type > DBUS_MESSAGE_TYPE_INVALID && type < DBUS_NUM_MESSAGE_TYPES) ++ if (!get_recipients_from_list ( ++ bus_matchmaker_get_rules (matchmaker, type), ++ sender, addressed_recipient, message, recipients_p)) ++ goto nomem; ++ ++ return TRUE; + + nomem: + _dbus_list_clear (recipients_p); +-- +1.6.3.3 + diff --git a/recipes/dbus/dbus-1.3.0/will-3.patch b/recipes/dbus/dbus-1.3.0/will-3.patch new file mode 100644 index 0000000000..80e1f33a03 --- /dev/null +++ b/recipes/dbus/dbus-1.3.0/will-3.patch @@ -0,0 +1,119 @@ +From 8946958989828312ecf58dbaa581cbcebea8bcea Mon Sep 17 00:00:00 2001 +From: Will Thompson +Date: Wed, 29 Jul 2009 17:53:37 +0100 +Subject: [PATCH 3/6] Don't bother re-matching features we've checked. + +This is currently not a big deal, but will make more of a difference +once the set of match rules is partitioned by more features than just +the message type. +--- + bus/signals.c | 29 ++++++++++++++++++----------- + 1 files changed, 18 insertions(+), 11 deletions(-) + +diff --git a/bus/signals.c b/bus/signals.c +index 10e0b5e..0509dd5 100644 +--- a/bus/signals.c ++++ b/bus/signals.c +@@ -1369,8 +1369,11 @@ static dbus_bool_t + match_rule_matches (BusMatchRule *rule, + DBusConnection *sender, + DBusConnection *addressed_recipient, +- DBusMessage *message) ++ DBusMessage *message, ++ BusMatchFlags already_matched) + { ++ int flags; ++ + /* All features of the match rule are AND'd together, + * so FALSE if any of them don't match. + */ +@@ -1379,8 +1382,11 @@ match_rule_matches (BusMatchRule *rule, + * or for addressed_recipient may mean a message with no + * specific recipient (i.e. a signal) + */ +- +- if (rule->flags & BUS_MATCH_MESSAGE_TYPE) ++ ++ /* Don't bother re-matching features we've already checked implicitly. */ ++ flags = rule->flags & (~already_matched); ++ ++ if (flags & BUS_MATCH_MESSAGE_TYPE) + { + _dbus_assert (rule->message_type != DBUS_MESSAGE_TYPE_INVALID); + +@@ -1388,7 +1394,7 @@ match_rule_matches (BusMatchRule *rule, + return FALSE; + } + +- if (rule->flags & BUS_MATCH_INTERFACE) ++ if (flags & BUS_MATCH_INTERFACE) + { + const char *iface; + +@@ -1402,7 +1408,7 @@ match_rule_matches (BusMatchRule *rule, + return FALSE; + } + +- if (rule->flags & BUS_MATCH_MEMBER) ++ if (flags & BUS_MATCH_MEMBER) + { + const char *member; + +@@ -1416,7 +1422,7 @@ match_rule_matches (BusMatchRule *rule, + return FALSE; + } + +- if (rule->flags & BUS_MATCH_SENDER) ++ if (flags & BUS_MATCH_SENDER) + { + _dbus_assert (rule->sender != NULL); + +@@ -1433,7 +1439,7 @@ match_rule_matches (BusMatchRule *rule, + } + } + +- if (rule->flags & BUS_MATCH_DESTINATION) ++ if (flags & BUS_MATCH_DESTINATION) + { + const char *destination; + +@@ -1456,7 +1462,7 @@ match_rule_matches (BusMatchRule *rule, + } + } + +- if (rule->flags & BUS_MATCH_PATH) ++ if (flags & BUS_MATCH_PATH) + { + const char *path; + +@@ -1470,7 +1476,7 @@ match_rule_matches (BusMatchRule *rule, + return FALSE; + } + +- if (rule->flags & BUS_MATCH_ARGS) ++ if (flags & BUS_MATCH_ARGS) + { + int i; + DBusMessageIter iter; +@@ -1567,7 +1573,8 @@ get_recipients_from_list (DBusList **rules, + #endif + + if (match_rule_matches (rule, +- sender, addressed_recipient, message)) ++ sender, addressed_recipient, message, ++ BUS_MATCH_MESSAGE_TYPE)) + { + _dbus_verbose ("Rule matched\n"); + +@@ -2004,7 +2011,7 @@ check_matches (dbus_bool_t expected_to_match, + _dbus_assert (rule != NULL); + + /* We can't test sender/destination rules since we pass NULL here */ +- matched = match_rule_matches (rule, NULL, NULL, message); ++ matched = match_rule_matches (rule, NULL, NULL, message, 0); + + if (matched != expected_to_match) + { +-- +1.6.3.3 + diff --git a/recipes/dbus/dbus-1.3.0/will-4.patch b/recipes/dbus/dbus-1.3.0/will-4.patch new file mode 100644 index 0000000000..2b2303bab3 --- /dev/null +++ b/recipes/dbus/dbus-1.3.0/will-4.patch @@ -0,0 +1,56 @@ +From 9da8cbb9d9155bce885e0cfb39ba18a22ee6a76d Mon Sep 17 00:00:00 2001 +From: Will Thompson +Date: Wed, 29 Jul 2009 18:52:28 +0100 +Subject: [PATCH 4/6] Extract freeing a DBusList + +--- + bus/signals.c | 26 ++++++++++++++------------ + 1 files changed, 14 insertions(+), 12 deletions(-) + +diff --git a/bus/signals.c b/bus/signals.c +index 0509dd5..3cf846e 100644 +--- a/bus/signals.c ++++ b/bus/signals.c +@@ -1029,6 +1029,19 @@ struct BusMatchmaker + DBusList *rules_by_type[DBUS_NUM_MESSAGE_TYPES]; + }; + ++static void ++rule_list_free (DBusList **rules) ++{ ++ while (*rules != NULL) ++ { ++ BusMatchRule *rule; ++ ++ rule = (*rules)->data; ++ bus_match_rule_unref (rule); ++ _dbus_list_remove_link (rules, *rules); ++ } ++} ++ + BusMatchmaker* + bus_matchmaker_new (void) + { +@@ -1074,18 +1087,7 @@ bus_matchmaker_unref (BusMatchmaker *matchmaker) + int i; + + for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++) +- { +- DBusList **rules = bus_matchmaker_get_rules (matchmaker, i); +- +- while (*rules != NULL) +- { +- BusMatchRule *rule; +- +- rule = (*rules)->data; +- bus_match_rule_unref (rule); +- _dbus_list_remove_link (rules, *rules); +- } +- } ++ rule_list_free (bus_matchmaker_get_rules (matchmaker, i)); + + dbus_free (matchmaker); + } +-- +1.6.3.3 + diff --git a/recipes/dbus/dbus-1.3.0/will-5.patch b/recipes/dbus/dbus-1.3.0/will-5.patch new file mode 100644 index 0000000000..ed100005cf --- /dev/null +++ b/recipes/dbus/dbus-1.3.0/will-5.patch @@ -0,0 +1,116 @@ +From a40a026527e718547f32e134e7c27a561b1eba47 Mon Sep 17 00:00:00 2001 +From: Will Thompson +Date: Wed, 29 Jul 2009 20:03:40 +0100 +Subject: [PATCH 5/6] Extract rule_list_remove_by_connection + +--- + bus/signals.c | 82 +++++++++++++++++++++++++++++++------------------------- + 1 files changed, 45 insertions(+), 37 deletions(-) + +diff --git a/bus/signals.c b/bus/signals.c +index 3cf846e..c6f122b 100644 +--- a/bus/signals.c ++++ b/bus/signals.c +@@ -1285,11 +1285,54 @@ bus_matchmaker_remove_rule_by_value (BusMatchmaker *matchmaker, + return TRUE; + } + ++static void ++rule_list_remove_by_connection (DBusList **rules, ++ DBusConnection *disconnected) ++{ ++ DBusList *link; ++ ++ link = _dbus_list_get_first_link (rules); ++ while (link != NULL) ++ { ++ BusMatchRule *rule; ++ DBusList *next; ++ ++ rule = link->data; ++ next = _dbus_list_get_next_link (rules, link); ++ ++ if (rule->matches_go_to == disconnected) ++ { ++ bus_matchmaker_remove_rule_link (rules, link); ++ } ++ else if (((rule->flags & BUS_MATCH_SENDER) && *rule->sender == ':') || ++ ((rule->flags & BUS_MATCH_DESTINATION) && *rule->destination == ':')) ++ { ++ /* The rule matches to/from a base service, see if it's the ++ * one being disconnected, since we know this service name ++ * will never be recycled. ++ */ ++ const char *name; ++ ++ name = bus_connection_get_name (disconnected); ++ _dbus_assert (name != NULL); /* because we're an active connection */ ++ ++ if (((rule->flags & BUS_MATCH_SENDER) && ++ strcmp (rule->sender, name) == 0) || ++ ((rule->flags & BUS_MATCH_DESTINATION) && ++ strcmp (rule->destination, name) == 0)) ++ { ++ bus_matchmaker_remove_rule_link (rules, link); ++ } ++ } ++ ++ link = next; ++ } ++} ++ + void + bus_matchmaker_disconnected (BusMatchmaker *matchmaker, + DBusConnection *disconnected) + { +- DBusList *link; + int i; + + /* FIXME +@@ -1307,42 +1350,7 @@ bus_matchmaker_disconnected (BusMatchmaker *matchmaker, + { + DBusList **rules = bus_matchmaker_get_rules (matchmaker, i); + +- link = _dbus_list_get_first_link (rules); +- while (link != NULL) +- { +- BusMatchRule *rule; +- DBusList *next; +- +- rule = link->data; +- next = _dbus_list_get_next_link (rules, link); +- +- if (rule->matches_go_to == disconnected) +- { +- bus_matchmaker_remove_rule_link (rules, link); +- } +- else if (((rule->flags & BUS_MATCH_SENDER) && *rule->sender == ':') || +- ((rule->flags & BUS_MATCH_DESTINATION) && *rule->destination == ':')) +- { +- /* The rule matches to/from a base service, see if it's the +- * one being disconnected, since we know this service name +- * will never be recycled. +- */ +- const char *name; +- +- name = bus_connection_get_name (disconnected); +- _dbus_assert (name != NULL); /* because we're an active connection */ +- +- if (((rule->flags & BUS_MATCH_SENDER) && +- strcmp (rule->sender, name) == 0) || +- ((rule->flags & BUS_MATCH_DESTINATION) && +- strcmp (rule->destination, name) == 0)) +- { +- bus_matchmaker_remove_rule_link (rules, link); +- } +- } +- +- link = next; +- } ++ rule_list_remove_by_connection (rules, disconnected); + } + } + +-- +1.6.3.3 + diff --git a/recipes/dbus/dbus-1.3.0/will-6.patch b/recipes/dbus/dbus-1.3.0/will-6.patch new file mode 100644 index 0000000000..05d9c49e30 --- /dev/null +++ b/recipes/dbus/dbus-1.3.0/will-6.patch @@ -0,0 +1,456 @@ +From 023bb6fdc82304866353a28cd503863e80c3ea0d Mon Sep 17 00:00:00 2001 +From: Will Thompson +Date: Thu, 30 Jul 2009 10:49:33 +0100 +Subject: [PATCH 6/6] Group match rules by their interface. + +In my informal studies of "normal" sets of match rules, only checking +match rules with the appropriate interface for the message reduces the +number that need to be checked by almost 100x on average (ranging from +halving for messages from the bus daemon, to a >200x reduction in many +cases). This reduces the overhead added to dispatching each message by +having lots of irrelevant match rules. +--- + bus/signals.c | 292 ++++++++++++++++++++++++++++++++++++++++++++++----------- + 1 files changed, 239 insertions(+), 53 deletions(-) + +diff --git a/bus/signals.c b/bus/signals.c +index c6f122b..23bf98a 100644 +--- a/bus/signals.c ++++ b/bus/signals.c +@@ -1018,15 +1018,25 @@ bus_match_rule_parse (DBusConnection *matches_go_to, + return rule; + } + ++typedef struct RulePool RulePool; ++struct RulePool ++{ ++ /* Maps non-NULL interface names to non-NULL (DBusList **)s */ ++ DBusHashTable *rules_by_iface; ++ ++ /* List of BusMatchRules which don't specify an interface */ ++ DBusList *rules_without_iface; ++}; ++ + struct BusMatchmaker + { + int refcount; + +- /* lists of rules, grouped by the type of message they match. 0 ++ /* Pools of rules, grouped by the type of message they match. 0 + * (DBUS_MESSAGE_TYPE_INVALID) represents rules that do not specify a message + * type. + */ +- DBusList *rules_by_type[DBUS_NUM_MESSAGE_TYPES]; ++ RulePool rules_by_type[DBUS_NUM_MESSAGE_TYPES]; + }; + + static void +@@ -1042,28 +1052,139 @@ rule_list_free (DBusList **rules) + } + } + ++static void ++rule_list_ptr_free (DBusList **list) ++{ ++ /* We have to cope with NULL because the hash table frees the "existing" ++ * value (which is NULL) when creating a new table entry... ++ */ ++ if (list != NULL) ++ { ++ rule_list_free (list); ++ dbus_free (list); ++ } ++} ++ + BusMatchmaker* + bus_matchmaker_new (void) + { + BusMatchmaker *matchmaker; ++ int i; + + matchmaker = dbus_new0 (BusMatchmaker, 1); + if (matchmaker == NULL) + return NULL; + + matchmaker->refcount = 1; +- ++ ++ for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++) ++ { ++ RulePool *p = matchmaker->rules_by_type + i; ++ ++ p->rules_by_iface = _dbus_hash_table_new (DBUS_HASH_STRING, ++ dbus_free, (DBusFreeFunction) rule_list_ptr_free); ++ ++ if (p->rules_by_iface == NULL) ++ goto nomem; ++ } ++ + return matchmaker; ++ ++ nomem: ++ for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++) ++ { ++ RulePool *p = matchmaker->rules_by_type + i; ++ ++ if (p->rules_by_iface == NULL) ++ break; ++ else ++ _dbus_hash_table_unref (p->rules_by_iface); ++ } ++ ++ return NULL; + } + + static DBusList ** + bus_matchmaker_get_rules (BusMatchmaker *matchmaker, +- int message_type) ++ int message_type, ++ const char *interface, ++ dbus_bool_t create) + { ++ RulePool *p; ++ + _dbus_assert (message_type >= 0); + _dbus_assert (message_type < DBUS_NUM_MESSAGE_TYPES); + +- return matchmaker->rules_by_type + message_type; ++ _dbus_verbose ("Looking up rules for message_type %d, interface %s\n", ++ message_type, ++ interface != NULL ? interface : ""); ++ ++ p = matchmaker->rules_by_type + message_type; ++ ++ if (interface == NULL) ++ { ++ return &p->rules_without_iface; ++ } ++ else ++ { ++ DBusList **list; ++ ++ list = _dbus_hash_table_lookup_string (p->rules_by_iface, interface); ++ ++ if (list == NULL && create) ++ { ++ char *dupped_interface; ++ ++ list = dbus_new0 (DBusList *, 1); ++ if (list == NULL) ++ return NULL; ++ ++ dupped_interface = _dbus_strdup (interface); ++ if (dupped_interface == NULL) ++ { ++ dbus_free (list); ++ return NULL; ++ } ++ ++ _dbus_verbose ("Adding list for type %d, iface %s\n", message_type, ++ interface); ++ ++ if (!_dbus_hash_table_insert_string (p->rules_by_iface, ++ dupped_interface, list)) ++ { ++ dbus_free (list); ++ dbus_free (dupped_interface); ++ return NULL; ++ } ++ } ++ ++ return list; ++ } ++} ++ ++static void ++bus_matchmaker_gc_rules (BusMatchmaker *matchmaker, ++ int message_type, ++ const char *interface, ++ DBusList **rules) ++{ ++ RulePool *p; ++ ++ if (interface == NULL) ++ return; ++ ++ if (*rules != NULL) ++ return; ++ ++ _dbus_verbose ("GCing HT entry for message_type %u, interface %s\n", ++ message_type, interface); ++ ++ p = matchmaker->rules_by_type + message_type; ++ ++ _dbus_assert (_dbus_hash_table_lookup_string (p->rules_by_iface, interface) ++ == rules); ++ ++ _dbus_hash_table_remove_string (p->rules_by_iface, interface); + } + + BusMatchmaker * +@@ -1087,7 +1208,12 @@ bus_matchmaker_unref (BusMatchmaker *matchmaker) + int i; + + for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++) +- rule_list_free (bus_matchmaker_get_rules (matchmaker, i)); ++ { ++ RulePool *p = matchmaker->rules_by_type + i; ++ ++ _dbus_hash_table_unref (p->rules_by_iface); ++ rule_list_free (&p->rules_without_iface); ++ } + + dbus_free (matchmaker); + } +@@ -1102,7 +1228,15 @@ bus_matchmaker_add_rule (BusMatchmaker *matchmaker, + + _dbus_assert (bus_connection_is_active (rule->matches_go_to)); + +- rules = bus_matchmaker_get_rules (matchmaker, rule->message_type); ++ _dbus_verbose ("Adding rule with message_type %d, interface %s\n", ++ rule->message_type, ++ rule->interface != NULL ? rule->interface : ""); ++ ++ rules = bus_matchmaker_get_rules (matchmaker, rule->message_type, ++ rule->interface, TRUE); ++ ++ if (rules == NULL) ++ return FALSE; + + if (!_dbus_list_append (rules, rule)) + return FALSE; +@@ -1110,9 +1244,11 @@ bus_matchmaker_add_rule (BusMatchmaker *matchmaker, + if (!bus_connection_add_match_rule (rule->matches_go_to, rule)) + { + _dbus_list_remove_last (rules, rule); ++ bus_matchmaker_gc_rules (matchmaker, rule->message_type, ++ rule->interface, rules); + return FALSE; + } +- ++ + bus_match_rule_ref (rule); + + #ifdef DBUS_ENABLE_VERBOSE_MODE +@@ -1224,10 +1360,23 @@ bus_matchmaker_remove_rule (BusMatchmaker *matchmaker, + { + DBusList **rules; + ++ _dbus_verbose ("Removing rule with message_type %d, interface %s\n", ++ rule->message_type, ++ rule->interface != NULL ? rule->interface : ""); ++ + bus_connection_remove_match_rule (rule->matches_go_to, rule); + +- rules = bus_matchmaker_get_rules (matchmaker, rule->message_type); ++ rules = bus_matchmaker_get_rules (matchmaker, rule->message_type, ++ rule->interface, FALSE); ++ ++ /* We should only be asked to remove a rule by identity right after it was ++ * added, so there should be a list for it. ++ */ ++ _dbus_assert (rules != NULL); ++ + _dbus_list_remove (rules, rule); ++ bus_matchmaker_gc_rules (matchmaker, rule->message_type, rule->interface, ++ rules); + + #ifdef DBUS_ENABLE_VERBOSE_MODE + { +@@ -1248,31 +1397,38 @@ bus_matchmaker_remove_rule_by_value (BusMatchmaker *matchmaker, + BusMatchRule *value, + DBusError *error) + { +- /* FIXME this is an unoptimized linear scan */ + DBusList **rules; +- DBusList *link; ++ DBusList *link = NULL; + +- rules = bus_matchmaker_get_rules (matchmaker, value->message_type); ++ _dbus_verbose ("Removing rule by value with message_type %d, interface %s\n", ++ value->message_type, ++ value->interface != NULL ? value->interface : ""); + +- /* we traverse backward because bus_connection_remove_match_rule() +- * removes the most-recently-added rule +- */ +- link = _dbus_list_get_last_link (rules); +- while (link != NULL) ++ rules = bus_matchmaker_get_rules (matchmaker, value->message_type, ++ value->interface, FALSE); ++ ++ if (rules != NULL) + { +- BusMatchRule *rule; +- DBusList *prev; ++ /* we traverse backward because bus_connection_remove_match_rule() ++ * removes the most-recently-added rule ++ */ ++ link = _dbus_list_get_last_link (rules); ++ while (link != NULL) ++ { ++ BusMatchRule *rule; ++ DBusList *prev; + +- rule = link->data; +- prev = _dbus_list_get_prev_link (rules, link); ++ rule = link->data; ++ prev = _dbus_list_get_prev_link (rules, link); + +- if (match_rule_equal (rule, value)) +- { +- bus_matchmaker_remove_rule_link (rules, link); +- break; +- } ++ if (match_rule_equal (rule, value)) ++ { ++ bus_matchmaker_remove_rule_link (rules, link); ++ break; ++ } + +- link = prev; ++ link = prev; ++ } + } + + if (link == NULL) +@@ -1282,6 +1438,9 @@ bus_matchmaker_remove_rule_by_value (BusMatchmaker *matchmaker, + return FALSE; + } + ++ bus_matchmaker_gc_rules (matchmaker, value->message_type, value->interface, ++ rules); ++ + return TRUE; + } + +@@ -1341,16 +1500,29 @@ bus_matchmaker_disconnected (BusMatchmaker *matchmaker, + * for the rules belonging to the connection, since we keep + * a list of those; but for the rules that just refer to + * the connection we'd need to do something more elaborate. +- * + */ +- ++ + _dbus_assert (bus_connection_is_active (disconnected)); + ++ _dbus_verbose ("Removing all rules for connection %p\n", disconnected); ++ + for (i = DBUS_MESSAGE_TYPE_INVALID; i < DBUS_NUM_MESSAGE_TYPES; i++) + { +- DBusList **rules = bus_matchmaker_get_rules (matchmaker, i); ++ RulePool *p = matchmaker->rules_by_type + i; ++ DBusHashIter iter; ++ ++ rule_list_remove_by_connection (&p->rules_without_iface, disconnected); ++ ++ _dbus_hash_iter_init (p->rules_by_iface, &iter); ++ while (_dbus_hash_iter_next (&iter)) ++ { ++ DBusList **items = _dbus_hash_iter_get_value (&iter); + +- rule_list_remove_by_connection (rules, disconnected); ++ rule_list_remove_by_connection (items, disconnected); ++ ++ if (*items == NULL) ++ _dbus_hash_iter_remove_entry (&iter); ++ } + } + } + +@@ -1565,6 +1737,9 @@ get_recipients_from_list (DBusList **rules, + { + DBusList *link; + ++ if (rules == NULL) ++ return TRUE; ++ + link = _dbus_list_get_first_link (rules); + while (link != NULL) + { +@@ -1581,10 +1756,10 @@ get_recipients_from_list (DBusList **rules, + dbus_free (s); + } + #endif +- ++ + if (match_rule_matches (rule, + sender, addressed_recipient, message, +- BUS_MATCH_MESSAGE_TYPE)) ++ BUS_MATCH_MESSAGE_TYPE | BUS_MATCH_INTERFACE)) + { + _dbus_verbose ("Rule matched\n"); + +@@ -1616,12 +1791,9 @@ bus_matchmaker_get_recipients (BusMatchmaker *matchmaker, + DBusMessage *message, + DBusList **recipients_p) + { +- /* FIXME for now this is a wholly unoptimized linear search */ +- /* Guessing the important optimization is to skip the signal-related +- * match lists when processing method call and exception messages. +- * So separate match rule lists for signals? +- */ + int type; ++ const char *interface; ++ DBusList **neither, **just_type, **just_iface, **both; + + _dbus_assert (*recipients_p == NULL); + +@@ -1638,25 +1810,39 @@ bus_matchmaker_get_recipients (BusMatchmaker *matchmaker, + if (addressed_recipient != NULL) + bus_connection_mark_stamp (addressed_recipient); + +- /* We always need to try the rules that don't specify a message type */ +- if (!get_recipients_from_list ( +- bus_matchmaker_get_rules (matchmaker, DBUS_MESSAGE_TYPE_INVALID), +- sender, addressed_recipient, message, recipients_p)) +- goto nomem; +- +- /* Also try rules that match the type of this message */ + type = dbus_message_get_type (message); ++ interface = dbus_message_get_interface (message); ++ ++ neither = bus_matchmaker_get_rules (matchmaker, DBUS_MESSAGE_TYPE_INVALID, ++ NULL, FALSE); ++ just_type = just_iface = both = NULL; ++ ++ if (interface != NULL) ++ just_iface = bus_matchmaker_get_rules (matchmaker, ++ DBUS_MESSAGE_TYPE_INVALID, interface, FALSE); ++ + if (type > DBUS_MESSAGE_TYPE_INVALID && type < DBUS_NUM_MESSAGE_TYPES) +- if (!get_recipients_from_list ( +- bus_matchmaker_get_rules (matchmaker, type), +- sender, addressed_recipient, message, recipients_p)) +- goto nomem; ++ { ++ just_type = bus_matchmaker_get_rules (matchmaker, type, NULL, FALSE); + +- return TRUE; ++ if (interface != NULL) ++ both = bus_matchmaker_get_rules (matchmaker, type, interface, FALSE); ++ } + +- nomem: +- _dbus_list_clear (recipients_p); +- return FALSE; ++ if (!(get_recipients_from_list (neither, sender, addressed_recipient, ++ message, recipients_p) && ++ get_recipients_from_list (just_iface, sender, addressed_recipient, ++ message, recipients_p) && ++ get_recipients_from_list (just_type, sender, addressed_recipient, ++ message, recipients_p) && ++ get_recipients_from_list (both, sender, addressed_recipient, ++ message, recipients_p))) ++ { ++ _dbus_list_clear (recipients_p); ++ return FALSE; ++ } ++ ++ return TRUE; + } + + #ifdef DBUS_BUILD_TESTS +-- +1.6.3.3 + diff --git a/recipes/dbus/dbus_1.3.0.bb b/recipes/dbus/dbus_1.3.0.bb index 562ed1bfad..3abc40a0d4 100644 --- a/recipes/dbus/dbus_1.3.0.bb +++ b/recipes/dbus/dbus_1.3.0.bb @@ -2,6 +2,14 @@ include dbus.inc SRC_URI = "\ http://dbus.freedesktop.org/releases/dbus/dbus-${PV}.tar.gz \ + \ + file://will-1.patch;patch=1 \ + file://will-2.patch;patch=1 \ + file://will-3.patch;patch=1 \ + file://will-4.patch;patch=1 \ + file://will-5.patch;patch=1 \ + file://will-6.patch;patch=1 \ + \ file://tmpdir.patch;patch=1 \ file://fix-install-daemon.patch;patch=1 \ file://0001-Make-the-default-DBus-reply-timeout-configurable.patch;patch=1 \ @@ -11,4 +19,4 @@ SRC_URI = "\ # This is the development version of dbus that will lead to 1.4.x DEFAULT_PREFERENCE = "-1" -PR = "r0" +PR = "r1" -- 2.11.4.GIT