+/*
+ * called at event creation if probe is missing.
+ * called with session mutex held.
+ */
+static
+int add_pending_probe(struct ltt_event *event, const char *name)
+{
+ struct cds_hlist_head *head;
+ struct ust_pending_probe *e;
+ size_t name_len = strlen(name) + 1;
+ u32 hash = jhash(name, name_len - 1, 0);
+
+ head = &pending_probe_table[hash & (PENDING_PROBE_HASH_SIZE - 1)];
+ e = zmalloc(sizeof(struct ust_pending_probe) + name_len);
+ if (!e)
+ return -ENOMEM;
+ memcpy(&e->name[0], name, name_len);
+ cds_hlist_add_head(&e->node, head);
+ e->event = event;
+ event->pending_probe = e;
+ return 0;
+}
+
+/*
+ * remove a pending probe. called when at event teardown and when an
+ * event is fixed (probe is loaded).
+ * called with session mutex held.
+ */
+static
+void remove_pending_probe(struct ust_pending_probe *e)
+{
+ if (!e)
+ return;
+ cds_hlist_del(&e->node);
+ free(e);
+}
+
+/*
+ * Called at library load: connect the probe on the events pending on
+ * probe load.
+ * called with session mutex held.
+ */
+int pending_probe_fix_events(const struct lttng_event_desc *desc)
+{
+ struct cds_hlist_head *head;
+ struct cds_hlist_node *node, *p;
+ struct ust_pending_probe *e;
+ const char *name = desc->name;
+ size_t name_len = strlen(name) + 1;
+ u32 hash = jhash(name, name_len - 1, 0);
+ int ret = 0;
+
+ head = &pending_probe_table[hash & (PENDING_PROBE_HASH_SIZE - 1)];
+ cds_hlist_for_each_entry_safe(e, node, p, head, node) {
+ struct ltt_event *event;
+ struct ltt_channel *chan;
+
+ if (strcmp(name, e->name))
+ continue;
+ event = e->event;
+ chan = event->chan;
+ assert(!event->desc);
+ event->desc = desc;
+ event->pending_probe = NULL;
+ remove_pending_probe(e);
+ ret |= __tracepoint_probe_register(name,
+ event->desc->probe_callback,
+ event);
+ if (ret)
+ continue;
+ event->id = chan->free_event_id++;
+ ret |= _ltt_event_metadata_statedump(chan->session, chan,
+ event);
+ }
+ return ret;
+}
+