X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=libust%2Flttng-ust-abi.c;h=1d32e777be7c62126f44c7281c0d4539c5835660;hb=1c5e467e5da8d549fa499c3ceb9739c5f704260d;hp=dca010c9f97353c68011eac4cab506f23d089804;hpb=1ea11eab9f65504b2d217ef16f53f52ff941c630;p=lttng-ust.git diff --git a/libust/lttng-ust-abi.c b/libust/lttng-ust-abi.c index dca010c9..1d32e777 100644 --- a/libust/lttng-ust-abi.c +++ b/libust/lttng-ust-abi.c @@ -37,13 +37,6 @@ * 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 @@ -159,9 +158,13 @@ int objd_unref(int id) if (!obj) return -EINVAL; - if (!(--obj->u.s.f_count)) { + 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); @@ -172,7 +175,15 @@ int objd_unref(int id) 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; } /* @@ -185,12 +196,22 @@ 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, <tng_ops); + return root_handle; +} + +static int lttng_abi_create_session(void) { struct ltt_session *session; @@ -251,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; } @@ -333,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) @@ -379,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; @@ -477,35 +506,46 @@ static const struct objd_ops lttng_session_ops = { .cmd = lttng_session_cmd, }; -#if 0 +struct stream_priv_data { + struct 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 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, @@ -575,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: @@ -610,8 +655,13 @@ long lttng_metadata_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); + } default: return -EINVAL; } @@ -668,6 +718,51 @@ 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.) + * TODO: Add buffer flush. + */ +static +long lttng_rb_cmd(int objd, unsigned int cmd, unsigned long arg) +{ + //struct stream_priv_data *priv = objd_private(objd); + + switch (cmd) { + default: + return -EINVAL; + } +} + +static +int lttng_rb_release(int objd) +{ + struct stream_priv_data *priv = objd_private(objd); + struct 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 *