* by the caller.
*/
-struct obj {
+struct lttng_ust_obj {
union {
struct {
void *private_data;
- const struct objd_ops *ops;
+ const struct lttng_ust_objd_ops *ops;
int f_count;
} s;
int freelist_next; /* offset freelist. end is -1. */
} u;
};
-struct objd_table {
- struct obj *array;
+struct lttng_ust_objd_table {
+ struct lttng_ust_obj *array;
unsigned int len, allocated_len;
int freelist_head; /* offset freelist head. end is -1 */
};
-static struct objd_table objd_table = {
+static struct lttng_ust_objd_table objd_table = {
.freelist_head = -1,
};
static
-int objd_alloc(void *private_data, const struct objd_ops *ops)
+int objd_alloc(void *private_data, const struct lttng_ust_objd_ops *ops)
{
- struct obj *obj;
+ struct lttng_ust_obj *obj;
if (objd_table.freelist_head != -1) {
obj = &objd_table.array[objd_table.freelist_head];
if (objd_table.len >= objd_table.allocated_len) {
unsigned int new_allocated_len, old_allocated_len;
- struct obj *new_table, *old_table;
+ struct lttng_ust_obj *new_table, *old_table;
old_allocated_len = objd_table.allocated_len;
old_table = objd_table.array;
new_allocated_len = 1;
else
new_allocated_len = old_allocated_len << 1;
- new_table = zmalloc(sizeof(struct obj) * new_allocated_len);
+ new_table = zmalloc(sizeof(struct lttng_ust_obj) * new_allocated_len);
if (!new_table)
return -ENOMEM;
memcpy(new_table, old_table,
- sizeof(struct obj) * old_allocated_len);
+ sizeof(struct lttng_ust_obj) * old_allocated_len);
free(old_table);
objd_table.array = new_table;
objd_table.allocated_len = new_allocated_len;
}
static
-struct obj *_objd_get(int id)
+struct lttng_ust_obj *_objd_get(int id)
{
if (id >= objd_table.len)
return NULL;
static
void *objd_private(int id)
{
- struct obj *obj = _objd_get(id);
+ struct lttng_ust_obj *obj = _objd_get(id);
assert(obj);
return obj->u.s.private_data;
}
static
void objd_set_private(int id, void *private_data)
{
- struct obj *obj = _objd_get(id);
+ struct lttng_ust_obj *obj = _objd_get(id);
assert(obj);
obj->u.s.private_data = private_data;
}
-const struct objd_ops *objd_ops(int id)
+const struct lttng_ust_objd_ops *objd_ops(int id)
{
- struct obj *obj = _objd_get(id);
+ struct lttng_ust_obj *obj = _objd_get(id);
if (!obj)
return NULL;
static
void objd_free(int id)
{
- struct obj *obj = _objd_get(id);
+ struct lttng_ust_obj *obj = _objd_get(id);
assert(obj);
obj->u.freelist_next = objd_table.freelist_head;
static
void objd_ref(int id)
{
- struct obj *obj = _objd_get(id);
+ struct lttng_ust_obj *obj = _objd_get(id);
obj->u.s.f_count++;
}
int objd_unref(int id)
{
- struct obj *obj = _objd_get(id);
+ struct lttng_ust_obj *obj = _objd_get(id);
if (!obj)
return -EINVAL;
return -EINVAL;
}
if ((--obj->u.s.f_count) == 1) {
- const struct objd_ops *ops = objd_ops(id);
+ const struct lttng_ust_objd_ops *ops = objd_ops(id);
if (ops->release)
ops->release(id);
{
int i;
- for (i = 0; i < objd_table.allocated_len; i++) {
- struct obj *obj = _objd_get(i);
- const struct objd_ops *ops;
-
- if (!obj)
- continue;
- ops = obj->u.s.ops;
- if (ops->release)
- ops->release(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;
}
/*
* We send commands over a socket.
*/
-static const struct objd_ops lttng_ops;
-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 lttng_ust_objd_ops lttng_ops;
+static const struct lttng_ust_objd_ops lttng_session_ops;
+static const struct lttng_ust_objd_ops lttng_channel_ops;
+static const struct lttng_ust_objd_ops lttng_metadata_ops;
+static const struct lttng_ust_objd_ops lttng_event_ops;
+static const struct lttng_ust_objd_ops lib_ring_buffer_objd_ops;
enum channel_type {
PER_CPU_CHANNEL,
int root_handle;
root_handle = objd_alloc(NULL, <tng_ops);
- assert(root_handle == 0);
return root_handle;
}
+static
int lttng_abi_create_session(void)
{
struct ltt_session *session;
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;
}
}
}
-static const struct objd_ops lttng_ops = {
+static const struct lttng_ust_objd_ops lttng_ops = {
.cmd = lttng_cmd,
};
enum channel_type channel_type)
{
struct ltt_session *session = objd_private(session_objd);
- const struct objd_ops *ops;
+ const struct lttng_ust_objd_ops *ops;
const char *transport_name;
struct ltt_channel *chan;
int chan_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;
}
}
-static const struct objd_ops lttng_session_ops = {
+static const struct lttng_ust_objd_ops lttng_session_ops = {
.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,
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:
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;
}
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;
}
return 0;
}
-static const struct objd_ops lttng_channel_ops = {
+static const struct lttng_ust_objd_ops lttng_channel_ops = {
.release = lttng_channel_release,
//.poll = lttng_channel_poll,
.cmd = lttng_channel_cmd,
};
-static const struct objd_ops lttng_metadata_ops = {
+static const struct lttng_ust_objd_ops lttng_metadata_ops = {
.release = lttng_channel_release,
.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 lttng_ust_objd_ops lib_ring_buffer_objd_ops = {
+ .release = lttng_rb_release,
+ .cmd = lttng_rb_cmd,
+};
+
/**
* lttng_event_cmd - lttng control through object descriptors
*
}
/* TODO: filter control ioctl */
-static const struct objd_ops lttng_event_ops = {
+static const struct lttng_ust_objd_ops lttng_event_ops = {
.release = lttng_event_release,
.cmd = lttng_event_cmd,
};