X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=liblttng-ust%2Flttng-ust-abi.c;h=dbf533069f9b252a88327f91b5c6b106f2489983;hb=35897f8b2d311b756b81657dad9c53ef1c0fad8a;hp=639165eb3b21ad6a8606d7f3c0e720945f652d04;hpb=a3f61e7f689a5fc60b833a773f462989dc6cc78f;p=lttng-ust.git diff --git a/liblttng-ust/lttng-ust-abi.c b/liblttng-ust/lttng-ust-abi.c index 639165eb..dbf53306 100644 --- a/liblttng-ust/lttng-ust-abi.c +++ b/liblttng-ust/lttng-ust-abi.c @@ -29,8 +29,20 @@ #include #include #include -#include "lttng/core.h" +#include #include "ltt-tracer.h" +#include "tracepoint-internal.h" +#include + +struct ltt_tracepoint_list { + struct tracepoint_iter iter; + int got_first; +}; + +static int lttng_ust_abi_close_in_progress; + +static +int lttng_abi_tracepoint_list(void); /* * Object descriptor table. Should be protected from concurrent access @@ -197,6 +209,7 @@ 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; +static const struct lttng_ust_objd_ops lttng_tracepoint_list_ops; enum channel_type { PER_CPU_CHANNEL, @@ -233,33 +246,13 @@ objd_error: return ret; } -#if 0 -static -int lttng_abi_tracepoint_list(void) -{ - int list_objd, ret; - - /* TODO: Create list private data */ - list_objd = objd_alloc(NULL, <tng_tracepoint_list_ops); - if (list_objd < 0) { - ret = list_objd; - goto objd_error; - } - - return list_objd; - -objd_error: - return ret; -} -#endif //0 - static long lttng_abi_tracer_version(int objd, struct lttng_ust_tracer_version *v) { - v->version = LTTNG_UST_VERSION; - v->patchlevel = LTTNG_UST_PATCHLEVEL; - v->sublevel = LTTNG_UST_SUBLEVEL; + v->major = LTTNG_UST_MAJOR_VERSION; + v->minor = LTTNG_UST_MINOR_VERSION; + v->patchlevel = LTTNG_UST_PATCHLEVEL_VERSION; return 0; } @@ -314,8 +307,7 @@ long lttng_cmd(int objd, unsigned int cmd, unsigned long arg) return lttng_abi_tracer_version(objd, (struct lttng_ust_tracer_version *) arg); case LTTNG_UST_TRACEPOINT_LIST: - return -ENOSYS; //TODO - //return lttng_abi_tracepoint_list(); + return lttng_abi_tracepoint_list(); case LTTNG_UST_WAIT_QUIESCENT: synchronize_trace(); return 0; @@ -339,10 +331,9 @@ void lttng_metadata_create_events(int channel_objd) struct ltt_channel *channel = objd_private(channel_objd); static struct lttng_ust_event metadata_params = { .instrumentation = LTTNG_UST_TRACEPOINT, - .name = "lttng_metadata", + .name = "lttng_ust:metadata", }; struct ltt_event *event; - int ret; /* * We tolerate no failure path after event creation. It will stay @@ -350,7 +341,6 @@ void lttng_metadata_create_events(int channel_objd) */ event = ltt_event_create(channel, &metadata_params, NULL); if (!event) { - ret = -EINVAL; goto create_error; } return; @@ -370,12 +360,8 @@ int lttng_abi_create_channel(int session_objd, struct ltt_channel *chan; int chan_objd; int ret = 0; + struct ltt_channel chan_priv_init; - chan_objd = objd_alloc(NULL, <tng_channel_ops); - if (chan_objd < 0) { - ret = chan_objd; - goto objd_error; - } switch (channel_type) { case PER_CPU_CHANNEL: if (chan_param->output == LTTNG_UST_MMAP) { @@ -395,8 +381,17 @@ int lttng_abi_create_channel(int session_objd, break; default: transport_name = ""; - break; + return -EINVAL; + } + chan_objd = objd_alloc(NULL, ops); + if (chan_objd < 0) { + ret = chan_objd; + goto objd_error; } + memset(&chan_priv_init, 0, sizeof(chan_priv_init)); + /* Copy of session UUID for consumer (availability through shm) */ + memcpy(chan_priv_init.uuid, session->uuid, sizeof(session->uuid)); + /* * We tolerate no failure path after channel creation. It will stay * invariant for the rest of the session. @@ -408,7 +403,8 @@ int lttng_abi_create_channel(int session_objd, chan_param->read_timer_interval, &chan_param->shm_fd, &chan_param->wait_fd, - &chan_param->memory_map_size); + &chan_param->memory_map_size, + &chan_priv_init); if (!chan) { ret = -EINVAL; goto chan_error; @@ -421,8 +417,6 @@ int lttng_abi_create_channel(int session_objd, } /* The channel created holds a reference on the session */ objd_ref(session_objd); - /* Copy of session UUID for consumer (availability through shm) */ - memcpy(chan->uuid, session->uuid, sizeof(session->uuid)); return chan_objd; @@ -507,6 +501,102 @@ static const struct lttng_ust_objd_ops lttng_session_ops = { .cmd = lttng_session_cmd, }; +/* + * beware: we don't keep the mutex over the send, but we must walk the + * whole list each time we are called again. So sending one tracepoint + * at a time means this is O(n^2). TODO: do as in the kernel and send + * multiple tracepoints for each call to amortize this cost. + */ +static +void ltt_tracepoint_list_get(struct ltt_tracepoint_list *list, + char *tp_list_entry) +{ +next: + if (!list->got_first) { + tracepoint_iter_start(&list->iter); + list->got_first = 1; + goto copy; + } + tracepoint_iter_next(&list->iter); +copy: + if (!list->iter.tracepoint) { + tp_list_entry[0] = '\0'; /* end of list */ + } else { + if (!strcmp((*list->iter.tracepoint)->name, + "lttng_ust:metadata")) + goto next; + memcpy(tp_list_entry, (*list->iter.tracepoint)->name, + LTTNG_UST_SYM_NAME_LEN); + } +} + +static +long lttng_tracepoint_list_cmd(int objd, unsigned int cmd, unsigned long arg) +{ + struct ltt_tracepoint_list *list = objd_private(objd); + char *str = (char *) arg; + + switch (cmd) { + case LTTNG_UST_TRACEPOINT_LIST_GET: + ltt_tracepoint_list_get(list, str); + if (str[0] == '\0') + return -ENOENT; + return 0; + default: + return -EINVAL; + } +} + +static +int lttng_abi_tracepoint_list(void) +{ + int list_objd, ret; + struct ltt_tracepoint_list *list; + + list_objd = objd_alloc(NULL, <tng_tracepoint_list_ops); + if (list_objd < 0) { + ret = list_objd; + goto objd_error; + } + list = zmalloc(sizeof(*list)); + if (!list) { + ret = -ENOMEM; + goto alloc_error; + } + objd_set_private(list_objd, list); + + return list_objd; + +alloc_error: + { + int err; + + err = lttng_ust_objd_unref(list_objd); + assert(!err); + } +objd_error: + return ret; +} + +static +int lttng_release_tracepoint_list(int objd) +{ + struct ltt_tracepoint_list *list = objd_private(objd); + + if (list) { + tracepoint_iter_stop(&list->iter); + free(list); + return 0; + } else { + return -EINVAL; + } +} + +static const struct lttng_ust_objd_ops lttng_tracepoint_list_ops = { + .release = lttng_release_tracepoint_list, + .cmd = lttng_tracepoint_list_cmd, +}; + struct stream_priv_data { struct lttng_ust_lib_ring_buffer *buf; struct ltt_channel *ltt_chan; @@ -755,7 +845,21 @@ int lttng_rb_release(int objd) buf = priv->buf; channel = priv->ltt_chan; free(priv); - channel->ops->buffer_read_close(buf, channel->handle); + /* + * If we are at ABI exit, we don't want to close the + * buffer opened for read: it is being shared between + * the parent and child (right after fork), and we don't + * want the child to close it for the parent. For a real + * exit, we don't care about marking it as closed, as + * the consumer daemon (if there is one) will do fine + * even if we don't mark it as "closed" for reading on + * our side. + * We only mark it as closed if it is being explicitely + * released by the session daemon with an explicit + * release command. + */ + if (!lttng_ust_abi_close_in_progress) + channel->ops->buffer_read_close(buf, channel->handle); return lttng_ust_objd_unref(channel->objd); } @@ -819,5 +923,7 @@ static const struct lttng_ust_objd_ops lttng_event_ops = { void lttng_ust_abi_exit(void) { + lttng_ust_abi_close_in_progress = 1; objd_table_destroy(); + lttng_ust_abi_close_in_progress = 0; }