Rename ltt_events_exit to lttng_ust_events_exit
[lttng-ust.git] / libust / lttng-ust-abi.c
index 13b94c4d7315b908d41fd389b87094ef7be1391b..be9d1d31d82133e6e2277aeaaa520c359e34753c 100644 (file)
  * by the caller.
  */
 
-struct obj;
-
-struct objd_ops {
-       long (*cmd)(int objd, unsigned int cmd, unsigned long arg);
-       int (*release)(int objd);
-};
-
 struct obj {
        union {
                struct {
@@ -100,7 +93,8 @@ int objd_alloc(void *private_data, const struct objd_ops *ops)
 end:
        obj->u.s.private_data = private_data;
        obj->u.s.ops = ops;
-       obj->u.s.f_count = 1;
+       obj->u.s.f_count = 2;   /* count == 1 : object is allocated */
+                               /* count == 2 : allocated + hold ref */
        return obj - objd_table.array;
 }
 
@@ -109,6 +103,8 @@ struct obj *_objd_get(int id)
 {
        if (id >= objd_table.len)
                return NULL;
+       if (!objd_table.array[id].u.s.f_count)
+               return NULL;
        return &objd_table.array[id];
 }
 
@@ -128,11 +124,12 @@ void objd_set_private(int id, void *private_data)
        obj->u.s.private_data = private_data;
 }
 
-static
 const struct objd_ops *objd_ops(int id)
 {
        struct obj *obj = _objd_get(id);
-       assert(obj);
+
+       if (!obj)
+               return NULL;
        return obj->u.s.ops;
 }
 
@@ -144,6 +141,8 @@ void objd_free(int id)
        assert(obj);
        obj->u.freelist_next = objd_table.freelist_head;
        objd_table.freelist_head = obj - objd_table.array;
+       assert(obj->u.s.f_count == 1);
+       obj->u.s.f_count = 0;   /* deallocated */
 }
 
 static
@@ -153,24 +152,38 @@ void objd_ref(int id)
        obj->u.s.f_count++;
 }
 
-static
-void objd_unref(int id)
+int objd_unref(int id)
 {
        struct obj *obj = _objd_get(id);
 
-       if (!(--obj->u.s.f_count)) {
+       if (!obj)
+               return -EINVAL;
+       if (obj->u.s.f_count == 1) {
+               ERR("Reference counting error\n");
+               return -EINVAL;
+       }
+       if ((--obj->u.s.f_count) == 1) {
                const struct objd_ops *ops = objd_ops(id);
-
+               
                if (ops->release)
                        ops->release(id);
                objd_free(id);
        }
+       return 0;
 }
 
 static
 void objd_table_destroy(void)
 {
+       int i;
+
+       for (i = 0; i < objd_table.allocated_len; i++)
+               (void) objd_unref(i);
        free(objd_table.array);
+       objd_table.array = NULL;
+       objd_table.len = 0;
+       objd_table.allocated_len = 0;
+       objd_table.freelist_head = -1;
 }
 
 /*
@@ -183,12 +196,21 @@ static const struct objd_ops lttng_session_ops;
 static const struct objd_ops lttng_channel_ops;
 static const struct objd_ops lttng_metadata_ops;
 static const struct objd_ops lttng_event_ops;
+static const struct objd_ops lib_ring_buffer_objd_ops;
 
 enum channel_type {
        PER_CPU_CHANNEL,
        METADATA_CHANNEL,
 };
 
+int lttng_abi_create_root_handle(void)
+{
+       int root_handle;
+
+       root_handle = objd_alloc(NULL, &lttng_ops);
+       return root_handle;
+}
+
 static
 int lttng_abi_create_session(void)
 {
@@ -250,8 +272,14 @@ long lttng_abi_add_context(int objd,
                return -EPERM;
 
        switch (context_param->ctx) {
+       case LTTNG_UST_CONTEXT_PTHREAD_ID:
+               return lttng_add_pthread_id_to_ctx(ctx);
        case LTTNG_UST_CONTEXT_VTID:
-               //TODO return lttng_add_vtid_to_ctx(ctx);
+               return lttng_add_vtid_to_ctx(ctx);
+       case LTTNG_UST_CONTEXT_VPID:
+               return lttng_add_vpid_to_ctx(ctx);
+       case LTTNG_UST_CONTEXT_PROCNAME:
+               return lttng_add_procname_to_ctx(ctx);
        default:
                return -EINVAL;
        }
@@ -332,7 +360,6 @@ create_error:
        return;         /* not allowed to return error */
 }
 
