ABI update
[lttng-modules.git] / ltt-events.c
index 3060c07e05d2386d8d90d0482b3040d3d0f970b9..d6cb397e6a61d44a83c1e8eaa898e8f18976107f 100644 (file)
@@ -7,9 +7,13 @@
  */
 
 #include <linux/module.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
 #include "ltt-events.h"
 
 static LIST_HEAD(sessions);
+static LIST_HEAD(ltt_transport_list);
 static DEFINE_MUTEX(sessions_mutex);
 static struct kmem_cache *event_cache;
 
@@ -56,6 +60,38 @@ int ltt_session_destroy(struct ltt_session *session)
        kfree(session);
 }
 
+int ltt_session_start(struct ltt_session *session)
+{
+       int ret = 0;
+
+       mutex_lock(&sessions_mutex);
+       if (session->active) {
+               ret = -EBUSY;
+               goto end;
+       }
+       session->active = 1;
+       synchronize_trace();    /* Wait for in-flight events to complete */
+end:
+       mutex_unlock(&sessions_mutex);
+       return ret
+}
+
+int ltt_session_stop(struct ltt_session *session)
+{
+       int ret = 0;
+
+       mutex_lock(&sessions_mutex);
+       if (!session->active) {
+               ret = -EBUSY;
+               goto end;
+       }
+       session->active = 0;
+       synchronize_trace();    /* Wait for in-flight events to complete */
+end:
+       mutex_unlock(&sessions_mutex);
+       return ret
+}
+
 struct ltt_channel *ltt_channel_create(struct ltt_session *session,
                                       int overwrite, void *buf_addr,
                                       size_t subbuf_size, size_t num_subbuf,
@@ -63,22 +99,35 @@ struct ltt_channel *ltt_channel_create(struct ltt_session *session,
                                       unsigned int read_timer_interval)
 {
        struct ltt_channel *chan;
+       struct ltt_transport *transport = NULL, *tran_iter;
+       char *transport_name;
 
        mutex_lock(&sessions_mutex);
        if (session->active)
                goto active;    /* Refuse to add channel to active session */
+       transport_name = overwrite ? "relay-overwrite" : "relay-discard";
+       list_for_each_entry(tran_iter, &ltt_transport_list, node) {
+               if (!strcmp(tran_iter->name, transport_name)) {
+                       transport = tran_iter;
+                       break;
+               }
+       }
+       if (!transport)
+               goto notransport;
        chan = kmalloc(sizeof(struct ltt_channel), GFP_KERNEL);
        if (!chan)
-               return NULL;
+               goto nomem;
        chan->session = session;
        init_waitqueue_head(&chan->notify_wait);
-
-       /* TODO: create rb channel */
+       transport->ops.channel_create(session, buf_addr, subbuf_size,
+                                     num_subbuf, switch_timer_interval,
+                                     read_timer_interval);
        list_add(&chan->list, &session->chan);
        mutex_unlock(&sessions_mutex);
        return chan;
 
-exist:
+nomem:
+notransport:
 active:
        mutex_unlock(&sessions_mutex);
        return NULL;
@@ -89,7 +138,7 @@ active:
  */
 int _ltt_channel_destroy(struct ltt_channel *chan)
 {
-       /* TODO: destroy rb channel */
+       transport->ops.channel_destroy(chan);
        list_del(&chan->list);
        kfree(chan);
 }
@@ -163,6 +212,46 @@ int _ltt_event_destroy(struct ltt_event *event)
        kmem_cache_free(event);
 }
 
+/**
+ * ltt_transport_register - LTT transport registration
+ * @transport: transport structure
+ *
+ * Registers a transport which can be used as output to extract the data out of
+ * LTTng. The module calling this registration function must ensure that no
+ * trap-inducing code will be executed by the transport functions. E.g.
+ * vmalloc_sync_all() must be called between a vmalloc and the moment the memory
+ * is made visible to the transport function. This registration acts as a
+ * vmalloc_sync_all. Therefore, only if the module allocates virtual memory
+ * after its registration must it synchronize the TLBs.
+ */
+void ltt_transport_register(struct ltt_transport *transport)
+{
+       /*
+        * Make sure no page fault can be triggered by the module about to be
+        * registered. We deal with this here so we don't have to call
+        * vmalloc_sync_all() in each module's init.
+        */
+       vmalloc_sync_all();
+
+       mutex_lock(&sessions_mutex);
+       list_add_tail(&transport->node, &ltt_transport_list);
+       mutex_unlock(&sessions_mutex);
+}
+EXPORT_SYMBOL_GPL(ltt_transport_register);
+
+/**
+ * ltt_transport_unregister - LTT transport unregistration
+ * @transport: transport structure
+ */
+void ltt_transport_unregister(struct ltt_transport *transport)
+{
+       mutex_lock(&sessions_mutex);
+       list_del(&transport->node);
+       mutex_unlock(&sessions_mutex);
+}
+EXPORT_SYMBOL_GPL(ltt_transport_unregister);
+
+
 static int __init ltt_events_init(void)
 {
        int ret;
@@ -170,9 +259,6 @@ static int __init ltt_events_init(void)
        events_cache = KMEM_CACHE(ltt_event, 0);
        if (!events_cache)
                return -ENOMEM;
-
-       /* TODO: show ABI to userspace */
-
        return 0;
 }
 
@@ -180,8 +266,6 @@ static void __exit ltt_events_exit(void)
 {
        struct ltt_session *session, *tmpsession;
 
-       /* TODO: hide ABI from userspace, wait for callers to release refs. */
-
        list_for_each_entry_safe(session, tmpsession, &sessions, list)
                ltt_session_destroy(session);
        kmem_cache_destroy(events_cache);
This page took 0.025438 seconds and 4 git commands to generate.