aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/dbus/dbus-1.3.0/will-6.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/dbus/dbus-1.3.0/will-6.patch')
-rw-r--r--recipes/dbus/dbus-1.3.0/will-6.patch456
1 files changed, 456 insertions, 0 deletions
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
+