-static
 int lttng_abi_create_channel(int session_objd,
                             struct lttng_ust_channel *chan_param,
                             enum channel_type channel_type)
@@ -378,7 +405,10 @@ int lttng_abi_create_channel(int session_objd,
                                  chan_param->subbuf_size,
                                  chan_param->num_subbuf,
                                  chan_param->switch_timer_interval,
-                                 chan_param->read_timer_interval);
+                                 chan_param->read_timer_interval,
+                                 &chan_param->shm_fd,
+                                 &chan_param->wait_fd,
+                                 &chan_param->memory_map_size);
        if (!chan) {
                ret = -EINVAL;
                goto chan_error;
@@ -396,7 +426,12 @@ int lttng_abi_create_channel(int session_objd,
        return chan_objd;
 
 chan_error:
-       objd_unref(chan_objd);
+       {
+               int err;
+
+               err = objd_unref(chan_objd);
+               assert(!err);
+       }
 objd_error:
        return ret;
 }
@@ -454,49 +489,63 @@ long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg)
  * individual file is released).
  */
 static
-int lttng_session_release(int objd)
+int lttng_release_session(int objd)
 {
        struct ltt_session *session = objd_private(objd);
 
-       if (session)
+       if (session) {
                ltt_session_destroy(session);
-       return 0;
+               return 0;
+       } else {
+               return -EINVAL;
+       }
 }
 
 static const struct objd_ops lttng_session_ops = {
-       .release = lttng_session_release,
+       .release = lttng_release_session,
        .cmd = lttng_session_cmd,
 };
 
-#if 0
+struct stream_priv_data {
+       struct lttng_ust_lib_ring_buffer *buf;
+       struct ltt_channel *ltt_chan;
+};
+
 static
-int lttng_abi_open_stream(int channel_objd)
+int lttng_abi_open_stream(int channel_objd, struct lttng_ust_stream *info)
 {
        struct ltt_channel *channel = objd_private(channel_objd);
-       struct lib_ring_buffer *buf;
+       struct lttng_ust_lib_ring_buffer *buf;
+       struct stream_priv_data *priv;
        int stream_objd, ret;
 
-       buf = channel->ops->buffer_read_open(channel->chan);
+       buf = channel->ops->buffer_read_open(channel->chan, channel->handle,
+                       &info->shm_fd, &info->wait_fd, &info->memory_map_size);
        if (!buf)
                return -ENOENT;
 
-       stream_objd = objd_alloc(buf, &lib_ring_buffer_objd_ops);
+       priv = zmalloc(sizeof(*priv));
+       if (!priv) {
+               ret = -ENOMEM;
+               goto alloc_error;
+       }
+       priv->buf = buf;
+       priv->ltt_chan = channel;
+       stream_objd = objd_alloc(priv, &lib_ring_buffer_objd_ops);
        if (stream_objd < 0) {
                ret = stream_objd;
                goto objd_error;
        }
-       /*
-        * The stream holds a reference to the channel within the generic ring
-        * buffer library, so no need to hold a refcount on the channel and
-        * session files here.
-        */
+       /* Hold a reference on the channel object descriptor */
+       objd_ref(channel_objd);
        return stream_objd;
 
 objd_error:
-       channel->ops->buffer_read_close(buf);
+       free(priv);
+alloc_error:
+       channel->ops->buffer_read_close(buf, channel->handle);
        return ret;
 }
