aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael 'Mickey' Lauer <mickey@vanille-media.de>2010-01-05 19:11:50 +0100
committerMichael 'Mickey' Lauer <mickey@vanille-media.de>2010-01-05 19:16:56 +0100
commitfc2765595a6bb6e5cd9ee92f2a80648e69619dcb (patch)
tree29ccffaecbadf7c2889e28bf4643b9fb9435e0d5
parent58766d5f466609a51a2b606cc7a9795b58998aed (diff)
downloadopenembedded-fc2765595a6bb6e5cd9ee92f2a80648e69619dcb.tar.gz
dbus-1.3.0: add performance optimization patches from https://bugs.freedesktop.org/show_bug.cgi?id=23117
-rw-r--r--recipes/dbus/dbus-1.3.0/will-1.patch25
-rw-r--r--recipes/dbus/dbus-1.3.0/will-2.patch370
-rw-r--r--recipes/dbus/dbus-1.3.0/will-3.patch119
-rw-r--r--recipes/dbus/dbus-1.3.0/will-4.patch56
-rw-r--r--recipes/dbus/dbus-1.3.0/will-5.patch116
-rw-r--r--recipes/dbus/dbus-1.3.0/will-6.patch456
-rw-r--r--recipes/dbus/dbus_1.3.0.bb10
7 files changed, 1151 insertions, 1 deletions
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 <will.thompson@collabora.co.uk>
+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 <will.thompson@collabora.co.uk>
+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 <will.thompson@collabora.co.uk>
+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 <will.thompson@collabora.co.uk>
+Date: Wed, 29 Jul 2009 18:52:28 +0100
+Subject: [PATCH 4/6] Extract freeing a DBusList<BusMatchRule>
+
+---
+ 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 <will.thompson@collabora.co.uk>
+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 <will.thompson@collabora.co.uk>
+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 : "<null>");
++
++ 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 : "<null>");
++
++ 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 : "<null>");
++
+ 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 : "<null>");
+
+- /* 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"