-#endif //0
 
 static
 int lttng_abi_create_event(int channel_objd,
@@ -527,7 +576,12 @@ int lttng_abi_create_event(int channel_objd,
        return event_objd;
 
 event_error:
-       objd_unref(event_objd);
+       {
+               int err;
+
+               err = objd_unref(event_objd);
+               assert(!err);
+       }
 objd_error:
        return ret;
 }
@@ -561,8 +615,13 @@ long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg)
 
        switch (cmd) {
        case LTTNG_UST_STREAM:
-               return -ENOSYS; //TODO
-               //return lttng_abi_open_stream(objd);
+       {
+               struct lttng_ust_stream *stream;
+
+               stream = (struct lttng_ust_stream *) arg;
+               /* stream used as output */
+               return lttng_abi_open_stream(objd, stream);
+       }
        case LTTNG_UST_EVENT:
                return lttng_abi_create_event(objd, (struct lttng_ust_event *) arg);
        case LTTNG_UST_CONTEXT:
@@ -573,6 +632,8 @@ long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg)
                return ltt_channel_enable(channel);
        case LTTNG_UST_DISABLE:
                return ltt_channel_disable(channel);
+       case LTTNG_UST_FLUSH_BUFFER:
+               return channel->ops->flush_buffer(channel->chan, channel->handle);
        default:
                return -EINVAL;
        }
@@ -594,10 +655,19 @@ long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg)
 static
 long lttng_metadata_cmd(int objd, unsigned int cmd, unsigned long arg)
 {
+       struct ltt_channel *channel = objd_private(objd);
+
        switch (cmd) {
        case LTTNG_UST_STREAM:
-               return -ENOSYS; //TODO
-               //return lttng_abi_open_stream(objd);
+       {
+               struct lttng_ust_stream *stream;
+
+               stream = (struct lttng_ust_stream *) arg;
+               /* stream used as output */
+               return lttng_abi_open_stream(objd, stream);
+       }
+       case LTTNG_UST_FLUSH_BUFFER:
+               return channel->ops->flush_buffer(channel->chan, channel->handle);
        default:
                return -EINVAL;
        }
@@ -639,7 +709,7 @@ int lttng_channel_release(int objd)
        struct ltt_channel *channel = objd_private(objd);
 
        if (channel)
-               objd_unref(channel->session->objd);
+               return objd_unref(channel->session->objd);
        return 0;
 }
 
@@ -654,6 +724,48 @@ static const struct objd_ops lttng_metadata_ops = {
        .cmd = lttng_metadata_cmd,
 };
 
+/**
+ *     lttng_rb_cmd - lttng ring buffer control through object descriptors
+ *
+ *     @objd: the object descriptor
+ *     @cmd: the command
+ *     @arg: command arg
+ *
+ *     This object descriptor implements lttng commands:
+ *             (None for now. Access is done directly though shm.)
+ */
+static
+long lttng_rb_cmd(int objd, unsigned int cmd, unsigned long arg)
+{
+       switch (cmd) {
+       default:
+               return -EINVAL;
+       }
+}
+
+static
+int lttng_rb_release(int objd)
+{
+       struct stream_priv_data *priv = objd_private(objd);
+       struct lttng_ust_lib_ring_buffer *buf;
+       struct ltt_channel *channel;
+
+       if (priv) {
+               buf = priv->buf;
+               channel = priv->ltt_chan;
+               free(priv);
+               channel->ops->buffer_read_close(buf, channel->handle);
+
+               return objd_unref(channel->objd);
+       }
+       return 0;
+}
+
+static const struct objd_ops lib_ring_buffer_objd_ops = {
+       .release = lttng_rb_release,
+       .cmd = lttng_rb_cmd,
+};
+
 /**
  *     lttng_event_cmd - lttng control through object descriptors
  *
@@ -694,7 +806,7 @@ int lttng_event_release(int objd)
        struct ltt_event *event = objd_private(objd);
 
        if (event)
-               objd_unref(event->chan->objd);
+               return objd_unref(event->chan->objd);
        return 0;
 }
 
@@ -704,15 +816,7 @@ static const struct objd_ops lttng_event_ops = {
        .cmd = lttng_event_cmd,
 };
 
-void __attribute__((constructor)) lttng_ust_abi_init(void)
-{
-       init_usterr();
-       /* TODO: initialize socket */
-}
-
-static
-void __attribute__((destructor)) lttng_ust_abi_exit(void)
+void lttng_ust_abi_exit(void)
 {
-       /* TODO: teardown socket */
        objd_table_destroy();
 }
This page took 0.027838 seconds and 4 git commands to generate.