library mass rename: add lttng- prefix
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 3 Nov 2011 16:35:30 +0000 (12:35 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 3 Nov 2011 16:35:30 +0000 (12:35 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
77 files changed:
Makefile.am
configure.ac
include/lttng/ust-comm.h
include/lttng/usterr-signal-safe.h
include/usterr.h
liblttng-ust-ctl/Makefile.am [new file with mode: 0644]
liblttng-ust-ctl/ustctl.c [new file with mode: 0644]
liblttng-ust-fork/Makefile.am [new file with mode: 0644]
liblttng-ust-fork/ustfork.c [new file with mode: 0644]
liblttng-ust-java/.gitignore [new file with mode: 0644]
liblttng-ust-java/Makefile.am [new file with mode: 0644]
liblttng-ust-java/README [new file with mode: 0644]
liblttng-ust-java/UST.c [new file with mode: 0644]
liblttng-ust-java/UST.java [new file with mode: 0644]
liblttng-ust-java/ust_java.h [new file with mode: 0644]
liblttng-ust-malloc/Makefile.am [new file with mode: 0644]
liblttng-ust-malloc/README [new file with mode: 0644]
liblttng-ust-malloc/mallocwrap.c [new file with mode: 0644]
liblttng-ust-malloc/run [new file with mode: 0644]
liblttng-ust/Makefile.am [new file with mode: 0644]
liblttng-ust/ltt-context.c [new file with mode: 0644]
liblttng-ust/ltt-events.c [new file with mode: 0644]
liblttng-ust/ltt-probes.c [new file with mode: 0644]
liblttng-ust/ltt-ring-buffer-client-discard.c [new file with mode: 0644]
liblttng-ust/ltt-ring-buffer-client-overwrite.c [new file with mode: 0644]
liblttng-ust/ltt-ring-buffer-client.h [new file with mode: 0644]
liblttng-ust/ltt-ring-buffer-metadata-client.c [new file with mode: 0644]
liblttng-ust/ltt-ring-buffer-metadata-client.h [new file with mode: 0644]
liblttng-ust/ltt-tracer-core.h [new file with mode: 0644]
liblttng-ust/ltt-tracer.h [new file with mode: 0644]
liblttng-ust/lttng-context-procname.c [new file with mode: 0644]
liblttng-ust/lttng-context-pthread-id.c [new file with mode: 0644]
liblttng-ust/lttng-context-vpid.c [new file with mode: 0644]
liblttng-ust/lttng-context-vtid.c [new file with mode: 0644]
liblttng-ust/lttng-ust-abi.c [new file with mode: 0644]
liblttng-ust/lttng-ust-comm.c [new file with mode: 0644]
liblttng-ust/probes/lttng-probe-ust.c [new file with mode: 0644]
liblttng-ust/probes/lttng-probe-ust.h [new file with mode: 0644]
liblttng-ust/tracepoint.c [new file with mode: 0644]
liblttng-ust/ust-core.c [new file with mode: 0644]
libust/Makefile.am [deleted file]
libust/ltt-context.c [deleted file]
libust/ltt-events.c [deleted file]
libust/ltt-probes.c [deleted file]
libust/ltt-ring-buffer-client-discard.c [deleted file]
libust/ltt-ring-buffer-client-overwrite.c [deleted file]
libust/ltt-ring-buffer-client.h [deleted file]
libust/ltt-ring-buffer-metadata-client.c [deleted file]
libust/ltt-ring-buffer-metadata-client.h [deleted file]
libust/ltt-tracer-core.h [deleted file]
libust/ltt-tracer.h [deleted file]
libust/lttng-context-procname.c [deleted file]
libust/lttng-context-pthread-id.c [deleted file]
libust/lttng-context-vpid.c [deleted file]
libust/lttng-context-vtid.c [deleted file]
libust/lttng-ust-abi.c [deleted file]
libust/lttng-ust-comm.c [deleted file]
libust/probes/lttng-probe-ust.c [deleted file]
libust/probes/lttng-probe-ust.h [deleted file]
libust/tracepoint.c [deleted file]
libust/ust-core.c [deleted file]
libustctl/Makefile.am [deleted file]
libustctl/ustctl.c [deleted file]
libustfork/Makefile.am [deleted file]
libustfork/ustfork.c [deleted file]
libustinstr-malloc/Makefile.am [deleted file]
libustinstr-malloc/README [deleted file]
libustinstr-malloc/mallocwrap.c [deleted file]
libustinstr-malloc/run [deleted file]
libustjava/.gitignore [deleted file]
libustjava/Makefile.am [deleted file]
libustjava/README [deleted file]
libustjava/UST.c [deleted file]
libustjava/UST.java [deleted file]
libustjava/ust_java.h [deleted file]
tests/fork/Makefile.am
tests/hello/Makefile.am

index b9cc1e7d1637977d40d97d36adc71ea9ecdd46e5..f966498bf5bcd749c0cecd06730280e430822c8d 100644 (file)
@@ -1,10 +1,14 @@
 ACLOCAL_AMFLAGS = -I config
 
-SUBDIRS = . snprintf liblttng-ust-comm libringbuffer libust libustctl \
-               include doc libustjava libustfork tests
+SUBDIRS = . include doc snprintf libringbuffer liblttng-ust-comm \
+               liblttng-ust \
+               liblttng-ust-ctl \
+               liblttng-ust-fork \
+               liblttng-ust-java \
+               tests
 
 #temporarily disabled
-# . libustinstr-malloc
+# liblttng-ust-malloc
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = ust.pc
index be93880c987813122ffef888d9eb00a293af05d4..88a31e9c5364a8d5073829ffb9c779903b73cf9d 100644 (file)
@@ -189,14 +189,19 @@ AM_CONDITIONAL(BUILD_JNI_INTERFACE, test "$with_jni_interface" = "yes")
 
 AC_CONFIG_FILES([
        Makefile
+       include/Makefile
+       include/lttng/version.h
        doc/Makefile
        doc/man/Makefile
        doc/info/Makefile
-       include/Makefile
-       liblttng-ust-comm/Makefile
+       snprintf/Makefile
        libringbuffer/Makefile
-       libust/Makefile
-       libustctl/Makefile
+       liblttng-ust-comm/Makefile
+       liblttng-ust/Makefile
+       liblttng-ust-ctl/Makefile
+       liblttng-ust-fork/Makefile
+       liblttng-ust-java/Makefile
+       liblttng-ust-malloc/Makefile
        tests/Makefile
        tests/hello/Makefile
        tests/ust-basic-tracing/Makefile
@@ -217,11 +222,6 @@ AC_CONFIG_FILES([
        tests/register_test/Makefile
        tests/libustctl_function_tests/Makefile
        tests/exit-fast/Makefile
-       libustinstr-malloc/Makefile
-       libustfork/Makefile
-       snprintf/Makefile
        ust.pc
-       include/lttng/version.h
-       libustjava/Makefile
 ])
 AC_OUTPUT
index 5fa417eec081a7cd4fe48cbfbca30661ad408851..e2a4661798ab46b7a4bca5254fe544b7105b0af2 100644 (file)
@@ -33,7 +33,7 @@
 /*
  * Default timeout the application waits for the sessiond to send its
  * "register done" command. Can be overridden with the environment
- * variable "UST_REGISTER_TIMEOUT". Note that if the sessiond is not
+ * variable "LTTNG_UST_REGISTER_TIMEOUT". Note that if the sessiond is not
  * found, the application proceeds directly without any delay.
  */
 #define LTTNG_UST_DEFAULT_CONSTRUCTOR_TIMEOUT_MS       3000
index 894149a3464056e5c13ab22a1874649ab96d8b10..b8e03dbd9ccd6d651ef670f9409a9c3ad5c69785 100644 (file)
@@ -102,7 +102,7 @@ static inline void __attribute__ ((format (printf, 1, 2)))
                fflush(stderr);                 \
        } while(0)
 
-#ifdef UST_DEBUG
+#ifdef LTTNG_UST_DEBUG
 # define DBG(fmt, args...)                     ERRMSG(fmt, ## args)
 # define DBG_raw(fmt, args...)                                 \
        do {                                                    \
index 820d4f03d9bd062524a060556ce99398ff2da1cb..fd5c80ae56475b40f46a067dc5be93010da5ad00 100644 (file)
@@ -63,7 +63,7 @@ static inline int ust_debug(void)
                        __func__);                              \
        } while(0)
 
-#ifdef UST_DEBUG
+#ifdef LTTNG_UST_DEBUG
 # define DBG(fmt, args...)             ERRMSG(fmt, ## args)
 # define DBG_raw(fmt, args...)                                 \
        do {                                                    \
diff --git a/liblttng-ust-ctl/Makefile.am b/liblttng-ust-ctl/Makefile.am
new file mode 100644 (file)
index 0000000..69d747d
--- /dev/null
@@ -0,0 +1,11 @@
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/liblttng-ust-comm
+AM_CFLAGS = -fno-strict-aliasing
+
+lib_LTLIBRARIES = liblttng-ust-ctl.la
+
+liblttng_ust_ctl_la_SOURCES = ustctl.c
+
+liblttng_ust_ctl_la_LIBADD = \
+       $(top_builddir)/liblttng-ust-comm/liblttng-ust-comm.la \
+       $(top_builddir)/libringbuffer/libringbuffer.la \
+       $(top_builddir)/snprintf/libustsnprintf.la
diff --git a/liblttng-ust-ctl/ustctl.c b/liblttng-ust-ctl/ustctl.c
new file mode 100644 (file)
index 0000000..6f3d1ed
--- /dev/null
@@ -0,0 +1,668 @@
+/*
+ * Copyright (C) 2011 - Julien Desfossez <julien.desfossez@polymtl.ca>
+ *                      Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; only version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <string.h>
+#include <lttng/ust-ctl.h>
+#include <lttng/ust-abi.h>
+#include <lttng/usterr-signal-safe.h>
+#include <lttng/ust-comm.h>
+
+#include "../libringbuffer/backend.h"
+#include "../libringbuffer/frontend.h"
+
+volatile enum ust_loglevel ust_loglevel;
+
+static
+void init_object(struct lttng_ust_object_data *data)
+{
+       data->handle = -1;
+       data->shm_fd = -1;
+       data->wait_fd = -1;
+       data->memory_map_size = 0;
+}
+
+void release_object(int sock, struct lttng_ust_object_data *data)
+{
+       struct ustcomm_ust_msg lum;
+       struct ustcomm_ust_reply lur;
+       int ret;
+
+       if (data->shm_fd >= 0)
+               close(data->shm_fd);
+       if (data->wait_fd >= 0)
+               close(data->wait_fd);
+       memset(&lum, 0, sizeof(lum));
+       lum.handle = data->handle;
+       lum.cmd = LTTNG_UST_RELEASE;
+       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+       assert(!ret);
+       free(data);
+}
+
+/*
+ * Send registration done packet to the application.
+ */
+int ustctl_register_done(int sock)
+{
+       struct ustcomm_ust_msg lum;
+       struct ustcomm_ust_reply lur;
+       int ret;
+
+       DBG("Sending register done command to %d", sock);
+       memset(&lum, 0, sizeof(lum));
+       lum.handle = LTTNG_UST_ROOT_HANDLE;
+       lum.cmd = LTTNG_UST_REGISTER_DONE;
+       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+       if (ret)
+               return ret;
+       if (lur.ret_code != USTCOMM_OK) {
+               DBG("Return code: %s", ustcomm_get_readable_code(lur.ret_code));
+               goto error;
+       }
+       return 0;
+
+error:
+       return -1;
+}
+
+/*
+ * returns session handle.
+ */
+int ustctl_create_session(int sock)
+{
+       struct ustcomm_ust_msg lum;
+       struct ustcomm_ust_reply lur;
+       int ret, session_handle;
+
+       /* Create session */
+       memset(&lum, 0, sizeof(lum));
+       lum.handle = LTTNG_UST_ROOT_HANDLE;
+       lum.cmd = LTTNG_UST_SESSION;
+       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+       if (ret)
+               return ret;
+       session_handle = lur.ret_val;
+       DBG("received session handle %u", session_handle);
+       return session_handle;
+}
+
+/* open the metadata global channel */
+int ustctl_open_metadata(int sock, int session_handle,
+               struct lttng_ust_channel_attr *chops,
+               struct lttng_ust_object_data **_metadata_data)
+{
+       struct ustcomm_ust_msg lum;
+       struct ustcomm_ust_reply lur;
+       struct lttng_ust_object_data *metadata_data;
+       int ret;
+
+       metadata_data = malloc(sizeof(*metadata_data));
+       if (!metadata_data)
+               return -ENOMEM;
+       init_object(metadata_data);
+       /* Create metadata channel */
+       memset(&lum, 0, sizeof(lum));
+       lum.handle = session_handle;
+       lum.cmd = LTTNG_UST_METADATA;
+       lum.u.channel.overwrite = chops->overwrite;
+       lum.u.channel.subbuf_size = chops->subbuf_size;
+       lum.u.channel.num_subbuf = chops->num_subbuf;
+       lum.u.channel.switch_timer_interval = chops->switch_timer_interval;
+       lum.u.channel.read_timer_interval = chops->read_timer_interval;
+       lum.u.channel.output = chops->output;
+       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+       if (ret) {
+               free(metadata_data);
+               return ret;
+       }
+       if (lur.ret_code != USTCOMM_OK) {
+               free(metadata_data);
+               return lur.ret_code;
+       }
+       metadata_data->handle = lur.ret_val;
+       DBG("received metadata handle %u", metadata_data->handle);
+       metadata_data->memory_map_size = lur.u.channel.memory_map_size;
+       /* get shm fd */
+       ret = ustcomm_recv_fd(sock);
+       if (ret < 0)
+               goto error;
+       metadata_data->shm_fd = ret;
+       /* get wait fd */
+       ret = ustcomm_recv_fd(sock);
+       if (ret < 0)
+               goto error;
+       metadata_data->wait_fd = ret;
+       *_metadata_data = metadata_data;
+       return 0;
+
+error:
+       release_object(sock, metadata_data);
+       return -EINVAL;
+}
+
+int ustctl_create_channel(int sock, int session_handle,
+               struct lttng_ust_channel_attr *chops,
+               struct lttng_ust_object_data **_channel_data)
+{
+       struct ustcomm_ust_msg lum;
+       struct ustcomm_ust_reply lur;
+       struct lttng_ust_object_data *channel_data;
+       int ret;
+
+       channel_data = malloc(sizeof(*channel_data));
+       if (!channel_data)
+               return -ENOMEM;
+       init_object(channel_data);
+       /* Create metadata channel */
+       memset(&lum, 0, sizeof(lum));
+       lum.handle = session_handle;
+       lum.cmd = LTTNG_UST_CHANNEL;
+       lum.u.channel.overwrite = chops->overwrite;
+       lum.u.channel.subbuf_size = chops->subbuf_size;
+       lum.u.channel.num_subbuf = chops->num_subbuf;
+       lum.u.channel.switch_timer_interval = chops->switch_timer_interval;
+       lum.u.channel.read_timer_interval = chops->read_timer_interval;
+       lum.u.channel.output = chops->output;
+       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+       if (ret) {
+               free(channel_data);
+               return ret;
+       }
+       if (lur.ret_code != USTCOMM_OK) {
+               free(channel_data);
+               return lur.ret_code;
+       }
+       channel_data->handle = lur.ret_val;
+       DBG("received channel handle %u", channel_data->handle);
+       channel_data->memory_map_size = lur.u.channel.memory_map_size;
+       /* get shm fd */
+       ret = ustcomm_recv_fd(sock);
+       if (ret < 0)
+               goto error;
+       channel_data->shm_fd = ret;
+       /* get wait fd */
+       ret = ustcomm_recv_fd(sock);
+       if (ret < 0)
+               goto error;
+       channel_data->wait_fd = ret;
+       *_channel_data = channel_data;
+       return 0;
+
+error:
+       release_object(sock, channel_data);
+       return -EINVAL;
+}
+
+/*
+ * Return -ENOENT if no more stream is available for creation.
+ * Return 0 on success.
+ * Return negative error value on error.
+ */
+int ustctl_create_stream(int sock, struct lttng_ust_object_data *channel_data,
+               struct lttng_ust_object_data **_stream_data)
+{
+       struct ustcomm_ust_msg lum;
+       struct ustcomm_ust_reply lur;
+       struct lttng_ust_object_data *stream_data;
+       int ret, fd;
+
+       stream_data = malloc(sizeof(*stream_data));
+       if (!stream_data)
+               return -ENOMEM;
+       init_object(stream_data);
+       memset(&lum, 0, sizeof(lum));
+       lum.handle = channel_data->handle;
+       lum.cmd = LTTNG_UST_STREAM;
+       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+       if (ret) {
+               free(stream_data);
+               return ret;
+       }
+       if (lur.ret_code != USTCOMM_OK) {
+               free(stream_data);
+               return lur.ret_code;
+       }
+
+       stream_data->handle = lur.ret_val;
+       DBG("received stream handle %u", stream_data->handle);
+       stream_data->memory_map_size = lur.u.stream.memory_map_size;
+       /* get shm fd */
+       fd = ustcomm_recv_fd(sock);
+       if (fd < 0)
+               goto error;
+       stream_data->shm_fd = fd;
+       /* get wait fd */
+       fd = ustcomm_recv_fd(sock);
+       if (fd < 0)
+               goto error;
+       stream_data->wait_fd = fd;
+       *_stream_data = stream_data;
+       return ret;
+
+error:
+       release_object(sock, stream_data);
+       return -EINVAL;
+}
+
+int ustctl_create_event(int sock, struct lttng_ust_event *ev,
+               struct lttng_ust_object_data *channel_data,
+               struct lttng_ust_object_data **_event_data)
+{
+       struct ustcomm_ust_msg lum;
+       struct ustcomm_ust_reply lur;
+       struct lttng_ust_object_data *event_data;
+       int ret;
+
+       event_data = malloc(sizeof(*event_data));
+       if (!event_data)
+               return -ENOMEM;
+       init_object(event_data);
+       memset(&lum, 0, sizeof(lum));
+       lum.handle = channel_data->handle;
+       lum.cmd = LTTNG_UST_EVENT;
+       strncpy(lum.u.event.name, ev->name,
+               LTTNG_UST_SYM_NAME_LEN);
+       lum.u.event.instrumentation = ev->instrumentation;
+       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+       if (ret) {
+               free(event_data);
+               return ret;
+       }
+       event_data->handle = lur.ret_val;
+       DBG("received event handle %u", event_data->handle);
+       *_event_data = event_data;
+       return 0;
+}
+
+int ustctl_add_context(int sock, struct lttng_ust_context *ctx,
+               struct lttng_ust_object_data *obj_data,
+               struct lttng_ust_object_data **_context_data)
+{
+       struct ustcomm_ust_msg lum;
+       struct ustcomm_ust_reply lur;
+       struct lttng_ust_object_data *context_data;
+       int ret;
+
+       context_data = malloc(sizeof(*context_data));
+       if (!context_data)
+               return -ENOMEM;
+       init_object(context_data);
+       memset(&lum, 0, sizeof(lum));
+       lum.handle = obj_data->handle;
+       lum.cmd = LTTNG_UST_CONTEXT;
+       lum.u.context.ctx = ctx->ctx;
+       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+       if (ret) {
+               free(context_data);
+               return ret;
+       }
+       context_data->handle = lur.ret_val;
+       DBG("received context handle %u", context_data->handle);
+       *_context_data = context_data;
+       return ret;
+}
+
+/* Enable event, channel and session ioctl */
+int ustctl_enable(int sock, struct lttng_ust_object_data *object)
+{
+       struct ustcomm_ust_msg lum;
+       struct ustcomm_ust_reply lur;
+       int ret;
+
+       memset(&lum, 0, sizeof(lum));
+       lum.handle = object->handle;
+       lum.cmd = LTTNG_UST_ENABLE;
+       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+       if (ret)
+               return ret;
+       DBG("enabled handle %u", object->handle);
+       return 0;
+}
+
+/* Disable event, channel and session ioctl */
+int ustctl_disable(int sock, struct lttng_ust_object_data *object)
+{
+       struct ustcomm_ust_msg lum;
+       struct ustcomm_ust_reply lur;
+       int ret;
+
+       memset(&lum, 0, sizeof(lum));
+       lum.handle = object->handle;
+       lum.cmd = LTTNG_UST_DISABLE;
+       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+       if (ret)
+               return ret;
+       DBG("disable handle %u", object->handle);
+       return 0;
+}
+
+int ustctl_start_session(int sock, int handle)
+{
+       struct lttng_ust_object_data obj;
+
+       obj.handle = handle;
+       return ustctl_enable(sock, &obj);
+}
+
+int ustctl_stop_session(int sock, int handle)
+{
+       struct lttng_ust_object_data obj;
+
+       obj.handle = handle;
+       return ustctl_disable(sock, &obj);
+}
+
+
+int ustctl_tracepoint_list(int sock)
+{
+       return -ENOSYS; /* not implemented */
+}
+
+int ustctl_tracer_version(int sock, struct lttng_ust_tracer_version *v)
+{
+       struct ustcomm_ust_msg lum;
+       struct ustcomm_ust_reply lur;
+       int ret;
+
+       memset(&lum, 0, sizeof(lum));
+       lum.handle = LTTNG_UST_ROOT_HANDLE;
+       lum.cmd = LTTNG_UST_TRACER_VERSION;
+       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+       if (ret)
+               return ret;
+       memcpy(v, &lur.u.version, sizeof(*v));
+       DBG("received tracer version");
+       return 0;
+}
+
+int ustctl_wait_quiescent(int sock)
+{
+       struct ustcomm_ust_msg lum;
+       struct ustcomm_ust_reply lur;
+       int ret;
+
+       memset(&lum, 0, sizeof(lum));
+       lum.handle = LTTNG_UST_ROOT_HANDLE;
+       lum.cmd = LTTNG_UST_WAIT_QUIESCENT;
+       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+       if (ret)
+               return ret;
+       DBG("waited for quiescent state");
+       return 0;
+}
+
+int ustctl_flush_buffer(int sock, struct lttng_ust_object_data *channel_data)
+{
+       struct ustcomm_ust_msg lum;
+       struct ustcomm_ust_reply lur;
+
+       memset(&lum, 0, sizeof(lum));
+       lum.handle = channel_data->handle;
+       lum.cmd = LTTNG_UST_FLUSH_BUFFER;
+       return ustcomm_send_app_cmd(sock, &lum, &lur);
+}
+
+int ustctl_calibrate(int sock, struct lttng_ust_calibrate *calibrate)
+{
+       return -ENOSYS;
+}
+
+/* Buffer operations */
+
+/* Map channel shm into process memory */
+struct lttng_ust_shm_handle *ustctl_map_channel(struct lttng_ust_object_data *chan_data)
+{
+       struct lttng_ust_shm_handle *handle;
+       struct channel *chan;
+       size_t chan_size;
+
+       handle = channel_handle_create(chan_data->shm_fd,
+               chan_data->wait_fd,
+               chan_data->memory_map_size);
+       if (!handle) {
+               ERR("create handle error");
+               return NULL;
+       }
+       /*
+        * Set to -1 because the lttng_ust_shm_handle destruction will take care
+        * of closing shm_fd and wait_fd.
+        */
+       chan_data->shm_fd = -1;
+       chan_data->wait_fd = -1;
+
+       /*
+        * TODO: add consistency checks to be resilient if the
+        * application try to feed us with incoherent channel structure
+        * values.
+        */
+       chan = shmp(handle, handle->chan);
+       /* chan is object 0. This is hardcoded. */
+       chan_size = handle->table->objects[0].allocated_len;
+       handle->shadow_chan = malloc(chan_size);
+       if (!handle->shadow_chan) {
+               channel_destroy(chan, handle, 1);
+               return NULL;
+       }
+       memcpy(handle->shadow_chan, chan, chan_size);
+       return handle;
+}
+
+/* Add stream to channel shm and map its shm into process memory */
+int ustctl_add_stream(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_object_data *stream_data)
+{
+       int ret;
+
+       if (!stream_data->handle)
+               return -ENOENT;
+       /* map stream */
+       ret = channel_handle_add_stream(handle,
+               stream_data->shm_fd,
+               stream_data->wait_fd,
+               stream_data->memory_map_size);
+       if (ret) {
+               ERR("add stream error\n");
+               return ret;
+       }
+       /*
+        * Set to -1 because the lttng_ust_shm_handle destruction will take care
+        * of closing shm_fd and wait_fd.
+        */
+       stream_data->shm_fd = -1;
+       stream_data->wait_fd = -1;
+       return 0;
+}
+
+void ustctl_unmap_channel(struct lttng_ust_shm_handle *handle)
+{
+       struct channel *chan;
+
+       chan = shmp(handle, handle->chan);
+       channel_destroy(chan, handle, 1);
+}
+
+struct lttng_ust_lib_ring_buffer *ustctl_open_stream_read(struct lttng_ust_shm_handle *handle,
+       int cpu)
+{
+       struct channel *chan = handle->shadow_chan;
+       int shm_fd, wait_fd;
+       uint64_t memory_map_size;
+       struct lttng_ust_lib_ring_buffer *buf;
+       int ret;
+
+       buf = channel_get_ring_buffer(&chan->backend.config,
+               chan, cpu, handle, &shm_fd, &wait_fd, &memory_map_size);
+       if (!buf)
+               return NULL;
+       ret = lib_ring_buffer_open_read(buf, handle, 1);
+       if (ret)
+               return NULL;
+       return buf;
+}
+
+void ustctl_close_stream_read(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_lib_ring_buffer *buf)
+{
+       lib_ring_buffer_release_read(buf, handle, 1);
+}
+
+/* For mmap mode, readable without "get" operation */
+
+void *ustctl_get_mmap_base(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_lib_ring_buffer *buf)
+{
+       return shmp(handle, buf->backend.memory_map);
+}
+
+/* returns the length to mmap. */
+int ustctl_get_mmap_len(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_lib_ring_buffer *buf,
+               unsigned long *len)
+{
+       unsigned long mmap_buf_len;
+       struct channel *chan = handle->shadow_chan;
+
+       if (chan->backend.config.output != RING_BUFFER_MMAP)
+               return -EINVAL;
+       mmap_buf_len = chan->backend.buf_size;
+       if (chan->backend.extra_reader_sb)
+               mmap_buf_len += chan->backend.subbuf_size;
+       if (mmap_buf_len > INT_MAX)
+               return -EFBIG;
+       *len = mmap_buf_len;
+       return 0;
+}
+
+/* returns the maximum size for sub-buffers. */
+int ustctl_get_max_subbuf_size(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_lib_ring_buffer *buf,
+               unsigned long *len)
+{
+       struct channel *chan = handle->shadow_chan;
+
+       *len = chan->backend.subbuf_size;
+       return 0;
+}
+
+/*
+ * For mmap mode, operate on the current packet (between get/put or
+ * get_next/put_next).
+ */
+
+/* returns the offset of the subbuffer belonging to the mmap reader. */
+int ustctl_get_mmap_read_offset(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_lib_ring_buffer *buf, unsigned long *off)
+{
+       struct channel *chan = handle->shadow_chan;
+       unsigned long sb_bindex;
+
+       if (chan->backend.config.output != RING_BUFFER_MMAP)
+               return -EINVAL;
+       sb_bindex = subbuffer_id_get_index(&chan->backend.config,
+                                          buf->backend.buf_rsb.id);
+       *off = shmp(handle, shmp_index(handle, buf->backend.array, sb_bindex)->shmp)->mmap_offset;
+       return 0;
+}
+
+/* returns the size of the current sub-buffer, without padding (for mmap). */
+int ustctl_get_subbuf_size(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_lib_ring_buffer *buf, unsigned long *len)
+{
+       struct channel *chan = handle->shadow_chan;
+
+       *len = lib_ring_buffer_get_read_data_size(&chan->backend.config, buf,
+               handle);
+       return 0;
+}
+
+/* returns the size of the current sub-buffer, without padding (for mmap). */
+int ustctl_get_padded_subbuf_size(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_lib_ring_buffer *buf, unsigned long *len)
+{
+       struct channel *chan = handle->shadow_chan;
+
+       *len = lib_ring_buffer_get_read_data_size(&chan->backend.config, buf,
+               handle);
+       *len = PAGE_ALIGN(*len);
+       return 0;
+}
+
+/* Get exclusive read access to the next sub-buffer that can be read. */
+int ustctl_get_next_subbuf(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_lib_ring_buffer *buf)
+{
+       return lib_ring_buffer_get_next_subbuf(buf, handle);
+}
+
+
+/* Release exclusive sub-buffer access, move consumer forward. */
+int ustctl_put_next_subbuf(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_lib_ring_buffer *buf)
+{
+       lib_ring_buffer_put_next_subbuf(buf, handle);
+       return 0;
+}
+
+/* snapshot */
+
+/* Get a snapshot of the current ring buffer producer and consumer positions */
+int ustctl_snapshot(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_lib_ring_buffer *buf)
+{
+       return lib_ring_buffer_snapshot(buf, &buf->cons_snapshot,
+                       &buf->prod_snapshot, handle);
+}
+
+/* Get the consumer position (iteration start) */
+int ustctl_snapshot_get_consumed(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_lib_ring_buffer *buf, unsigned long *pos)
+{
+       *pos = buf->cons_snapshot;
+       return 0;
+}
+
+/* Get the producer position (iteration end) */
+int ustctl_snapshot_get_produced(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_lib_ring_buffer *buf, unsigned long *pos)
+{
+       *pos = buf->prod_snapshot;
+       return 0;
+}
+
+/* Get exclusive read access to the specified sub-buffer position */
+int ustctl_get_subbuf(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_lib_ring_buffer *buf, unsigned long *pos)
+{
+       return lib_ring_buffer_get_subbuf(buf, *pos, handle);
+}
+
+/* Release exclusive sub-buffer access */
+int ustctl_put_subbuf(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_lib_ring_buffer *buf)
+{
+       lib_ring_buffer_put_subbuf(buf, handle);
+       return 0;
+}
+
+int ustctl_buffer_flush(struct lttng_ust_shm_handle *handle,
+               struct lttng_ust_lib_ring_buffer *buf)
+{
+       lib_ring_buffer_switch_slow(buf, SWITCH_ACTIVE, handle);
+       return 0;
+}
diff --git a/liblttng-ust-fork/Makefile.am b/liblttng-ust-fork/Makefile.am
new file mode 100644 (file)
index 0000000..e0e42a3
--- /dev/null
@@ -0,0 +1,9 @@
+AM_CPPFLAGS = -I$(top_srcdir)/include
+AM_CFLAGS = -fno-strict-aliasing
+
+lib_LTLIBRARIES = liblttng-ust-fork.la
+liblttng_ust_fork_la_SOURCES = ustfork.c
+liblttng_ust_fork_la_LIBADD = \
+       -ldl \
+       $(top_builddir)/liblttng-ust/liblttng-ust.la
+libustfork_CFLAGS = -DUST_COMPONENT=liblttng-ust-fork -fno-strict-aliasing
diff --git a/liblttng-ust-fork/ustfork.c b/liblttng-ust-fork/ustfork.c
new file mode 100644 (file)
index 0000000..5e6acba
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2009  Pierre-Marc Fournier
+ * Copyright (C) 2011  Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1 of
+ * the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#define _GNU_SOURCE
+#include <dlfcn.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <signal.h>
+#include <sched.h>
+#include <stdarg.h>
+#include "usterr.h"
+
+#include <lttng/ust.h>
+
+struct user_desc;
+
+pid_t fork(void)
+{
+       static pid_t (*plibc_func)(void) = NULL;
+       ust_fork_info_t fork_info;
+       pid_t retval;
+
+       if (plibc_func == NULL) {
+               plibc_func = dlsym(RTLD_NEXT, "fork");
+               if (plibc_func == NULL) {
+                       fprintf(stderr, "libustfork: unable to find \"fork\" symbol\n");
+                       return -1;
+               }
+       }
+
+       ust_before_fork(&fork_info);
+       /* Do the real fork */
+       retval = plibc_func();
+       if (retval == 0) {
+               /* child */
+               ust_after_fork_child(&fork_info);
+       } else {
+               ust_after_fork_parent(&fork_info);
+       }
+       return retval;
+}
+
+struct ustfork_clone_info {
+       int (*fn)(void *);
+       void *arg;
+       ust_fork_info_t fork_info;
+};
+
+static int clone_fn(void *arg)
+{
+       struct ustfork_clone_info *info = (struct ustfork_clone_info *) arg;
+
+       /* clone is now done and we are in child */
+       ust_after_fork_child(&info->fork_info);
+       return info->fn(info->arg);
+}
+
+int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...)
+{
+       static int (*plibc_func)(int (*fn)(void *), void *child_stack,
+                       int flags, void *arg, pid_t *ptid,
+                       struct user_desc *tls, pid_t *ctid) = NULL;
+       /* var args */
+       pid_t *ptid;
+       struct user_desc *tls;
+       pid_t *ctid;
+       /* end of var args */
+       va_list ap;
+       int retval;
+
+       va_start(ap, arg);
+       ptid = va_arg(ap, pid_t *);
+       tls = va_arg(ap, struct user_desc *);
+       ctid = va_arg(ap, pid_t *);
+       va_end(ap);
+
+       if (plibc_func == NULL) {
+               plibc_func = dlsym(RTLD_NEXT, "clone");
+               if (plibc_func == NULL) {
+                       fprintf(stderr, "libustfork: unable to find \"clone\" symbol.\n");
+                       return -1;
+               }
+       }
+
+       if (flags & CLONE_VM) {
+               /*
+                * Creating a thread, no need to intervene, just pass on
+                * the arguments.
+                */
+               retval = plibc_func(fn, child_stack, flags, arg, ptid,
+                               tls, ctid);
+       } else {
+               /* Creating a real process, we need to intervene. */
+               struct ustfork_clone_info info = { fn: fn, arg: arg };
+
+               ust_before_fork(&info.fork_info);
+               retval = plibc_func(clone_fn, child_stack, flags, &info,
+                               ptid, tls, ctid);
+               /* The child doesn't get here. */
+               ust_after_fork_parent(&info.fork_info);
+       }
+       return retval;
+}
diff --git a/liblttng-ust-java/.gitignore b/liblttng-ust-java/.gitignore
new file mode 100644 (file)
index 0000000..ab97d04
--- /dev/null
@@ -0,0 +1,2 @@
+UST.class
+UST.h
diff --git a/liblttng-ust-java/Makefile.am b/liblttng-ust-java/Makefile.am
new file mode 100644 (file)
index 0000000..fb25cb7
--- /dev/null
@@ -0,0 +1,21 @@
+if BUILD_JNI_INTERFACE
+
+AM_CPPFLAGS = -I$(top_srcdir)/include
+
+lib_LTLIBRARIES = liblttng-ust-java.la
+liblttng_ust_java_la_SOURCES = UST.c UST.h ust_java.h
+dist_noinst_DATA = UST.java
+liblttng_ust_java_la_LIBADD = -lc -L$(top_builddir)/liblttng-ust/.libs -llttng-ust
+
+all: UST.class UST.h
+
+clean-local:
+       rm -rf UST.h UST.class
+
+UST.class: UST.java
+       javac -d "$(builddir)" "$(srcdir)/UST.java"
+
+UST.h: UST.class
+       javah -jni UST
+
+endif
diff --git a/liblttng-ust-java/README b/liblttng-ust-java/README
new file mode 100644 (file)
index 0000000..37834e6
--- /dev/null
@@ -0,0 +1,12 @@
+This directory contains a simple API for instrumenting java applications.
+
+Configuration examples to build this library:
+
+dependency: sun-java6-jdk
+./configure --with-java-jdk=/usr/lib/jvm/java-6-sun --with-jni-interface
+
+dependency: openjdk-6-jdk
+./configure --with-java-jdk=/usr/lib/jvm/java-6-openjdk --with-jni-interface
+
+dependency: gcj-4.4-jdk
+./configure --with-java-jdk=/usr/lib/jvm/java-gcj --with-jni-interface
diff --git a/liblttng-ust-java/UST.c b/liblttng-ust-java/UST.c
new file mode 100644 (file)
index 0000000..7ad1c71
--- /dev/null
@@ -0,0 +1,15 @@
+#include <jni.h>
+
+#define TRACEPOINT_CREATE_PROBES
+#include "ust_java.h"
+
+JNIEXPORT void JNICALL Java_UST_ust_1java_1event (JNIEnv *env, jobject jobj,
+                                               jstring ev_name, jstring args)
+{
+       jboolean iscopy;
+       const char *ev_name_cstr = (*env)->GetStringUTFChars(env, ev_name,
+                                                       &iscopy);
+       const char *args_cstr = (*env)->GetStringUTFChars(env, args, &iscopy);
+
+       tracepoint(ust_java_event, ev_name_cstr, args_cstr);
+}
diff --git a/liblttng-ust-java/UST.java b/liblttng-ust-java/UST.java
new file mode 100644 (file)
index 0000000..be5f7c7
--- /dev/null
@@ -0,0 +1,9 @@
+import java.util.*;
+
+class UST {
+       public static native void ust_java_event(String name, String arg);
+       static {
+               System.loadLibrary("ustjava");
+       }
+}
+
diff --git a/liblttng-ust-java/ust_java.h b/liblttng-ust-java/ust_java.h
new file mode 100644 (file)
index 0000000..366b373
--- /dev/null
@@ -0,0 +1,44 @@
+#undef TRACEPOINT_SYSTEM
+#define TRACEPOINT_SYSTEM ust_java
+
+#if !defined(_TRACEPOINT_UST_JAVA_H) || defined(TRACEPOINT_HEADER_MULTI_READ)
+#define _TRACEPOINT_UST_JAVA_H
+
+/*
+ * Copyright (C) 2011  Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1 of
+ * the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <ust/tracepoint.h>
+
+TRACEPOINT_EVENT(ust_java_event,
+       TP_PROTO(const char *name, const char *args),
+       TP_ARGS(name, args),
+       TP_FIELDS(
+               ctf_string(name, name)
+               ctf_string(args, args)
+       )
+)
+
+#endif /* _TRACEPOINT_UST_JAVA_H */
+
+#undef TRACEPOINT_INCLUDE_PATH
+#define TRACEPOINT_INCLUDE_PATH .
+#undef TRACEPOINT_INCLUDE_FILE
+#define TRACEPOINT_INCLUDE_FILE ust_java
+
+/* This part must be outside protection */
+#include <ust/tracepoint-event.h>
diff --git a/liblttng-ust-malloc/Makefile.am b/liblttng-ust-malloc/Makefile.am
new file mode 100644 (file)
index 0000000..eb2ea75
--- /dev/null
@@ -0,0 +1,9 @@
+AM_CPPFLAGS = -I$(top_srcdir)/include
+AM_CFLAGS = -fno-strict-aliasing
+
+lib_LTLIBRARIES = liblttng-ust-malloc.la
+liblttng_ust_malloc_la_SOURCES = mallocwrap.c
+liblttng_ust_malloc_la_LIBADD = -ldl
+
+noinst_SCRIPTS = run
+EXTRA_DIST = run
diff --git a/liblttng-ust-malloc/README b/liblttng-ust-malloc/README
new file mode 100644 (file)
index 0000000..c58a7e6
--- /dev/null
@@ -0,0 +1,9 @@
+libustinstr-malloc is used for instrumenting calls to malloc(3) in a program,
+without need for recompiling it.
+
+libustinstr-malloc defines a malloc() function that is instrumented with a
+marker. It also calls the libc malloc afterwards. When loaded with LD_PRELOAD,
+it replaces the libc malloc() function, in effect instrumenting all calls to
+malloc().
+
+See the "run" script for a usage example.
diff --git a/liblttng-ust-malloc/mallocwrap.c b/liblttng-ust-malloc/mallocwrap.c
new file mode 100644 (file)
index 0000000..6e66856
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009  Pierre-Marc Fournier
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#define _GNU_SOURCE
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <ust/marker.h>
+
+void *malloc(size_t size)
+{
+       static void *(*plibc_malloc)(size_t size) = NULL;
+       void *retval;
+
+       if (plibc_malloc == NULL) {
+               plibc_malloc = dlsym(RTLD_NEXT, "malloc");
+               if (plibc_malloc == NULL) {
+                       fprintf(stderr, "mallocwrap: unable to find malloc\n");
+                       return NULL;
+               }
+       }
+
+       retval = plibc_malloc(size);
+
+       ust_marker(malloc, "size %d ptr %p", (int)size, retval);
+
+       return retval;
+}
+
+void free(void *ptr)
+{
+       static void *(*plibc_free)(void *ptr) = NULL;
+
+       if (plibc_free == NULL) {
+               plibc_free = dlsym(RTLD_NEXT, "free");
+               if (plibc_free == NULL) {
+                       fprintf(stderr, "mallocwrap: unable to find free\n");
+                       return;
+               }
+       }
+
+       ust_marker(free, "ptr %p", ptr);
+
+       plibc_free(ptr);
+}
+
+UST_MARKER_LIB
diff --git a/liblttng-ust-malloc/run b/liblttng-ust-malloc/run
new file mode 100644 (file)
index 0000000..ce4fd10
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+LD_VERBOSE=1 LD_LIBRARY_PATH=.:../libust/.libs:../../liburcu LD_PRELOAD=liburcu.so:libust.so:.libs/libmallocwrap.so $1
diff --git a/liblttng-ust/Makefile.am b/liblttng-ust/Makefile.am
new file mode 100644 (file)
index 0000000..19d7482
--- /dev/null
@@ -0,0 +1,38 @@
+AM_CPPFLAGS = -I$(top_srcdir)/include
+AM_CFLAGS = -fno-strict-aliasing
+
+lib_LTLIBRARIES = liblttng-ust.la
+
+liblttng_ust_la_SOURCES = \
+       tracepoint.c \
+       ltt-tracer.h \
+       ltt-tracer-core.h \
+       ltt-ring-buffer-client.h \
+       ltt-ring-buffer-client-discard.c \
+       ltt-ring-buffer-client-overwrite.c \
+       ltt-ring-buffer-metadata-client.h \
+       ltt-ring-buffer-metadata-client.c \
+       ltt-events.c \
+       ltt-probes.c \
+       lttng-ust-abi.c \
+       lttng-ust-comm.c \
+       ust-core.c \
+       probes/lttng-probe-ust.c \
+       probes/lttng-probe-ust.h \
+       lttng-context-vtid.c \
+       lttng-context-vpid.c \
+       lttng-context-pthread-id.c \
+       lttng-context-procname.c \
+       ltt-context.c
+
+liblttng_ust_la_LDFLAGS = -no-undefined -version-info 0:0:0
+
+liblttng_ust_la_LIBADD = \
+       -lpthread \
+       -lrt \
+       -luuid \
+       $(top_builddir)/snprintf/libustsnprintf.la \
+       $(top_builddir)/libringbuffer/libringbuffer.la \
+       $(top_builddir)/liblttng-ust-comm/liblttng-ust-comm.la
+
+liblttng_ust_la_CFLAGS = -DUST_COMPONENT="liblttng-ust" -fno-strict-aliasing
diff --git a/liblttng-ust/ltt-context.c b/liblttng-ust/ltt-context.c
new file mode 100644 (file)
index 0000000..90747a5
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * ltt-context.c
+ *
+ * Copyright 2011 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * LTTng UST trace/channel/event context management.
+ *
+ * Dual LGPL v2.1/GPL v2 license.
+ */
+
+#include <lttng/ust-events.h>
+#include <lttng/ust-tracer.h>
+#include <lttng/core.h>
+#include <string.h>
+#include <assert.h>
+
+int lttng_find_context(struct lttng_ctx *ctx, const char *name)
+{
+       unsigned int i;
+
+       for (i = 0; i < ctx->nr_fields; i++) {
+               /* Skip allocated (but non-initialized) contexts */
+               if (!ctx->fields[i].event_field.name)
+                       continue;
+               if (!strcmp(ctx->fields[i].event_field.name, name))
+                       return 1;
+       }
+       return 0;
+}
+
+/*
+ * Note: as we append context information, the pointer location may change.
+ */
+struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p)
+{
+       struct lttng_ctx_field *field;
+       struct lttng_ctx *ctx;
+
+       if (!*ctx_p) {
+               *ctx_p = zmalloc(sizeof(struct lttng_ctx));
+               if (!*ctx_p)
+                       return NULL;
+       }
+       ctx = *ctx_p;
+       if (ctx->nr_fields + 1 > ctx->allocated_fields) {
+               struct lttng_ctx_field *new_fields;
+
+               ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields);
+               new_fields = zmalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field));
+               if (!new_fields)
+                       return NULL;
+               if (ctx->fields)
+                       memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields);
+               free(ctx->fields);
+               ctx->fields = new_fields;
+       }
+       field = &ctx->fields[ctx->nr_fields];
+       ctx->nr_fields++;
+       return field;
+}
+
+/*
+ * Remove last context field.
+ */
+void lttng_remove_context_field(struct lttng_ctx **ctx_p,
+                               struct lttng_ctx_field *field)
+{
+       struct lttng_ctx *ctx;
+
+       ctx = *ctx_p;
+       ctx->nr_fields--;
+       assert(&ctx->fields[ctx->nr_fields] == field);
+       memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field));
+}
+
+void lttng_destroy_context(struct lttng_ctx *ctx)
+{
+       int i;
+
+       if (!ctx)
+               return;
+       for (i = 0; i < ctx->nr_fields; i++) {
+               if (ctx->fields[i].destroy)
+                       ctx->fields[i].destroy(&ctx->fields[i]);
+       }
+       free(ctx->fields);
+       free(ctx);
+}
diff --git a/liblttng-ust/ltt-events.c b/liblttng-ust/ltt-events.c
new file mode 100644 (file)
index 0000000..68531bc
--- /dev/null
@@ -0,0 +1,1010 @@
+/*
+ * ltt-events.c
+ *
+ * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * Holds LTTng per-session event registry.
+ *
+ * Dual LGPL v2.1/GPL v2 license.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <endian.h>
+#include <urcu/list.h>
+#include <urcu/hlist.h>
+#include <pthread.h>
+#include <urcu-bp.h>
+#include <urcu/compiler.h>
+#include <urcu/uatomic.h>
+#include <uuid/uuid.h>
+#include <lttng/tracepoint.h>
+#include <errno.h>
+#include <sys/shm.h>
+#include <sys/ipc.h>
+#include <lttng/ust-events.h>
+#include <lttng/usterr-signal-safe.h>
+#include "lttng/core.h"
+#include "ltt-tracer.h"
+#include "ltt-tracer-core.h"
+#include "lttng/wait.h"
+#include "../libringbuffer/shm.h"
+
+typedef u32 uint32_t;
+#include <lttng/kcompat/jhash.h>
+
+/*
+ * The sessions mutex is the centralized mutex across UST tracing
+ * control and probe registration. All operations within this file are
+ * called by the communication thread, under ust_lock protection.
+ */
+static DEFINE_MUTEX(sessions_mutex);
+
+void ust_lock(void)
+{
+       pthread_mutex_lock(&sessions_mutex);
+}
+
+void ust_unlock(void)
+{
+       pthread_mutex_unlock(&sessions_mutex);
+}
+
+static CDS_LIST_HEAD(sessions);
+static CDS_LIST_HEAD(ltt_transport_list);
+
+/*
+ * Pending probes hash table, containing the registered ltt events for
+ * which tracepoint probes are still missing. Protected by the sessions
+ * mutex.
+ */
+#define PENDING_PROBE_HASH_BITS                6
+#define PENDING_PROBE_HASH_SIZE                (1 << PENDING_PROBE_HASH_BITS)
+static struct cds_hlist_head pending_probe_table[PENDING_PROBE_HASH_SIZE];
+
+struct ust_pending_probe {
+       struct ltt_event *event;
+       struct cds_hlist_node node;
+       char name[];
+};
+
+static void _ltt_event_destroy(struct ltt_event *event);
+static void _ltt_channel_destroy(struct ltt_channel *chan);
+static int _ltt_event_unregister(struct ltt_event *event);
+static
+int _ltt_event_metadata_statedump(struct ltt_session *session,
+                                 struct ltt_channel *chan,
+                                 struct ltt_event *event);
+static
+int _ltt_session_metadata_statedump(struct ltt_session *session);
+
+/*
+ * called at event creation if probe is missing.
+ * called with session mutex held.
+ */
+static
+int add_pending_probe(struct ltt_event *event, const char *name)
+{
+       struct cds_hlist_head *head;
+       struct ust_pending_probe *e;
+       size_t name_len = strlen(name) + 1;
+       u32 hash = jhash(name, name_len - 1, 0);
+
+       head = &pending_probe_table[hash & (PENDING_PROBE_HASH_SIZE - 1)];
+       e = zmalloc(sizeof(struct ust_pending_probe) + name_len);
+       if (!e)
+               return -ENOMEM;
+       memcpy(&e->name[0], name, name_len);
+       cds_hlist_add_head(&e->node, head);
+       e->event = event;
+       event->pending_probe = e;
+       return 0;
+}
+
+/*
+ * remove a pending probe. called when at event teardown and when an
+ * event is fixed (probe is loaded).
+ * called with session mutex held.
+ */
+static
+void remove_pending_probe(struct ust_pending_probe *e)
+{
+       if (!e)
+               return;
+       cds_hlist_del(&e->node);
+       free(e);
+}
+
+/*
+ * Called at library load: connect the probe on the events pending on
+ * probe load.
+ * called with session mutex held.
+ */
+int pending_probe_fix_events(const struct lttng_event_desc *desc)
+{
+       struct cds_hlist_head *head;
+       struct cds_hlist_node *node, *p;
+       struct ust_pending_probe *e;
+       const char *name = desc->name;
+       size_t name_len = strlen(name) + 1;
+       u32 hash = jhash(name, name_len - 1, 0);
+       int ret = 0;
+
+       head = &pending_probe_table[hash & (PENDING_PROBE_HASH_SIZE - 1)];
+       cds_hlist_for_each_entry_safe(e, node, p, head, node) {
+               struct ltt_event *event;
+               struct ltt_channel *chan;
+
+               if (strcmp(name, e->name))
+                       continue;
+               event = e->event;
+               chan = event->chan;
+               assert(!event->desc);
+               event->desc = desc;
+               event->pending_probe = NULL;
+               remove_pending_probe(e);
+               ret |= __tracepoint_probe_register(name,
+                               event->desc->probe_callback,
+                               event);
+               if (ret)
+                       continue;
+               event->id = chan->free_event_id++;
+               ret |= _ltt_event_metadata_statedump(chan->session, chan,
+                               event);
+       }
+       return ret;
+}
+
+void synchronize_trace(void)
+{
+       synchronize_rcu();
+}
+
+struct ltt_session *ltt_session_create(void)
+{
+       struct ltt_session *session;
+
+       session = zmalloc(sizeof(struct ltt_session));
+       if (!session)
+               return NULL;
+       CDS_INIT_LIST_HEAD(&session->chan);
+       CDS_INIT_LIST_HEAD(&session->events);
+       uuid_generate(session->uuid);
+       cds_list_add(&session->list, &sessions);
+       return session;
+}
+
+void ltt_session_destroy(struct ltt_session *session)
+{
+       struct ltt_channel *chan, *tmpchan;
+       struct ltt_event *event, *tmpevent;
+       int ret;
+
+       CMM_ACCESS_ONCE(session->active) = 0;
+       cds_list_for_each_entry(event, &session->events, list) {
+               ret = _ltt_event_unregister(event);
+               WARN_ON(ret);
+       }
+       synchronize_trace();    /* Wait for in-flight events to complete */
+       cds_list_for_each_entry_safe(event, tmpevent, &session->events, list)
+               _ltt_event_destroy(event);
+       cds_list_for_each_entry_safe(chan, tmpchan, &session->chan, list)
+               _ltt_channel_destroy(chan);
+       cds_list_del(&session->list);
+       free(session);
+}
+
+int ltt_session_enable(struct ltt_session *session)
+{
+       int ret = 0;
+       struct ltt_channel *chan;
+
+       if (session->active) {
+               ret = -EBUSY;
+               goto end;
+       }
+
+       /*
+        * Snapshot the number of events per channel to know the type of header
+        * we need to use.
+        */
+       cds_list_for_each_entry(chan, &session->chan, list) {
+               if (chan->header_type)
+                       continue;               /* don't change it if session stop/restart */
+               if (chan->free_event_id < 31)
+                       chan->header_type = 1;  /* compact */
+               else
+                       chan->header_type = 2;  /* large */
+       }
+
+       CMM_ACCESS_ONCE(session->active) = 1;
+       CMM_ACCESS_ONCE(session->been_active) = 1;
+       ret = _ltt_session_metadata_statedump(session);
+       if (ret)
+               CMM_ACCESS_ONCE(session->active) = 0;
+end:
+       return ret;
+}
+
+int ltt_session_disable(struct ltt_session *session)
+{
+       int ret = 0;
+
+       if (!session->active) {
+               ret = -EBUSY;
+               goto end;
+       }
+       CMM_ACCESS_ONCE(session->active) = 0;
+end:
+       return ret;
+}
+
+int ltt_channel_enable(struct ltt_channel *channel)
+{
+       int old;
+
+       if (channel == channel->session->metadata)
+               return -EPERM;
+       old = uatomic_xchg(&channel->enabled, 1);
+       if (old)
+               return -EEXIST;
+       return 0;
+}
+
+int ltt_channel_disable(struct ltt_channel *channel)
+{
+       int old;
+
+       if (channel == channel->session->metadata)
+               return -EPERM;
+       old = uatomic_xchg(&channel->enabled, 0);
+       if (!old)
+               return -EEXIST;
+       return 0;
+}
+
+int ltt_event_enable(struct ltt_event *event)
+{
+       int old;
+
+       if (event->chan == event->chan->session->metadata)
+               return -EPERM;
+       old = uatomic_xchg(&event->enabled, 1);
+       if (old)
+               return -EEXIST;
+       return 0;
+}
+
+int ltt_event_disable(struct ltt_event *event)
+{
+       int old;
+
+       if (event->chan == event->chan->session->metadata)
+               return -EPERM;
+       old = uatomic_xchg(&event->enabled, 0);
+       if (!old)
+               return -EEXIST;
+       return 0;
+}
+
+static struct ltt_transport *ltt_transport_find(const char *name)
+{
+       struct ltt_transport *transport;
+
+       cds_list_for_each_entry(transport, &ltt_transport_list, node) {
+               if (!strcmp(transport->name, name))
+                       return transport;
+       }
+       return NULL;
+}
+
+struct ltt_channel *ltt_channel_create(struct ltt_session *session,
+                                      const char *transport_name,
+                                      void *buf_addr,
+                                      size_t subbuf_size, size_t num_subbuf,
+                                      unsigned int switch_timer_interval,
+                                      unsigned int read_timer_interval,
+                                      int *shm_fd, int *wait_fd,
+                                      uint64_t *memory_map_size)
+{
+       struct ltt_channel *chan;
+       struct ltt_transport *transport;
+
+       if (session->been_active)
+               goto active;    /* Refuse to add channel to active session */
+       transport = ltt_transport_find(transport_name);
+       if (!transport) {
+               DBG("LTTng transport %s not found\n",
+                      transport_name);
+               goto notransport;
+       }
+       chan = zmalloc(sizeof(struct ltt_channel));
+       if (!chan)
+               goto nomem;
+       chan->session = session;
+       chan->id = session->free_chan_id++;
+       /*
+        * Note: the channel creation op already writes into the packet
+        * headers. Therefore the "chan" information used as input
+        * should be already accessible.
+        */
+       transport->ops.channel_create("[lttng]", chan, buf_addr,
+                       subbuf_size, num_subbuf, switch_timer_interval,
+                       read_timer_interval, shm_fd, wait_fd,
+                       memory_map_size);
+       if (!chan->chan)
+               goto create_error;
+       chan->enabled = 1;
+       chan->ops = &transport->ops;
+       cds_list_add(&chan->list, &session->chan);
+       return chan;
+
+create_error:
+       free(chan);
+nomem:
+notransport:
+active:
+       return NULL;
+}
+
+/*
+ * Only used internally at session destruction.
+ */
+static
+void _ltt_channel_destroy(struct ltt_channel *chan)
+{
+       chan->ops->channel_destroy(chan);
+       cds_list_del(&chan->list);
+       lttng_destroy_context(chan->ctx);
+       free(chan);
+}
+
+/*
+ * Supports event creation while tracing session is active.
+ */
+struct ltt_event *ltt_event_create(struct ltt_channel *chan,
+                                  struct lttng_ust_event *event_param,
+                                  void *filter)
+{
+       struct ltt_event *event;
+       int ret;
+
+       if (chan->used_event_id == -1UL)
+               goto full;
+       /*
+        * This is O(n^2) (for each event, the loop is called at event
+        * creation). Might require a hash if we have lots of events.
+        */
+       cds_list_for_each_entry(event, &chan->session->events, list)
+               if (event->desc && !strcmp(event->desc->name, event_param->name))
+                       goto exist;
+       event = zmalloc(sizeof(struct ltt_event));
+       if (!event)
+               goto cache_error;
+       event->chan = chan;
+       event->filter = filter;
+       /*
+        * used_event_id counts the maximum number of event IDs that can
+        * register if all probes register.
+        */
+       chan->used_event_id++;
+       event->enabled = 1;
+       event->instrumentation = event_param->instrumentation;
+       /* Populate ltt_event structure before tracepoint registration. */
+       cmm_smp_wmb();
+       switch (event_param->instrumentation) {
+       case LTTNG_UST_TRACEPOINT:
+               event->desc = ltt_event_get(event_param->name);
+               if (event->desc) {
+                       ret = __tracepoint_probe_register(event_param->name,
+                                       event->desc->probe_callback,
+                                       event);
+                       if (ret)
+                               goto register_error;
+                       event->id = chan->free_event_id++;
+               } else {
+                       /*
+                        * If the probe is not present, event->desc stays NULL,
+                        * waiting for the probe to register, and the event->id
+                        * stays unallocated.
+                        */
+                       ret = add_pending_probe(event, event_param->name);
+                       if (ret)
+                               goto add_pending_error;
+               }
+               break;
+       default:
+               WARN_ON_ONCE(1);
+       }
+       if (event->desc) {
+               ret = _ltt_event_metadata_statedump(chan->session, chan, event);
+               if (ret)
+                       goto statedump_error;
+       }
+       cds_list_add(&event->list, &chan->session->events);
+       return event;
+
+statedump_error:
+       if (event->desc) {
+               WARN_ON_ONCE(__tracepoint_probe_unregister(event_param->name,
+                                       event->desc->probe_callback,
+                                       event));
+               ltt_event_put(event->desc);
+       }
+add_pending_error:
+register_error:
+       free(event);
+cache_error:
+exist:
+full:
+       return NULL;
+}
+
+/*
+ * Only used internally at session destruction.
+ */
+int _ltt_event_unregister(struct ltt_event *event)
+{
+       int ret = -EINVAL;
+
+       switch (event->instrumentation) {
+       case LTTNG_UST_TRACEPOINT:
+               if (event->desc) {
+                       ret = __tracepoint_probe_unregister(event->desc->name,
+                                                         event->desc->probe_callback,
+                                                         event);
+                       if (ret)
+                               return ret;
+               } else {
+                       remove_pending_probe(event->pending_probe);
+                       ret = 0;
+               }
+               break;
+       default:
+               WARN_ON_ONCE(1);
+       }
+       return ret;
+}
+
+/*
+ * Only used internally at session destruction.
+ */
+static
+void _ltt_event_destroy(struct ltt_event *event)
+{
+       switch (event->instrumentation) {
+       case LTTNG_UST_TRACEPOINT:
+               if (event->desc) {
+                       ltt_event_put(event->desc);
+               }
+               break;
+       default:
+               WARN_ON_ONCE(1);
+       }
+       cds_list_del(&event->list);
+       lttng_destroy_context(event->ctx);
+       free(event);
+}
+
+/*
+ * We have exclusive access to our metadata buffer (protected by the
+ * ust_lock), so we can do racy operations such as looking for
+ * remaining space left in packet and write, since mutual exclusion
+ * protects us from concurrent writes.
+ */
+int lttng_metadata_printf(struct ltt_session *session,
+                         const char *fmt, ...)
+{
+       struct lttng_ust_lib_ring_buffer_ctx ctx;
+       struct ltt_channel *chan = session->metadata;
+       char *str = NULL;
+       int ret = 0, waitret;
+       size_t len, reserve_len, pos;
+       va_list ap;
+
+       WARN_ON_ONCE(!CMM_ACCESS_ONCE(session->active));
+
+       va_start(ap, fmt);
+       ret = vasprintf(&str, fmt, ap);
+       va_end(ap);
+       if (ret < 0)
+               return -ENOMEM;
+
+       len = strlen(str);
+       pos = 0;
+
+       for (pos = 0; pos < len; pos += reserve_len) {
+               reserve_len = min_t(size_t,
+                               chan->ops->packet_avail_size(chan->chan, chan->handle),
+                               len - pos);
+               lib_ring_buffer_ctx_init(&ctx, chan->chan, NULL, reserve_len,
+                                        sizeof(char), -1, chan->handle);
+               /*
+                * We don't care about metadata buffer's records lost
+                * count, because we always retry here. Report error if
+                * we need to bail out after timeout or being
+                * interrupted.
+                */
+               waitret = wait_cond_interruptible_timeout(
+                       ({
+                               ret = chan->ops->event_reserve(&ctx, 0);
+                               ret != -ENOBUFS || !ret;
+                       }),
+                       LTTNG_METADATA_TIMEOUT_MSEC);
+               if (waitret == -ETIMEDOUT || waitret == -EINTR || ret) {
+                       DBG("LTTng: Failure to write metadata to buffers (%s)\n",
+                               waitret == -EINTR ? "interrupted" :
+                                       (ret == -ENOBUFS ? "timeout" : "I/O error"));
+                       if (waitret == -EINTR)
+                               ret = waitret;
+                       goto end;
+               }
+               chan->ops->event_write(&ctx, &str[pos], reserve_len);
+               chan->ops->event_commit(&ctx);
+       }
+end:
+       free(str);
+       return ret;
+}
+
+static
+int _ltt_field_statedump(struct ltt_session *session,
+                        const struct lttng_event_field *field)
+{
+       int ret = 0;
+
+       switch (field->type.atype) {
+       case atype_integer:
+               ret = lttng_metadata_printf(session,
+                       "               integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n",
+                       field->type.u.basic.integer.size,
+                       field->type.u.basic.integer.alignment,
+                       field->type.u.basic.integer.signedness,
+                       (field->type.u.basic.integer.encoding == lttng_encode_none)
+                               ? "none"
+                               : (field->type.u.basic.integer.encoding == lttng_encode_UTF8)
+                                       ? "UTF8"
+                                       : "ASCII",
+                       field->type.u.basic.integer.base,
+#if (BYTE_ORDER == BIG_ENDIAN)
+                       field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
+#else
+                       field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
+#endif
+                       field->name);
+               break;
+       case atype_float:
+               ret = lttng_metadata_printf(session,
+                       "               floating_point { exp_dig = %u; mant_dig = %u; align = %u;%s } _%s;\n",
+                       field->type.u.basic._float.exp_dig,
+                       field->type.u.basic._float.mant_dig,
+                       field->type.u.basic._float.alignment,
+#if (BYTE_ORDER == BIG_ENDIAN)
+                       field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
+#else
+                       field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
+#endif
+                       field->name);
+               break;
+       case atype_enum:
+               ret = lttng_metadata_printf(session,
+                       "               %s %s;\n",
+                       field->type.u.basic.enumeration.name,
+                       field->name);
+               break;
+       case atype_array:
+       {
+               const struct lttng_basic_type *elem_type;
+
+               elem_type = &field->type.u.array.elem_type;
+               ret = lttng_metadata_printf(session,
+                       "               integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n",
+                       elem_type->u.basic.integer.size,
+                       elem_type->u.basic.integer.alignment,
+                       elem_type->u.basic.integer.signedness,
+                       (elem_type->u.basic.integer.encoding == lttng_encode_none)
+                               ? "none"
+                               : (elem_type->u.basic.integer.encoding == lttng_encode_UTF8)
+                                       ? "UTF8"
+                                       : "ASCII",
+                       elem_type->u.basic.integer.base,
+#if (BYTE_ORDER == BIG_ENDIAN)
+                       elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
+#else
+                       elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
+#endif
+                       field->name, field->type.u.array.length);
+               break;
+       }
+       case atype_sequence:
+       {
+               const struct lttng_basic_type *elem_type;
+               const struct lttng_basic_type *length_type;
+
+               elem_type = &field->type.u.sequence.elem_type;
+               length_type = &field->type.u.sequence.length_type;
+               ret = lttng_metadata_printf(session,
+                       "               integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n",
+                       length_type->u.basic.integer.size,
+                       (unsigned int) length_type->u.basic.integer.alignment,
+                       length_type->u.basic.integer.signedness,
+                       (length_type->u.basic.integer.encoding == lttng_encode_none)
+                               ? "none"
+                               : ((length_type->u.basic.integer.encoding == lttng_encode_UTF8)
+                                       ? "UTF8"
+                                       : "ASCII"),
+                       length_type->u.basic.integer.base,
+#if (BYTE_ORDER == BIG_ENDIAN)
+                       length_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
+#else
+                       length_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
+#endif
+                       field->name);
+               if (ret)
+                       return ret;
+
+               ret = lttng_metadata_printf(session,
+                       "               integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n",
+                       elem_type->u.basic.integer.size,
+                       (unsigned int) elem_type->u.basic.integer.alignment,
+                       elem_type->u.basic.integer.signedness,
+                       (elem_type->u.basic.integer.encoding == lttng_encode_none)
+                               ? "none"
+                               : ((elem_type->u.basic.integer.encoding == lttng_encode_UTF8)
+                                       ? "UTF8"
+                                       : "ASCII"),
+                       elem_type->u.basic.integer.base,
+#if (BYTE_ORDER == BIG_ENDIAN)
+                       elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
+#else
+                       elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
+#endif
+                       field->name,
+                       field->name);
+               break;
+       }
+
+       case atype_string:
+               /* Default encoding is UTF8 */
+               ret = lttng_metadata_printf(session,
+                       "               string%s _%s;\n",
+                       field->type.u.basic.string.encoding == lttng_encode_ASCII ?
+                               " { encoding = ASCII; }" : "",
+                       field->name);
+               break;
+       default:
+               WARN_ON_ONCE(1);
+               return -EINVAL;
+       }
+       return ret;
+}
+
+static
+int _ltt_context_metadata_statedump(struct ltt_session *session,
+                                   struct lttng_ctx *ctx)
+{
+       int ret = 0;
+       int i;
+
+       if (!ctx)
+               return 0;
+       for (i = 0; i < ctx->nr_fields; i++) {
+               const struct lttng_ctx_field *field = &ctx->fields[i];
+
+               ret = _ltt_field_statedump(session, &field->event_field);
+               if (ret)
+                       return ret;
+       }
+       return ret;
+}
+
+static
+int _ltt_fields_metadata_statedump(struct ltt_session *session,
+                                  struct ltt_event *event)
+{
+       const struct lttng_event_desc *desc = event->desc;
+       int ret = 0;
+       int i;
+
+       for (i = 0; i < desc->nr_fields; i++) {
+               const struct lttng_event_field *field = &desc->fields[i];
+
+               ret = _ltt_field_statedump(session, field);
+               if (ret)
+                       return ret;
+       }
+       return ret;
+}
+
+static
+int _ltt_event_metadata_statedump(struct ltt_session *session,
+                                 struct ltt_channel *chan,
+                                 struct ltt_event *event)
+{
+       int ret = 0;
+
+       if (event->metadata_dumped || !CMM_ACCESS_ONCE(session->active))
+               return 0;
+       if (chan == session->metadata)
+               return 0;
+       /*
+        * Don't print events for which probe load is pending.
+        */
+       if (!event->desc)
+               return 0;
+
+       ret = lttng_metadata_printf(session,
+               "event {\n"
+               "       name = %s;\n"
+               "       id = %u;\n"
+               "       stream_id = %u;\n",
+               event->desc->name,
+               event->id,
+               event->chan->id);
+       if (ret)
+               goto end;
+
+       if (event->ctx) {
+               ret = lttng_metadata_printf(session,
+                       "       context := struct {\n");
+               if (ret)
+                       goto end;
+       }
+       ret = _ltt_context_metadata_statedump(session, event->ctx);
+       if (ret)
+               goto end;
+       if (event->ctx) {
+               ret = lttng_metadata_printf(session,
+                       "       };\n");
+               if (ret)
+                       goto end;
+       }
+
+       ret = lttng_metadata_printf(session,
+               "       fields := struct {\n"
+               );
+       if (ret)
+               goto end;
+
+       ret = _ltt_fields_metadata_statedump(session, event);
+       if (ret)
+               goto end;
+
+       /*
+        * LTTng space reservation can only reserve multiples of the
+        * byte size.
+        */
+       ret = lttng_metadata_printf(session,
+               "       };\n"
+               "};\n\n");
+       if (ret)
+               goto end;
+
+       event->metadata_dumped = 1;
+end:
+       return ret;
+
+}
+
+static
+int _ltt_channel_metadata_statedump(struct ltt_session *session,
+                                   struct ltt_channel *chan)
+{
+       int ret = 0;
+
+       if (chan->metadata_dumped || !CMM_ACCESS_ONCE(session->active))
+               return 0;
+       if (chan == session->metadata)
+               return 0;
+
+       WARN_ON_ONCE(!chan->header_type);
+       ret = lttng_metadata_printf(session,
+               "stream {\n"
+               "       id = %u;\n"
+               "       event.header := %s;\n"
+               "       packet.context := struct packet_context;\n",
+               chan->id,
+               chan->header_type == 1 ? "struct event_header_compact" :
+                       "struct event_header_large");
+       if (ret)
+               goto end;
+
+       if (chan->ctx) {
+               ret = lttng_metadata_printf(session,
+                       "       event.context := struct {\n");
+               if (ret)
+                       goto end;
+       }
+       ret = _ltt_context_metadata_statedump(session, chan->ctx);
+       if (ret)
+               goto end;
+       if (chan->ctx) {
+               ret = lttng_metadata_printf(session,
+                       "       };\n");
+               if (ret)
+                       goto end;
+       }
+
+       ret = lttng_metadata_printf(session,
+               "};\n\n");
+
+       chan->metadata_dumped = 1;
+end:
+       return ret;
+}
+
+static
+int _ltt_stream_packet_context_declare(struct ltt_session *session)
+{
+       return lttng_metadata_printf(session,
+               "struct packet_context {\n"
+               "       uint64_t timestamp_begin;\n"
+               "       uint64_t timestamp_end;\n"
+               "       uint32_t events_discarded;\n"
+               "       uint32_t content_size;\n"
+               "       uint32_t packet_size;\n"
+               "       uint32_t cpu_id;\n"
+               "};\n\n"
+               );
+}
+
+/*
+ * Compact header:
+ * id: range: 0 - 30.
+ * id 31 is reserved to indicate an extended header.
+ *
+ * Large header:
+ * id: range: 0 - 65534.
+ * id 65535 is reserved to indicate an extended header.
+ */
+static
+int _ltt_event_header_declare(struct ltt_session *session)
+{
+       return lttng_metadata_printf(session,
+       "struct event_header_compact {\n"
+       "       enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n"
+       "       variant <id> {\n"
+       "               struct {\n"
+       "                       uint27_t timestamp;\n"
+       "               } compact;\n"
+       "               struct {\n"
+       "                       uint32_t id;\n"
+       "                       uint64_t timestamp;\n"
+       "               } extended;\n"
+       "       } v;\n"
+       "} align(%u);\n"
+       "\n"
+       "struct event_header_large {\n"
+       "       enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n"
+       "       variant <id> {\n"
+       "               struct {\n"
+       "                       uint32_t timestamp;\n"
+       "               } compact;\n"
+       "               struct {\n"
+       "                       uint32_t id;\n"
+       "                       uint64_t timestamp;\n"
+       "               } extended;\n"
+       "       } v;\n"
+       "} align(%u);\n\n",
+       lttng_alignof(uint32_t) * CHAR_BIT,
+       lttng_alignof(uint16_t) * CHAR_BIT
+       );
+}
+
+/*
+ * Output metadata into this session's metadata buffers.
+ */
+static
+int _ltt_session_metadata_statedump(struct ltt_session *session)
+{
+       unsigned char *uuid_c = session->uuid;
+       char uuid_s[37];
+       struct ltt_channel *chan;
+       struct ltt_event *event;
+       int ret = 0;
+
+       if (!CMM_ACCESS_ONCE(session->active))
+               return 0;
+       if (session->metadata_dumped)
+               goto skip_session;
+       if (!session->metadata) {
+               DBG("LTTng: attempt to start tracing, but metadata channel is not found. Operation abort.\n");
+               return -EPERM;
+       }
+
+       snprintf(uuid_s, sizeof(uuid_s),
+               "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+               uuid_c[0], uuid_c[1], uuid_c[2], uuid_c[3],
+               uuid_c[4], uuid_c[5], uuid_c[6], uuid_c[7],
+               uuid_c[8], uuid_c[9], uuid_c[10], uuid_c[11],
+               uuid_c[12], uuid_c[13], uuid_c[14], uuid_c[15]);
+
+       ret = lttng_metadata_printf(session,
+               "typealias integer { size = 8; align = %u; signed = false; } := uint8_t;\n"
+               "typealias integer { size = 16; align = %u; signed = false; } := uint16_t;\n"
+               "typealias integer { size = 32; align = %u; signed = false; } := uint32_t;\n"
+               "typealias integer { size = 64; align = %u; signed = false; } := uint64_t;\n"
+               "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n"
+               "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n"
+               "\n"
+               "trace {\n"
+               "       major = %u;\n"
+               "       minor = %u;\n"
+               "       uuid = \"%s\";\n"
+               "       byte_order = %s;\n"
+               "       packet.header := struct {\n"
+               "               uint32_t magic;\n"
+               "               uint8_t  uuid[16];\n"
+               "               uint32_t stream_id;\n"
+               "       };\n"
+               "};\n\n",
+               lttng_alignof(uint8_t) * CHAR_BIT,
+               lttng_alignof(uint16_t) * CHAR_BIT,
+               lttng_alignof(uint32_t) * CHAR_BIT,
+               lttng_alignof(uint64_t) * CHAR_BIT,
+               CTF_VERSION_MAJOR,
+               CTF_VERSION_MINOR,
+               uuid_s,
+#if (BYTE_ORDER == BIG_ENDIAN)
+               "be"
+#else
+               "le"
+#endif
+               );
+       if (ret)
+               goto end;
+
+       ret = _ltt_stream_packet_context_declare(session);
+       if (ret)
+               goto end;
+
+       ret = _ltt_event_header_declare(session);
+       if (ret)
+               goto end;
+
+skip_session:
+       cds_list_for_each_entry(chan, &session->chan, list) {
+               ret = _ltt_channel_metadata_statedump(session, chan);
+               if (ret)
+                       goto end;
+       }
+
+       cds_list_for_each_entry(event, &session->events, list) {
+               ret = _ltt_event_metadata_statedump(session, event->chan, event);
+               if (ret)
+                       goto end;
+       }
+       session->metadata_dumped = 1;
+end:
+       return ret;
+}
+
+/**
+ * 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. Called with ust_lock held.
+ */
+void ltt_transport_register(struct ltt_transport *transport)
+{
+       cds_list_add_tail(&transport->node, &ltt_transport_list);
+}
+
+/**
+ * ltt_transport_unregister - LTT transport unregistration
+ * @transport: transport structure
+ * Called with ust_lock held.
+ */
+void ltt_transport_unregister(struct ltt_transport *transport)
+{
+       cds_list_del(&transport->node);
+}
+
+void lttng_ust_events_exit(void)
+{
+       struct ltt_session *session, *tmpsession;
+
+       cds_list_for_each_entry_safe(session, tmpsession, &sessions, list)
+               ltt_session_destroy(session);
+}
diff --git a/liblttng-ust/ltt-probes.c b/liblttng-ust/ltt-probes.c
new file mode 100644 (file)
index 0000000..66ee971
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * ltt-probes.c
+ *
+ * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * Holds LTTng probes registry.
+ *
+ * Dual LGPL v2.1/GPL v2 license.
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <urcu/list.h>
+#include <lttng/core.h>
+#include <lttng/ust-events.h>
+
+#include "ltt-tracer-core.h"
+
+/*
+ * probe list is protected by ust_lock()/ust_unlock().
+ */
+static CDS_LIST_HEAD(probe_list);
+
+static
+const struct lttng_event_desc *find_event(const char *name)
+{
+       struct lttng_probe_desc *probe_desc;
+       int i;
+
+       cds_list_for_each_entry(probe_desc, &probe_list, head) {
+               for (i = 0; i < probe_desc->nr_events; i++) {
+                       if (!strcmp(probe_desc->event_desc[i].name, name))
+                               return &probe_desc->event_desc[i];
+               }
+       }
+       return NULL;
+}
+
+int ltt_probe_register(struct lttng_probe_desc *desc)
+{
+       int ret = 0;
+       int i;
+
+       ust_lock();
+       /*
+        * TODO: This is O(N^2). Turn into a hash table when probe registration
+        * overhead becomes an issue.
+        */
+       for (i = 0; i < desc->nr_events; i++) {
+               if (find_event(desc->event_desc[i].name)) {
+                       ret = -EEXIST;
+                       goto end;
+               }
+       }
+       cds_list_add(&desc->head, &probe_list);
+
+       /*
+        * fix the events awaiting probe load.
+        */
+       for (i = 0; i < desc->nr_events; i++) {
+               ret = pending_probe_fix_events(&desc->event_desc[i]);
+               assert(!ret);
+       }
+end:
+       ust_unlock();
+       return ret;
+}
+
+void ltt_probe_unregister(struct lttng_probe_desc *desc)
+{
+       ust_lock();
+       cds_list_del(&desc->head);
+       ust_unlock();
+}
+
+/*
+ * called with UST lock held.
+ */
+const struct lttng_event_desc *ltt_event_get(const char *name)
+{
+       const struct lttng_event_desc *event;
+
+       event = find_event(name);
+       if (!event)
+               return NULL;
+       return event;
+}
+
+void ltt_event_put(const struct lttng_event_desc *event)
+{
+}
+
+#if 0
+static
+void *tp_list_start(struct seq_file *m, loff_t *pos)
+{
+       struct lttng_probe_desc *probe_desc;
+       int iter = 0, i;
+
+       pthread_mutex_lock(&probe_mutex);
+       cds_list_for_each_entry(probe_desc, &probe_list, head) {
+               for (i = 0; i < probe_desc->nr_events; i++) {
+                       if (iter++ >= *pos)
+                               return (void *) &probe_desc->event_desc[i];
+               }
+       }
+       /* End of list */
+       return NULL;
+}
+
+static
+void *tp_list_next(struct seq_file *m, void *p, loff_t *ppos)
+{
+       struct lttng_probe_desc *probe_desc;
+       int iter = 0, i;
+
+       (*ppos)++;
+       cds_list_for_each_entry(probe_desc, &probe_list, head) {
+               for (i = 0; i < probe_desc->nr_events; i++) {
+                       if (iter++ >= *ppos)
+                               return (void *) &probe_desc->event_desc[i];
+               }
+       }
+       /* End of list */
+       return NULL;
+}
+
+static
+void tp_list_stop(struct seq_file *m, void *p)
+{
+       pthread_mutex_unlock(&probe_mutex);
+}
+
+static
+int tp_list_show(struct seq_file *m, void *p)
+{
+       const struct lttng_event_desc *probe_desc = p;
+
+       /*
+        * Don't export lttng internal events (metadata).
+        */
+       if (!strncmp(probe_desc->name, "lttng_", sizeof("lttng_") - 1))
+               return 0;
+       seq_printf(m,   "event { name = %s; };\n",
+                  probe_desc->name);
+       return 0;
+}
+
+static
+const struct seq_operations lttng_tracepoint_list_seq_ops = {
+       .start = tp_list_start,
+       .next = tp_list_next,
+       .stop = tp_list_stop,
+       .show = tp_list_show,
+};
+
+static
+int lttng_tracepoint_list_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &lttng_tracepoint_list_seq_ops);
+}
+
+const struct file_operations lttng_tracepoint_list_fops = {
+       .open = lttng_tracepoint_list_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = seq_release,
+};
+#endif //0
diff --git a/liblttng-ust/ltt-ring-buffer-client-discard.c b/liblttng-ust/ltt-ring-buffer-client-discard.c
new file mode 100644 (file)
index 0000000..e89026c
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * ltt-ring-buffer-client-discard.c
+ *
+ * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * LTTng lib ring buffer client (discard mode).
+ *
+ * Dual LGPL v2.1/GPL v2 license.
+ */
+
+#include "ltt-tracer.h"
+
+#define RING_BUFFER_MODE_TEMPLATE              RING_BUFFER_DISCARD
+#define RING_BUFFER_MODE_TEMPLATE_STRING       "discard"
+#define RING_BUFFER_MODE_TEMPLATE_INIT \
+       ltt_ring_buffer_client_discard_init
+#define RING_BUFFER_MODE_TEMPLATE_EXIT \
+       ltt_ring_buffer_client_discard_exit
+#include "ltt-ring-buffer-client.h"
diff --git a/liblttng-ust/ltt-ring-buffer-client-overwrite.c b/liblttng-ust/ltt-ring-buffer-client-overwrite.c
new file mode 100644 (file)
index 0000000..8590a7e
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * ltt-ring-buffer-client-overwrite.c
+ *
+ * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * LTTng lib ring buffer client (overwrite mode).
+ *
+ * Dual LGPL v2.1/GPL v2 license.
+ */
+
+#include "ltt-tracer.h"
+
+#define RING_BUFFER_MODE_TEMPLATE              RING_BUFFER_OVERWRITE
+#define RING_BUFFER_MODE_TEMPLATE_STRING       "overwrite"
+#define RING_BUFFER_MODE_TEMPLATE_INIT \
+       ltt_ring_buffer_client_overwrite_init
+#define RING_BUFFER_MODE_TEMPLATE_EXIT \
+       ltt_ring_buffer_client_overwrite_exit
+#include "ltt-ring-buffer-client.h"
diff --git a/liblttng-ust/ltt-ring-buffer-client.h b/liblttng-ust/ltt-ring-buffer-client.h
new file mode 100644 (file)
index 0000000..a1bc8c3
--- /dev/null
@@ -0,0 +1,554 @@
+/*
+ * ltt-ring-buffer-client.h
+ *
+ * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * LTTng lib ring buffer client template.
+ *
+ * Dual LGPL v2.1/GPL v2 license.
+ */
+
+#include <stdint.h>
+#include <lttng/ust-events.h>
+#include "lttng/bitfield.h"
+#include "lttng/clock.h"
+#include "ltt-tracer.h"
+#include "../libringbuffer/frontend_types.h"
+
+/*
+ * Keep the natural field alignment for _each field_ within this structure if
+ * you ever add/remove a field from this header. Packed attribute is not used
+ * because gcc generates poor code on at least powerpc and mips. Don't ever
+ * let gcc add padding between the structure elements.
+ */
+
+struct packet_header {
+       /* Trace packet header */
+       uint32_t magic;                 /*
+                                        * Trace magic number.
+                                        * contains endianness information.
+                                        */
+       uint8_t uuid[16];
+       uint32_t stream_id;
+
+       struct {
+               /* Stream packet context */
+               uint64_t timestamp_begin;       /* Cycle count at subbuffer start */
+               uint64_t timestamp_end;         /* Cycle count at subbuffer end */
+               uint32_t events_discarded;      /*
+                                                * Events lost in this subbuffer since
+                                                * the beginning of the trace.
+                                                * (may overflow)
+                                                */
+               uint32_t content_size;          /* Size of data in subbuffer */
+               uint32_t packet_size;           /* Subbuffer size (include padding) */
+               uint32_t cpu_id;                /* CPU id associated with stream */
+               uint8_t header_end;             /* End of header */
+       } ctx;
+};
+
+
+static inline notrace u64 lib_ring_buffer_clock_read(struct channel *chan)
+{
+       return trace_clock_read64();
+}
+
+static inline
+size_t ctx_get_size(size_t offset, struct lttng_ctx *ctx)
+{
+       int i;
+       size_t orig_offset = offset;
+
+       if (caa_likely(!ctx))
+               return 0;
+       for (i = 0; i < ctx->nr_fields; i++)
+               offset += ctx->fields[i].get_size(offset);
+       return offset - orig_offset;
+}
+
+static inline
+void ctx_record(struct lttng_ust_lib_ring_buffer_ctx *bufctx,
+               struct ltt_channel *chan,
+               struct lttng_ctx *ctx)
+{
+       int i;
+
+       if (caa_likely(!ctx))
+               return;
+       for (i = 0; i < ctx->nr_fields; i++)
+               ctx->fields[i].record(&ctx->fields[i], bufctx, chan);
+}
+
+/*
+ * record_header_size - Calculate the header size and padding necessary.
+ * @config: ring buffer instance configuration
+ * @chan: channel
+ * @offset: offset in the write buffer
+ * @pre_header_padding: padding to add before the header (output)
+ * @ctx: reservation context
+ *
+ * Returns the event header size (including padding).
+ *
+ * The payload must itself determine its own alignment from the biggest type it
+ * contains.
+ */
+static __inline__
+unsigned char record_header_size(const struct lttng_ust_lib_ring_buffer_config *config,
+                                struct channel *chan, size_t offset,
+                                size_t *pre_header_padding,
+                                struct lttng_ust_lib_ring_buffer_ctx *ctx)
+{
+       struct ltt_channel *ltt_chan = channel_get_private(chan);
+       struct ltt_event *event = ctx->priv;
+       size_t orig_offset = offset;
+       size_t padding;
+
+       switch (ltt_chan->header_type) {
+       case 1: /* compact */
+               padding = lib_ring_buffer_align(offset, lttng_alignof(uint32_t));
+               offset += padding;
+               if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) {
+                       offset += sizeof(uint32_t);     /* id and timestamp */
+               } else {
+                       /* Minimum space taken by 5-bit id */
+                       offset += sizeof(uint8_t);
+                       /* Align extended struct on largest member */
+                       offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t));
+                       offset += sizeof(uint32_t);     /* id */
+                       offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t));
+                       offset += sizeof(uint64_t);     /* timestamp */
+               }
+               break;
+       case 2: /* large */
+               padding = lib_ring_buffer_align(offset, lttng_alignof(uint16_t));
+               offset += padding;
+               offset += sizeof(uint16_t);
+               if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) {
+                       offset += lib_ring_buffer_align(offset, lttng_alignof(uint32_t));
+                       offset += sizeof(uint32_t);     /* timestamp */
+               } else {
+                       /* Align extended struct on largest member */
+                       offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t));
+                       offset += sizeof(uint32_t);     /* id */
+                       offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t));
+                       offset += sizeof(uint64_t);     /* timestamp */
+               }
+               break;
+       default:
+               padding = 0;
+               WARN_ON_ONCE(1);
+       }
+       offset += ctx_get_size(offset, event->ctx);
+       offset += ctx_get_size(offset, ltt_chan->ctx);
+
+       *pre_header_padding = padding;
+       return offset - orig_offset;
+}
+
+#include "../libringbuffer/api.h"
+
+static
+void ltt_write_event_header_slow(const struct lttng_ust_lib_ring_buffer_config *config,
+                                struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                                uint32_t event_id);
+
+/*
+ * ltt_write_event_header
+ *
+ * Writes the event header to the offset (already aligned on 32-bits).
+ *
+ * @config: ring buffer instance configuration
+ * @ctx: reservation context
+ * @event_id: event ID
+ */
+static __inline__
+void ltt_write_event_header(const struct lttng_ust_lib_ring_buffer_config *config,
+                           struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                           uint32_t event_id)
+{
+       struct ltt_channel *ltt_chan = channel_get_private(ctx->chan);
+       struct ltt_event *event = ctx->priv;
+
+       if (caa_unlikely(ctx->rflags))
+               goto slow_path;
+
+       switch (ltt_chan->header_type) {
+       case 1: /* compact */
+       {
+               uint32_t id_time = 0;
+
+               bt_bitfield_write(&id_time, uint32_t, 0, 5, event_id);
+               bt_bitfield_write(&id_time, uint32_t, 5, 27, ctx->tsc);
+               lib_ring_buffer_write(config, ctx, &id_time, sizeof(id_time));
+               break;
+       }
+       case 2: /* large */
+       {
+               uint32_t timestamp = (uint32_t) ctx->tsc;
+               uint16_t id = event_id;
+
+               lib_ring_buffer_write(config, ctx, &id, sizeof(id));
+               lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint32_t));
+               lib_ring_buffer_write(config, ctx, &timestamp, sizeof(timestamp));
+               break;
+       }
+       default:
+               WARN_ON_ONCE(1);
+       }
+
+       ctx_record(ctx, ltt_chan, ltt_chan->ctx);
+       ctx_record(ctx, ltt_chan, event->ctx);
+       lib_ring_buffer_align_ctx(ctx, ctx->largest_align);
+
+       return;
+
+slow_path:
+       ltt_write_event_header_slow(config, ctx, event_id);
+}
+
+static
+void ltt_write_event_header_slow(const struct lttng_ust_lib_ring_buffer_config *config,
+                                struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                                uint32_t event_id)
+{
+       struct ltt_channel *ltt_chan = channel_get_private(ctx->chan);
+       struct ltt_event *event = ctx->priv;
+
+       switch (ltt_chan->header_type) {
+       case 1: /* compact */
+               if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) {
+                       uint32_t id_time = 0;
+
+                       bt_bitfield_write(&id_time, uint32_t, 0, 5, event_id);
+                       bt_bitfield_write(&id_time, uint32_t, 5, 27, ctx->tsc);
+                       lib_ring_buffer_write(config, ctx, &id_time, sizeof(id_time));
+               } else {
+                       uint8_t id = 0;
+                       uint64_t timestamp = ctx->tsc;
+
+                       bt_bitfield_write(&id, uint8_t, 0, 5, 31);
+                       lib_ring_buffer_write(config, ctx, &id, sizeof(id));
+                       /* Align extended struct on largest member */
+                       lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t));
+                       lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id));
+                       lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t));
+                       lib_ring_buffer_write(config, ctx, &timestamp, sizeof(timestamp));
+               }
+               break;
+       case 2: /* large */
+       {
+               if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) {
+                       uint32_t timestamp = (uint32_t) ctx->tsc;
+                       uint16_t id = event_id;
+
+                       lib_ring_buffer_write(config, ctx, &id, sizeof(id));
+                       lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint32_t));
+                       lib_ring_buffer_write(config, ctx, &timestamp, sizeof(timestamp));
+               } else {
+                       uint16_t id = 65535;
+                       uint64_t timestamp = ctx->tsc;
+
+                       lib_ring_buffer_write(config, ctx, &id, sizeof(id));
+                       /* Align extended struct on largest member */
+                       lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t));
+                       lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id));
+                       lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t));
+                       lib_ring_buffer_write(config, ctx, &timestamp, sizeof(timestamp));
+               }
+               break;
+       }
+       default:
+               WARN_ON_ONCE(1);
+       }
+       ctx_record(ctx, ltt_chan, ltt_chan->ctx);
+       ctx_record(ctx, ltt_chan, event->ctx);
+       lib_ring_buffer_align_ctx(ctx, ctx->largest_align);
+}
+
+static const struct lttng_ust_lib_ring_buffer_config client_config;
+
+static u64 client_ring_buffer_clock_read(struct channel *chan)
+{
+       return lib_ring_buffer_clock_read(chan);
+}
+
+static
+size_t client_record_header_size(const struct lttng_ust_lib_ring_buffer_config *config,
+                                struct channel *chan, size_t offset,
+                                size_t *pre_header_padding,
+                                struct lttng_ust_lib_ring_buffer_ctx *ctx)
+{
+       return record_header_size(config, chan, offset,
+                                 pre_header_padding, ctx);
+}
+
+/**
+ * client_packet_header_size - called on buffer-switch to a new sub-buffer
+ *
+ * Return header size without padding after the structure. Don't use packed
+ * structure because gcc generates inefficient code on some architectures
+ * (powerpc, mips..)
+ */
+static size_t client_packet_header_size(void)
+{
+       return offsetof(struct packet_header, ctx.header_end);
+}
+
+static void client_buffer_begin(struct lttng_ust_lib_ring_buffer *buf, u64 tsc,
+                               unsigned int subbuf_idx,
+                               struct lttng_ust_shm_handle *handle)
+{
+       struct channel *chan = shmp(handle, buf->backend.chan);
+       struct packet_header *header =
+               (struct packet_header *)
+                       lib_ring_buffer_offset_address(&buf->backend,
+                               subbuf_idx * chan->backend.subbuf_size,
+                               handle);
+       struct ltt_channel *ltt_chan = channel_get_private(chan);
+       struct ltt_session *session = ltt_chan->session;
+
+       header->magic = CTF_MAGIC_NUMBER;
+       memcpy(header->uuid, session->uuid, sizeof(session->uuid));
+       header->stream_id = ltt_chan->id;
+       header->ctx.timestamp_begin = tsc;
+       header->ctx.timestamp_end = 0;
+       header->ctx.events_discarded = 0;
+       header->ctx.content_size = 0xFFFFFFFF; /* for debugging */
+       header->ctx.packet_size = 0xFFFFFFFF;
+       header->ctx.cpu_id = buf->backend.cpu;
+}
+
+/*
+ * offset is assumed to never be 0 here : never deliver a completely empty
+ * subbuffer. data_size is between 1 and subbuf_size.
+ */
+static void client_buffer_end(struct lttng_ust_lib_ring_buffer *buf, u64 tsc,
+                             unsigned int subbuf_idx, unsigned long data_size,
+                             struct lttng_ust_shm_handle *handle)
+{
+       struct channel *chan = shmp(handle, buf->backend.chan);
+       struct packet_header *header =
+               (struct packet_header *)
+                       lib_ring_buffer_offset_address(&buf->backend,
+                               subbuf_idx * chan->backend.subbuf_size,
+                               handle);
+       unsigned long records_lost = 0;
+
+       header->ctx.timestamp_end = tsc;
+       header->ctx.content_size = data_size * CHAR_BIT;        /* in bits */
+       header->ctx.packet_size = PAGE_ALIGN(data_size) * CHAR_BIT; /* in bits */
+       /*
+        * We do not care about the records lost count, because the metadata
+        * channel waits and retry.
+        */
+       (void) lib_ring_buffer_get_records_lost_full(&client_config, buf);
+       records_lost += lib_ring_buffer_get_records_lost_wrap(&client_config, buf);
+       records_lost += lib_ring_buffer_get_records_lost_big(&client_config, buf);
+       header->ctx.events_discarded = records_lost;
+}
+
+static int client_buffer_create(struct lttng_ust_lib_ring_buffer *buf, void *priv,
+                               int cpu, const char *name, struct lttng_ust_shm_handle *handle)
+{
+       return 0;
+}
+
+static void client_buffer_finalize(struct lttng_ust_lib_ring_buffer *buf, void *priv, int cpu, struct lttng_ust_shm_handle *handle)
+{
+}
+
+static const struct lttng_ust_lib_ring_buffer_config client_config = {
+       .cb.ring_buffer_clock_read = client_ring_buffer_clock_read,
+       .cb.record_header_size = client_record_header_size,
+       .cb.subbuffer_header_size = client_packet_header_size,
+       .cb.buffer_begin = client_buffer_begin,
+       .cb.buffer_end = client_buffer_end,
+       .cb.buffer_create = client_buffer_create,
+       .cb.buffer_finalize = client_buffer_finalize,
+
+       .tsc_bits = 32,
+       .alloc = RING_BUFFER_ALLOC_PER_CPU,
+       .sync = RING_BUFFER_SYNC_GLOBAL,
+       .mode = RING_BUFFER_MODE_TEMPLATE,
+       .backend = RING_BUFFER_PAGE,
+       .output = RING_BUFFER_MMAP,
+       .oops = RING_BUFFER_OOPS_CONSISTENCY,
+       .ipi = RING_BUFFER_NO_IPI_BARRIER,
+       .wakeup = RING_BUFFER_WAKEUP_BY_WRITER,
+};
+
+static
+struct ltt_channel *_channel_create(const char *name,
+                               struct ltt_channel *ltt_chan, void *buf_addr,
+                               size_t subbuf_size, size_t num_subbuf,
+                               unsigned int switch_timer_interval,
+                               unsigned int read_timer_interval,
+                               int *shm_fd, int *wait_fd,
+                               uint64_t *memory_map_size)
+{
+       ltt_chan->handle = channel_create(&client_config, name, ltt_chan, buf_addr,
+                             subbuf_size, num_subbuf, switch_timer_interval,
+                             read_timer_interval, shm_fd, wait_fd,
+                             memory_map_size);
+       if (!ltt_chan->handle)
+               return NULL;
+       ltt_chan->chan = shmp(ltt_chan->handle, ltt_chan->handle->chan);
+       return ltt_chan;
+}
+
+static
+void ltt_channel_destroy(struct ltt_channel *ltt_chan)
+{
+       channel_destroy(ltt_chan->chan, ltt_chan->handle, 0);
+}
+
+static
+struct lttng_ust_lib_ring_buffer *ltt_buffer_read_open(struct channel *chan,
+                                            struct lttng_ust_shm_handle *handle,
+                                            int *shm_fd, int *wait_fd,
+                                            uint64_t *memory_map_size)
+{
+       struct lttng_ust_lib_ring_buffer *buf;
+       int cpu;
+
+       for_each_channel_cpu(cpu, chan) {
+               buf = channel_get_ring_buffer(&client_config, chan,
+                               cpu, handle, shm_fd, wait_fd,
+                               memory_map_size);
+               if (!lib_ring_buffer_open_read(buf, handle, 0))
+                       return buf;
+       }
+       return NULL;
+}
+
+static
+void ltt_buffer_read_close(struct lttng_ust_lib_ring_buffer *buf,
+                          struct lttng_ust_shm_handle *handle)
+{
+       lib_ring_buffer_release_read(buf, handle, 0);
+}
+
+static
+int ltt_event_reserve(struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                     uint32_t event_id)
+{
+       struct ltt_channel *ltt_chan = channel_get_private(ctx->chan);
+       int ret, cpu;
+
+       cpu = lib_ring_buffer_get_cpu(&client_config);
+       if (cpu < 0)
+               return -EPERM;
+       ctx->cpu = cpu;
+
+       switch (ltt_chan->header_type) {
+       case 1: /* compact */
+               if (event_id > 30)
+                       ctx->rflags |= LTT_RFLAG_EXTENDED;
+               break;
+       case 2: /* large */
+               if (event_id > 65534)
+                       ctx->rflags |= LTT_RFLAG_EXTENDED;
+               break;
+       default:
+               WARN_ON_ONCE(1);
+       }
+
+       ret = lib_ring_buffer_reserve(&client_config, ctx);
+       if (ret)
+               goto put;
+       ltt_write_event_header(&client_config, ctx, event_id);
+       return 0;
+put:
+       lib_ring_buffer_put_cpu(&client_config);
+       return ret;
+}
+
+static
+void ltt_event_commit(struct lttng_ust_lib_ring_buffer_ctx *ctx)
+{
+       lib_ring_buffer_commit(&client_config, ctx);
+       lib_ring_buffer_put_cpu(&client_config);
+}
+
+static
+void ltt_event_write(struct lttng_ust_lib_ring_buffer_ctx *ctx, const void *src,
+                    size_t len)
+{
+       lib_ring_buffer_write(&client_config, ctx, src, len);
+}
+
+#if 0
+static
+wait_queue_head_t *ltt_get_reader_wait_queue(struct channel *chan)
+{
+       return &chan->read_wait;
+}
+
+static
+wait_queue_head_t *ltt_get_hp_wait_queue(struct channel *chan)
+{
+       return &chan->hp_wait;
+}
+#endif //0
+
+static
+int ltt_is_finalized(struct channel *chan)
+{
+       return lib_ring_buffer_channel_is_finalized(chan);
+}
+
+static
+int ltt_is_disabled(struct channel *chan)
+{
+       return lib_ring_buffer_channel_is_disabled(chan);
+}
+
+static
+int ltt_flush_buffer(struct channel *chan, struct lttng_ust_shm_handle *handle)
+{
+       struct lttng_ust_lib_ring_buffer *buf;
+       int cpu;
+
+       for_each_channel_cpu(cpu, chan) {
+               int shm_fd, wait_fd;
+               uint64_t memory_map_size;
+
+               buf = channel_get_ring_buffer(&client_config, chan,
+                               cpu, handle, &shm_fd, &wait_fd,
+                               &memory_map_size);
+               lib_ring_buffer_switch(&client_config, buf,
+                               SWITCH_ACTIVE, handle);
+       }
+       return 0;
+}
+
+static struct ltt_transport ltt_relay_transport = {
+       .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING "-mmap",
+       .ops = {
+               .channel_create = _channel_create,
+               .channel_destroy = ltt_channel_destroy,
+               .buffer_read_open = ltt_buffer_read_open,
+               .buffer_read_close = ltt_buffer_read_close,
+               .event_reserve = ltt_event_reserve,
+               .event_commit = ltt_event_commit,
+               .event_write = ltt_event_write,
+               .packet_avail_size = NULL,      /* Would be racy anyway */
+               //.get_reader_wait_queue = ltt_get_reader_wait_queue,
+               //.get_hp_wait_queue = ltt_get_hp_wait_queue,
+               .is_finalized = ltt_is_finalized,
+               .is_disabled = ltt_is_disabled,
+               .flush_buffer = ltt_flush_buffer,
+       },
+};
+
+void RING_BUFFER_MODE_TEMPLATE_INIT(void)
+{
+       DBG("LTT : ltt ring buffer client init\n");
+       ltt_transport_register(&ltt_relay_transport);
+}
+
+void RING_BUFFER_MODE_TEMPLATE_EXIT(void)
+{
+       DBG("LTT : ltt ring buffer client exit\n");
+       ltt_transport_unregister(&ltt_relay_transport);
+}
diff --git a/liblttng-ust/ltt-ring-buffer-metadata-client.c b/liblttng-ust/ltt-ring-buffer-metadata-client.c
new file mode 100644 (file)
index 0000000..e1747c4
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * ltt-ring-buffer-metadata-client.c
+ *
+ * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * LTTng lib ring buffer metadta client.
+ *
+ * Dual LGPL v2.1/GPL v2 license.
+ */
+
+#include "ltt-tracer.h"
+
+#define RING_BUFFER_MODE_TEMPLATE              RING_BUFFER_DISCARD
+#define RING_BUFFER_MODE_TEMPLATE_STRING       "metadata"
+#define RING_BUFFER_MODE_TEMPLATE_INIT \
+       ltt_ring_buffer_metadata_client_init
+#define RING_BUFFER_MODE_TEMPLATE_EXIT \
+       ltt_ring_buffer_metadata_client_exit
+#include "ltt-ring-buffer-metadata-client.h"
diff --git a/liblttng-ust/ltt-ring-buffer-metadata-client.h b/liblttng-ust/ltt-ring-buffer-metadata-client.h
new file mode 100644 (file)
index 0000000..d1a83d5
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * ltt-ring-buffer-client.h
+ *
+ * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * LTTng lib ring buffer client template.
+ *
+ * Dual LGPL v2.1/GPL v2 license.
+ */
+
+#include <stdint.h>
+#include <lttng/ust-events.h>
+#include "lttng/bitfield.h"
+#include "ltt-tracer.h"
+#include "../libringbuffer/frontend_types.h"
+
+struct metadata_packet_header {
+       uint32_t magic;                 /* 0x75D11D57 */
+       uint8_t  uuid[16];              /* Unique Universal Identifier */
+       uint32_t checksum;              /* 0 if unused */
+       uint32_t content_size;          /* in bits */
+       uint32_t packet_size;           /* in bits */
+       uint8_t  compression_scheme;    /* 0 if unused */
+       uint8_t  encryption_scheme;     /* 0 if unused */
+       uint8_t  checksum_scheme;       /* 0 if unused */
+       uint8_t  major;                 /* CTF spec major version number */
+       uint8_t  minor;                 /* CTF spec minor version number */
+       uint8_t  header_end[0];
+};
+
+struct metadata_record_header {
+       uint8_t header_end[0];          /* End of header */
+};
+
+static const struct lttng_ust_lib_ring_buffer_config client_config;
+
+static inline
+u64 lib_ring_buffer_clock_read(struct channel *chan)
+{
+       return 0;
+}
+
+static inline
+unsigned char record_header_size(const struct lttng_ust_lib_ring_buffer_config *config,
+                                struct channel *chan, size_t offset,
+                                size_t *pre_header_padding,
+                                struct lttng_ust_lib_ring_buffer_ctx *ctx)
+{
+       return 0;
+}
+
+#include "../libringbuffer/api.h"
+
+static u64 client_ring_buffer_clock_read(struct channel *chan)
+{
+       return 0;
+}
+
+static
+size_t client_record_header_size(const struct lttng_ust_lib_ring_buffer_config *config,
+                                struct channel *chan, size_t offset,
+                                size_t *pre_header_padding,
+                                struct lttng_ust_lib_ring_buffer_ctx *ctx)
+{
+       return 0;
+}
+
+/**
+ * client_packet_header_size - called on buffer-switch to a new sub-buffer
+ *
+ * Return header size without padding after the structure. Don't use packed
+ * structure because gcc generates inefficient code on some architectures
+ * (powerpc, mips..)
+ */
+static size_t client_packet_header_size(void)
+{
+       return offsetof(struct metadata_packet_header, header_end);
+}
+
+static void client_buffer_begin(struct lttng_ust_lib_ring_buffer *buf, u64 tsc,
+                               unsigned int subbuf_idx,
+                               struct lttng_ust_shm_handle *handle)
+{
+       struct channel *chan = shmp(handle, buf->backend.chan);
+       struct metadata_packet_header *header =
+               (struct metadata_packet_header *)
+                       lib_ring_buffer_offset_address(&buf->backend,
+                               subbuf_idx * chan->backend.subbuf_size,
+                               handle);
+       struct ltt_channel *ltt_chan = channel_get_private(chan);
+       struct ltt_session *session = ltt_chan->session;
+
+       header->magic = TSDL_MAGIC_NUMBER;
+       memcpy(header->uuid, session->uuid, sizeof(session->uuid));
+       header->checksum = 0;           /* 0 if unused */
+       header->content_size = 0xFFFFFFFF; /* in bits, for debugging */
+       header->packet_size = 0xFFFFFFFF;  /* in bits, for debugging */
+       header->compression_scheme = 0; /* 0 if unused */
+       header->encryption_scheme = 0;  /* 0 if unused */
+       header->checksum_scheme = 0;    /* 0 if unused */
+       header->major = CTF_SPEC_MAJOR;
+       header->minor = CTF_SPEC_MINOR;
+
+}
+
+/*
+ * offset is assumed to never be 0 here : never deliver a completely empty
+ * subbuffer. data_size is between 1 and subbuf_size.
+ */
+static void client_buffer_end(struct lttng_ust_lib_ring_buffer *buf, u64 tsc,
+                             unsigned int subbuf_idx, unsigned long data_size,
+                             struct lttng_ust_shm_handle *handle)
+{
+       struct channel *chan = shmp(handle, buf->backend.chan);
+       struct metadata_packet_header *header =
+               (struct metadata_packet_header *)
+                       lib_ring_buffer_offset_address(&buf->backend,
+                               subbuf_idx * chan->backend.subbuf_size,
+                               handle);
+       unsigned long records_lost = 0;
+
+       header->content_size = data_size * CHAR_BIT;            /* in bits */
+       header->packet_size = PAGE_ALIGN(data_size) * CHAR_BIT; /* in bits */
+       records_lost += lib_ring_buffer_get_records_lost_full(&client_config, buf);
+       records_lost += lib_ring_buffer_get_records_lost_wrap(&client_config, buf);
+       records_lost += lib_ring_buffer_get_records_lost_big(&client_config, buf);
+       WARN_ON_ONCE(records_lost != 0);
+}
+
+static int client_buffer_create(struct lttng_ust_lib_ring_buffer *buf, void *priv,
+                               int cpu, const char *name,
+                               struct lttng_ust_shm_handle *handle)
+{
+       return 0;
+}
+
+static void client_buffer_finalize(struct lttng_ust_lib_ring_buffer *buf,
+                                  void *priv, int cpu,
+                                  struct lttng_ust_shm_handle *handle)
+{
+}
+
+static const struct lttng_ust_lib_ring_buffer_config client_config = {
+       .cb.ring_buffer_clock_read = client_ring_buffer_clock_read,
+       .cb.record_header_size = client_record_header_size,
+       .cb.subbuffer_header_size = client_packet_header_size,
+       .cb.buffer_begin = client_buffer_begin,
+       .cb.buffer_end = client_buffer_end,
+       .cb.buffer_create = client_buffer_create,
+       .cb.buffer_finalize = client_buffer_finalize,
+
+       .tsc_bits = 0,
+       .alloc = RING_BUFFER_ALLOC_GLOBAL,
+       .sync = RING_BUFFER_SYNC_GLOBAL,
+       .mode = RING_BUFFER_MODE_TEMPLATE,
+       .backend = RING_BUFFER_PAGE,
+       .output = RING_BUFFER_MMAP,
+       .oops = RING_BUFFER_OOPS_CONSISTENCY,
+       .ipi = RING_BUFFER_NO_IPI_BARRIER,
+       .wakeup = RING_BUFFER_WAKEUP_BY_WRITER,
+};
+
+static
+struct ltt_channel *_channel_create(const char *name,
+                               struct ltt_channel *ltt_chan, void *buf_addr,
+                               size_t subbuf_size, size_t num_subbuf,
+                               unsigned int switch_timer_interval,
+                               unsigned int read_timer_interval,
+                               int *shm_fd, int *wait_fd,
+                               uint64_t *memory_map_size)
+{
+       ltt_chan->handle = channel_create(&client_config, name, ltt_chan, buf_addr,
+                             subbuf_size, num_subbuf, switch_timer_interval,
+                             read_timer_interval, shm_fd, wait_fd,
+                             memory_map_size);
+       if (!ltt_chan->handle)
+               return NULL;
+       ltt_chan->chan = shmp(ltt_chan->handle, ltt_chan->handle->chan);
+       return ltt_chan;
+}
+
+static
+void ltt_channel_destroy(struct ltt_channel *ltt_chan)
+{
+       channel_destroy(ltt_chan->chan, ltt_chan->handle, 0);
+}
+
+static
+struct lttng_ust_lib_ring_buffer *ltt_buffer_read_open(struct channel *chan,
+                                            struct lttng_ust_shm_handle *handle,
+                                            int *shm_fd, int *wait_fd,
+                                            uint64_t *memory_map_size)
+{
+       struct lttng_ust_lib_ring_buffer *buf;
+
+       buf = channel_get_ring_buffer(&client_config, chan,
+                       0, handle, shm_fd, wait_fd, memory_map_size);
+       if (!lib_ring_buffer_open_read(buf, handle, 0))
+               return buf;
+       return NULL;
+}
+
+static
+void ltt_buffer_read_close(struct lttng_ust_lib_ring_buffer *buf,
+                          struct lttng_ust_shm_handle *handle)
+{
+       lib_ring_buffer_release_read(buf, handle, 0);
+}
+
+static
+int ltt_event_reserve(struct lttng_ust_lib_ring_buffer_ctx *ctx, uint32_t event_id)
+{
+       return lib_ring_buffer_reserve(&client_config, ctx);
+}
+
+static
+void ltt_event_commit(struct lttng_ust_lib_ring_buffer_ctx *ctx)
+{
+       lib_ring_buffer_commit(&client_config, ctx);
+}
+
+static
+void ltt_event_write(struct lttng_ust_lib_ring_buffer_ctx *ctx, const void *src,
+                    size_t len)
+{
+       lib_ring_buffer_write(&client_config, ctx, src, len);
+}
+
+static
+size_t ltt_packet_avail_size(struct channel *chan, struct lttng_ust_shm_handle *handle)
+                            
+{
+       unsigned long o_begin;
+       struct lttng_ust_lib_ring_buffer *buf;
+
+       buf = shmp(handle, chan->backend.buf[0].shmp);  /* Only for global buffer ! */
+       o_begin = v_read(&client_config, &buf->offset);
+       if (subbuf_offset(o_begin, chan) != 0) {
+               return chan->backend.subbuf_size - subbuf_offset(o_begin, chan);
+       } else {
+               return chan->backend.subbuf_size - subbuf_offset(o_begin, chan)
+                       - sizeof(struct metadata_packet_header);
+       }
+}
+
+#if 0
+static
+wait_queue_head_t *ltt_get_reader_wait_queue(struct channel *chan)
+{
+       return &chan->read_wait;
+}
+
+static
+wait_queue_head_t *ltt_get_hp_wait_queue(struct channel *chan)
+{
+       return &chan->hp_wait;
+}
+#endif //0
+
+static
+int ltt_is_finalized(struct channel *chan)
+{
+       return lib_ring_buffer_channel_is_finalized(chan);
+}
+
+static
+int ltt_is_disabled(struct channel *chan)
+{
+       return lib_ring_buffer_channel_is_disabled(chan);
+}
+
+static
+int ltt_flush_buffer(struct channel *chan, struct lttng_ust_shm_handle *handle)
+{
+       struct lttng_ust_lib_ring_buffer *buf;
+       int shm_fd, wait_fd;
+       uint64_t memory_map_size;
+
+       buf = channel_get_ring_buffer(&client_config, chan,
+                       0, handle, &shm_fd, &wait_fd,
+                       &memory_map_size);
+       lib_ring_buffer_switch(&client_config, buf,
+                       SWITCH_ACTIVE, handle);
+       return 0;
+}
+
+static struct ltt_transport ltt_relay_transport = {
+       .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING "-mmap",
+       .ops = {
+               .channel_create = _channel_create,
+               .channel_destroy = ltt_channel_destroy,
+               .buffer_read_open = ltt_buffer_read_open,
+               .buffer_read_close = ltt_buffer_read_close,
+               .event_reserve = ltt_event_reserve,
+               .event_commit = ltt_event_commit,
+               .event_write = ltt_event_write,
+               .packet_avail_size = ltt_packet_avail_size,
+               //.get_reader_wait_queue = ltt_get_reader_wait_queue,
+               //.get_hp_wait_queue = ltt_get_hp_wait_queue,
+               .is_finalized = ltt_is_finalized,
+               .is_disabled = ltt_is_disabled,
+               .flush_buffer = ltt_flush_buffer,
+       },
+};
+
+void RING_BUFFER_MODE_TEMPLATE_INIT(void)
+{
+       DBG("LTT : ltt ring buffer client init\n");
+       ltt_transport_register(&ltt_relay_transport);
+}
+
+void RING_BUFFER_MODE_TEMPLATE_EXIT(void)
+{
+       DBG("LTT : ltt ring buffer client exit\n");
+       ltt_transport_unregister(&ltt_relay_transport);
+}
diff --git a/liblttng-ust/ltt-tracer-core.h b/liblttng-ust/ltt-tracer-core.h
new file mode 100644 (file)
index 0000000..20ed0c0
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _LTT_TRACER_CORE_H
+#define _LTT_TRACER_CORE_H
+
+/*
+ * Copyright (C) 2005-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This contains the core definitions for the Linux Trace Toolkit.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1 of
+ * the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <lttng/kcompat/kcompat.h>
+#include <lttng/core.h>
+#include <lttng/ust-tracer.h>
+#include <urcu/list.h>
+#include <lttng/usterr-signal-safe.h>
+#include "lttng/bug.h"
+
+#include <lttng/ringbuffer-config.h>
+
+struct ltt_session;
+struct ltt_channel;
+struct ltt_event;
+
+void ust_lock(void);
+void ust_unlock(void);
+
+#endif /* _LTT_TRACER_CORE_H */
diff --git a/liblttng-ust/ltt-tracer.h b/liblttng-ust/ltt-tracer.h
new file mode 100644 (file)
index 0000000..6ab80e7
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef _LTT_TRACER_H
+#define _LTT_TRACER_H
+
+/*
+ * Copyright (C) 2005-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This contains the definitions for the Linux Trace Toolkit tracer.
+ *
+ * Ported to userspace by Pierre-Marc Fournier.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1 of
+ * the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <lttng/core.h>
+#include <lttng/compat.h>
+#include <lttng/ust-events.h>
+#include "ltt-tracer-core.h"
+
+/* Number of bytes to log with a read/write event */
+#define LTT_LOG_RW_SIZE                        32L
+#define LTT_MAX_SMALL_SIZE             0xFFFFU
+
+/* Tracer properties */
+#define CTF_MAGIC_NUMBER               0xC1FC1FC1
+#define TSDL_MAGIC_NUMBER              0x75D11D57
+
+/* CTF specification version followed */
+#define CTF_SPEC_MAJOR                 1
+#define CTF_SPEC_MINOR                 8
+
+/* Tracer major/minor versions */
+#define CTF_VERSION_MAJOR              0
+#define CTF_VERSION_MINOR              1
+
+/*
+ * Number of milliseconds to retry before failing metadata writes on buffer full
+ * condition. (10 seconds)
+ */
+#define LTTNG_METADATA_TIMEOUT_MSEC    10000
+
+#define LTT_RFLAG_EXTENDED             RING_BUFFER_RFLAG_END
+#define LTT_RFLAG_END                  (LTT_RFLAG_EXTENDED << 1)
+
+#endif /* _LTT_TRACER_H */
diff --git a/liblttng-ust/lttng-context-procname.c b/liblttng-ust/lttng-context-procname.c
new file mode 100644 (file)
index 0000000..b9bae82
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * (C) Copyright       2009-2011 -
+ *             Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * LTTng UST procname context.
+ *
+ * Dual LGPL v2.1/GPL v2 license.
+ */
+
+#include <sys/prctl.h>
+#include <lttng/ust-events.h>
+#include <lttng/ust-tracer.h>
+#include <lttng/ringbuffer-config.h>
+#include <assert.h>
+
+#define PROCNAME_LEN   17      /* includes \0 */
+
+/*
+ * We cache the result to ensure we don't trigger a system call for
+ * each event.
+ * Upon exec, procname changes, but exec takes care of throwing away
+ * this cached version.
+ */
+static char cached_procname[17];
+
+static inline
+char *wrapper_getprocname(void)
+{
+       int ret;
+
+       if (caa_unlikely(!cached_procname[0])) {
+               ret = prctl(PR_GET_NAME, (unsigned long) cached_procname,
+                       0, 0, 0);
+               assert(!ret);
+       }
+       return cached_procname;
+}
+
+void lttng_context_procname_reset(void)
+{
+       cached_procname[0] = '\0';
+}
+
+static
+size_t procname_get_size(size_t offset)
+{
+       size_t size = 0;
+
+       size += PROCNAME_LEN;
+       return size;
+}
+
+static
+void procname_record(struct lttng_ctx_field *field,
+                struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                struct ltt_channel *chan)
+{
+       char *procname;
+
+       procname = wrapper_getprocname();
+       chan->ops->event_write(ctx, procname, PROCNAME_LEN);
+}
+
+int lttng_add_procname_to_ctx(struct lttng_ctx **ctx)
+{
+       struct lttng_ctx_field *field;
+
+       field = lttng_append_context(ctx);
+       if (!field)
+               return -ENOMEM;
+       if (lttng_find_context(*ctx, "procname")) {
+               lttng_remove_context_field(ctx, field);
+               return -EEXIST;
+       }
+       field->event_field.name = "procname";
+       field->event_field.type.atype = atype_array;
+       field->event_field.type.u.array.elem_type.atype = atype_integer;
+       field->event_field.type.u.array.elem_type.u.basic.integer.size = sizeof(char) * CHAR_BIT;
+       field->event_field.type.u.array.elem_type.u.basic.integer.alignment = lttng_alignof(char) * CHAR_BIT;
+       field->event_field.type.u.array.elem_type.u.basic.integer.signedness = lttng_is_signed_type(char);
+       field->event_field.type.u.array.elem_type.u.basic.integer.reverse_byte_order = 0;
+       field->event_field.type.u.array.elem_type.u.basic.integer.base = 10;
+       field->event_field.type.u.array.elem_type.u.basic.integer.encoding = lttng_encode_UTF8;
+       field->event_field.type.u.array.length = PROCNAME_LEN;
+       field->get_size = procname_get_size;
+       field->record = procname_record;
+       return 0;
+}
diff --git a/liblttng-ust/lttng-context-pthread-id.c b/liblttng-ust/lttng-context-pthread-id.c
new file mode 100644 (file)
index 0000000..62eda80
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * (C) Copyright       2009-2011 -
+ *             Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * LTTng UST pthread_id context.
+ *
+ * Dual LGPL v2.1/GPL v2 license.
+ */
+
+#include <pthread.h>
+#include <lttng/ust-events.h>
+#include <lttng/ust-tracer.h>
+#include <lttng/ringbuffer-config.h>
+
+static
+size_t pthread_id_get_size(size_t offset)
+{
+       size_t size = 0;
+
+       size += lib_ring_buffer_align(offset, lttng_alignof(unsigned long));
+       size += sizeof(unsigned long);
+       return size;
+}
+
+static
+void pthread_id_record(struct lttng_ctx_field *field,
+                struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                struct ltt_channel *chan)
+{
+       unsigned long pthread_id;
+
+       pthread_id = (unsigned long) pthread_self();
+       lib_ring_buffer_align_ctx(ctx, lttng_alignof(pthread_id));
+       chan->ops->event_write(ctx, &pthread_id, sizeof(pthread_id));
+}
+
+int lttng_add_pthread_id_to_ctx(struct lttng_ctx **ctx)
+{
+       struct lttng_ctx_field *field;
+
+       field = lttng_append_context(ctx);
+       if (!field)
+               return -ENOMEM;
+       if (lttng_find_context(*ctx, "pthread_id")) {
+               lttng_remove_context_field(ctx, field);
+               return -EEXIST;
+       }
+       field->event_field.name = "pthread_id";
+       field->event_field.type.atype = atype_integer;
+       field->event_field.type.u.basic.integer.size = sizeof(unsigned long) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(unsigned long);
+       field->event_field.type.u.basic.integer.reverse_byte_order = 0;
+       field->event_field.type.u.basic.integer.base = 10;
+       field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
+       field->get_size = pthread_id_get_size;
+       field->record = pthread_id_record;
+       return 0;
+}
diff --git a/liblttng-ust/lttng-context-vpid.c b/liblttng-ust/lttng-context-vpid.c
new file mode 100644 (file)
index 0000000..db76747
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * (C) Copyright       2009-2011 -
+ *             Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * LTTng UST vpid context.
+ *
+ * Dual LGPL v2.1/GPL v2 license.
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <lttng/ust-events.h>
+#include <lttng/ust-tracer.h>
+#include <lttng/ringbuffer-config.h>
+
+#ifdef __linux__
+static inline
+pid_t wrapper_getpid(void)
+{
+       return getpid();
+}
+
+void lttng_context_vpid_reset(void)
+{
+}
+#else
+/*
+ * We cache the result to ensure we don't trigger a system call for
+ * each event.
+ */
+static pid_t cached_vpid;
+
+static inline
+pid_t wrapper_getpid(void)
+{
+       if (caa_unlikely(!cached_vpid))
+               cached_vpid = getpid();
+       return cached_vpid;
+}
+
+/*
+ * Upon fork or clone, the PID assigned to our thread is not the same as
+ * we kept in cache.
+ */
+void lttng_context_vpid_reset(void)
+{
+       cached_vpid = 0;
+}
+#endif
+
+static
+size_t vpid_get_size(size_t offset)
+{
+       size_t size = 0;
+
+       size += lib_ring_buffer_align(offset, lttng_alignof(pid_t));
+       size += sizeof(pid_t);
+       return size;
+}
+
+static
+void vpid_record(struct lttng_ctx_field *field,
+                struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                struct ltt_channel *chan)
+{
+       pid_t pid;
+
+       pid = wrapper_getpid();
+       lib_ring_buffer_align_ctx(ctx, lttng_alignof(pid));
+       chan->ops->event_write(ctx, &pid, sizeof(pid));
+}
+
+int lttng_add_vpid_to_ctx(struct lttng_ctx **ctx)
+{
+       struct lttng_ctx_field *field;
+
+       field = lttng_append_context(ctx);
+       if (!field)
+               return -ENOMEM;
+       if (lttng_find_context(*ctx, "vpid")) {
+               lttng_remove_context_field(ctx, field);
+               return -EEXIST;
+       }
+       field->event_field.name = "vpid";
+       field->event_field.type.atype = atype_integer;
+       field->event_field.type.u.basic.integer.size = sizeof(pid_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.alignment = lttng_alignof(pid_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(pid_t);
+       field->event_field.type.u.basic.integer.reverse_byte_order = 0;
+       field->event_field.type.u.basic.integer.base = 10;
+       field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
+       field->get_size = vpid_get_size;
+       field->record = vpid_record;
+       return 0;
+}
diff --git a/liblttng-ust/lttng-context-vtid.c b/liblttng-ust/lttng-context-vtid.c
new file mode 100644 (file)
index 0000000..6f7e078
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * (C) Copyright       2009-2011 -
+ *             Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * LTTng UST vtid context.
+ *
+ * Dual LGPL v2.1/GPL v2 license.
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <lttng/ust-events.h>
+#include <lttng/ust-tracer.h>
+#include <lttng/ringbuffer-config.h>
+
+#ifdef __linux__
+#include <syscall.h>
+#endif
+
+#if defined(_syscall0)
+_syscall0(pid_t, gettid)
+#elif defined(__NR_gettid)
+static inline pid_t gettid(void)
+{
+       return syscall(__NR_gettid);
+}
+#else
+#warning "use pid as tid"
+static inline pid_t gettid(void)
+{
+       return getpid();
+}
+#endif
+
+/*
+ * We cache the result to ensure we don't trigger a system call for
+ * each event.
+ */
+static __thread pid_t cached_vtid;
+
+/*
+ * Upon fork or clone, the TID assigned to our thread is not the same as
+ * we kept in cache. Luckily, we are the only thread surviving in the
+ * child process, so we can simply clear our cached version.
+ */
+void lttng_context_vtid_reset(void)
+{
+       cached_vtid = 0;
+}
+
+static
+size_t vtid_get_size(size_t offset)
+{
+       size_t size = 0;
+
+       size += lib_ring_buffer_align(offset, lttng_alignof(pid_t));
+       size += sizeof(pid_t);
+       return size;
+}
+
+static
+void vtid_record(struct lttng_ctx_field *field,
+                struct lttng_ust_lib_ring_buffer_ctx *ctx,
+                struct ltt_channel *chan)
+{
+       if (caa_unlikely(!cached_vtid))
+               cached_vtid = gettid();
+       lib_ring_buffer_align_ctx(ctx, lttng_alignof(cached_vtid));
+       chan->ops->event_write(ctx, &cached_vtid, sizeof(cached_vtid));
+}
+
+int lttng_add_vtid_to_ctx(struct lttng_ctx **ctx)
+{
+       struct lttng_ctx_field *field;
+
+       field = lttng_append_context(ctx);
+       if (!field)
+               return -ENOMEM;
+       if (lttng_find_context(*ctx, "vtid")) {
+               lttng_remove_context_field(ctx, field);
+               return -EEXIST;
+       }
+       field->event_field.name = "vtid";
+       field->event_field.type.atype = atype_integer;
+       field->event_field.type.u.basic.integer.size = sizeof(pid_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.alignment = lttng_alignof(pid_t) * CHAR_BIT;
+       field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(pid_t);
+       field->event_field.type.u.basic.integer.reverse_byte_order = 0;
+       field->event_field.type.u.basic.integer.base = 10;
+       field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
+       field->get_size = vtid_get_size;
+       field->record = vtid_record;
+       return 0;
+}
diff --git a/liblttng-ust/lttng-ust-abi.c b/liblttng-ust/lttng-ust-abi.c
new file mode 100644 (file)
index 0000000..6d17c20
--- /dev/null
@@ -0,0 +1,822 @@
+/*
+ * lttng-ust-abi.c
+ *
+ * Copyright 2010-2011 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * LTTng UST ABI
+ *
+ * Mimic system calls for:
+ * - session creation, returns an object descriptor or failure.
+ *   - channel creation, returns an object descriptor or failure.
+ *     - Operates on a session object descriptor
+ *     - Takes all channel options as parameters.
+ *   - stream get, returns an object descriptor or failure.
+ *     - Operates on a channel object descriptor.
+ *   - stream notifier get, returns an object descriptor or failure.
+ *     - Operates on a channel object descriptor.
+ *   - event creation, returns an object descriptor or failure.
+ *     - Operates on a channel object descriptor
+ *     - Takes an event name as parameter
+ *     - Takes an instrumentation source as parameter
+ *       - e.g. tracepoints, dynamic_probes...
+ *     - Takes instrumentation source specific arguments.
+ *
+ * Dual LGPL v2.1/GPL v2 license.
+ */
+
+#include <lttng/ust-abi.h>
+#include <urcu/compiler.h>
+#include <urcu/list.h>
+#include <lttng/ust-events.h>
+#include <lttng/usterr-signal-safe.h>
+#include "lttng/core.h"
+#include "ltt-tracer.h"
+
+/*
+ * Object descriptor table. Should be protected from concurrent access
+ * by the caller.
+ */
+
+struct lttng_ust_obj {
+       union {
+               struct {
+                       void *private_data;
+                       const struct lttng_ust_objd_ops *ops;
+                       int f_count;
+               } s;
+               int freelist_next;      /* offset freelist. end is -1. */
+       } u;
+};
+
+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 lttng_ust_objd_table objd_table = {
+       .freelist_head = -1,
+};
+
+static
+int objd_alloc(void *private_data, const struct lttng_ust_objd_ops *ops)
+{
+       struct lttng_ust_obj *obj;
+
+       if (objd_table.freelist_head != -1) {
+               obj = &objd_table.array[objd_table.freelist_head];
+               objd_table.freelist_head = obj->u.freelist_next;
+               goto end;
+       }
+
+       if (objd_table.len >= objd_table.allocated_len) {
+               unsigned int new_allocated_len, old_allocated_len;
+               struct lttng_ust_obj *new_table, *old_table;
+
+               old_allocated_len = objd_table.allocated_len;
+               old_table = objd_table.array;
+               if (!old_allocated_len)
+                       new_allocated_len = 1;
+               else
+                       new_allocated_len = old_allocated_len << 1;
+               new_table = zmalloc(sizeof(struct lttng_ust_obj) * new_allocated_len);
+               if (!new_table)
+                       return -ENOMEM;
+               memcpy(new_table, old_table,
+                      sizeof(struct lttng_ust_obj) * old_allocated_len);
+               free(old_table);
+               objd_table.array = new_table;
+               objd_table.allocated_len = new_allocated_len;
+       }
+       obj = &objd_table.array[objd_table.len];
+       objd_table.len++;
+end:
+       obj->u.s.private_data = private_data;
+       obj->u.s.ops = ops;
+       obj->u.s.f_count = 2;   /* count == 1 : object is allocated */
+                               /* count == 2 : allocated + hold ref */
+       return obj - objd_table.array;
+}
+
+static
+struct lttng_ust_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];
+}
+
+static
+void *objd_private(int 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 lttng_ust_obj *obj = _objd_get(id);
+       assert(obj);
+       obj->u.s.private_data = private_data;
+}
+
+const struct lttng_ust_objd_ops *objd_ops(int id)
+{
+       struct lttng_ust_obj *obj = _objd_get(id);
+
+       if (!obj)
+               return NULL;
+       return obj->u.s.ops;
+}
+
+static
+void objd_free(int id)
+{
+       struct lttng_ust_obj *obj = _objd_get(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
+void objd_ref(int id)
+{
+       struct lttng_ust_obj *obj = _objd_get(id);
+       obj->u.s.f_count++;
+}
+
+int lttng_ust_objd_unref(int id)
+{
+       struct lttng_ust_obj *obj = _objd_get(id);
+
+       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 lttng_ust_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) lttng_ust_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;
+}
+
+/*
+ * This is LTTng's own personal way to create an ABI for sessiond.
+ * We send commands over a socket.
+ */
+
+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,
+       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)
+{
+       struct ltt_session *session;
+       int session_objd, ret;
+
+       session = ltt_session_create();
+       if (!session)
+               return -ENOMEM;
+       session_objd = objd_alloc(session, &lttng_session_ops);
+       if (session_objd < 0) {
+               ret = session_objd;
+               goto objd_error;
+       }
+       session->objd = session_objd;
+       return session_objd;
+
+objd_error:
+       ltt_session_destroy(session);
+       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, &lttng_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;
+       return 0;
+}
+
+static
+long lttng_abi_add_context(int objd,
+       struct lttng_ust_context *context_param,
+       struct lttng_ctx **ctx, struct ltt_session *session)
+{
+       if (session->been_active)
+               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:
+               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;
+       }
+}
+
+/**
+ *     lttng_cmd - lttng control through socket commands
+ *
+ *     @objd: the object descriptor
+ *     @cmd: the command
+ *     @arg: command arg
+ *
+ *     This descriptor implements lttng commands:
+ *     LTTNG_UST_SESSION
+ *             Returns a LTTng trace session object descriptor
+ *     LTTNG_UST_TRACER_VERSION
+ *             Returns the LTTng kernel tracer version
+ *     LTTNG_UST_TRACEPOINT_LIST
+ *             Returns a file descriptor listing available tracepoints
+ *     LTTNG_UST_WAIT_QUIESCENT
+ *             Returns after all previously running probes have completed
+ *
+ * The returned session will be deleted when its file descriptor is closed.
+ */
+static
+long lttng_cmd(int objd, unsigned int cmd, unsigned long arg)
+{
+       switch (cmd) {
+       case LTTNG_UST_SESSION:
+               return lttng_abi_create_session();
+       case LTTNG_UST_TRACER_VERSION:
+               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();
+       case LTTNG_UST_WAIT_QUIESCENT:
+               synchronize_trace();
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+static const struct lttng_ust_objd_ops lttng_ops = {
+       .cmd = lttng_cmd,
+};
+
+/*
+ * We tolerate no failure in this function (if one happens, we print a dmesg
+ * error, but cannot return any error, because the channel information is
+ * invariant.
+ */
+static
+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",
+       };
+       struct ltt_event *event;
+       int ret;
+
+       /*
+        * We tolerate no failure path after event creation. It will stay
+        * invariant for the rest of the session.
+        */
+       event = ltt_event_create(channel, &metadata_params, NULL);
+       if (!event) {
+               ret = -EINVAL;
+               goto create_error;
+       }
+       return;
+
+create_error:
+       WARN_ON(1);
+       return;         /* not allowed to return error */
+}
+
+int lttng_abi_create_channel(int session_objd,
+                            struct lttng_ust_channel *chan_param,
+                            enum channel_type channel_type)
+{
+       struct ltt_session *session = objd_private(session_objd);
+       const struct lttng_ust_objd_ops *ops;
+       const char *transport_name;
+       struct ltt_channel *chan;
+       int chan_objd;
+       int ret = 0;
+
+       chan_objd = objd_alloc(NULL, &lttng_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) {
+                       transport_name = chan_param->overwrite ?
+                               "relay-overwrite-mmap" : "relay-discard-mmap";
+               } else {
+                       return -EINVAL;
+               }
+               ops = &lttng_channel_ops;
+               break;
+       case METADATA_CHANNEL:
+               if (chan_param->output == LTTNG_UST_MMAP)
+                       transport_name = "relay-metadata-mmap";
+               else
+                       return -EINVAL;
+               ops = &lttng_metadata_ops;
+               break;
+       default:
+               transport_name = "<unknown>";
+               break;
+       }
+       /*
+        * We tolerate no failure path after channel creation. It will stay
+        * invariant for the rest of the session.
+        */
+       chan = ltt_channel_create(session, transport_name, NULL,
+                                 chan_param->subbuf_size,
+                                 chan_param->num_subbuf,
+                                 chan_param->switch_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;
+       }
+       objd_set_private(chan_objd, chan);
+       chan->objd = chan_objd;
+       if (channel_type == METADATA_CHANNEL) {
+               session->metadata = chan;
+               lttng_metadata_create_events(chan_objd);
+       }
+
+       /* The channel created holds a reference on the session */
+       objd_ref(session_objd);
+
+       return chan_objd;
+
+chan_error:
+       {
+               int err;
+
+               err = lttng_ust_objd_unref(chan_objd);
+               assert(!err);
+       }
+objd_error:
+       return ret;
+}
+
+/**
+ *     lttng_session_cmd - lttng session object command
+ *
+ *     @obj: the object
+ *     @cmd: the command
+ *     @arg: command arg
+ *
+ *     This descriptor implements lttng commands:
+ *     LTTNG_UST_CHANNEL
+ *             Returns a LTTng channel object descriptor
+ *     LTTNG_UST_ENABLE
+ *             Enables tracing for a session (weak enable)
+ *     LTTNG_UST_DISABLE
+ *             Disables tracing for a session (strong disable)
+ *     LTTNG_UST_METADATA
+ *             Returns a LTTng metadata object descriptor
+ *
+ * The returned channel will be deleted when its file descriptor is closed.
+ */
+static
+long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg)
+{
+       struct ltt_session *session = objd_private(objd);
+
+       switch (cmd) {
+       case LTTNG_UST_CHANNEL:
+               return lttng_abi_create_channel(objd,
+                               (struct lttng_ust_channel *) arg,
+                               PER_CPU_CHANNEL);
+       case LTTNG_UST_SESSION_START:
+       case LTTNG_UST_ENABLE:
+               return ltt_session_enable(session);
+       case LTTNG_UST_SESSION_STOP:
+       case LTTNG_UST_DISABLE:
+               return ltt_session_disable(session);
+       case LTTNG_UST_METADATA:
+               return lttng_abi_create_channel(objd,
+                               (struct lttng_ust_channel *) arg,
+                               METADATA_CHANNEL);
+       default:
+               return -EINVAL;
+       }
+}
+
+/*
+ * Called when the last file reference is dropped.
+ *
+ * Big fat note: channels and events are invariant for the whole session after
+ * their creation. So this session destruction also destroys all channel and
+ * event structures specific to this session (they are not destroyed when their
+ * individual file is released).
+ */
+static
+int lttng_release_session(int objd)
+{
+       struct ltt_session *session = objd_private(objd);
+
+       if (session) {
+               ltt_session_destroy(session);
+               return 0;
+       } else {
+               return -EINVAL;
+       }
+}
+
+static const struct lttng_ust_objd_ops lttng_session_ops = {
+       .release = lttng_release_session,
+       .cmd = lttng_session_cmd,
+};
+
+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, struct lttng_ust_stream *info)
+{
+       struct ltt_channel *channel = objd_private(channel_objd);
+       struct lttng_ust_lib_ring_buffer *buf;
+       struct stream_priv_data *priv;
+       int stream_objd, ret;
+
+       buf = channel->ops->buffer_read_open(channel->chan, channel->handle,
+                       &info->shm_fd, &info->wait_fd, &info->memory_map_size);
+       if (!buf)
+               return -ENOENT;
+
+       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;
+       }
+       /* Hold a reference on the channel object descriptor */
+       objd_ref(channel_objd);
+       return stream_objd;
+
+objd_error:
+       free(priv);
+alloc_error:
+       channel->ops->buffer_read_close(buf, channel->handle);
+       return ret;
+}
+
+static
+int lttng_abi_create_event(int channel_objd,
+                          struct lttng_ust_event *event_param)
+{
+       struct ltt_channel *channel = objd_private(channel_objd);
+       struct ltt_event *event;
+       int event_objd, ret;
+
+       event_param->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+       event_objd = objd_alloc(NULL, &lttng_event_ops);
+       if (event_objd < 0) {
+               ret = event_objd;
+               goto objd_error;
+       }
+       /*
+        * We tolerate no failure path after event creation. It will stay
+        * invariant for the rest of the session.
+        */
+       event = ltt_event_create(channel, event_param, NULL);
+       if (!event) {
+               ret = -EINVAL;
+               goto event_error;
+       }
+       objd_set_private(event_objd, event);
+       /* The event holds a reference on the channel */
+       objd_ref(channel_objd);
+       return event_objd;
+
+event_error:
+       {
+               int err;
+
+               err = lttng_ust_objd_unref(event_objd);
+               assert(!err);
+       }
+objd_error:
+       return ret;
+}
+
+/**
+ *     lttng_channel_cmd - lttng control through object descriptors
+ *
+ *     @objd: the object descriptor
+ *     @cmd: the command
+ *     @arg: command arg
+ *
+ *     This object descriptor implements lttng commands:
+ *      LTTNG_UST_STREAM
+ *              Returns an event stream object descriptor or failure.
+ *              (typically, one event stream records events from one CPU)
+ *     LTTNG_UST_EVENT
+ *             Returns an event object descriptor or failure.
+ *     LTTNG_UST_CONTEXT
+ *             Prepend a context field to each event in the channel
+ *     LTTNG_UST_ENABLE
+ *             Enable recording for events in this channel (weak enable)
+ *     LTTNG_UST_DISABLE
+ *             Disable recording for events in this channel (strong disable)
+ *
+ * Channel and event file descriptors also hold a reference on the session.
+ */
+static
+long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg)
+{
+       struct ltt_channel *channel = objd_private(objd);
+
+       switch (cmd) {
+       case LTTNG_UST_STREAM:
+       {
+               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 lttng_abi_add_context(objd,
+                               (struct lttng_ust_context *) arg,
+                               &channel->ctx, channel->session);
+       case LTTNG_UST_ENABLE:
+               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;
+       }
+}
+
+/**
+ *     lttng_metadata_cmd - lttng control through object descriptors
+ *
+ *     @objd: the object descriptor
+ *     @cmd: the command
+ *     @arg: command arg
+ *
+ *     This object descriptor implements lttng commands:
+ *      LTTNG_UST_STREAM
+ *              Returns an event stream file descriptor or failure.
+ *
+ * Channel and event file descriptors also hold a reference on the session.
+ */
+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:
+       {
+               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;
+       }
+}
+
+#if 0
+/**
+ *     lttng_channel_poll - lttng stream addition/removal monitoring
+ *
+ *     @file: the file
+ *     @wait: poll table
+ */
+unsigned int lttng_channel_poll(struct file *file, poll_table *wait)
+{
+       struct ltt_channel *channel = file->private_data;
+       unsigned int mask = 0;
+
+       if (file->f_mode & FMODE_READ) {
+               poll_wait_set_exclusive(wait);
+               poll_wait(file, channel->ops->get_hp_wait_queue(channel->chan),
+                         wait);
+
+               if (channel->ops->is_disabled(channel->chan))
+                       return POLLERR;
+               if (channel->ops->is_finalized(channel->chan))
+                       return POLLHUP;
+               if (channel->ops->buffer_has_read_closed_stream(channel->chan))
+                       return POLLIN | POLLRDNORM;
+               return 0;
+       }
+       return mask;
+
+}
+#endif //0
+
+static
+int lttng_channel_release(int objd)
+{
+       struct ltt_channel *channel = objd_private(objd);
+
+       if (channel)
+               return lttng_ust_objd_unref(channel->session->objd);
+       return 0;
+}
+
+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 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 lttng_ust_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
+ *
+ *     @objd: the object descriptor
+ *     @cmd: the command
+ *     @arg: command arg
+ *
+ *     This object descriptor implements lttng commands:
+ *     LTTNG_UST_CONTEXT
+ *             Prepend a context field to each record of this event
+ *     LTTNG_UST_ENABLE
+ *             Enable recording for this event (weak enable)
+ *     LTTNG_UST_DISABLE
+ *             Disable recording for this event (strong disable)
+ */
+static
+long lttng_event_cmd(int objd, unsigned int cmd, unsigned long arg)
+{
+       struct ltt_event *event = objd_private(objd);
+
+       switch (cmd) {
+       case LTTNG_UST_CONTEXT:
+               return lttng_abi_add_context(objd,
+                               (struct lttng_ust_context *) arg,
+                               &event->ctx, event->chan->session);
+       case LTTNG_UST_ENABLE:
+               return ltt_event_enable(event);
+       case LTTNG_UST_DISABLE:
+               return ltt_event_disable(event);
+       default:
+               return -EINVAL;
+       }
+}
+
+static
+int lttng_event_release(int objd)
+{
+       struct ltt_event *event = objd_private(objd);
+
+       if (event)
+               return lttng_ust_objd_unref(event->chan->objd);
+       return 0;
+}
+
+/* TODO: filter control ioctl */
+static const struct lttng_ust_objd_ops lttng_event_ops = {
+       .release = lttng_event_release,
+       .cmd = lttng_event_cmd,
+};
+
+void lttng_ust_abi_exit(void)
+{
+       objd_table_destroy();
+}
diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c
new file mode 100644 (file)
index 0000000..d35511b
--- /dev/null
@@ -0,0 +1,935 @@
+/*
+ * lttng-ust-comm.c
+ *
+ * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#define _LGPL_SOURCE
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/prctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <time.h>
+#include <assert.h>
+#include <signal.h>
+#include <urcu/uatomic.h>
+#include <urcu/futex.h>
+
+#include <lttng/ust-comm.h>
+#include <lttng/ust-events.h>
+#include <lttng/usterr-signal-safe.h>
+#include <lttng/ust-abi.h>
+#include <lttng/tracepoint.h>
+#include <lttng/tracepoint-internal.h>
+#include <lttng/ust.h>
+#include "ltt-tracer-core.h"
+
+/*
+ * Has lttng ust comm constructor been called ?
+ */
+static int initialized;
+
+/*
+ * The ust_lock/ust_unlock lock is used as a communication thread mutex.
+ * Held when handling a command, also held by fork() to deal with
+ * removal of threads, and by exit path.
+ */
+
+/* Should the ust comm thread quit ? */
+static int lttng_ust_comm_should_quit;
+
+/*
+ * Wait for either of these before continuing to the main
+ * program:
+ * - the register_done message from sessiond daemon
+ *   (will let the sessiond daemon enable sessions before main
+ *   starts.)
+ * - sessiond daemon is not reachable.
+ * - timeout (ensuring applications are resilient to session
+ *   daemon problems).
+ */
+static sem_t constructor_wait;
+/*
+ * Doing this for both the global and local sessiond.
+ */
+static int sem_count = { 2 };
+
+/*
+ * Info about socket and associated listener thread.
+ */
+struct sock_info {
+       const char *name;
+       pthread_t ust_listener; /* listener thread */
+       int root_handle;
+       int constructor_sem_posted;
+       int allowed;
+       int global;
+
+       char sock_path[PATH_MAX];
+       int socket;
+
+       char wait_shm_path[PATH_MAX];
+       char *wait_shm_mmap;
+};
+
+/* Socket from app (connect) to session daemon (listen) for communication */
+struct sock_info global_apps = {
+       .name = "global",
+       .global = 1,
+
+       .root_handle = -1,
+       .allowed = 1,
+
+       .sock_path = DEFAULT_GLOBAL_APPS_UNIX_SOCK,
+       .socket = -1,
+
+       .wait_shm_path = DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH,
+};
+
+/* TODO: allow global_apps_sock_path override */
+
+struct sock_info local_apps = {
+       .name = "local",
+       .global = 0,
+       .root_handle = -1,
+       .allowed = 0,   /* Check setuid bit first */
+
+       .socket = -1,
+};
+
+static int wait_poll_fallback;
+
+extern void ltt_ring_buffer_client_overwrite_init(void);
+extern void ltt_ring_buffer_client_discard_init(void);
+extern void ltt_ring_buffer_metadata_client_init(void);
+extern void ltt_ring_buffer_client_overwrite_exit(void);
+extern void ltt_ring_buffer_client_discard_exit(void);
+extern void ltt_ring_buffer_metadata_client_exit(void);
+
+static
+int setup_local_apps(void)
+{
+       const char *home_dir;
+       uid_t uid;
+
+       uid = getuid();
+       /*
+        * Disallow per-user tracing for setuid binaries.
+        */
+       if (uid != geteuid()) {
+               local_apps.allowed = 0;
+               return 0;
+       } else {
+               local_apps.allowed = 1;
+       }
+       home_dir = (const char *) getenv("HOME");
+       if (!home_dir)
+               return -ENOENT;
+       snprintf(local_apps.sock_path, PATH_MAX,
+                DEFAULT_HOME_APPS_UNIX_SOCK, home_dir);
+       snprintf(local_apps.wait_shm_path, PATH_MAX,
+                DEFAULT_HOME_APPS_WAIT_SHM_PATH, uid);
+       return 0;
+}
+
+static
+int register_app_to_sessiond(int socket)
+{
+       ssize_t ret;
+       int prctl_ret;
+       struct {
+               uint32_t major;
+               uint32_t minor;
+               pid_t pid;
+               pid_t ppid;
+               uid_t uid;
+               gid_t gid;
+               char name[16];  /* process name */
+       } reg_msg;
+
+       reg_msg.major = LTTNG_UST_COMM_VERSION_MAJOR;
+       reg_msg.minor = LTTNG_UST_COMM_VERSION_MINOR;
+       reg_msg.pid = getpid();
+       reg_msg.ppid = getppid();
+       reg_msg.uid = getuid();
+       reg_msg.gid = getgid();
+       prctl_ret = prctl(PR_GET_NAME, (unsigned long) reg_msg.name, 0, 0, 0);
+       if (prctl_ret) {
+               ERR("Error executing prctl");
+               return -errno;
+       }
+
+       ret = ustcomm_send_unix_sock(socket, &reg_msg, sizeof(reg_msg));
+       if (ret >= 0 && ret != sizeof(reg_msg))
+               return -EIO;
+       return ret;
+}
+
+static
+int send_reply(int sock, struct ustcomm_ust_reply *lur)
+{
+       ssize_t len;
+
+       len = ustcomm_send_unix_sock(sock, lur, sizeof(*lur));
+       switch (len) {
+       case sizeof(*lur):
+               DBG("message successfully sent");
+               return 0;
+       case -1:
+               if (errno == ECONNRESET) {
+                       printf("remote end closed connection\n");
+                       return 0;
+               }
+               return -1;
+       default:
+               printf("incorrect message size: %zd\n", len);
+               return -1;
+       }
+}
+
+static
+int handle_register_done(struct sock_info *sock_info)
+{
+       int ret;
+
+       if (sock_info->constructor_sem_posted)
+               return 0;
+       sock_info->constructor_sem_posted = 1;
+       if (uatomic_read(&sem_count) <= 0) {
+               return 0;
+       }
+       ret = uatomic_add_return(&sem_count, -1);
+       if (ret == 0) {
+               ret = sem_post(&constructor_wait);
+               assert(!ret);
+       }
+       return 0;
+}
+
+static
+int handle_message(struct sock_info *sock_info,
+               int sock, struct ustcomm_ust_msg *lum)
+{
+       int ret = 0;
+       const struct lttng_ust_objd_ops *ops;
+       struct ustcomm_ust_reply lur;
+       int shm_fd, wait_fd;
+
+       ust_lock();
+
+       memset(&lur, 0, sizeof(lur));
+
+       if (lttng_ust_comm_should_quit) {
+               ret = -EPERM;
+               goto end;
+       }
+
+       ops = objd_ops(lum->handle);
+       if (!ops) {
+               ret = -ENOENT;
+               goto end;
+       }
+
+       switch (lum->cmd) {
+       case LTTNG_UST_REGISTER_DONE:
+               if (lum->handle == LTTNG_UST_ROOT_HANDLE)
+                       ret = handle_register_done(sock_info);
+               else
+                       ret = -EINVAL;
+               break;
+       case LTTNG_UST_RELEASE:
+               if (lum->handle == LTTNG_UST_ROOT_HANDLE)
+                       ret = -EPERM;
+               else
+                       ret = lttng_ust_objd_unref(lum->handle);
+               break;
+       default:
+               if (ops->cmd)
+                       ret = ops->cmd(lum->handle, lum->cmd,
+                                       (unsigned long) &lum->u);
+               else
+                       ret = -ENOSYS;
+               break;
+       }
+
+end:
+       lur.handle = lum->handle;
+       lur.cmd = lum->cmd;
+       lur.ret_val = ret;
+       if (ret >= 0) {
+               lur.ret_code = USTCOMM_OK;
+       } else {
+               //lur.ret_code = USTCOMM_SESSION_FAIL;
+               lur.ret_code = ret;
+       }
+       switch (lum->cmd) {
+       case LTTNG_UST_STREAM:
+               /*
+                * Special-case reply to send stream info.
+                * Use lum.u output.
+                */
+               lur.u.stream.memory_map_size = lum->u.stream.memory_map_size;
+               shm_fd = lum->u.stream.shm_fd;
+               wait_fd = lum->u.stream.wait_fd;
+               break;
+       case LTTNG_UST_METADATA:
+       case LTTNG_UST_CHANNEL:
+               lur.u.channel.memory_map_size = lum->u.channel.memory_map_size;
+               shm_fd = lum->u.channel.shm_fd;
+               wait_fd = lum->u.channel.wait_fd;
+               break;
+       case LTTNG_UST_VERSION:
+               lur.u.version = lum->u.version;
+               break;
+       }
+       ret = send_reply(sock, &lur);
+       if (ret < 0) {
+               perror("error sending reply");
+               goto error;
+       }
+
+       if ((lum->cmd == LTTNG_UST_STREAM
+            || lum->cmd == LTTNG_UST_CHANNEL
+            || lum->cmd == LTTNG_UST_METADATA)
+                       && lur.ret_code == USTCOMM_OK) {
+               /* we also need to send the file descriptors. */
+               ret = ustcomm_send_fds_unix_sock(sock,
+                       &shm_fd, &shm_fd,
+                       1, sizeof(int));
+               if (ret < 0) {
+                       perror("send shm_fd");
+                       goto error;
+               }
+               ret = ustcomm_send_fds_unix_sock(sock,
+                       &wait_fd, &wait_fd,
+                       1, sizeof(int));
+               if (ret < 0) {
+                       perror("send wait_fd");
+                       goto error;
+               }
+       }
+error:
+       ust_unlock();
+       return ret;
+}
+
+static
+void cleanup_sock_info(struct sock_info *sock_info)
+{
+       int ret;
+
+       if (sock_info->socket != -1) {
+               ret = close(sock_info->socket);
+               if (ret) {
+                       ERR("Error closing apps socket");
+               }
+               sock_info->socket = -1;
+       }
+       if (sock_info->root_handle != -1) {
+               ret = lttng_ust_objd_unref(sock_info->root_handle);
+               if (ret) {
+                       ERR("Error unref root handle");
+               }
+               sock_info->root_handle = -1;
+       }
+       sock_info->constructor_sem_posted = 0;
+       if (sock_info->wait_shm_mmap) {
+               ret = munmap(sock_info->wait_shm_mmap, sysconf(_SC_PAGE_SIZE));
+               if (ret) {
+                       ERR("Error unmapping wait shm");
+               }
+               sock_info->wait_shm_mmap = NULL;
+       }
+}
+
+/*
+ * Using fork to set umask in the child process (not multi-thread safe).
+ * We deal with the shm_open vs ftruncate race (happening when the
+ * sessiond owns the shm and does not let everybody modify it, to ensure
+ * safety against shm_unlink) by simply letting the mmap fail and
+ * retrying after a few seconds.
+ * For global shm, everybody has rw access to it until the sessiond
+ * starts.
+ */
+static
+int get_wait_shm(struct sock_info *sock_info, size_t mmap_size)
+{
+       int wait_shm_fd, ret;
+       pid_t pid;
+
+       /*
+        * Try to open read-only.
+        */
+       wait_shm_fd = shm_open(sock_info->wait_shm_path, O_RDONLY, 0);
+       if (wait_shm_fd >= 0) {
+               goto end;
+       } else if (wait_shm_fd < 0 && errno != ENOENT) {
+               /*
+                * Real-only open did not work, and it's not because the
+                * entry was not present. It's a failure that prohibits
+                * using shm.
+                */
+               ERR("Error opening shm %s", sock_info->wait_shm_path);
+               goto end;
+       }
+       /*
+        * If the open failed because the file did not exist, try
+        * creating it ourself.
+        */
+       pid = fork();
+       if (pid > 0) {
+               int status;
+
+               /*
+                * Parent: wait for child to return, in which case the
+                * shared memory map will have been created.
+                */
+               pid = wait(&status);
+               if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+                       wait_shm_fd = -1;
+                       goto end;
+               }
+               /*
+                * Try to open read-only again after creation.
+                */
+               wait_shm_fd = shm_open(sock_info->wait_shm_path, O_RDONLY, 0);
+               if (wait_shm_fd < 0) {
+                       /*
+                        * Real-only open did not work. It's a failure
+                        * that prohibits using shm.
+                        */
+                       ERR("Error opening shm %s", sock_info->wait_shm_path);
+                       goto end;
+               }
+               goto end;
+       } else if (pid == 0) {
+               int create_mode;
+
+               /* Child */
+               create_mode = S_IRUSR | S_IWUSR | S_IRGRP;
+               if (sock_info->global)
+                       create_mode |= S_IROTH | S_IWGRP | S_IWOTH;
+               /*
+                * We're alone in a child process, so we can modify the
+                * process-wide umask.
+                */
+               umask(~create_mode);
+               /*
+                * Try creating shm (or get rw access).
+                * We don't do an exclusive open, because we allow other
+                * processes to create+ftruncate it concurrently.
+                */
+               wait_shm_fd = shm_open(sock_info->wait_shm_path,
+                               O_RDWR | O_CREAT, create_mode);
+               if (wait_shm_fd >= 0) {
+                       ret = ftruncate(wait_shm_fd, mmap_size);
+                       if (ret) {
+                               PERROR("ftruncate");
+                               exit(EXIT_FAILURE);
+                       }
+                       exit(EXIT_SUCCESS);
+               }
+               /*
+                * For local shm, we need to have rw access to accept
+                * opening it: this means the local sessiond will be
+                * able to wake us up. For global shm, we open it even
+                * if rw access is not granted, because the root.root
+                * sessiond will be able to override all rights and wake
+                * us up.
+                */
+               if (!sock_info->global && errno != EACCES) {
+                       ERR("Error opening shm %s", sock_info->wait_shm_path);
+                       exit(EXIT_FAILURE);
+               }
+               /*
+                * The shm exists, but we cannot open it RW. Report
+                * success.
+                */
+               exit(EXIT_SUCCESS);
+       } else {
+               return -1;
+       }
+end:
+       if (wait_shm_fd >= 0 && !sock_info->global) {
+               struct stat statbuf;
+
+               /*
+                * Ensure that our user is the owner of the shm file for
+                * local shm. If we do not own the file, it means our
+                * sessiond will not have access to wake us up (there is
+                * probably a rogue process trying to fake our
+                * sessiond). Fallback to polling method in this case.
+                */
+               ret = fstat(wait_shm_fd, &statbuf);
+               if (ret) {
+                       PERROR("fstat");
+                       goto error_close;
+               }
+               if (statbuf.st_uid != getuid())
+                       goto error_close;
+       }
+       return wait_shm_fd;
+
+error_close:
+       ret = close(wait_shm_fd);
+       if (ret) {
+               PERROR("Error closing fd");
+       }
+       return -1;
+}
+
+static
+char *get_map_shm(struct sock_info *sock_info)
+{
+       size_t mmap_size = sysconf(_SC_PAGE_SIZE);
+       int wait_shm_fd, ret;
+       char *wait_shm_mmap;
+
+       wait_shm_fd = get_wait_shm(sock_info, mmap_size);
+       if (wait_shm_fd < 0) {
+               goto error;
+       }
+       wait_shm_mmap = mmap(NULL, mmap_size, PROT_READ,
+                 MAP_SHARED, wait_shm_fd, 0);
+       /* close shm fd immediately after taking the mmap reference */
+       ret = close(wait_shm_fd);
+       if (ret) {
+               PERROR("Error closing fd");
+       }
+       if (wait_shm_mmap == MAP_FAILED) {
+               DBG("mmap error (can be caused by race with sessiond). Fallback to poll mode.");
+               goto error;
+       }
+       return wait_shm_mmap;
+
+error:
+       return NULL;
+}
+
+static
+void wait_for_sessiond(struct sock_info *sock_info)
+{
+       int ret;
+
+       ust_lock();
+       if (lttng_ust_comm_should_quit) {
+               goto quit;
+       }
+       if (wait_poll_fallback) {
+               goto error;
+       }
+       if (!sock_info->wait_shm_mmap) {
+               sock_info->wait_shm_mmap = get_map_shm(sock_info);
+               if (!sock_info->wait_shm_mmap)
+                       goto error;
+       }
+       ust_unlock();
+
+       DBG("Waiting for %s apps sessiond", sock_info->name);
+       /* Wait for futex wakeup */
+       if (uatomic_read((int32_t *) sock_info->wait_shm_mmap) == 0) {
+               ret = futex_async((int32_t *) sock_info->wait_shm_mmap,
+                       FUTEX_WAIT, 0, NULL, NULL, 0);
+               if (ret < 0) {
+                       if (errno == EFAULT) {
+                               wait_poll_fallback = 1;
+                               WARN(
+"Linux kernels 2.6.33 to 3.0 (with the exception of stable versions) "
+"do not support FUTEX_WAKE on read-only memory mappings correctly. "
+"Please upgrade your kernel "
+"(fix is commit 9ea71503a8ed9184d2d0b8ccc4d269d05f7940ae in Linux kernel "
+"mainline). LTTng-UST will use polling mode fallback.");
+                       }
+                       PERROR("futex");
+               }
+       }
+       return;
+
+quit:
+       ust_unlock();
+       return;
+
+error:
+       ust_unlock();
+       return;
+}
+
+/*
+ * This thread does not allocate any resource, except within
+ * handle_message, within mutex protection. This mutex protects against
+ * fork and exit.
+ * The other moment it allocates resources is at socket connexion, which
+ * is also protected by the mutex.
+ */
+static
+void *ust_listener_thread(void *arg)
+{
+       struct sock_info *sock_info = arg;
+       int sock, ret, prev_connect_failed = 0, has_waited = 0;
+
+       /* Restart trying to connect to the session daemon */
+restart:
+       if (prev_connect_failed) {
+               /* Wait for sessiond availability with pipe */
+               wait_for_sessiond(sock_info);
+               if (has_waited) {
+                       has_waited = 0;
+                       /*
+                        * Sleep for 5 seconds before retrying after a
+                        * sequence of failure / wait / failure. This
+                        * deals with a killed or broken session daemon.
+                        */
+                       sleep(5);
+               }
+               has_waited = 1;
+               prev_connect_failed = 0;
+       }
+       ust_lock();
+
+       if (lttng_ust_comm_should_quit) {
+               ust_unlock();
+               goto quit;
+       }
+
+       if (sock_info->socket != -1) {
+               ret = close(sock_info->socket);
+               if (ret) {
+                       ERR("Error closing %s apps socket", sock_info->name);
+               }
+               sock_info->socket = -1;
+       }
+
+       /* Register */
+       ret = ustcomm_connect_unix_sock(sock_info->sock_path);
+       if (ret < 0) {
+               ERR("Error connecting to %s apps socket", sock_info->name);
+               prev_connect_failed = 1;
+               /*
+                * If we cannot find the sessiond daemon, don't delay
+                * constructor execution.
+                */
+               ret = handle_register_done(sock_info);
+               assert(!ret);
+               ust_unlock();
+               goto restart;
+       }
+
+       sock_info->socket = sock = ret;
+
+       /*
+        * Create only one root handle per listener thread for the whole
+        * process lifetime.
+        */
+       if (sock_info->root_handle == -1) {
+               ret = lttng_abi_create_root_handle();
+               if (ret < 0) {
+                       ERR("Error creating root handle");
+                       ust_unlock();
+                       goto quit;
+               }
+               sock_info->root_handle = ret;
+       }
+
+       ret = register_app_to_sessiond(sock);
+       if (ret < 0) {
+               ERR("Error registering to %s apps socket", sock_info->name);
+               prev_connect_failed = 1;
+               /*
+                * If we cannot register to the sessiond daemon, don't
+                * delay constructor execution.
+                */
+               ret = handle_register_done(sock_info);
+               assert(!ret);
+               ust_unlock();
+               goto restart;
+       }
+       ust_unlock();
+
+       for (;;) {
+               ssize_t len;
+               struct ustcomm_ust_msg lum;
+
+               len = ustcomm_recv_unix_sock(sock, &lum, sizeof(lum));
+               switch (len) {
+               case 0: /* orderly shutdown */
+                       DBG("%s ltt-sessiond has performed an orderly shutdown\n", sock_info->name);
+                       goto end;
+               case sizeof(lum):
+                       DBG("message received\n");
+                       ret = handle_message(sock_info, sock, &lum);
+                       if (ret < 0) {
+                               ERR("Error handling message for %s socket", sock_info->name);
+                       }
+                       continue;
+               case -1:
+                       if (errno == ECONNRESET) {
+                               ERR("%s remote end closed connection\n", sock_info->name);
+                               goto end;
+                       }
+                       goto end;
+               default:
+                       ERR("incorrect message size (%s socket): %zd\n", sock_info->name, len);
+                       continue;
+               }
+
+       }
+end:
+       goto restart;   /* try to reconnect */
+quit:
+       return NULL;
+}
+
+/*
+ * Return values: -1: don't wait. 0: wait forever. 1: timeout wait.
+ */
+static
+int get_timeout(struct timespec *constructor_timeout)
+{
+       long constructor_delay_ms = LTTNG_UST_DEFAULT_CONSTRUCTOR_TIMEOUT_MS;
+       char *str_delay;
+       int ret;
+
+       str_delay = getenv("LTTNG_UST_REGISTER_TIMEOUT");
+       if (str_delay) {
+               constructor_delay_ms = strtol(str_delay, NULL, 10);
+       }
+
+       switch (constructor_delay_ms) {
+       case -1:/* fall-through */
+       case 0:
+               return constructor_delay_ms;
+       default:
+               break;
+       }
+
+       /*
+        * If we are unable to find the current time, don't wait.
+        */
+       ret = clock_gettime(CLOCK_REALTIME, constructor_timeout);
+       if (ret) {
+               return -1;
+       }
+       constructor_timeout->tv_sec += constructor_delay_ms / 1000UL;
+       constructor_timeout->tv_nsec +=
+               (constructor_delay_ms % 1000UL) * 1000000UL;
+       if (constructor_timeout->tv_nsec >= 1000000000UL) {
+               constructor_timeout->tv_sec++;
+               constructor_timeout->tv_nsec -= 1000000000UL;
+       }
+       return 1;
+}
+
+/*
+ * sessiond monitoring thread: monitor presence of global and per-user
+ * sessiond by polling the application common named pipe.
+ */
+/* TODO */
+
+void __attribute__((constructor)) lttng_ust_init(void)
+{
+       struct timespec constructor_timeout;
+       int timeout_mode;
+       int ret;
+
+       if (uatomic_xchg(&initialized, 1) == 1)
+               return;
+
+       /*
+        * We want precise control over the order in which we construct
+        * our sub-libraries vs starting to receive commands from
+        * sessiond (otherwise leading to errors when trying to create
+        * sessiond before the init functions are completed).
+        */
+       init_usterr();
+       init_tracepoint();
+       ltt_ring_buffer_metadata_client_init();
+       ltt_ring_buffer_client_overwrite_init();
+       ltt_ring_buffer_client_discard_init();
+
+       timeout_mode = get_timeout(&constructor_timeout);
+
+       ret = sem_init(&constructor_wait, 0, 0);
+       assert(!ret);
+
+       ret = setup_local_apps();
+       if (ret) {
+               ERR("Error setting up to local apps");
+       }
+       ret = pthread_create(&local_apps.ust_listener, NULL,
+                       ust_listener_thread, &local_apps);
+
+       if (local_apps.allowed) {
+               ret = pthread_create(&global_apps.ust_listener, NULL,
+                               ust_listener_thread, &global_apps);
+       } else {
+               handle_register_done(&local_apps);
+       }
+
+       switch (timeout_mode) {
+       case 1: /* timeout wait */
+               do {
+                       ret = sem_timedwait(&constructor_wait,
+                                       &constructor_timeout);
+               } while (ret < 0 && errno == EINTR);
+               if (ret < 0 && errno == ETIMEDOUT) {
+                       ERR("Timed out waiting for ltt-sessiond");
+               } else {
+                       assert(!ret);
+               }
+               break;
+       case -1:/* wait forever */
+               do {
+                       ret = sem_wait(&constructor_wait);
+               } while (ret < 0 && errno == EINTR);
+               assert(!ret);
+               break;
+       case 0: /* no timeout */
+               break;
+       }
+}
+
+static
+void lttng_ust_cleanup(int exiting)
+{
+       cleanup_sock_info(&global_apps);
+       if (local_apps.allowed) {
+               cleanup_sock_info(&local_apps);
+       }
+       lttng_ust_abi_exit();
+       lttng_ust_events_exit();
+       ltt_ring_buffer_client_discard_exit();
+       ltt_ring_buffer_client_overwrite_exit();
+       ltt_ring_buffer_metadata_client_exit();
+       exit_tracepoint();
+       if (!exiting) {
+               /* Reinitialize values for fork */
+               sem_count = 2;
+               lttng_ust_comm_should_quit = 0;
+               initialized = 0;
+       }
+}
+
+void __attribute__((destructor)) lttng_ust_exit(void)
+{
+       int ret;
+
+       /*
+        * Using pthread_cancel here because:
+        * A) we don't want to hang application teardown.
+        * B) the thread is not allocating any resource.
+        */
+
+       /*
+        * Require the communication thread to quit. Synchronize with
+        * mutexes to ensure it is not in a mutex critical section when
+        * pthread_cancel is later called.
+        */
+       ust_lock();
+       lttng_ust_comm_should_quit = 1;
+       ust_unlock();
+
+       ret = pthread_cancel(global_apps.ust_listener);
+       if (ret) {
+               ERR("Error cancelling global ust listener thread");
+       }
+       if (local_apps.allowed) {
+               ret = pthread_cancel(local_apps.ust_listener);
+               if (ret) {
+                       ERR("Error cancelling local ust listener thread");
+               }
+       }
+       lttng_ust_cleanup(1);
+}
+
+/*
+ * We exclude the worker threads across fork and clone (except
+ * CLONE_VM), because these system calls only keep the forking thread
+ * running in the child.  Therefore, we don't want to call fork or clone
+ * in the middle of an tracepoint or ust tracing state modification.
+ * Holding this mutex protects these structures across fork and clone.
+ */
+void ust_before_fork(ust_fork_info_t *fork_info)
+{
+       /*
+        * Disable signals. This is to avoid that the child intervenes
+        * before it is properly setup for tracing. It is safer to
+        * disable all signals, because then we know we are not breaking
+        * anything by restoring the original mask.
+         */
+       sigset_t all_sigs;
+       int ret;
+
+       /* Disable signals */
+       sigfillset(&all_sigs);
+       ret = sigprocmask(SIG_BLOCK, &all_sigs, &fork_info->orig_sigs);
+       if (ret == -1) {
+               PERROR("sigprocmask");
+       }
+       ust_lock();
+       rcu_bp_before_fork();
+}
+
+static void ust_after_fork_common(ust_fork_info_t *fork_info)
+{
+       int ret;
+
+       DBG("process %d", getpid());
+       ust_unlock();
+       /* Restore signals */
+       ret = sigprocmask(SIG_SETMASK, &fork_info->orig_sigs, NULL);
+       if (ret == -1) {
+               PERROR("sigprocmask");
+       }
+}
+
+void ust_after_fork_parent(ust_fork_info_t *fork_info)
+{
+       DBG("process %d", getpid());
+       rcu_bp_after_fork_parent();
+       /* Release mutexes and reenable signals */
+       ust_after_fork_common(fork_info);
+}
+
+/*
+ * After fork, in the child, we need to cleanup all the leftover state,
+ * except the worker thread which already magically disappeared thanks
+ * to the weird Linux fork semantics. After tyding up, we call
+ * lttng_ust_init() again to start over as a new PID.
+ *
+ * This is meant for forks() that have tracing in the child between the
+ * fork and following exec call (if there is any).
+ */
+void ust_after_fork_child(ust_fork_info_t *fork_info)
+{
+       DBG("process %d", getpid());
+       /* Release urcu mutexes */
+       rcu_bp_after_fork_child();
+       lttng_ust_cleanup(0);
+       lttng_context_vtid_reset();
+       /* Release mutexes and reenable signals */
+       ust_after_fork_common(fork_info);
+       lttng_ust_init();
+}
diff --git a/liblttng-ust/probes/lttng-probe-ust.c b/liblttng-ust/probes/lttng-probe-ust.c
new file mode 100644 (file)
index 0000000..a5fba86
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * probes/lttng-probe-ust.c
+ *
+ * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * LTTng UST core probes.
+ *
+ * Dual LGPL v2.1/GPL v2 license.
+ */
+
+/*
+ * Create LTTng tracepoint probes.
+ */
+#define TRACEPOINT_CREATE_PROBES
+
+#include "lttng-probe-ust.h"
diff --git a/liblttng-ust/probes/lttng-probe-ust.h b/liblttng-ust/probes/lttng-probe-ust.h
new file mode 100644 (file)
index 0000000..3394d08
--- /dev/null
@@ -0,0 +1,51 @@
+#undef TRACEPOINT_SYSTEM
+#define TRACEPOINT_SYSTEM lttng_ust
+
+#if !defined(_TRACEPOINT_LTTNG_UST_H) || defined(TRACEPOINT_HEADER_MULTI_READ)
+#define _TRACEPOINT_LTTNG_UST_H
+
+/*
+ * Copyright (C) 2011  Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; version 2.1 of
+ * the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+#include <lttng/tracepoint.h>
+
+TRACEPOINT_EVENT(lttng_metadata,
+
+       TP_PROTO(const char *str),
+
+       TP_ARGS(str),
+
+       /*
+        * Not exactly a string: more a sequence of bytes (dynamic
+        * array) without the length. This is a dummy anyway: we only
+        * use this declaration to generate an event metadata entry.
+        */
+       TP_FIELDS(
+               ctf_string(str, str)
+       )
+)
+
+#undef TRACEPOINT_INCLUDE_PATH
+#define TRACEPOINT_INCLUDE_PATH ./probes
+#undef TRACEPOINT_INCLUDE_FILE
+#define TRACEPOINT_INCLUDE_FILE lttng-probe-ust
+
+#endif /* _TRACEPOINT_LTTNG_UST_H */
+
+/* This part must be outside protection */
+#include <lttng/tracepoint-event.h>
diff --git a/liblttng-ust/tracepoint.c b/liblttng-ust/tracepoint.c
new file mode 100644 (file)
index 0000000..8bf8752
--- /dev/null
@@ -0,0 +1,669 @@
+/*
+ * Copyright (C) 2008-2011 Mathieu Desnoyers
+ * Copyright (C) 2009 Pierre-Marc Fournier
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Ported to userspace by Pierre-Marc Fournier.
+ */
+
+#define _LGPL_SOURCE
+#include <errno.h>
+#include <lttng/tracepoint.h>
+#include <lttng/tracepoint-internal.h>
+#include <lttng/core.h>
+#include <lttng/kcompat/kcompat.h>
+#include <urcu-bp.h>
+#include <urcu/hlist.h>
+#include <urcu/uatomic.h>
+
+#include <lttng/usterr-signal-safe.h>
+#include "ltt-tracer-core.h"
+
+/* Set to 1 to enable tracepoint debug output */
+static const int tracepoint_debug;
+static int initialized;
+static void (*new_tracepoint_cb)(struct tracepoint *);
+
+/* libraries that contain tracepoints (struct tracepoint_lib) */
+static CDS_LIST_HEAD(libs);
+
+/*
+ * The UST lock protects the library tracepoints, the hash table, and
+ * the library list.
+ * All calls to the tracepoint API must be protected by the UST lock,
+ * excepts calls to tracepoint_register_lib and
+ * tracepoint_unregister_lib, which take the UST lock themselves.
+ */
+
+/*
+ * Tracepoint hash table, containing the active tracepoints.
+ * Protected by tracepoints_mutex.
+ */
+#define TRACEPOINT_HASH_BITS 6
+#define TRACEPOINT_TABLE_SIZE (1 << TRACEPOINT_HASH_BITS)
+static struct cds_hlist_head tracepoint_table[TRACEPOINT_TABLE_SIZE];
+
+static CDS_LIST_HEAD(old_probes);
+static int need_update;
+
+/*
+ * Note about RCU :
+ * It is used to to delay the free of multiple probes array until a quiescent
+ * state is reached.
+ * Tracepoint entries modifications are protected by the tracepoints_mutex.
+ */
+struct tracepoint_entry {
+       struct cds_hlist_node hlist;
+       struct tracepoint_probe *probes;
+       int refcount;   /* Number of times armed. 0 if disarmed. */
+       char name[0];
+};
+
+struct tp_probes {
+       union {
+               struct cds_list_head list;
+       } u;
+       struct tracepoint_probe probes[0];
+};
+
+static inline void *allocate_probes(int count)
+{
+       struct tp_probes *p  = zmalloc(count * sizeof(struct tracepoint_probe)
+                       + sizeof(struct tp_probes));
+       return p == NULL ? NULL : p->probes;
+}
+
+static inline void release_probes(void *old)
+{
+       if (old) {
+               struct tp_probes *tp_probes = _ust_container_of(old,
+                       struct tp_probes, probes[0]);
+               synchronize_rcu();
+               free(tp_probes);
+       }
+}
+
+static void debug_print_probes(struct tracepoint_entry *entry)
+{
+       int i;
+
+       if (!tracepoint_debug || !entry->probes)
+               return;
+
+       for (i = 0; entry->probes[i].func; i++)
+               DBG("Probe %d : %p", i, entry->probes[i].func);
+}
+
+static void *
+tracepoint_entry_add_probe(struct tracepoint_entry *entry,
+                          void *probe, void *data)
+{
+       int nr_probes = 0;
+       struct tracepoint_probe *old, *new;
+
+       WARN_ON(!probe);
+
+       debug_print_probes(entry);
+       old = entry->probes;
+       if (old) {
+               /* (N -> N+1), (N != 0, 1) probes */
+               for (nr_probes = 0; old[nr_probes].func; nr_probes++)
+                       if (old[nr_probes].func == probe &&
+                           old[nr_probes].data == data)
+                               return ERR_PTR(-EEXIST);
+       }
+       /* + 2 : one for new probe, one for NULL func */
+       new = allocate_probes(nr_probes + 2);
+       if (new == NULL)
+               return ERR_PTR(-ENOMEM);
+       if (old)
+               memcpy(new, old, nr_probes * sizeof(struct tracepoint_probe));
+       new[nr_probes].func = probe;
+       new[nr_probes].data = data;
+       new[nr_probes + 1].func = NULL;
+       entry->refcount = nr_probes + 1;
+       entry->probes = new;
+       debug_print_probes(entry);
+       return old;
+}
+
+static void *
+tracepoint_entry_remove_probe(struct tracepoint_entry *entry, void *probe,
+                             void *data)
+{
+       int nr_probes = 0, nr_del = 0, i;
+       struct tracepoint_probe *old, *new;
+
+       old = entry->probes;
+
+       if (!old)
+               return ERR_PTR(-ENOENT);
+
+       debug_print_probes(entry);
+       /* (N -> M), (N > 1, M >= 0) probes */
+       for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
+               if (!probe ||
+                    (old[nr_probes].func == probe &&
+                    old[nr_probes].data == data))
+                       nr_del++;
+       }
+
+       if (nr_probes - nr_del == 0) {
+               /* N -> 0, (N > 1) */
+               entry->probes = NULL;
+               entry->refcount = 0;
+               debug_print_probes(entry);
+               return old;
+       } else {
+               int j = 0;
+               /* N -> M, (N > 1, M > 0) */
+               /* + 1 for NULL */
+               new = allocate_probes(nr_probes - nr_del + 1);
+               if (new == NULL)
+                       return ERR_PTR(-ENOMEM);
+               for (i = 0; old[i].func; i++)
+                       if (probe &&
+                           (old[i].func != probe || old[i].data != data))
+                               new[j++] = old[i];
+               new[nr_probes - nr_del].func = NULL;
+               entry->refcount = nr_probes - nr_del;
+               entry->probes = new;
+       }
+       debug_print_probes(entry);
+       return old;
+}
+
+/*
+ * Get tracepoint if the tracepoint is present in the tracepoint hash table.
+ * Must be called with tracepoints_mutex held.
+ * Returns NULL if not present.
+ */
+static struct tracepoint_entry *get_tracepoint(const char *name)
+{
+       struct cds_hlist_head *head;
+       struct cds_hlist_node *node;
+       struct tracepoint_entry *e;
+       u32 hash = jhash(name, strlen(name), 0);
+
+       head = &tracepoint_table[hash & (TRACEPOINT_TABLE_SIZE - 1)];
+       cds_hlist_for_each_entry(e, node, head, hlist) {
+               if (!strcmp(name, e->name))
+                       return e;
+       }
+       return NULL;
+}
+
+/*
+ * Add the tracepoint to the tracepoint hash table. Must be called with
+ * tracepoints_mutex held.
+ */
+static struct tracepoint_entry *add_tracepoint(const char *name)
+{
+       struct cds_hlist_head *head;
+       struct cds_hlist_node *node;
+       struct tracepoint_entry *e;
+       size_t name_len = strlen(name) + 1;
+       u32 hash = jhash(name, name_len-1, 0);
+
+       head = &tracepoint_table[hash & (TRACEPOINT_TABLE_SIZE - 1)];
+       cds_hlist_for_each_entry(e, node, head, hlist) {
+               if (!strcmp(name, e->name)) {
+                       DBG("tracepoint %s busy", name);
+                       return ERR_PTR(-EEXIST);        /* Already there */
+               }
+       }
+       /*
+        * Using zmalloc here to allocate a variable length element. Could
+        * cause some memory fragmentation if overused.
+        */
+       e = zmalloc(sizeof(struct tracepoint_entry) + name_len);
+       if (!e)
+               return ERR_PTR(-ENOMEM);
+       memcpy(&e->name[0], name, name_len);
+       e->probes = NULL;
+       e->refcount = 0;
+       cds_hlist_add_head(&e->hlist, head);
+       return e;
+}
+
+/*
+ * Remove the tracepoint from the tracepoint hash table. Must be called with
+ * ust_lock held.
+ */
+static inline void remove_tracepoint(struct tracepoint_entry *e)
+{
+       cds_hlist_del(&e->hlist);
+       free(e);
+}
+
+/*
+ * Sets the probe callback corresponding to one tracepoint.
+ */
+static void set_tracepoint(struct tracepoint_entry **entry,
+       struct tracepoint *elem, int active)
+{
+       WARN_ON(strcmp((*entry)->name, elem->name) != 0);
+
+       /*
+        * rcu_assign_pointer has a cmm_smp_wmb() which makes sure that the new
+        * probe callbacks array is consistent before setting a pointer to it.
+        * This array is referenced by __DO_TRACE from
+        * include/linux/tracepoints.h. A matching cmm_smp_read_barrier_depends()
+        * is used.
+        */
+       rcu_assign_pointer(elem->probes, (*entry)->probes);
+       elem->state = active;
+}
+
+/*
+ * Disable a tracepoint and its probe callback.
+ * Note: only waiting an RCU period after setting elem->call to the empty
+ * function insures that the original callback is not used anymore. This insured
+ * by preempt_disable around the call site.
+ */
+static void disable_tracepoint(struct tracepoint *elem)
+{
+       elem->state = 0;
+       rcu_assign_pointer(elem->probes, NULL);
+}
+
+/**
+ * tracepoint_update_probe_range - Update a probe range
+ * @begin: beginning of the range
+ * @end: end of the range
+ *
+ * Updates the probe callback corresponding to a range of tracepoints.
+ */
+static
+void tracepoint_update_probe_range(struct tracepoint * const *begin,
+                                  struct tracepoint * const *end)
+{
+       struct tracepoint * const *iter;
+       struct tracepoint_entry *mark_entry;
+
+       for (iter = begin; iter < end; iter++) {
+               if (!*iter)
+                       continue;       /* skip dummy */
+               if (!(*iter)->name) {
+                       disable_tracepoint(*iter);
+                       continue;
+               }
+               mark_entry = get_tracepoint((*iter)->name);
+               if (mark_entry) {
+                       set_tracepoint(&mark_entry, *iter,
+                                       !!mark_entry->refcount);
+               } else {
+                       disable_tracepoint(*iter);
+               }
+       }
+}
+
+static void lib_update_tracepoints(void)
+{
+       struct tracepoint_lib *lib;
+
+       cds_list_for_each_entry(lib, &libs, list) {
+               tracepoint_update_probe_range(lib->tracepoints_start,
+                               lib->tracepoints_start + lib->tracepoints_count);
+       }
+}
+
+/*
+ * Update probes, removing the faulty probes.
+ */
+static void tracepoint_update_probes(void)
+{
+       /* tracepoints registered from libraries and executable. */
+       lib_update_tracepoints();
+}
+
+static struct tracepoint_probe *
+tracepoint_add_probe(const char *name, void *probe, void *data)
+{
+       struct tracepoint_entry *entry;
+       struct tracepoint_probe *old;
+
+       entry = get_tracepoint(name);
+       if (!entry) {
+               entry = add_tracepoint(name);
+               if (IS_ERR(entry))
+                       return (struct tracepoint_probe *)entry;
+       }
+       old = tracepoint_entry_add_probe(entry, probe, data);
+       if (IS_ERR(old) && !entry->refcount)
+               remove_tracepoint(entry);
+       return old;
+}
+
+/**
+ * __tracepoint_probe_register -  Connect a probe to a tracepoint
+ * @name: tracepoint name
+ * @probe: probe handler
+ *
+ * Returns 0 if ok, error value on error.
+ * The probe address must at least be aligned on the architecture pointer size.
+ * Called with the UST lock held.
+ */
+int __tracepoint_probe_register(const char *name, void *probe, void *data)
+{
+       void *old;
+
+       old = tracepoint_add_probe(name, probe, data);
+       if (IS_ERR(old))
+               return PTR_ERR(old);
+
+       tracepoint_update_probes();             /* may update entry */
+       release_probes(old);
+       return 0;
+}
+
+static void *tracepoint_remove_probe(const char *name, void *probe, void *data)
+{
+       struct tracepoint_entry *entry;
+       void *old;
+
+       entry = get_tracepoint(name);
+       if (!entry)
+               return ERR_PTR(-ENOENT);
+       old = tracepoint_entry_remove_probe(entry, probe, data);
+       if (IS_ERR(old))
+               return old;
+       if (!entry->refcount)
+               remove_tracepoint(entry);
+       return old;
+}
+
+/**
+ * tracepoint_probe_unregister -  Disconnect a probe from a tracepoint
+ * @name: tracepoint name
+ * @probe: probe function pointer
+ * @probe: probe data pointer
+ *
+ * Called with the UST lock held.
+ */
+int __tracepoint_probe_unregister(const char *name, void *probe, void *data)
+{
+       void *old;
+
+       old = tracepoint_remove_probe(name, probe, data);
+       if (IS_ERR(old))
+               return PTR_ERR(old);
+
+       tracepoint_update_probes();             /* may update entry */
+       release_probes(old);
+       return 0;
+}
+
+static void tracepoint_add_old_probes(void *old)
+{
+       need_update = 1;
+       if (old) {
+               struct tp_probes *tp_probes = _ust_container_of(old,
+                       struct tp_probes, probes[0]);
+               cds_list_add(&tp_probes->u.list, &old_probes);
+       }
+}
+
+/**
+ * tracepoint_probe_register_noupdate -  register a probe but not connect
+ * @name: tracepoint name
+ * @probe: probe handler
+ *
+ * caller must call tracepoint_probe_update_all()
+ * Called with the UST lock held.
+ */
+int tracepoint_probe_register_noupdate(const char *name, void *probe,
+                                      void *data)
+{
+       void *old;
+
+       old = tracepoint_add_probe(name, probe, data);
+       if (IS_ERR(old)) {
+               return PTR_ERR(old);
+       }
+       tracepoint_add_old_probes(old);
+       return 0;
+}
+
+/**
+ * tracepoint_probe_unregister_noupdate -  remove a probe but not disconnect
+ * @name: tracepoint name
+ * @probe: probe function pointer
+ *
+ * caller must call tracepoint_probe_update_all()
+ * Called with the UST lock held.
+ */
+int tracepoint_probe_unregister_noupdate(const char *name, void *probe,
+                                        void *data)
+{
+       void *old;
+
+       old = tracepoint_remove_probe(name, probe, data);
+       if (IS_ERR(old)) {
+               return PTR_ERR(old);
+       }
+       tracepoint_add_old_probes(old);
+       return 0;
+}
+
+/**
+ * tracepoint_probe_update_all -  update tracepoints
+ * Called with the UST lock held.
+ */
+void tracepoint_probe_update_all(void)
+{
+       CDS_LIST_HEAD(release_probes);
+       struct tp_probes *pos, *next;
+
+       if (!need_update) {
+               return;
+       }
+       if (!cds_list_empty(&old_probes))
+               cds_list_replace_init(&old_probes, &release_probes);
+       need_update = 0;
+
+       tracepoint_update_probes();
+       cds_list_for_each_entry_safe(pos, next, &release_probes, u.list) {
+               cds_list_del(&pos->u.list);
+               synchronize_rcu();
+               free(pos);
+       }
+}
+
+/*
+ * Returns 0 if current not found.
+ * Returns 1 if current found.
+ *
+ * Called with tracepoint mutex held
+ */
+int lib_get_iter_tracepoints(struct tracepoint_iter *iter)
+{
+       struct tracepoint_lib *iter_lib;
+       int found = 0;
+
+       cds_list_for_each_entry(iter_lib, &libs, list) {
+               if (iter_lib < iter->lib)
+                       continue;
+               else if (iter_lib > iter->lib)
+                       iter->tracepoint = NULL;
+               found = tracepoint_get_iter_range(&iter->tracepoint,
+                       iter_lib->tracepoints_start,
+                       iter_lib->tracepoints_start + iter_lib->tracepoints_count);
+               if (found) {
+                       iter->lib = iter_lib;
+                       break;
+               }
+       }
+       return found;
+}
+
+/**
+ * tracepoint_get_iter_range - Get a next tracepoint iterator given a range.
+ * @tracepoint: current tracepoints (in), next tracepoint (out)
+ * @begin: beginning of the range
+ * @end: end of the range
+ *
+ * Returns whether a next tracepoint has been found (1) or not (0).
+ * Will return the first tracepoint in the range if the input tracepoint is
+ * NULL.
+ * Called with tracepoint mutex held.
+ */
+int tracepoint_get_iter_range(struct tracepoint * const **tracepoint,
+       struct tracepoint * const *begin, struct tracepoint * const *end)
+{
+       if (!*tracepoint && begin != end)
+               *tracepoint = begin;
+       while (*tracepoint >= begin && *tracepoint < end) {
+               if (!**tracepoint)
+                       (*tracepoint)++;        /* skip dummy */
+               else
+                       return 1;
+       }
+       return 0;
+}
+
+/*
+ * Called with tracepoint mutex held.
+ */
+static void tracepoint_get_iter(struct tracepoint_iter *iter)
+{
+       int found = 0;
+
+       /* tracepoints in libs. */
+       found = lib_get_iter_tracepoints(iter);
+       if (!found)
+               tracepoint_iter_reset(iter);
+}
+
+/*
+ * Called with UST lock held.
+ */
+void tracepoint_iter_start(struct tracepoint_iter *iter)
+{
+       tracepoint_get_iter(iter);
+}
+
+/*
+ * Called with UST lock held.
+ */
+void tracepoint_iter_next(struct tracepoint_iter *iter)
+{
+       iter->tracepoint++;
+       /*
+        * iter->tracepoint may be invalid because we blindly incremented it.
+        * Make sure it is valid by marshalling on the tracepoints, getting the
+        * tracepoints from following modules if necessary.
+        */
+       tracepoint_get_iter(iter);
+}
+
+/*
+ * Called with UST lock held.
+ */
+void tracepoint_iter_stop(struct tracepoint_iter *iter)
+{
+}
+
+void tracepoint_iter_reset(struct tracepoint_iter *iter)
+{
+       iter->tracepoint = NULL;
+}
+
+void tracepoint_set_new_tracepoint_cb(void (*cb)(struct tracepoint *))
+{
+       new_tracepoint_cb = cb;
+}
+
+static void new_tracepoints(struct tracepoint * const *start, struct tracepoint * const *end)
+{
+       if (new_tracepoint_cb) {
+               struct tracepoint * const *t;
+
+               for (t = start; t < end; t++) {
+                       if (*t)
+                               new_tracepoint_cb(*t);
+               }
+       }
+}
+
+int tracepoint_register_lib(struct tracepoint * const *tracepoints_start,
+                           int tracepoints_count)
+{
+       struct tracepoint_lib *pl, *iter;
+
+       init_tracepoint();
+
+       pl = (struct tracepoint_lib *) zmalloc(sizeof(struct tracepoint_lib));
+
+       pl->tracepoints_start = tracepoints_start;
+       pl->tracepoints_count = tracepoints_count;
+
+       ust_lock();
+       /*
+        * We sort the libs by struct lib pointer address.
+        */
+       cds_list_for_each_entry_reverse(iter, &libs, list) {
+               BUG_ON(iter == pl);    /* Should never be in the list twice */
+               if (iter < pl) {
+                       /* We belong to the location right after iter. */
+                       cds_list_add(&pl->list, &iter->list);
+                       goto lib_added;
+               }
+       }
+       /* We should be added at the head of the list */
+       cds_list_add(&pl->list, &libs);
+lib_added:
+       new_tracepoints(tracepoints_start, tracepoints_start + tracepoints_count);
+
+       /* TODO: update just the loaded lib */
+       lib_update_tracepoints();
+       ust_unlock();
+
+       DBG("just registered a tracepoints section from %p and having %d tracepoints",
+               tracepoints_start, tracepoints_count);
+
+       return 0;
+}
+
+int tracepoint_unregister_lib(struct tracepoint * const *tracepoints_start)
+{
+       struct tracepoint_lib *lib;
+
+       ust_lock();
+       cds_list_for_each_entry(lib, &libs, list) {
+               if (lib->tracepoints_start == tracepoints_start) {
+                       struct tracepoint_lib *lib2free = lib;
+                       cds_list_del(&lib->list);
+                       free(lib2free);
+                       break;
+               }
+       }
+       ust_unlock();
+
+       return 0;
+}
+
+void init_tracepoint(void)
+{
+       if (uatomic_xchg(&initialized, 1) == 1)
+               return;
+       init_usterr();
+}
+
+void exit_tracepoint(void)
+{
+       initialized = 0;
+}
diff --git a/liblttng-ust/ust-core.c b/liblttng-ust/ust-core.c
new file mode 100644 (file)
index 0000000..404e0b2
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * ust-core.c
+ *
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; only
+ * version 2.1 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <lttng/usterr-signal-safe.h>
+#include <stdlib.h>
+
+volatile enum ust_loglevel ust_loglevel;
+
+void init_usterr(void)
+{
+       char *ust_debug;
+
+       if (ust_loglevel == UST_LOGLEVEL_UNKNOWN) {
+               ust_debug = getenv("LTTNG_UST_DEBUG");
+               if (ust_debug)
+                       ust_loglevel = UST_LOGLEVEL_DEBUG;
+               else
+                       ust_loglevel = UST_LOGLEVEL_NORMAL;
+       }
+}
diff --git a/libust/Makefile.am b/libust/Makefile.am
deleted file mode 100644 (file)
index 9295d6b..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-AM_CPPFLAGS = -I$(top_srcdir)/include
-AM_CFLAGS = -fno-strict-aliasing
-
-lib_LTLIBRARIES = libust.la
-
-libust_la_SOURCES = \
-       tracepoint.c \
-       ltt-tracer.h \
-       ltt-tracer-core.h \
-       ltt-ring-buffer-client.h \
-       ltt-ring-buffer-client-discard.c \
-       ltt-ring-buffer-client-overwrite.c \
-       ltt-ring-buffer-metadata-client.h \
-       ltt-ring-buffer-metadata-client.c \
-       ltt-events.c \
-       ltt-probes.c \
-       lttng-ust-abi.c \
-       lttng-ust-comm.c \
-       ust-core.c \
-       probes/lttng-probe-ust.c \
-       probes/lttng-probe-ust.h \
-       lttng-context-vtid.c \
-       lttng-context-vpid.c \
-       lttng-context-pthread-id.c \
-       lttng-context-procname.c \
-       ltt-context.c
-
-libust_la_LDFLAGS = -no-undefined -version-info 0:0:0
-
-libust_la_LIBADD = \
-       -lpthread \
-       -lrt \
-       -luuid \
-       $(top_builddir)/snprintf/libustsnprintf.la \
-       $(top_builddir)/libringbuffer/libringbuffer.la \
-       $(top_builddir)/liblttng-ust-comm/liblttng-ust-comm.la
-
-libust_la_CFLAGS = -DUST_COMPONENT="libust" -fno-strict-aliasing
diff --git a/libust/ltt-context.c b/libust/ltt-context.c
deleted file mode 100644 (file)
index 90747a5..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * ltt-context.c
- *
- * Copyright 2011 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * LTTng UST trace/channel/event context management.
- *
- * Dual LGPL v2.1/GPL v2 license.
- */
-
-#include <lttng/ust-events.h>
-#include <lttng/ust-tracer.h>
-#include <lttng/core.h>
-#include <string.h>
-#include <assert.h>
-
-int lttng_find_context(struct lttng_ctx *ctx, const char *name)
-{
-       unsigned int i;
-
-       for (i = 0; i < ctx->nr_fields; i++) {
-               /* Skip allocated (but non-initialized) contexts */
-               if (!ctx->fields[i].event_field.name)
-                       continue;
-               if (!strcmp(ctx->fields[i].event_field.name, name))
-                       return 1;
-       }
-       return 0;
-}
-
-/*
- * Note: as we append context information, the pointer location may change.
- */
-struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p)
-{
-       struct lttng_ctx_field *field;
-       struct lttng_ctx *ctx;
-
-       if (!*ctx_p) {
-               *ctx_p = zmalloc(sizeof(struct lttng_ctx));
-               if (!*ctx_p)
-                       return NULL;
-       }
-       ctx = *ctx_p;
-       if (ctx->nr_fields + 1 > ctx->allocated_fields) {
-               struct lttng_ctx_field *new_fields;
-
-               ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields);
-               new_fields = zmalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field));
-               if (!new_fields)
-                       return NULL;
-               if (ctx->fields)
-                       memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields);
-               free(ctx->fields);
-               ctx->fields = new_fields;
-       }
-       field = &ctx->fields[ctx->nr_fields];
-       ctx->nr_fields++;
-       return field;
-}
-
-/*
- * Remove last context field.
- */
-void lttng_remove_context_field(struct lttng_ctx **ctx_p,
-                               struct lttng_ctx_field *field)
-{
-       struct lttng_ctx *ctx;
-
-       ctx = *ctx_p;
-       ctx->nr_fields--;
-       assert(&ctx->fields[ctx->nr_fields] == field);
-       memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field));
-}
-
-void lttng_destroy_context(struct lttng_ctx *ctx)
-{
-       int i;
-
-       if (!ctx)
-               return;
-       for (i = 0; i < ctx->nr_fields; i++) {
-               if (ctx->fields[i].destroy)
-                       ctx->fields[i].destroy(&ctx->fields[i]);
-       }
-       free(ctx->fields);
-       free(ctx);
-}
diff --git a/libust/ltt-events.c b/libust/ltt-events.c
deleted file mode 100644 (file)
index 68531bc..0000000
+++ /dev/null
@@ -1,1010 +0,0 @@
-/*
- * ltt-events.c
- *
- * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * Holds LTTng per-session event registry.
- *
- * Dual LGPL v2.1/GPL v2 license.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <endian.h>
-#include <urcu/list.h>
-#include <urcu/hlist.h>
-#include <pthread.h>
-#include <urcu-bp.h>
-#include <urcu/compiler.h>
-#include <urcu/uatomic.h>
-#include <uuid/uuid.h>
-#include <lttng/tracepoint.h>
-#include <errno.h>
-#include <sys/shm.h>
-#include <sys/ipc.h>
-#include <lttng/ust-events.h>
-#include <lttng/usterr-signal-safe.h>
-#include "lttng/core.h"
-#include "ltt-tracer.h"
-#include "ltt-tracer-core.h"
-#include "lttng/wait.h"
-#include "../libringbuffer/shm.h"
-
-typedef u32 uint32_t;
-#include <lttng/kcompat/jhash.h>
-
-/*
- * The sessions mutex is the centralized mutex across UST tracing
- * control and probe registration. All operations within this file are
- * called by the communication thread, under ust_lock protection.
- */
-static DEFINE_MUTEX(sessions_mutex);
-
-void ust_lock(void)
-{
-       pthread_mutex_lock(&sessions_mutex);
-}
-
-void ust_unlock(void)
-{
-       pthread_mutex_unlock(&sessions_mutex);
-}
-
-static CDS_LIST_HEAD(sessions);
-static CDS_LIST_HEAD(ltt_transport_list);
-
-/*
- * Pending probes hash table, containing the registered ltt events for
- * which tracepoint probes are still missing. Protected by the sessions
- * mutex.
- */
-#define PENDING_PROBE_HASH_BITS                6
-#define PENDING_PROBE_HASH_SIZE                (1 << PENDING_PROBE_HASH_BITS)
-static struct cds_hlist_head pending_probe_table[PENDING_PROBE_HASH_SIZE];
-
-struct ust_pending_probe {
-       struct ltt_event *event;
-       struct cds_hlist_node node;
-       char name[];
-};
-
-static void _ltt_event_destroy(struct ltt_event *event);
-static void _ltt_channel_destroy(struct ltt_channel *chan);
-static int _ltt_event_unregister(struct ltt_event *event);
-static
-int _ltt_event_metadata_statedump(struct ltt_session *session,
-                                 struct ltt_channel *chan,
-                                 struct ltt_event *event);
-static
-int _ltt_session_metadata_statedump(struct ltt_session *session);
-
-/*
- * called at event creation if probe is missing.
- * called with session mutex held.
- */
-static
-int add_pending_probe(struct ltt_event *event, const char *name)
-{
-       struct cds_hlist_head *head;
-       struct ust_pending_probe *e;
-       size_t name_len = strlen(name) + 1;
-       u32 hash = jhash(name, name_len - 1, 0);
-
-       head = &pending_probe_table[hash & (PENDING_PROBE_HASH_SIZE - 1)];
-       e = zmalloc(sizeof(struct ust_pending_probe) + name_len);
-       if (!e)
-               return -ENOMEM;
-       memcpy(&e->name[0], name, name_len);
-       cds_hlist_add_head(&e->node, head);
-       e->event = event;
-       event->pending_probe = e;
-       return 0;
-}
-
-/*
- * remove a pending probe. called when at event teardown and when an
- * event is fixed (probe is loaded).
- * called with session mutex held.
- */
-static
-void remove_pending_probe(struct ust_pending_probe *e)
-{
-       if (!e)
-               return;
-       cds_hlist_del(&e->node);
-       free(e);
-}
-
-/*
- * Called at library load: connect the probe on the events pending on
- * probe load.
- * called with session mutex held.
- */
-int pending_probe_fix_events(const struct lttng_event_desc *desc)
-{
-       struct cds_hlist_head *head;
-       struct cds_hlist_node *node, *p;
-       struct ust_pending_probe *e;
-       const char *name = desc->name;
-       size_t name_len = strlen(name) + 1;
-       u32 hash = jhash(name, name_len - 1, 0);
-       int ret = 0;
-
-       head = &pending_probe_table[hash & (PENDING_PROBE_HASH_SIZE - 1)];
-       cds_hlist_for_each_entry_safe(e, node, p, head, node) {
-               struct ltt_event *event;
-               struct ltt_channel *chan;
-
-               if (strcmp(name, e->name))
-                       continue;
-               event = e->event;
-               chan = event->chan;
-               assert(!event->desc);
-               event->desc = desc;
-               event->pending_probe = NULL;
-               remove_pending_probe(e);
-               ret |= __tracepoint_probe_register(name,
-                               event->desc->probe_callback,
-                               event);
-               if (ret)
-                       continue;
-               event->id = chan->free_event_id++;
-               ret |= _ltt_event_metadata_statedump(chan->session, chan,
-                               event);
-       }
-       return ret;
-}
-
-void synchronize_trace(void)
-{
-       synchronize_rcu();
-}
-
-struct ltt_session *ltt_session_create(void)
-{
-       struct ltt_session *session;
-
-       session = zmalloc(sizeof(struct ltt_session));
-       if (!session)
-               return NULL;
-       CDS_INIT_LIST_HEAD(&session->chan);
-       CDS_INIT_LIST_HEAD(&session->events);
-       uuid_generate(session->uuid);
-       cds_list_add(&session->list, &sessions);
-       return session;
-}
-
-void ltt_session_destroy(struct ltt_session *session)
-{
-       struct ltt_channel *chan, *tmpchan;
-       struct ltt_event *event, *tmpevent;
-       int ret;
-
-       CMM_ACCESS_ONCE(session->active) = 0;
-       cds_list_for_each_entry(event, &session->events, list) {
-               ret = _ltt_event_unregister(event);
-               WARN_ON(ret);
-       }
-       synchronize_trace();    /* Wait for in-flight events to complete */
-       cds_list_for_each_entry_safe(event, tmpevent, &session->events, list)
-               _ltt_event_destroy(event);
-       cds_list_for_each_entry_safe(chan, tmpchan, &session->chan, list)
-               _ltt_channel_destroy(chan);
-       cds_list_del(&session->list);
-       free(session);
-}
-
-int ltt_session_enable(struct ltt_session *session)
-{
-       int ret = 0;
-       struct ltt_channel *chan;
-
-       if (session->active) {
-               ret = -EBUSY;
-               goto end;
-       }
-
-       /*
-        * Snapshot the number of events per channel to know the type of header
-        * we need to use.
-        */
-       cds_list_for_each_entry(chan, &session->chan, list) {
-               if (chan->header_type)
-                       continue;               /* don't change it if session stop/restart */
-               if (chan->free_event_id < 31)
-                       chan->header_type = 1;  /* compact */
-               else
-                       chan->header_type = 2;  /* large */
-       }
-
-       CMM_ACCESS_ONCE(session->active) = 1;
-       CMM_ACCESS_ONCE(session->been_active) = 1;
-       ret = _ltt_session_metadata_statedump(session);
-       if (ret)
-               CMM_ACCESS_ONCE(session->active) = 0;
-end:
-       return ret;
-}
-
-int ltt_session_disable(struct ltt_session *session)
-{
-       int ret = 0;
-
-       if (!session->active) {
-               ret = -EBUSY;
-               goto end;
-       }
-       CMM_ACCESS_ONCE(session->active) = 0;
-end:
-       return ret;
-}
-
-int ltt_channel_enable(struct ltt_channel *channel)
-{
-       int old;
-
-       if (channel == channel->session->metadata)
-               return -EPERM;
-       old = uatomic_xchg(&channel->enabled, 1);
-       if (old)
-               return -EEXIST;
-       return 0;
-}
-
-int ltt_channel_disable(struct ltt_channel *channel)
-{
-       int old;
-
-       if (channel == channel->session->metadata)
-               return -EPERM;
-       old = uatomic_xchg(&channel->enabled, 0);
-       if (!old)
-               return -EEXIST;
-       return 0;
-}
-
-int ltt_event_enable(struct ltt_event *event)
-{
-       int old;
-
-       if (event->chan == event->chan->session->metadata)
-               return -EPERM;
-       old = uatomic_xchg(&event->enabled, 1);
-       if (old)
-               return -EEXIST;
-       return 0;
-}
-
-int ltt_event_disable(struct ltt_event *event)
-{
-       int old;
-
-       if (event->chan == event->chan->session->metadata)
-               return -EPERM;
-       old = uatomic_xchg(&event->enabled, 0);
-       if (!old)
-               return -EEXIST;
-       return 0;
-}
-
-static struct ltt_transport *ltt_transport_find(const char *name)
-{
-       struct ltt_transport *transport;
-
-       cds_list_for_each_entry(transport, &ltt_transport_list, node) {
-               if (!strcmp(transport->name, name))
-                       return transport;
-       }
-       return NULL;
-}
-
-struct ltt_channel *ltt_channel_create(struct ltt_session *session,
-                                      const char *transport_name,
-                                      void *buf_addr,
-                                      size_t subbuf_size, size_t num_subbuf,
-                                      unsigned int switch_timer_interval,
-                                      unsigned int read_timer_interval,
-                                      int *shm_fd, int *wait_fd,
-                                      uint64_t *memory_map_size)
-{
-       struct ltt_channel *chan;
-       struct ltt_transport *transport;
-
-       if (session->been_active)
-               goto active;    /* Refuse to add channel to active session */
-       transport = ltt_transport_find(transport_name);
-       if (!transport) {
-               DBG("LTTng transport %s not found\n",
-                      transport_name);
-               goto notransport;
-       }
-       chan = zmalloc(sizeof(struct ltt_channel));
-       if (!chan)
-               goto nomem;
-       chan->session = session;
-       chan->id = session->free_chan_id++;
-       /*
-        * Note: the channel creation op already writes into the packet
-        * headers. Therefore the "chan" information used as input
-        * should be already accessible.
-        */
-       transport->ops.channel_create("[lttng]", chan, buf_addr,
-                       subbuf_size, num_subbuf, switch_timer_interval,
-                       read_timer_interval, shm_fd, wait_fd,
-                       memory_map_size);
-       if (!chan->chan)
-               goto create_error;
-       chan->enabled = 1;
-       chan->ops = &transport->ops;
-       cds_list_add(&chan->list, &session->chan);
-       return chan;
-
-create_error:
-       free(chan);
-nomem:
-notransport:
-active:
-       return NULL;
-}
-
-/*
- * Only used internally at session destruction.
- */
-static
-void _ltt_channel_destroy(struct ltt_channel *chan)
-{
-       chan->ops->channel_destroy(chan);
-       cds_list_del(&chan->list);
-       lttng_destroy_context(chan->ctx);
-       free(chan);
-}
-
-/*
- * Supports event creation while tracing session is active.
- */
-struct ltt_event *ltt_event_create(struct ltt_channel *chan,
-                                  struct lttng_ust_event *event_param,
-                                  void *filter)
-{
-       struct ltt_event *event;
-       int ret;
-
-       if (chan->used_event_id == -1UL)
-               goto full;
-       /*
-        * This is O(n^2) (for each event, the loop is called at event
-        * creation). Might require a hash if we have lots of events.
-        */
-       cds_list_for_each_entry(event, &chan->session->events, list)
-               if (event->desc && !strcmp(event->desc->name, event_param->name))
-                       goto exist;
-       event = zmalloc(sizeof(struct ltt_event));
-       if (!event)
-               goto cache_error;
-       event->chan = chan;
-       event->filter = filter;
-       /*
-        * used_event_id counts the maximum number of event IDs that can
-        * register if all probes register.
-        */
-       chan->used_event_id++;
-       event->enabled = 1;
-       event->instrumentation = event_param->instrumentation;
-       /* Populate ltt_event structure before tracepoint registration. */
-       cmm_smp_wmb();
-       switch (event_param->instrumentation) {
-       case LTTNG_UST_TRACEPOINT:
-               event->desc = ltt_event_get(event_param->name);
-               if (event->desc) {
-                       ret = __tracepoint_probe_register(event_param->name,
-                                       event->desc->probe_callback,
-                                       event);
-                       if (ret)
-                               goto register_error;
-                       event->id = chan->free_event_id++;
-               } else {
-                       /*
-                        * If the probe is not present, event->desc stays NULL,
-                        * waiting for the probe to register, and the event->id
-                        * stays unallocated.
-                        */
-                       ret = add_pending_probe(event, event_param->name);
-                       if (ret)
-                               goto add_pending_error;
-               }
-               break;
-       default:
-               WARN_ON_ONCE(1);
-       }
-       if (event->desc) {
-               ret = _ltt_event_metadata_statedump(chan->session, chan, event);
-               if (ret)
-                       goto statedump_error;
-       }
-       cds_list_add(&event->list, &chan->session->events);
-       return event;
-
-statedump_error:
-       if (event->desc) {
-               WARN_ON_ONCE(__tracepoint_probe_unregister(event_param->name,
-                                       event->desc->probe_callback,
-                                       event));
-               ltt_event_put(event->desc);
-       }
-add_pending_error:
-register_error:
-       free(event);
-cache_error:
-exist:
-full:
-       return NULL;
-}
-
-/*
- * Only used internally at session destruction.
- */
-int _ltt_event_unregister(struct ltt_event *event)
-{
-       int ret = -EINVAL;
-
-       switch (event->instrumentation) {
-       case LTTNG_UST_TRACEPOINT:
-               if (event->desc) {
-                       ret = __tracepoint_probe_unregister(event->desc->name,
-                                                         event->desc->probe_callback,
-                                                         event);
-                       if (ret)
-                               return ret;
-               } else {
-                       remove_pending_probe(event->pending_probe);
-                       ret = 0;
-               }
-               break;
-       default:
-               WARN_ON_ONCE(1);
-       }
-       return ret;
-}
-
-/*
- * Only used internally at session destruction.
- */
-static
-void _ltt_event_destroy(struct ltt_event *event)
-{
-       switch (event->instrumentation) {
-       case LTTNG_UST_TRACEPOINT:
-               if (event->desc) {
-                       ltt_event_put(event->desc);
-               }
-               break;
-       default:
-               WARN_ON_ONCE(1);
-       }
-       cds_list_del(&event->list);
-       lttng_destroy_context(event->ctx);
-       free(event);
-}
-
-/*
- * We have exclusive access to our metadata buffer (protected by the
- * ust_lock), so we can do racy operations such as looking for
- * remaining space left in packet and write, since mutual exclusion
- * protects us from concurrent writes.
- */
-int lttng_metadata_printf(struct ltt_session *session,
-                         const char *fmt, ...)
-{
-       struct lttng_ust_lib_ring_buffer_ctx ctx;
-       struct ltt_channel *chan = session->metadata;
-       char *str = NULL;
-       int ret = 0, waitret;
-       size_t len, reserve_len, pos;
-       va_list ap;
-
-       WARN_ON_ONCE(!CMM_ACCESS_ONCE(session->active));
-
-       va_start(ap, fmt);
-       ret = vasprintf(&str, fmt, ap);
-       va_end(ap);
-       if (ret < 0)
-               return -ENOMEM;
-
-       len = strlen(str);
-       pos = 0;
-
-       for (pos = 0; pos < len; pos += reserve_len) {
-               reserve_len = min_t(size_t,
-                               chan->ops->packet_avail_size(chan->chan, chan->handle),
-                               len - pos);
-               lib_ring_buffer_ctx_init(&ctx, chan->chan, NULL, reserve_len,
-                                        sizeof(char), -1, chan->handle);
-               /*
-                * We don't care about metadata buffer's records lost
-                * count, because we always retry here. Report error if
-                * we need to bail out after timeout or being
-                * interrupted.
-                */
-               waitret = wait_cond_interruptible_timeout(
-                       ({
-                               ret = chan->ops->event_reserve(&ctx, 0);
-                               ret != -ENOBUFS || !ret;
-                       }),
-                       LTTNG_METADATA_TIMEOUT_MSEC);
-               if (waitret == -ETIMEDOUT || waitret == -EINTR || ret) {
-                       DBG("LTTng: Failure to write metadata to buffers (%s)\n",
-                               waitret == -EINTR ? "interrupted" :
-                                       (ret == -ENOBUFS ? "timeout" : "I/O error"));
-                       if (waitret == -EINTR)
-                               ret = waitret;
-                       goto end;
-               }
-               chan->ops->event_write(&ctx, &str[pos], reserve_len);
-               chan->ops->event_commit(&ctx);
-       }
-end:
-       free(str);
-       return ret;
-}
-
-static
-int _ltt_field_statedump(struct ltt_session *session,
-                        const struct lttng_event_field *field)
-{
-       int ret = 0;
-
-       switch (field->type.atype) {
-       case atype_integer:
-               ret = lttng_metadata_printf(session,
-                       "               integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n",
-                       field->type.u.basic.integer.size,
-                       field->type.u.basic.integer.alignment,
-                       field->type.u.basic.integer.signedness,
-                       (field->type.u.basic.integer.encoding == lttng_encode_none)
-                               ? "none"
-                               : (field->type.u.basic.integer.encoding == lttng_encode_UTF8)
-                                       ? "UTF8"
-                                       : "ASCII",
-                       field->type.u.basic.integer.base,
-#if (BYTE_ORDER == BIG_ENDIAN)
-                       field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
-#else
-                       field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
-#endif
-                       field->name);
-               break;
-       case atype_float:
-               ret = lttng_metadata_printf(session,
-                       "               floating_point { exp_dig = %u; mant_dig = %u; align = %u;%s } _%s;\n",
-                       field->type.u.basic._float.exp_dig,
-                       field->type.u.basic._float.mant_dig,
-                       field->type.u.basic._float.alignment,
-#if (BYTE_ORDER == BIG_ENDIAN)
-                       field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
-#else
-                       field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
-#endif
-                       field->name);
-               break;
-       case atype_enum:
-               ret = lttng_metadata_printf(session,
-                       "               %s %s;\n",
-                       field->type.u.basic.enumeration.name,
-                       field->name);
-               break;
-       case atype_array:
-       {
-               const struct lttng_basic_type *elem_type;
-
-               elem_type = &field->type.u.array.elem_type;
-               ret = lttng_metadata_printf(session,
-                       "               integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n",
-                       elem_type->u.basic.integer.size,
-                       elem_type->u.basic.integer.alignment,
-                       elem_type->u.basic.integer.signedness,
-                       (elem_type->u.basic.integer.encoding == lttng_encode_none)
-                               ? "none"
-                               : (elem_type->u.basic.integer.encoding == lttng_encode_UTF8)
-                                       ? "UTF8"
-                                       : "ASCII",
-                       elem_type->u.basic.integer.base,
-#if (BYTE_ORDER == BIG_ENDIAN)
-                       elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
-#else
-                       elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
-#endif
-                       field->name, field->type.u.array.length);
-               break;
-       }
-       case atype_sequence:
-       {
-               const struct lttng_basic_type *elem_type;
-               const struct lttng_basic_type *length_type;
-
-               elem_type = &field->type.u.sequence.elem_type;
-               length_type = &field->type.u.sequence.length_type;
-               ret = lttng_metadata_printf(session,
-                       "               integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n",
-                       length_type->u.basic.integer.size,
-                       (unsigned int) length_type->u.basic.integer.alignment,
-                       length_type->u.basic.integer.signedness,
-                       (length_type->u.basic.integer.encoding == lttng_encode_none)
-                               ? "none"
-                               : ((length_type->u.basic.integer.encoding == lttng_encode_UTF8)
-                                       ? "UTF8"
-                                       : "ASCII"),
-                       length_type->u.basic.integer.base,
-#if (BYTE_ORDER == BIG_ENDIAN)
-                       length_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
-#else
-                       length_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
-#endif
-                       field->name);
-               if (ret)
-                       return ret;
-
-               ret = lttng_metadata_printf(session,
-                       "               integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n",
-                       elem_type->u.basic.integer.size,
-                       (unsigned int) elem_type->u.basic.integer.alignment,
-                       elem_type->u.basic.integer.signedness,
-                       (elem_type->u.basic.integer.encoding == lttng_encode_none)
-                               ? "none"
-                               : ((elem_type->u.basic.integer.encoding == lttng_encode_UTF8)
-                                       ? "UTF8"
-                                       : "ASCII"),
-                       elem_type->u.basic.integer.base,
-#if (BYTE_ORDER == BIG_ENDIAN)
-                       elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "",
-#else
-                       elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "",
-#endif
-                       field->name,
-                       field->name);
-               break;
-       }
-
-       case atype_string:
-               /* Default encoding is UTF8 */
-               ret = lttng_metadata_printf(session,
-                       "               string%s _%s;\n",
-                       field->type.u.basic.string.encoding == lttng_encode_ASCII ?
-                               " { encoding = ASCII; }" : "",
-                       field->name);
-               break;
-       default:
-               WARN_ON_ONCE(1);
-               return -EINVAL;
-       }
-       return ret;
-}
-
-static
-int _ltt_context_metadata_statedump(struct ltt_session *session,
-                                   struct lttng_ctx *ctx)
-{
-       int ret = 0;
-       int i;
-
-       if (!ctx)
-               return 0;
-       for (i = 0; i < ctx->nr_fields; i++) {
-               const struct lttng_ctx_field *field = &ctx->fields[i];
-
-               ret = _ltt_field_statedump(session, &field->event_field);
-               if (ret)
-                       return ret;
-       }
-       return ret;
-}
-
-static
-int _ltt_fields_metadata_statedump(struct ltt_session *session,
-                                  struct ltt_event *event)
-{
-       const struct lttng_event_desc *desc = event->desc;
-       int ret = 0;
-       int i;
-
-       for (i = 0; i < desc->nr_fields; i++) {
-               const struct lttng_event_field *field = &desc->fields[i];
-
-               ret = _ltt_field_statedump(session, field);
-               if (ret)
-                       return ret;
-       }
-       return ret;
-}
-
-static
-int _ltt_event_metadata_statedump(struct ltt_session *session,
-                                 struct ltt_channel *chan,
-                                 struct ltt_event *event)
-{
-       int ret = 0;
-
-       if (event->metadata_dumped || !CMM_ACCESS_ONCE(session->active))
-               return 0;
-       if (chan == session->metadata)
-               return 0;
-       /*
-        * Don't print events for which probe load is pending.
-        */
-       if (!event->desc)
-               return 0;
-
-       ret = lttng_metadata_printf(session,
-               "event {\n"
-               "       name = %s;\n"
-               "       id = %u;\n"
-               "       stream_id = %u;\n",
-               event->desc->name,
-               event->id,
-               event->chan->id);
-       if (ret)
-               goto end;
-
-       if (event->ctx) {
-               ret = lttng_metadata_printf(session,
-                       "       context := struct {\n");
-               if (ret)
-                       goto end;
-       }
-       ret = _ltt_context_metadata_statedump(session, event->ctx);
-       if (ret)
-               goto end;
-       if (event->ctx) {
-               ret = lttng_metadata_printf(session,
-                       "       };\n");
-               if (ret)
-                       goto end;
-       }
-
-       ret = lttng_metadata_printf(session,
-               "       fields := struct {\n"
-               );
-       if (ret)
-               goto end;
-
-       ret = _ltt_fields_metadata_statedump(session, event);
-       if (ret)
-               goto end;
-
-       /*
-        * LTTng space reservation can only reserve multiples of the
-        * byte size.
-        */
-       ret = lttng_metadata_printf(session,
-               "       };\n"
-               "};\n\n");
-       if (ret)
-               goto end;
-
-       event->metadata_dumped = 1;
-end:
-       return ret;
-
-}
-
-static
-int _ltt_channel_metadata_statedump(struct ltt_session *session,
-                                   struct ltt_channel *chan)
-{
-       int ret = 0;
-
-       if (chan->metadata_dumped || !CMM_ACCESS_ONCE(session->active))
-               return 0;
-       if (chan == session->metadata)
-               return 0;
-
-       WARN_ON_ONCE(!chan->header_type);
-       ret = lttng_metadata_printf(session,
-               "stream {\n"
-               "       id = %u;\n"
-               "       event.header := %s;\n"
-               "       packet.context := struct packet_context;\n",
-               chan->id,
-               chan->header_type == 1 ? "struct event_header_compact" :
-                       "struct event_header_large");
-       if (ret)
-               goto end;
-
-       if (chan->ctx) {
-               ret = lttng_metadata_printf(session,
-                       "       event.context := struct {\n");
-               if (ret)
-                       goto end;
-       }
-       ret = _ltt_context_metadata_statedump(session, chan->ctx);
-       if (ret)
-               goto end;
-       if (chan->ctx) {
-               ret = lttng_metadata_printf(session,
-                       "       };\n");
-               if (ret)
-                       goto end;
-       }
-
-       ret = lttng_metadata_printf(session,
-               "};\n\n");
-
-       chan->metadata_dumped = 1;
-end:
-       return ret;
-}
-
-static
-int _ltt_stream_packet_context_declare(struct ltt_session *session)
-{
-       return lttng_metadata_printf(session,
-               "struct packet_context {\n"
-               "       uint64_t timestamp_begin;\n"
-               "       uint64_t timestamp_end;\n"
-               "       uint32_t events_discarded;\n"
-               "       uint32_t content_size;\n"
-               "       uint32_t packet_size;\n"
-               "       uint32_t cpu_id;\n"
-               "};\n\n"
-               );
-}
-
-/*
- * Compact header:
- * id: range: 0 - 30.
- * id 31 is reserved to indicate an extended header.
- *
- * Large header:
- * id: range: 0 - 65534.
- * id 65535 is reserved to indicate an extended header.
- */
-static
-int _ltt_event_header_declare(struct ltt_session *session)
-{
-       return lttng_metadata_printf(session,
-       "struct event_header_compact {\n"
-       "       enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n"
-       "       variant <id> {\n"
-       "               struct {\n"
-       "                       uint27_t timestamp;\n"
-       "               } compact;\n"
-       "               struct {\n"
-       "                       uint32_t id;\n"
-       "                       uint64_t timestamp;\n"
-       "               } extended;\n"
-       "       } v;\n"
-       "} align(%u);\n"
-       "\n"
-       "struct event_header_large {\n"
-       "       enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n"
-       "       variant <id> {\n"
-       "               struct {\n"
-       "                       uint32_t timestamp;\n"
-       "               } compact;\n"
-       "               struct {\n"
-       "                       uint32_t id;\n"
-       "                       uint64_t timestamp;\n"
-       "               } extended;\n"
-       "       } v;\n"
-       "} align(%u);\n\n",
-       lttng_alignof(uint32_t) * CHAR_BIT,
-       lttng_alignof(uint16_t) * CHAR_BIT
-       );
-}
-
-/*
- * Output metadata into this session's metadata buffers.
- */
-static
-int _ltt_session_metadata_statedump(struct ltt_session *session)
-{
-       unsigned char *uuid_c = session->uuid;
-       char uuid_s[37];
-       struct ltt_channel *chan;
-       struct ltt_event *event;
-       int ret = 0;
-
-       if (!CMM_ACCESS_ONCE(session->active))
-               return 0;
-       if (session->metadata_dumped)
-               goto skip_session;
-       if (!session->metadata) {
-               DBG("LTTng: attempt to start tracing, but metadata channel is not found. Operation abort.\n");
-               return -EPERM;
-       }
-
-       snprintf(uuid_s, sizeof(uuid_s),
-               "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-               uuid_c[0], uuid_c[1], uuid_c[2], uuid_c[3],
-               uuid_c[4], uuid_c[5], uuid_c[6], uuid_c[7],
-               uuid_c[8], uuid_c[9], uuid_c[10], uuid_c[11],
-               uuid_c[12], uuid_c[13], uuid_c[14], uuid_c[15]);
-
-       ret = lttng_metadata_printf(session,
-               "typealias integer { size = 8; align = %u; signed = false; } := uint8_t;\n"
-               "typealias integer { size = 16; align = %u; signed = false; } := uint16_t;\n"
-               "typealias integer { size = 32; align = %u; signed = false; } := uint32_t;\n"
-               "typealias integer { size = 64; align = %u; signed = false; } := uint64_t;\n"
-               "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n"
-               "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n"
-               "\n"
-               "trace {\n"
-               "       major = %u;\n"
-               "       minor = %u;\n"
-               "       uuid = \"%s\";\n"
-               "       byte_order = %s;\n"
-               "       packet.header := struct {\n"
-               "               uint32_t magic;\n"
-               "               uint8_t  uuid[16];\n"
-               "               uint32_t stream_id;\n"
-               "       };\n"
-               "};\n\n",
-               lttng_alignof(uint8_t) * CHAR_BIT,
-               lttng_alignof(uint16_t) * CHAR_BIT,
-               lttng_alignof(uint32_t) * CHAR_BIT,
-               lttng_alignof(uint64_t) * CHAR_BIT,
-               CTF_VERSION_MAJOR,
-               CTF_VERSION_MINOR,
-               uuid_s,
-#if (BYTE_ORDER == BIG_ENDIAN)
-               "be"
-#else
-               "le"
-#endif
-               );
-       if (ret)
-               goto end;
-
-       ret = _ltt_stream_packet_context_declare(session);
-       if (ret)
-               goto end;
-
-       ret = _ltt_event_header_declare(session);
-       if (ret)
-               goto end;
-
-skip_session:
-       cds_list_for_each_entry(chan, &session->chan, list) {
-               ret = _ltt_channel_metadata_statedump(session, chan);
-               if (ret)
-                       goto end;
-       }
-
-       cds_list_for_each_entry(event, &session->events, list) {
-               ret = _ltt_event_metadata_statedump(session, event->chan, event);
-               if (ret)
-                       goto end;
-       }
-       session->metadata_dumped = 1;
-end:
-       return ret;
-}
-
-/**
- * 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. Called with ust_lock held.
- */
-void ltt_transport_register(struct ltt_transport *transport)
-{
-       cds_list_add_tail(&transport->node, &ltt_transport_list);
-}
-
-/**
- * ltt_transport_unregister - LTT transport unregistration
- * @transport: transport structure
- * Called with ust_lock held.
- */
-void ltt_transport_unregister(struct ltt_transport *transport)
-{
-       cds_list_del(&transport->node);
-}
-
-void lttng_ust_events_exit(void)
-{
-       struct ltt_session *session, *tmpsession;
-
-       cds_list_for_each_entry_safe(session, tmpsession, &sessions, list)
-               ltt_session_destroy(session);
-}
diff --git a/libust/ltt-probes.c b/libust/ltt-probes.c
deleted file mode 100644 (file)
index 66ee971..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * ltt-probes.c
- *
- * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * Holds LTTng probes registry.
- *
- * Dual LGPL v2.1/GPL v2 license.
- */
-
-#include <string.h>
-#include <errno.h>
-#include <urcu/list.h>
-#include <lttng/core.h>
-#include <lttng/ust-events.h>
-
-#include "ltt-tracer-core.h"
-
-/*
- * probe list is protected by ust_lock()/ust_unlock().
- */
-static CDS_LIST_HEAD(probe_list);
-
-static
-const struct lttng_event_desc *find_event(const char *name)
-{
-       struct lttng_probe_desc *probe_desc;
-       int i;
-
-       cds_list_for_each_entry(probe_desc, &probe_list, head) {
-               for (i = 0; i < probe_desc->nr_events; i++) {
-                       if (!strcmp(probe_desc->event_desc[i].name, name))
-                               return &probe_desc->event_desc[i];
-               }
-       }
-       return NULL;
-}
-
-int ltt_probe_register(struct lttng_probe_desc *desc)
-{
-       int ret = 0;
-       int i;
-
-       ust_lock();
-       /*
-        * TODO: This is O(N^2). Turn into a hash table when probe registration
-        * overhead becomes an issue.
-        */
-       for (i = 0; i < desc->nr_events; i++) {
-               if (find_event(desc->event_desc[i].name)) {
-                       ret = -EEXIST;
-                       goto end;
-               }
-       }
-       cds_list_add(&desc->head, &probe_list);
-
-       /*
-        * fix the events awaiting probe load.
-        */
-       for (i = 0; i < desc->nr_events; i++) {
-               ret = pending_probe_fix_events(&desc->event_desc[i]);
-               assert(!ret);
-       }
-end:
-       ust_unlock();
-       return ret;
-}
-
-void ltt_probe_unregister(struct lttng_probe_desc *desc)
-{
-       ust_lock();
-       cds_list_del(&desc->head);
-       ust_unlock();
-}
-
-/*
- * called with UST lock held.
- */
-const struct lttng_event_desc *ltt_event_get(const char *name)
-{
-       const struct lttng_event_desc *event;
-
-       event = find_event(name);
-       if (!event)
-               return NULL;
-       return event;
-}
-
-void ltt_event_put(const struct lttng_event_desc *event)
-{
-}
-
-#if 0
-static
-void *tp_list_start(struct seq_file *m, loff_t *pos)
-{
-       struct lttng_probe_desc *probe_desc;
-       int iter = 0, i;
-
-       pthread_mutex_lock(&probe_mutex);
-       cds_list_for_each_entry(probe_desc, &probe_list, head) {
-               for (i = 0; i < probe_desc->nr_events; i++) {
-                       if (iter++ >= *pos)
-                               return (void *) &probe_desc->event_desc[i];
-               }
-       }
-       /* End of list */
-       return NULL;
-}
-
-static
-void *tp_list_next(struct seq_file *m, void *p, loff_t *ppos)
-{
-       struct lttng_probe_desc *probe_desc;
-       int iter = 0, i;
-
-       (*ppos)++;
-       cds_list_for_each_entry(probe_desc, &probe_list, head) {
-               for (i = 0; i < probe_desc->nr_events; i++) {
-                       if (iter++ >= *ppos)
-                               return (void *) &probe_desc->event_desc[i];
-               }
-       }
-       /* End of list */
-       return NULL;
-}
-
-static
-void tp_list_stop(struct seq_file *m, void *p)
-{
-       pthread_mutex_unlock(&probe_mutex);
-}
-
-static
-int tp_list_show(struct seq_file *m, void *p)
-{
-       const struct lttng_event_desc *probe_desc = p;
-
-       /*
-        * Don't export lttng internal events (metadata).
-        */
-       if (!strncmp(probe_desc->name, "lttng_", sizeof("lttng_") - 1))
-               return 0;
-       seq_printf(m,   "event { name = %s; };\n",
-                  probe_desc->name);
-       return 0;
-}
-
-static
-const struct seq_operations lttng_tracepoint_list_seq_ops = {
-       .start = tp_list_start,
-       .next = tp_list_next,
-       .stop = tp_list_stop,
-       .show = tp_list_show,
-};
-
-static
-int lttng_tracepoint_list_open(struct inode *inode, struct file *file)
-{
-       return seq_open(file, &lttng_tracepoint_list_seq_ops);
-}
-
-const struct file_operations lttng_tracepoint_list_fops = {
-       .open = lttng_tracepoint_list_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = seq_release,
-};
-#endif //0
diff --git a/libust/ltt-ring-buffer-client-discard.c b/libust/ltt-ring-buffer-client-discard.c
deleted file mode 100644 (file)
index e89026c..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * ltt-ring-buffer-client-discard.c
- *
- * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * LTTng lib ring buffer client (discard mode).
- *
- * Dual LGPL v2.1/GPL v2 license.
- */
-
-#include "ltt-tracer.h"
-
-#define RING_BUFFER_MODE_TEMPLATE              RING_BUFFER_DISCARD
-#define RING_BUFFER_MODE_TEMPLATE_STRING       "discard"
-#define RING_BUFFER_MODE_TEMPLATE_INIT \
-       ltt_ring_buffer_client_discard_init
-#define RING_BUFFER_MODE_TEMPLATE_EXIT \
-       ltt_ring_buffer_client_discard_exit
-#include "ltt-ring-buffer-client.h"
diff --git a/libust/ltt-ring-buffer-client-overwrite.c b/libust/ltt-ring-buffer-client-overwrite.c
deleted file mode 100644 (file)
index 8590a7e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * ltt-ring-buffer-client-overwrite.c
- *
- * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * LTTng lib ring buffer client (overwrite mode).
- *
- * Dual LGPL v2.1/GPL v2 license.
- */
-
-#include "ltt-tracer.h"
-
-#define RING_BUFFER_MODE_TEMPLATE              RING_BUFFER_OVERWRITE
-#define RING_BUFFER_MODE_TEMPLATE_STRING       "overwrite"
-#define RING_BUFFER_MODE_TEMPLATE_INIT \
-       ltt_ring_buffer_client_overwrite_init
-#define RING_BUFFER_MODE_TEMPLATE_EXIT \
-       ltt_ring_buffer_client_overwrite_exit
-#include "ltt-ring-buffer-client.h"
diff --git a/libust/ltt-ring-buffer-client.h b/libust/ltt-ring-buffer-client.h
deleted file mode 100644 (file)
index a1bc8c3..0000000
+++ /dev/null
@@ -1,554 +0,0 @@
-/*
- * ltt-ring-buffer-client.h
- *
- * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * LTTng lib ring buffer client template.
- *
- * Dual LGPL v2.1/GPL v2 license.
- */
-
-#include <stdint.h>
-#include <lttng/ust-events.h>
-#include "lttng/bitfield.h"
-#include "lttng/clock.h"
-#include "ltt-tracer.h"
-#include "../libringbuffer/frontend_types.h"
-
-/*
- * Keep the natural field alignment for _each field_ within this structure if
- * you ever add/remove a field from this header. Packed attribute is not used
- * because gcc generates poor code on at least powerpc and mips. Don't ever
- * let gcc add padding between the structure elements.
- */
-
-struct packet_header {
-       /* Trace packet header */
-       uint32_t magic;                 /*
-                                        * Trace magic number.
-                                        * contains endianness information.
-                                        */
-       uint8_t uuid[16];
-       uint32_t stream_id;
-
-       struct {
-               /* Stream packet context */
-               uint64_t timestamp_begin;       /* Cycle count at subbuffer start */
-               uint64_t timestamp_end;         /* Cycle count at subbuffer end */
-               uint32_t events_discarded;      /*
-                                                * Events lost in this subbuffer since
-                                                * the beginning of the trace.
-                                                * (may overflow)
-                                                */
-               uint32_t content_size;          /* Size of data in subbuffer */
-               uint32_t packet_size;           /* Subbuffer size (include padding) */
-               uint32_t cpu_id;                /* CPU id associated with stream */
-               uint8_t header_end;             /* End of header */
-       } ctx;
-};
-
-
-static inline notrace u64 lib_ring_buffer_clock_read(struct channel *chan)
-{
-       return trace_clock_read64();
-}
-
-static inline
-size_t ctx_get_size(size_t offset, struct lttng_ctx *ctx)
-{
-       int i;
-       size_t orig_offset = offset;
-
-       if (caa_likely(!ctx))
-               return 0;
-       for (i = 0; i < ctx->nr_fields; i++)
-               offset += ctx->fields[i].get_size(offset);
-       return offset - orig_offset;
-}
-
-static inline
-void ctx_record(struct lttng_ust_lib_ring_buffer_ctx *bufctx,
-               struct ltt_channel *chan,
-               struct lttng_ctx *ctx)
-{
-       int i;
-
-       if (caa_likely(!ctx))
-               return;
-       for (i = 0; i < ctx->nr_fields; i++)
-               ctx->fields[i].record(&ctx->fields[i], bufctx, chan);
-}
-
-/*
- * record_header_size - Calculate the header size and padding necessary.
- * @config: ring buffer instance configuration
- * @chan: channel
- * @offset: offset in the write buffer
- * @pre_header_padding: padding to add before the header (output)
- * @ctx: reservation context
- *
- * Returns the event header size (including padding).
- *
- * The payload must itself determine its own alignment from the biggest type it
- * contains.
- */
-static __inline__
-unsigned char record_header_size(const struct lttng_ust_lib_ring_buffer_config *config,
-                                struct channel *chan, size_t offset,
-                                size_t *pre_header_padding,
-                                struct lttng_ust_lib_ring_buffer_ctx *ctx)
-{
-       struct ltt_channel *ltt_chan = channel_get_private(chan);
-       struct ltt_event *event = ctx->priv;
-       size_t orig_offset = offset;
-       size_t padding;
-
-       switch (ltt_chan->header_type) {
-       case 1: /* compact */
-               padding = lib_ring_buffer_align(offset, lttng_alignof(uint32_t));
-               offset += padding;
-               if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) {
-                       offset += sizeof(uint32_t);     /* id and timestamp */
-               } else {
-                       /* Minimum space taken by 5-bit id */
-                       offset += sizeof(uint8_t);
-                       /* Align extended struct on largest member */
-                       offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t));
-                       offset += sizeof(uint32_t);     /* id */
-                       offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t));
-                       offset += sizeof(uint64_t);     /* timestamp */
-               }
-               break;
-       case 2: /* large */
-               padding = lib_ring_buffer_align(offset, lttng_alignof(uint16_t));
-               offset += padding;
-               offset += sizeof(uint16_t);
-               if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) {
-                       offset += lib_ring_buffer_align(offset, lttng_alignof(uint32_t));
-                       offset += sizeof(uint32_t);     /* timestamp */
-               } else {
-                       /* Align extended struct on largest member */
-                       offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t));
-                       offset += sizeof(uint32_t);     /* id */
-                       offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t));
-                       offset += sizeof(uint64_t);     /* timestamp */
-               }
-               break;
-       default:
-               padding = 0;
-               WARN_ON_ONCE(1);
-       }
-       offset += ctx_get_size(offset, event->ctx);
-       offset += ctx_get_size(offset, ltt_chan->ctx);
-
-       *pre_header_padding = padding;
-       return offset - orig_offset;
-}
-
-#include "../libringbuffer/api.h"
-
-static
-void ltt_write_event_header_slow(const struct lttng_ust_lib_ring_buffer_config *config,
-                                struct lttng_ust_lib_ring_buffer_ctx *ctx,
-                                uint32_t event_id);
-
-/*
- * ltt_write_event_header
- *
- * Writes the event header to the offset (already aligned on 32-bits).
- *
- * @config: ring buffer instance configuration
- * @ctx: reservation context
- * @event_id: event ID
- */
-static __inline__
-void ltt_write_event_header(const struct lttng_ust_lib_ring_buffer_config *config,
-                           struct lttng_ust_lib_ring_buffer_ctx *ctx,
-                           uint32_t event_id)
-{
-       struct ltt_channel *ltt_chan = channel_get_private(ctx->chan);
-       struct ltt_event *event = ctx->priv;
-
-       if (caa_unlikely(ctx->rflags))
-               goto slow_path;
-
-       switch (ltt_chan->header_type) {
-       case 1: /* compact */
-       {
-               uint32_t id_time = 0;
-
-               bt_bitfield_write(&id_time, uint32_t, 0, 5, event_id);
-               bt_bitfield_write(&id_time, uint32_t, 5, 27, ctx->tsc);
-               lib_ring_buffer_write(config, ctx, &id_time, sizeof(id_time));
-               break;
-       }
-       case 2: /* large */
-       {
-               uint32_t timestamp = (uint32_t) ctx->tsc;
-               uint16_t id = event_id;
-
-               lib_ring_buffer_write(config, ctx, &id, sizeof(id));
-               lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint32_t));
-               lib_ring_buffer_write(config, ctx, &timestamp, sizeof(timestamp));
-               break;
-       }
-       default:
-               WARN_ON_ONCE(1);
-       }
-
-       ctx_record(ctx, ltt_chan, ltt_chan->ctx);
-       ctx_record(ctx, ltt_chan, event->ctx);
-       lib_ring_buffer_align_ctx(ctx, ctx->largest_align);
-
-       return;
-
-slow_path:
-       ltt_write_event_header_slow(config, ctx, event_id);
-}
-
-static
-void ltt_write_event_header_slow(const struct lttng_ust_lib_ring_buffer_config *config,
-                                struct lttng_ust_lib_ring_buffer_ctx *ctx,
-                                uint32_t event_id)
-{
-       struct ltt_channel *ltt_chan = channel_get_private(ctx->chan);
-       struct ltt_event *event = ctx->priv;
-
-       switch (ltt_chan->header_type) {
-       case 1: /* compact */
-               if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) {
-                       uint32_t id_time = 0;
-
-                       bt_bitfield_write(&id_time, uint32_t, 0, 5, event_id);
-                       bt_bitfield_write(&id_time, uint32_t, 5, 27, ctx->tsc);
-                       lib_ring_buffer_write(config, ctx, &id_time, sizeof(id_time));
-               } else {
-                       uint8_t id = 0;
-                       uint64_t timestamp = ctx->tsc;
-
-                       bt_bitfield_write(&id, uint8_t, 0, 5, 31);
-                       lib_ring_buffer_write(config, ctx, &id, sizeof(id));
-                       /* Align extended struct on largest member */
-                       lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t));
-                       lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id));
-                       lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t));
-                       lib_ring_buffer_write(config, ctx, &timestamp, sizeof(timestamp));
-               }
-               break;
-       case 2: /* large */
-       {
-               if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) {
-                       uint32_t timestamp = (uint32_t) ctx->tsc;
-                       uint16_t id = event_id;
-
-                       lib_ring_buffer_write(config, ctx, &id, sizeof(id));
-                       lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint32_t));
-                       lib_ring_buffer_write(config, ctx, &timestamp, sizeof(timestamp));
-               } else {
-                       uint16_t id = 65535;
-                       uint64_t timestamp = ctx->tsc;
-
-                       lib_ring_buffer_write(config, ctx, &id, sizeof(id));
-                       /* Align extended struct on largest member */
-                       lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t));
-                       lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id));
-                       lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t));
-                       lib_ring_buffer_write(config, ctx, &timestamp, sizeof(timestamp));
-               }
-               break;
-       }
-       default:
-               WARN_ON_ONCE(1);
-       }
-       ctx_record(ctx, ltt_chan, ltt_chan->ctx);
-       ctx_record(ctx, ltt_chan, event->ctx);
-       lib_ring_buffer_align_ctx(ctx, ctx->largest_align);
-}
-
-static const struct lttng_ust_lib_ring_buffer_config client_config;
-
-static u64 client_ring_buffer_clock_read(struct channel *chan)
-{
-       return lib_ring_buffer_clock_read(chan);
-}
-
-static
-size_t client_record_header_size(const struct lttng_ust_lib_ring_buffer_config *config,
-                                struct channel *chan, size_t offset,
-                                size_t *pre_header_padding,
-                                struct lttng_ust_lib_ring_buffer_ctx *ctx)
-{
-       return record_header_size(config, chan, offset,
-                                 pre_header_padding, ctx);
-}
-
-/**
- * client_packet_header_size - called on buffer-switch to a new sub-buffer
- *
- * Return header size without padding after the structure. Don't use packed
- * structure because gcc generates inefficient code on some architectures
- * (powerpc, mips..)
- */
-static size_t client_packet_header_size(void)
-{
-       return offsetof(struct packet_header, ctx.header_end);
-}
-
-static void client_buffer_begin(struct lttng_ust_lib_ring_buffer *buf, u64 tsc,
-                               unsigned int subbuf_idx,
-                               struct lttng_ust_shm_handle *handle)
-{
-       struct channel *chan = shmp(handle, buf->backend.chan);
-       struct packet_header *header =
-               (struct packet_header *)
-                       lib_ring_buffer_offset_address(&buf->backend,
-                               subbuf_idx * chan->backend.subbuf_size,
-                               handle);
-       struct ltt_channel *ltt_chan = channel_get_private(chan);
-       struct ltt_session *session = ltt_chan->session;
-
-       header->magic = CTF_MAGIC_NUMBER;
-       memcpy(header->uuid, session->uuid, sizeof(session->uuid));
-       header->stream_id = ltt_chan->id;
-       header->ctx.timestamp_begin = tsc;
-       header->ctx.timestamp_end = 0;
-       header->ctx.events_discarded = 0;
-       header->ctx.content_size = 0xFFFFFFFF; /* for debugging */
-       header->ctx.packet_size = 0xFFFFFFFF;
-       header->ctx.cpu_id = buf->backend.cpu;
-}
-
-/*
- * offset is assumed to never be 0 here : never deliver a completely empty
- * subbuffer. data_size is between 1 and subbuf_size.
- */
-static void client_buffer_end(struct lttng_ust_lib_ring_buffer *buf, u64 tsc,
-                             unsigned int subbuf_idx, unsigned long data_size,
-                             struct lttng_ust_shm_handle *handle)
-{
-       struct channel *chan = shmp(handle, buf->backend.chan);
-       struct packet_header *header =
-               (struct packet_header *)
-                       lib_ring_buffer_offset_address(&buf->backend,
-                               subbuf_idx * chan->backend.subbuf_size,
-                               handle);
-       unsigned long records_lost = 0;
-
-       header->ctx.timestamp_end = tsc;
-       header->ctx.content_size = data_size * CHAR_BIT;        /* in bits */
-       header->ctx.packet_size = PAGE_ALIGN(data_size) * CHAR_BIT; /* in bits */
-       /*
-        * We do not care about the records lost count, because the metadata
-        * channel waits and retry.
-        */
-       (void) lib_ring_buffer_get_records_lost_full(&client_config, buf);
-       records_lost += lib_ring_buffer_get_records_lost_wrap(&client_config, buf);
-       records_lost += lib_ring_buffer_get_records_lost_big(&client_config, buf);
-       header->ctx.events_discarded = records_lost;
-}
-
-static int client_buffer_create(struct lttng_ust_lib_ring_buffer *buf, void *priv,
-                               int cpu, const char *name, struct lttng_ust_shm_handle *handle)
-{
-       return 0;
-}
-
-static void client_buffer_finalize(struct lttng_ust_lib_ring_buffer *buf, void *priv, int cpu, struct lttng_ust_shm_handle *handle)
-{
-}
-
-static const struct lttng_ust_lib_ring_buffer_config client_config = {
-       .cb.ring_buffer_clock_read = client_ring_buffer_clock_read,
-       .cb.record_header_size = client_record_header_size,
-       .cb.subbuffer_header_size = client_packet_header_size,
-       .cb.buffer_begin = client_buffer_begin,
-       .cb.buffer_end = client_buffer_end,
-       .cb.buffer_create = client_buffer_create,
-       .cb.buffer_finalize = client_buffer_finalize,
-
-       .tsc_bits = 32,
-       .alloc = RING_BUFFER_ALLOC_PER_CPU,
-       .sync = RING_BUFFER_SYNC_GLOBAL,
-       .mode = RING_BUFFER_MODE_TEMPLATE,
-       .backend = RING_BUFFER_PAGE,
-       .output = RING_BUFFER_MMAP,
-       .oops = RING_BUFFER_OOPS_CONSISTENCY,
-       .ipi = RING_BUFFER_NO_IPI_BARRIER,
-       .wakeup = RING_BUFFER_WAKEUP_BY_WRITER,
-};
-
-static
-struct ltt_channel *_channel_create(const char *name,
-                               struct ltt_channel *ltt_chan, void *buf_addr,
-                               size_t subbuf_size, size_t num_subbuf,
-                               unsigned int switch_timer_interval,
-                               unsigned int read_timer_interval,
-                               int *shm_fd, int *wait_fd,
-                               uint64_t *memory_map_size)
-{
-       ltt_chan->handle = channel_create(&client_config, name, ltt_chan, buf_addr,
-                             subbuf_size, num_subbuf, switch_timer_interval,
-                             read_timer_interval, shm_fd, wait_fd,
-                             memory_map_size);
-       if (!ltt_chan->handle)
-               return NULL;
-       ltt_chan->chan = shmp(ltt_chan->handle, ltt_chan->handle->chan);
-       return ltt_chan;
-}
-
-static
-void ltt_channel_destroy(struct ltt_channel *ltt_chan)
-{
-       channel_destroy(ltt_chan->chan, ltt_chan->handle, 0);
-}
-
-static
-struct lttng_ust_lib_ring_buffer *ltt_buffer_read_open(struct channel *chan,
-                                            struct lttng_ust_shm_handle *handle,
-                                            int *shm_fd, int *wait_fd,
-                                            uint64_t *memory_map_size)
-{
-       struct lttng_ust_lib_ring_buffer *buf;
-       int cpu;
-
-       for_each_channel_cpu(cpu, chan) {
-               buf = channel_get_ring_buffer(&client_config, chan,
-                               cpu, handle, shm_fd, wait_fd,
-                               memory_map_size);
-               if (!lib_ring_buffer_open_read(buf, handle, 0))
-                       return buf;
-       }
-       return NULL;
-}
-
-static
-void ltt_buffer_read_close(struct lttng_ust_lib_ring_buffer *buf,
-                          struct lttng_ust_shm_handle *handle)
-{
-       lib_ring_buffer_release_read(buf, handle, 0);
-}
-
-static
-int ltt_event_reserve(struct lttng_ust_lib_ring_buffer_ctx *ctx,
-                     uint32_t event_id)
-{
-       struct ltt_channel *ltt_chan = channel_get_private(ctx->chan);
-       int ret, cpu;
-
-       cpu = lib_ring_buffer_get_cpu(&client_config);
-       if (cpu < 0)
-               return -EPERM;
-       ctx->cpu = cpu;
-
-       switch (ltt_chan->header_type) {
-       case 1: /* compact */
-               if (event_id > 30)
-                       ctx->rflags |= LTT_RFLAG_EXTENDED;
-               break;
-       case 2: /* large */
-               if (event_id > 65534)
-                       ctx->rflags |= LTT_RFLAG_EXTENDED;
-               break;
-       default:
-               WARN_ON_ONCE(1);
-       }
-
-       ret = lib_ring_buffer_reserve(&client_config, ctx);
-       if (ret)
-               goto put;
-       ltt_write_event_header(&client_config, ctx, event_id);
-       return 0;
-put:
-       lib_ring_buffer_put_cpu(&client_config);
-       return ret;
-}
-
-static
-void ltt_event_commit(struct lttng_ust_lib_ring_buffer_ctx *ctx)
-{
-       lib_ring_buffer_commit(&client_config, ctx);
-       lib_ring_buffer_put_cpu(&client_config);
-}
-
-static
-void ltt_event_write(struct lttng_ust_lib_ring_buffer_ctx *ctx, const void *src,
-                    size_t len)
-{
-       lib_ring_buffer_write(&client_config, ctx, src, len);
-}
-
-#if 0
-static
-wait_queue_head_t *ltt_get_reader_wait_queue(struct channel *chan)
-{
-       return &chan->read_wait;
-}
-
-static
-wait_queue_head_t *ltt_get_hp_wait_queue(struct channel *chan)
-{
-       return &chan->hp_wait;
-}
-#endif //0
-
-static
-int ltt_is_finalized(struct channel *chan)
-{
-       return lib_ring_buffer_channel_is_finalized(chan);
-}
-
-static
-int ltt_is_disabled(struct channel *chan)
-{
-       return lib_ring_buffer_channel_is_disabled(chan);
-}
-
-static
-int ltt_flush_buffer(struct channel *chan, struct lttng_ust_shm_handle *handle)
-{
-       struct lttng_ust_lib_ring_buffer *buf;
-       int cpu;
-
-       for_each_channel_cpu(cpu, chan) {
-               int shm_fd, wait_fd;
-               uint64_t memory_map_size;
-
-               buf = channel_get_ring_buffer(&client_config, chan,
-                               cpu, handle, &shm_fd, &wait_fd,
-                               &memory_map_size);
-               lib_ring_buffer_switch(&client_config, buf,
-                               SWITCH_ACTIVE, handle);
-       }
-       return 0;
-}
-
-static struct ltt_transport ltt_relay_transport = {
-       .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING "-mmap",
-       .ops = {
-               .channel_create = _channel_create,
-               .channel_destroy = ltt_channel_destroy,
-               .buffer_read_open = ltt_buffer_read_open,
-               .buffer_read_close = ltt_buffer_read_close,
-               .event_reserve = ltt_event_reserve,
-               .event_commit = ltt_event_commit,
-               .event_write = ltt_event_write,
-               .packet_avail_size = NULL,      /* Would be racy anyway */
-               //.get_reader_wait_queue = ltt_get_reader_wait_queue,
-               //.get_hp_wait_queue = ltt_get_hp_wait_queue,
-               .is_finalized = ltt_is_finalized,
-               .is_disabled = ltt_is_disabled,
-               .flush_buffer = ltt_flush_buffer,
-       },
-};
-
-void RING_BUFFER_MODE_TEMPLATE_INIT(void)
-{
-       DBG("LTT : ltt ring buffer client init\n");
-       ltt_transport_register(&ltt_relay_transport);
-}
-
-void RING_BUFFER_MODE_TEMPLATE_EXIT(void)
-{
-       DBG("LTT : ltt ring buffer client exit\n");
-       ltt_transport_unregister(&ltt_relay_transport);
-}
diff --git a/libust/ltt-ring-buffer-metadata-client.c b/libust/ltt-ring-buffer-metadata-client.c
deleted file mode 100644 (file)
index e1747c4..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * ltt-ring-buffer-metadata-client.c
- *
- * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * LTTng lib ring buffer metadta client.
- *
- * Dual LGPL v2.1/GPL v2 license.
- */
-
-#include "ltt-tracer.h"
-
-#define RING_BUFFER_MODE_TEMPLATE              RING_BUFFER_DISCARD
-#define RING_BUFFER_MODE_TEMPLATE_STRING       "metadata"
-#define RING_BUFFER_MODE_TEMPLATE_INIT \
-       ltt_ring_buffer_metadata_client_init
-#define RING_BUFFER_MODE_TEMPLATE_EXIT \
-       ltt_ring_buffer_metadata_client_exit
-#include "ltt-ring-buffer-metadata-client.h"
diff --git a/libust/ltt-ring-buffer-metadata-client.h b/libust/ltt-ring-buffer-metadata-client.h
deleted file mode 100644 (file)
index d1a83d5..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * ltt-ring-buffer-client.h
- *
- * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * LTTng lib ring buffer client template.
- *
- * Dual LGPL v2.1/GPL v2 license.
- */
-
-#include <stdint.h>
-#include <lttng/ust-events.h>
-#include "lttng/bitfield.h"
-#include "ltt-tracer.h"
-#include "../libringbuffer/frontend_types.h"
-
-struct metadata_packet_header {
-       uint32_t magic;                 /* 0x75D11D57 */
-       uint8_t  uuid[16];              /* Unique Universal Identifier */
-       uint32_t checksum;              /* 0 if unused */
-       uint32_t content_size;          /* in bits */
-       uint32_t packet_size;           /* in bits */
-       uint8_t  compression_scheme;    /* 0 if unused */
-       uint8_t  encryption_scheme;     /* 0 if unused */
-       uint8_t  checksum_scheme;       /* 0 if unused */
-       uint8_t  major;                 /* CTF spec major version number */
-       uint8_t  minor;                 /* CTF spec minor version number */
-       uint8_t  header_end[0];
-};
-
-struct metadata_record_header {
-       uint8_t header_end[0];          /* End of header */
-};
-
-static const struct lttng_ust_lib_ring_buffer_config client_config;
-
-static inline
-u64 lib_ring_buffer_clock_read(struct channel *chan)
-{
-       return 0;
-}
-
-static inline
-unsigned char record_header_size(const struct lttng_ust_lib_ring_buffer_config *config,
-                                struct channel *chan, size_t offset,
-                                size_t *pre_header_padding,
-                                struct lttng_ust_lib_ring_buffer_ctx *ctx)
-{
-       return 0;
-}
-
-#include "../libringbuffer/api.h"
-
-static u64 client_ring_buffer_clock_read(struct channel *chan)
-{
-       return 0;
-}
-
-static
-size_t client_record_header_size(const struct lttng_ust_lib_ring_buffer_config *config,
-                                struct channel *chan, size_t offset,
-                                size_t *pre_header_padding,
-                                struct lttng_ust_lib_ring_buffer_ctx *ctx)
-{
-       return 0;
-}
-
-/**
- * client_packet_header_size - called on buffer-switch to a new sub-buffer
- *
- * Return header size without padding after the structure. Don't use packed
- * structure because gcc generates inefficient code on some architectures
- * (powerpc, mips..)
- */
-static size_t client_packet_header_size(void)
-{
-       return offsetof(struct metadata_packet_header, header_end);
-}
-
-static void client_buffer_begin(struct lttng_ust_lib_ring_buffer *buf, u64 tsc,
-                               unsigned int subbuf_idx,
-                               struct lttng_ust_shm_handle *handle)
-{
-       struct channel *chan = shmp(handle, buf->backend.chan);
-       struct metadata_packet_header *header =
-               (struct metadata_packet_header *)
-                       lib_ring_buffer_offset_address(&buf->backend,
-                               subbuf_idx * chan->backend.subbuf_size,
-                               handle);
-       struct ltt_channel *ltt_chan = channel_get_private(chan);
-       struct ltt_session *session = ltt_chan->session;
-
-       header->magic = TSDL_MAGIC_NUMBER;
-       memcpy(header->uuid, session->uuid, sizeof(session->uuid));
-       header->checksum = 0;           /* 0 if unused */
-       header->content_size = 0xFFFFFFFF; /* in bits, for debugging */
-       header->packet_size = 0xFFFFFFFF;  /* in bits, for debugging */
-       header->compression_scheme = 0; /* 0 if unused */
-       header->encryption_scheme = 0;  /* 0 if unused */
-       header->checksum_scheme = 0;    /* 0 if unused */
-       header->major = CTF_SPEC_MAJOR;
-       header->minor = CTF_SPEC_MINOR;
-
-}
-
-/*
- * offset is assumed to never be 0 here : never deliver a completely empty
- * subbuffer. data_size is between 1 and subbuf_size.
- */
-static void client_buffer_end(struct lttng_ust_lib_ring_buffer *buf, u64 tsc,
-                             unsigned int subbuf_idx, unsigned long data_size,
-                             struct lttng_ust_shm_handle *handle)
-{
-       struct channel *chan = shmp(handle, buf->backend.chan);
-       struct metadata_packet_header *header =
-               (struct metadata_packet_header *)
-                       lib_ring_buffer_offset_address(&buf->backend,
-                               subbuf_idx * chan->backend.subbuf_size,
-                               handle);
-       unsigned long records_lost = 0;
-
-       header->content_size = data_size * CHAR_BIT;            /* in bits */
-       header->packet_size = PAGE_ALIGN(data_size) * CHAR_BIT; /* in bits */
-       records_lost += lib_ring_buffer_get_records_lost_full(&client_config, buf);
-       records_lost += lib_ring_buffer_get_records_lost_wrap(&client_config, buf);
-       records_lost += lib_ring_buffer_get_records_lost_big(&client_config, buf);
-       WARN_ON_ONCE(records_lost != 0);
-}
-
-static int client_buffer_create(struct lttng_ust_lib_ring_buffer *buf, void *priv,
-                               int cpu, const char *name,
-                               struct lttng_ust_shm_handle *handle)
-{
-       return 0;
-}
-
-static void client_buffer_finalize(struct lttng_ust_lib_ring_buffer *buf,
-                                  void *priv, int cpu,
-                                  struct lttng_ust_shm_handle *handle)
-{
-}
-
-static const struct lttng_ust_lib_ring_buffer_config client_config = {
-       .cb.ring_buffer_clock_read = client_ring_buffer_clock_read,
-       .cb.record_header_size = client_record_header_size,
-       .cb.subbuffer_header_size = client_packet_header_size,
-       .cb.buffer_begin = client_buffer_begin,
-       .cb.buffer_end = client_buffer_end,
-       .cb.buffer_create = client_buffer_create,
-       .cb.buffer_finalize = client_buffer_finalize,
-
-       .tsc_bits = 0,
-       .alloc = RING_BUFFER_ALLOC_GLOBAL,
-       .sync = RING_BUFFER_SYNC_GLOBAL,
-       .mode = RING_BUFFER_MODE_TEMPLATE,
-       .backend = RING_BUFFER_PAGE,
-       .output = RING_BUFFER_MMAP,
-       .oops = RING_BUFFER_OOPS_CONSISTENCY,
-       .ipi = RING_BUFFER_NO_IPI_BARRIER,
-       .wakeup = RING_BUFFER_WAKEUP_BY_WRITER,
-};
-
-static
-struct ltt_channel *_channel_create(const char *name,
-                               struct ltt_channel *ltt_chan, void *buf_addr,
-                               size_t subbuf_size, size_t num_subbuf,
-                               unsigned int switch_timer_interval,
-                               unsigned int read_timer_interval,
-                               int *shm_fd, int *wait_fd,
-                               uint64_t *memory_map_size)
-{
-       ltt_chan->handle = channel_create(&client_config, name, ltt_chan, buf_addr,
-                             subbuf_size, num_subbuf, switch_timer_interval,
-                             read_timer_interval, shm_fd, wait_fd,
-                             memory_map_size);
-       if (!ltt_chan->handle)
-               return NULL;
-       ltt_chan->chan = shmp(ltt_chan->handle, ltt_chan->handle->chan);
-       return ltt_chan;
-}
-
-static
-void ltt_channel_destroy(struct ltt_channel *ltt_chan)
-{
-       channel_destroy(ltt_chan->chan, ltt_chan->handle, 0);
-}
-
-static
-struct lttng_ust_lib_ring_buffer *ltt_buffer_read_open(struct channel *chan,
-                                            struct lttng_ust_shm_handle *handle,
-                                            int *shm_fd, int *wait_fd,
-                                            uint64_t *memory_map_size)
-{
-       struct lttng_ust_lib_ring_buffer *buf;
-
-       buf = channel_get_ring_buffer(&client_config, chan,
-                       0, handle, shm_fd, wait_fd, memory_map_size);
-       if (!lib_ring_buffer_open_read(buf, handle, 0))
-               return buf;
-       return NULL;
-}
-
-static
-void ltt_buffer_read_close(struct lttng_ust_lib_ring_buffer *buf,
-                          struct lttng_ust_shm_handle *handle)
-{
-       lib_ring_buffer_release_read(buf, handle, 0);
-}
-
-static
-int ltt_event_reserve(struct lttng_ust_lib_ring_buffer_ctx *ctx, uint32_t event_id)
-{
-       return lib_ring_buffer_reserve(&client_config, ctx);
-}
-
-static
-void ltt_event_commit(struct lttng_ust_lib_ring_buffer_ctx *ctx)
-{
-       lib_ring_buffer_commit(&client_config, ctx);
-}
-
-static
-void ltt_event_write(struct lttng_ust_lib_ring_buffer_ctx *ctx, const void *src,
-                    size_t len)
-{
-       lib_ring_buffer_write(&client_config, ctx, src, len);
-}
-
-static
-size_t ltt_packet_avail_size(struct channel *chan, struct lttng_ust_shm_handle *handle)
-                            
-{
-       unsigned long o_begin;
-       struct lttng_ust_lib_ring_buffer *buf;
-
-       buf = shmp(handle, chan->backend.buf[0].shmp);  /* Only for global buffer ! */
-       o_begin = v_read(&client_config, &buf->offset);
-       if (subbuf_offset(o_begin, chan) != 0) {
-               return chan->backend.subbuf_size - subbuf_offset(o_begin, chan);
-       } else {
-               return chan->backend.subbuf_size - subbuf_offset(o_begin, chan)
-                       - sizeof(struct metadata_packet_header);
-       }
-}
-
-#if 0
-static
-wait_queue_head_t *ltt_get_reader_wait_queue(struct channel *chan)
-{
-       return &chan->read_wait;
-}
-
-static
-wait_queue_head_t *ltt_get_hp_wait_queue(struct channel *chan)
-{
-       return &chan->hp_wait;
-}
-#endif //0
-
-static
-int ltt_is_finalized(struct channel *chan)
-{
-       return lib_ring_buffer_channel_is_finalized(chan);
-}
-
-static
-int ltt_is_disabled(struct channel *chan)
-{
-       return lib_ring_buffer_channel_is_disabled(chan);
-}
-
-static
-int ltt_flush_buffer(struct channel *chan, struct lttng_ust_shm_handle *handle)
-{
-       struct lttng_ust_lib_ring_buffer *buf;
-       int shm_fd, wait_fd;
-       uint64_t memory_map_size;
-
-       buf = channel_get_ring_buffer(&client_config, chan,
-                       0, handle, &shm_fd, &wait_fd,
-                       &memory_map_size);
-       lib_ring_buffer_switch(&client_config, buf,
-                       SWITCH_ACTIVE, handle);
-       return 0;
-}
-
-static struct ltt_transport ltt_relay_transport = {
-       .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING "-mmap",
-       .ops = {
-               .channel_create = _channel_create,
-               .channel_destroy = ltt_channel_destroy,
-               .buffer_read_open = ltt_buffer_read_open,
-               .buffer_read_close = ltt_buffer_read_close,
-               .event_reserve = ltt_event_reserve,
-               .event_commit = ltt_event_commit,
-               .event_write = ltt_event_write,
-               .packet_avail_size = ltt_packet_avail_size,
-               //.get_reader_wait_queue = ltt_get_reader_wait_queue,
-               //.get_hp_wait_queue = ltt_get_hp_wait_queue,
-               .is_finalized = ltt_is_finalized,
-               .is_disabled = ltt_is_disabled,
-               .flush_buffer = ltt_flush_buffer,
-       },
-};
-
-void RING_BUFFER_MODE_TEMPLATE_INIT(void)
-{
-       DBG("LTT : ltt ring buffer client init\n");
-       ltt_transport_register(&ltt_relay_transport);
-}
-
-void RING_BUFFER_MODE_TEMPLATE_EXIT(void)
-{
-       DBG("LTT : ltt ring buffer client exit\n");
-       ltt_transport_unregister(&ltt_relay_transport);
-}
diff --git a/libust/ltt-tracer-core.h b/libust/ltt-tracer-core.h
deleted file mode 100644 (file)
index 20ed0c0..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef _LTT_TRACER_CORE_H
-#define _LTT_TRACER_CORE_H
-
-/*
- * Copyright (C) 2005-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * This contains the core definitions for the Linux Trace Toolkit.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; version 2.1 of
- * the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-#include <lttng/kcompat/kcompat.h>
-#include <lttng/core.h>
-#include <lttng/ust-tracer.h>
-#include <urcu/list.h>
-#include <lttng/usterr-signal-safe.h>
-#include "lttng/bug.h"
-
-#include <lttng/ringbuffer-config.h>
-
-struct ltt_session;
-struct ltt_channel;
-struct ltt_event;
-
-void ust_lock(void);
-void ust_unlock(void);
-
-#endif /* _LTT_TRACER_CORE_H */
diff --git a/libust/ltt-tracer.h b/libust/ltt-tracer.h
deleted file mode 100644 (file)
index 6ab80e7..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef _LTT_TRACER_H
-#define _LTT_TRACER_H
-
-/*
- * Copyright (C) 2005-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * This contains the definitions for the Linux Trace Toolkit tracer.
- *
- * Ported to userspace by Pierre-Marc Fournier.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; version 2.1 of
- * the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-#include <stdarg.h>
-#include <stdint.h>
-#include <lttng/core.h>
-#include <lttng/compat.h>
-#include <lttng/ust-events.h>
-#include "ltt-tracer-core.h"
-
-/* Number of bytes to log with a read/write event */
-#define LTT_LOG_RW_SIZE                        32L
-#define LTT_MAX_SMALL_SIZE             0xFFFFU
-
-/* Tracer properties */
-#define CTF_MAGIC_NUMBER               0xC1FC1FC1
-#define TSDL_MAGIC_NUMBER              0x75D11D57
-
-/* CTF specification version followed */
-#define CTF_SPEC_MAJOR                 1
-#define CTF_SPEC_MINOR                 8
-
-/* Tracer major/minor versions */
-#define CTF_VERSION_MAJOR              0
-#define CTF_VERSION_MINOR              1
-
-/*
- * Number of milliseconds to retry before failing metadata writes on buffer full
- * condition. (10 seconds)
- */
-#define LTTNG_METADATA_TIMEOUT_MSEC    10000
-
-#define LTT_RFLAG_EXTENDED             RING_BUFFER_RFLAG_END
-#define LTT_RFLAG_END                  (LTT_RFLAG_EXTENDED << 1)
-
-#endif /* _LTT_TRACER_H */
diff --git a/libust/lttng-context-procname.c b/libust/lttng-context-procname.c
deleted file mode 100644 (file)
index b9bae82..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * (C) Copyright       2009-2011 -
- *             Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * LTTng UST procname context.
- *
- * Dual LGPL v2.1/GPL v2 license.
- */
-
-#include <sys/prctl.h>
-#include <lttng/ust-events.h>
-#include <lttng/ust-tracer.h>
-#include <lttng/ringbuffer-config.h>
-#include <assert.h>
-
-#define PROCNAME_LEN   17      /* includes \0 */
-
-/*
- * We cache the result to ensure we don't trigger a system call for
- * each event.
- * Upon exec, procname changes, but exec takes care of throwing away
- * this cached version.
- */
-static char cached_procname[17];
-
-static inline
-char *wrapper_getprocname(void)
-{
-       int ret;
-
-       if (caa_unlikely(!cached_procname[0])) {
-               ret = prctl(PR_GET_NAME, (unsigned long) cached_procname,
-                       0, 0, 0);
-               assert(!ret);
-       }
-       return cached_procname;
-}
-
-void lttng_context_procname_reset(void)
-{
-       cached_procname[0] = '\0';
-}
-
-static
-size_t procname_get_size(size_t offset)
-{
-       size_t size = 0;
-
-       size += PROCNAME_LEN;
-       return size;
-}
-
-static
-void procname_record(struct lttng_ctx_field *field,
-                struct lttng_ust_lib_ring_buffer_ctx *ctx,
-                struct ltt_channel *chan)
-{
-       char *procname;
-
-       procname = wrapper_getprocname();
-       chan->ops->event_write(ctx, procname, PROCNAME_LEN);
-}
-
-int lttng_add_procname_to_ctx(struct lttng_ctx **ctx)
-{
-       struct lttng_ctx_field *field;
-
-       field = lttng_append_context(ctx);
-       if (!field)
-               return -ENOMEM;
-       if (lttng_find_context(*ctx, "procname")) {
-               lttng_remove_context_field(ctx, field);
-               return -EEXIST;
-       }
-       field->event_field.name = "procname";
-       field->event_field.type.atype = atype_array;
-       field->event_field.type.u.array.elem_type.atype = atype_integer;
-       field->event_field.type.u.array.elem_type.u.basic.integer.size = sizeof(char) * CHAR_BIT;
-       field->event_field.type.u.array.elem_type.u.basic.integer.alignment = lttng_alignof(char) * CHAR_BIT;
-       field->event_field.type.u.array.elem_type.u.basic.integer.signedness = lttng_is_signed_type(char);
-       field->event_field.type.u.array.elem_type.u.basic.integer.reverse_byte_order = 0;
-       field->event_field.type.u.array.elem_type.u.basic.integer.base = 10;
-       field->event_field.type.u.array.elem_type.u.basic.integer.encoding = lttng_encode_UTF8;
-       field->event_field.type.u.array.length = PROCNAME_LEN;
-       field->get_size = procname_get_size;
-       field->record = procname_record;
-       return 0;
-}
diff --git a/libust/lttng-context-pthread-id.c b/libust/lttng-context-pthread-id.c
deleted file mode 100644 (file)
index 62eda80..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * (C) Copyright       2009-2011 -
- *             Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * LTTng UST pthread_id context.
- *
- * Dual LGPL v2.1/GPL v2 license.
- */
-
-#include <pthread.h>
-#include <lttng/ust-events.h>
-#include <lttng/ust-tracer.h>
-#include <lttng/ringbuffer-config.h>
-
-static
-size_t pthread_id_get_size(size_t offset)
-{
-       size_t size = 0;
-
-       size += lib_ring_buffer_align(offset, lttng_alignof(unsigned long));
-       size += sizeof(unsigned long);
-       return size;
-}
-
-static
-void pthread_id_record(struct lttng_ctx_field *field,
-                struct lttng_ust_lib_ring_buffer_ctx *ctx,
-                struct ltt_channel *chan)
-{
-       unsigned long pthread_id;
-
-       pthread_id = (unsigned long) pthread_self();
-       lib_ring_buffer_align_ctx(ctx, lttng_alignof(pthread_id));
-       chan->ops->event_write(ctx, &pthread_id, sizeof(pthread_id));
-}
-
-int lttng_add_pthread_id_to_ctx(struct lttng_ctx **ctx)
-{
-       struct lttng_ctx_field *field;
-
-       field = lttng_append_context(ctx);
-       if (!field)
-               return -ENOMEM;
-       if (lttng_find_context(*ctx, "pthread_id")) {
-               lttng_remove_context_field(ctx, field);
-               return -EEXIST;
-       }
-       field->event_field.name = "pthread_id";
-       field->event_field.type.atype = atype_integer;
-       field->event_field.type.u.basic.integer.size = sizeof(unsigned long) * CHAR_BIT;
-       field->event_field.type.u.basic.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT;
-       field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(unsigned long);
-       field->event_field.type.u.basic.integer.reverse_byte_order = 0;
-       field->event_field.type.u.basic.integer.base = 10;
-       field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
-       field->get_size = pthread_id_get_size;
-       field->record = pthread_id_record;
-       return 0;
-}
diff --git a/libust/lttng-context-vpid.c b/libust/lttng-context-vpid.c
deleted file mode 100644 (file)
index db76747..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * (C) Copyright       2009-2011 -
- *             Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * LTTng UST vpid context.
- *
- * Dual LGPL v2.1/GPL v2 license.
- */
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <lttng/ust-events.h>
-#include <lttng/ust-tracer.h>
-#include <lttng/ringbuffer-config.h>
-
-#ifdef __linux__
-static inline
-pid_t wrapper_getpid(void)
-{
-       return getpid();
-}
-
-void lttng_context_vpid_reset(void)
-{
-}
-#else
-/*
- * We cache the result to ensure we don't trigger a system call for
- * each event.
- */
-static pid_t cached_vpid;
-
-static inline
-pid_t wrapper_getpid(void)
-{
-       if (caa_unlikely(!cached_vpid))
-               cached_vpid = getpid();
-       return cached_vpid;
-}
-
-/*
- * Upon fork or clone, the PID assigned to our thread is not the same as
- * we kept in cache.
- */
-void lttng_context_vpid_reset(void)
-{
-       cached_vpid = 0;
-}
-#endif
-
-static
-size_t vpid_get_size(size_t offset)
-{
-       size_t size = 0;
-
-       size += lib_ring_buffer_align(offset, lttng_alignof(pid_t));
-       size += sizeof(pid_t);
-       return size;
-}
-
-static
-void vpid_record(struct lttng_ctx_field *field,
-                struct lttng_ust_lib_ring_buffer_ctx *ctx,
-                struct ltt_channel *chan)
-{
-       pid_t pid;
-
-       pid = wrapper_getpid();
-       lib_ring_buffer_align_ctx(ctx, lttng_alignof(pid));
-       chan->ops->event_write(ctx, &pid, sizeof(pid));
-}
-
-int lttng_add_vpid_to_ctx(struct lttng_ctx **ctx)
-{
-       struct lttng_ctx_field *field;
-
-       field = lttng_append_context(ctx);
-       if (!field)
-               return -ENOMEM;
-       if (lttng_find_context(*ctx, "vpid")) {
-               lttng_remove_context_field(ctx, field);
-               return -EEXIST;
-       }
-       field->event_field.name = "vpid";
-       field->event_field.type.atype = atype_integer;
-       field->event_field.type.u.basic.integer.size = sizeof(pid_t) * CHAR_BIT;
-       field->event_field.type.u.basic.integer.alignment = lttng_alignof(pid_t) * CHAR_BIT;
-       field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(pid_t);
-       field->event_field.type.u.basic.integer.reverse_byte_order = 0;
-       field->event_field.type.u.basic.integer.base = 10;
-       field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
-       field->get_size = vpid_get_size;
-       field->record = vpid_record;
-       return 0;
-}
diff --git a/libust/lttng-context-vtid.c b/libust/lttng-context-vtid.c
deleted file mode 100644 (file)
index 6f7e078..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * (C) Copyright       2009-2011 -
- *             Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * LTTng UST vtid context.
- *
- * Dual LGPL v2.1/GPL v2 license.
- */
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <lttng/ust-events.h>
-#include <lttng/ust-tracer.h>
-#include <lttng/ringbuffer-config.h>
-
-#ifdef __linux__
-#include <syscall.h>
-#endif
-
-#if defined(_syscall0)
-_syscall0(pid_t, gettid)
-#elif defined(__NR_gettid)
-static inline pid_t gettid(void)
-{
-       return syscall(__NR_gettid);
-}
-#else
-#warning "use pid as tid"
-static inline pid_t gettid(void)
-{
-       return getpid();
-}
-#endif
-
-/*
- * We cache the result to ensure we don't trigger a system call for
- * each event.
- */
-static __thread pid_t cached_vtid;
-
-/*
- * Upon fork or clone, the TID assigned to our thread is not the same as
- * we kept in cache. Luckily, we are the only thread surviving in the
- * child process, so we can simply clear our cached version.
- */
-void lttng_context_vtid_reset(void)
-{
-       cached_vtid = 0;
-}
-
-static
-size_t vtid_get_size(size_t offset)
-{
-       size_t size = 0;
-
-       size += lib_ring_buffer_align(offset, lttng_alignof(pid_t));
-       size += sizeof(pid_t);
-       return size;
-}
-
-static
-void vtid_record(struct lttng_ctx_field *field,
-                struct lttng_ust_lib_ring_buffer_ctx *ctx,
-                struct ltt_channel *chan)
-{
-       if (caa_unlikely(!cached_vtid))
-               cached_vtid = gettid();
-       lib_ring_buffer_align_ctx(ctx, lttng_alignof(cached_vtid));
-       chan->ops->event_write(ctx, &cached_vtid, sizeof(cached_vtid));
-}
-
-int lttng_add_vtid_to_ctx(struct lttng_ctx **ctx)
-{
-       struct lttng_ctx_field *field;
-
-       field = lttng_append_context(ctx);
-       if (!field)
-               return -ENOMEM;
-       if (lttng_find_context(*ctx, "vtid")) {
-               lttng_remove_context_field(ctx, field);
-               return -EEXIST;
-       }
-       field->event_field.name = "vtid";
-       field->event_field.type.atype = atype_integer;
-       field->event_field.type.u.basic.integer.size = sizeof(pid_t) * CHAR_BIT;
-       field->event_field.type.u.basic.integer.alignment = lttng_alignof(pid_t) * CHAR_BIT;
-       field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(pid_t);
-       field->event_field.type.u.basic.integer.reverse_byte_order = 0;
-       field->event_field.type.u.basic.integer.base = 10;
-       field->event_field.type.u.basic.integer.encoding = lttng_encode_none;
-       field->get_size = vtid_get_size;
-       field->record = vtid_record;
-       return 0;
-}
diff --git a/libust/lttng-ust-abi.c b/libust/lttng-ust-abi.c
deleted file mode 100644 (file)
index 6d17c20..0000000
+++ /dev/null
@@ -1,822 +0,0 @@
-/*
- * lttng-ust-abi.c
- *
- * Copyright 2010-2011 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * LTTng UST ABI
- *
- * Mimic system calls for:
- * - session creation, returns an object descriptor or failure.
- *   - channel creation, returns an object descriptor or failure.
- *     - Operates on a session object descriptor
- *     - Takes all channel options as parameters.
- *   - stream get, returns an object descriptor or failure.
- *     - Operates on a channel object descriptor.
- *   - stream notifier get, returns an object descriptor or failure.
- *     - Operates on a channel object descriptor.
- *   - event creation, returns an object descriptor or failure.
- *     - Operates on a channel object descriptor
- *     - Takes an event name as parameter
- *     - Takes an instrumentation source as parameter
- *       - e.g. tracepoints, dynamic_probes...
- *     - Takes instrumentation source specific arguments.
- *
- * Dual LGPL v2.1/GPL v2 license.
- */
-
-#include <lttng/ust-abi.h>
-#include <urcu/compiler.h>
-#include <urcu/list.h>
-#include <lttng/ust-events.h>
-#include <lttng/usterr-signal-safe.h>
-#include "lttng/core.h"
-#include "ltt-tracer.h"
-
-/*
- * Object descriptor table. Should be protected from concurrent access
- * by the caller.
- */
-
-struct lttng_ust_obj {
-       union {
-               struct {
-                       void *private_data;
-                       const struct lttng_ust_objd_ops *ops;
-                       int f_count;
-               } s;
-               int freelist_next;      /* offset freelist. end is -1. */
-       } u;
-};
-
-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 lttng_ust_objd_table objd_table = {
-       .freelist_head = -1,
-};
-
-static
-int objd_alloc(void *private_data, const struct lttng_ust_objd_ops *ops)
-{
-       struct lttng_ust_obj *obj;
-
-       if (objd_table.freelist_head != -1) {
-               obj = &objd_table.array[objd_table.freelist_head];
-               objd_table.freelist_head = obj->u.freelist_next;
-               goto end;
-       }
-
-       if (objd_table.len >= objd_table.allocated_len) {
-               unsigned int new_allocated_len, old_allocated_len;
-               struct lttng_ust_obj *new_table, *old_table;
-
-               old_allocated_len = objd_table.allocated_len;
-               old_table = objd_table.array;
-               if (!old_allocated_len)
-                       new_allocated_len = 1;
-               else
-                       new_allocated_len = old_allocated_len << 1;
-               new_table = zmalloc(sizeof(struct lttng_ust_obj) * new_allocated_len);
-               if (!new_table)
-                       return -ENOMEM;
-               memcpy(new_table, old_table,
-                      sizeof(struct lttng_ust_obj) * old_allocated_len);
-               free(old_table);
-               objd_table.array = new_table;
-               objd_table.allocated_len = new_allocated_len;
-       }
-       obj = &objd_table.array[objd_table.len];
-       objd_table.len++;
-end:
-       obj->u.s.private_data = private_data;
-       obj->u.s.ops = ops;
-       obj->u.s.f_count = 2;   /* count == 1 : object is allocated */
-                               /* count == 2 : allocated + hold ref */
-       return obj - objd_table.array;
-}
-
-static
-struct lttng_ust_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];
-}
-
-static
-void *objd_private(int 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 lttng_ust_obj *obj = _objd_get(id);
-       assert(obj);
-       obj->u.s.private_data = private_data;
-}
-
-const struct lttng_ust_objd_ops *objd_ops(int id)
-{
-       struct lttng_ust_obj *obj = _objd_get(id);
-
-       if (!obj)
-               return NULL;
-       return obj->u.s.ops;
-}
-
-static
-void objd_free(int id)
-{
-       struct lttng_ust_obj *obj = _objd_get(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
-void objd_ref(int id)
-{
-       struct lttng_ust_obj *obj = _objd_get(id);
-       obj->u.s.f_count++;
-}
-
-int lttng_ust_objd_unref(int id)
-{
-       struct lttng_ust_obj *obj = _objd_get(id);
-
-       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 lttng_ust_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) lttng_ust_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;
-}
-
-/*
- * This is LTTng's own personal way to create an ABI for sessiond.
- * We send commands over a socket.
- */
-
-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,
-       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)
-{
-       struct ltt_session *session;
-       int session_objd, ret;
-
-       session = ltt_session_create();
-       if (!session)
-               return -ENOMEM;
-       session_objd = objd_alloc(session, &lttng_session_ops);
-       if (session_objd < 0) {
-               ret = session_objd;
-               goto objd_error;
-       }
-       session->objd = session_objd;
-       return session_objd;
-
-objd_error:
-       ltt_session_destroy(session);
-       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, &lttng_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;
-       return 0;
-}
-
-static
-long lttng_abi_add_context(int objd,
-       struct lttng_ust_context *context_param,
-       struct lttng_ctx **ctx, struct ltt_session *session)
-{
-       if (session->been_active)
-               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:
-               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;
-       }
-}
-
-/**
- *     lttng_cmd - lttng control through socket commands
- *
- *     @objd: the object descriptor
- *     @cmd: the command
- *     @arg: command arg
- *
- *     This descriptor implements lttng commands:
- *     LTTNG_UST_SESSION
- *             Returns a LTTng trace session object descriptor
- *     LTTNG_UST_TRACER_VERSION
- *             Returns the LTTng kernel tracer version
- *     LTTNG_UST_TRACEPOINT_LIST
- *             Returns a file descriptor listing available tracepoints
- *     LTTNG_UST_WAIT_QUIESCENT
- *             Returns after all previously running probes have completed
- *
- * The returned session will be deleted when its file descriptor is closed.
- */
-static
-long lttng_cmd(int objd, unsigned int cmd, unsigned long arg)
-{
-       switch (cmd) {
-       case LTTNG_UST_SESSION:
-               return lttng_abi_create_session();
-       case LTTNG_UST_TRACER_VERSION:
-               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();
-       case LTTNG_UST_WAIT_QUIESCENT:
-               synchronize_trace();
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-static const struct lttng_ust_objd_ops lttng_ops = {
-       .cmd = lttng_cmd,
-};
-
-/*
- * We tolerate no failure in this function (if one happens, we print a dmesg
- * error, but cannot return any error, because the channel information is
- * invariant.
- */
-static
-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",
-       };
-       struct ltt_event *event;
-       int ret;
-
-       /*
-        * We tolerate no failure path after event creation. It will stay
-        * invariant for the rest of the session.
-        */
-       event = ltt_event_create(channel, &metadata_params, NULL);
-       if (!event) {
-               ret = -EINVAL;
-               goto create_error;
-       }
-       return;
-
-create_error:
-       WARN_ON(1);
-       return;         /* not allowed to return error */
-}
-
-int lttng_abi_create_channel(int session_objd,
-                            struct lttng_ust_channel *chan_param,
-                            enum channel_type channel_type)
-{
-       struct ltt_session *session = objd_private(session_objd);
-       const struct lttng_ust_objd_ops *ops;
-       const char *transport_name;
-       struct ltt_channel *chan;
-       int chan_objd;
-       int ret = 0;
-
-       chan_objd = objd_alloc(NULL, &lttng_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) {
-                       transport_name = chan_param->overwrite ?
-                               "relay-overwrite-mmap" : "relay-discard-mmap";
-               } else {
-                       return -EINVAL;
-               }
-               ops = &lttng_channel_ops;
-               break;
-       case METADATA_CHANNEL:
-               if (chan_param->output == LTTNG_UST_MMAP)
-                       transport_name = "relay-metadata-mmap";
-               else
-                       return -EINVAL;
-               ops = &lttng_metadata_ops;
-               break;
-       default:
-               transport_name = "<unknown>";
-               break;
-       }
-       /*
-        * We tolerate no failure path after channel creation. It will stay
-        * invariant for the rest of the session.
-        */
-       chan = ltt_channel_create(session, transport_name, NULL,
-                                 chan_param->subbuf_size,
-                                 chan_param->num_subbuf,
-                                 chan_param->switch_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;
-       }
-       objd_set_private(chan_objd, chan);
-       chan->objd = chan_objd;
-       if (channel_type == METADATA_CHANNEL) {
-               session->metadata = chan;
-               lttng_metadata_create_events(chan_objd);
-       }
-
-       /* The channel created holds a reference on the session */
-       objd_ref(session_objd);
-
-       return chan_objd;
-
-chan_error:
-       {
-               int err;
-
-               err = lttng_ust_objd_unref(chan_objd);
-               assert(!err);
-       }
-objd_error:
-       return ret;
-}
-
-/**
- *     lttng_session_cmd - lttng session object command
- *
- *     @obj: the object
- *     @cmd: the command
- *     @arg: command arg
- *
- *     This descriptor implements lttng commands:
- *     LTTNG_UST_CHANNEL
- *             Returns a LTTng channel object descriptor
- *     LTTNG_UST_ENABLE
- *             Enables tracing for a session (weak enable)
- *     LTTNG_UST_DISABLE
- *             Disables tracing for a session (strong disable)
- *     LTTNG_UST_METADATA
- *             Returns a LTTng metadata object descriptor
- *
- * The returned channel will be deleted when its file descriptor is closed.
- */
-static
-long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg)
-{
-       struct ltt_session *session = objd_private(objd);
-
-       switch (cmd) {
-       case LTTNG_UST_CHANNEL:
-               return lttng_abi_create_channel(objd,
-                               (struct lttng_ust_channel *) arg,
-                               PER_CPU_CHANNEL);
-       case LTTNG_UST_SESSION_START:
-       case LTTNG_UST_ENABLE:
-               return ltt_session_enable(session);
-       case LTTNG_UST_SESSION_STOP:
-       case LTTNG_UST_DISABLE:
-               return ltt_session_disable(session);
-       case LTTNG_UST_METADATA:
-               return lttng_abi_create_channel(objd,
-                               (struct lttng_ust_channel *) arg,
-                               METADATA_CHANNEL);
-       default:
-               return -EINVAL;
-       }
-}
-
-/*
- * Called when the last file reference is dropped.
- *
- * Big fat note: channels and events are invariant for the whole session after
- * their creation. So this session destruction also destroys all channel and
- * event structures specific to this session (they are not destroyed when their
- * individual file is released).
- */
-static
-int lttng_release_session(int objd)
-{
-       struct ltt_session *session = objd_private(objd);
-
-       if (session) {
-               ltt_session_destroy(session);
-               return 0;
-       } else {
-               return -EINVAL;
-       }
-}
-
-static const struct lttng_ust_objd_ops lttng_session_ops = {
-       .release = lttng_release_session,
-       .cmd = lttng_session_cmd,
-};
-
-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, struct lttng_ust_stream *info)
-{
-       struct ltt_channel *channel = objd_private(channel_objd);
-       struct lttng_ust_lib_ring_buffer *buf;
-       struct stream_priv_data *priv;
-       int stream_objd, ret;
-
-       buf = channel->ops->buffer_read_open(channel->chan, channel->handle,
-                       &info->shm_fd, &info->wait_fd, &info->memory_map_size);
-       if (!buf)
-               return -ENOENT;
-
-       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;
-       }
-       /* Hold a reference on the channel object descriptor */
-       objd_ref(channel_objd);
-       return stream_objd;
-
-objd_error:
-       free(priv);
-alloc_error:
-       channel->ops->buffer_read_close(buf, channel->handle);
-       return ret;
-}
-
-static
-int lttng_abi_create_event(int channel_objd,
-                          struct lttng_ust_event *event_param)
-{
-       struct ltt_channel *channel = objd_private(channel_objd);
-       struct ltt_event *event;
-       int event_objd, ret;
-
-       event_param->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
-       event_objd = objd_alloc(NULL, &lttng_event_ops);
-       if (event_objd < 0) {
-               ret = event_objd;
-               goto objd_error;
-       }
-       /*
-        * We tolerate no failure path after event creation. It will stay
-        * invariant for the rest of the session.
-        */
-       event = ltt_event_create(channel, event_param, NULL);
-       if (!event) {
-               ret = -EINVAL;
-               goto event_error;
-       }
-       objd_set_private(event_objd, event);
-       /* The event holds a reference on the channel */
-       objd_ref(channel_objd);
-       return event_objd;
-
-event_error:
-       {
-               int err;
-
-               err = lttng_ust_objd_unref(event_objd);
-               assert(!err);
-       }
-objd_error:
-       return ret;
-}
-
-/**
- *     lttng_channel_cmd - lttng control through object descriptors
- *
- *     @objd: the object descriptor
- *     @cmd: the command
- *     @arg: command arg
- *
- *     This object descriptor implements lttng commands:
- *      LTTNG_UST_STREAM
- *              Returns an event stream object descriptor or failure.
- *              (typically, one event stream records events from one CPU)
- *     LTTNG_UST_EVENT
- *             Returns an event object descriptor or failure.
- *     LTTNG_UST_CONTEXT
- *             Prepend a context field to each event in the channel
- *     LTTNG_UST_ENABLE
- *             Enable recording for events in this channel (weak enable)
- *     LTTNG_UST_DISABLE
- *             Disable recording for events in this channel (strong disable)
- *
- * Channel and event file descriptors also hold a reference on the session.
- */
-static
-long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg)
-{
-       struct ltt_channel *channel = objd_private(objd);
-
-       switch (cmd) {
-       case LTTNG_UST_STREAM:
-       {
-               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 lttng_abi_add_context(objd,
-                               (struct lttng_ust_context *) arg,
-                               &channel->ctx, channel->session);
-       case LTTNG_UST_ENABLE:
-               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;
-       }
-}
-
-/**
- *     lttng_metadata_cmd - lttng control through object descriptors
- *
- *     @objd: the object descriptor
- *     @cmd: the command
- *     @arg: command arg
- *
- *     This object descriptor implements lttng commands:
- *      LTTNG_UST_STREAM
- *              Returns an event stream file descriptor or failure.
- *
- * Channel and event file descriptors also hold a reference on the session.
- */
-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:
-       {
-               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;
-       }
-}
-
-#if 0
-/**
- *     lttng_channel_poll - lttng stream addition/removal monitoring
- *
- *     @file: the file
- *     @wait: poll table
- */
-unsigned int lttng_channel_poll(struct file *file, poll_table *wait)
-{
-       struct ltt_channel *channel = file->private_data;
-       unsigned int mask = 0;
-
-       if (file->f_mode & FMODE_READ) {
-               poll_wait_set_exclusive(wait);
-               poll_wait(file, channel->ops->get_hp_wait_queue(channel->chan),
-                         wait);
-
-               if (channel->ops->is_disabled(channel->chan))
-                       return POLLERR;
-               if (channel->ops->is_finalized(channel->chan))
-                       return POLLHUP;
-               if (channel->ops->buffer_has_read_closed_stream(channel->chan))
-                       return POLLIN | POLLRDNORM;
-               return 0;
-       }
-       return mask;
-
-}
-#endif //0
-
-static
-int lttng_channel_release(int objd)
-{
-       struct ltt_channel *channel = objd_private(objd);
-
-       if (channel)
-               return lttng_ust_objd_unref(channel->session->objd);
-       return 0;
-}
-
-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 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 lttng_ust_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
- *
- *     @objd: the object descriptor
- *     @cmd: the command
- *     @arg: command arg
- *
- *     This object descriptor implements lttng commands:
- *     LTTNG_UST_CONTEXT
- *             Prepend a context field to each record of this event
- *     LTTNG_UST_ENABLE
- *             Enable recording for this event (weak enable)
- *     LTTNG_UST_DISABLE
- *             Disable recording for this event (strong disable)
- */
-static
-long lttng_event_cmd(int objd, unsigned int cmd, unsigned long arg)
-{
-       struct ltt_event *event = objd_private(objd);
-
-       switch (cmd) {
-       case LTTNG_UST_CONTEXT:
-               return lttng_abi_add_context(objd,
-                               (struct lttng_ust_context *) arg,
-                               &event->ctx, event->chan->session);
-       case LTTNG_UST_ENABLE:
-               return ltt_event_enable(event);
-       case LTTNG_UST_DISABLE:
-               return ltt_event_disable(event);
-       default:
-               return -EINVAL;
-       }
-}
-
-static
-int lttng_event_release(int objd)
-{
-       struct ltt_event *event = objd_private(objd);
-
-       if (event)
-               return lttng_ust_objd_unref(event->chan->objd);
-       return 0;
-}
-
-/* TODO: filter control ioctl */
-static const struct lttng_ust_objd_ops lttng_event_ops = {
-       .release = lttng_event_release,
-       .cmd = lttng_event_cmd,
-};
-
-void lttng_ust_abi_exit(void)
-{
-       objd_table_destroy();
-}
diff --git a/libust/lttng-ust-comm.c b/libust/lttng-ust-comm.c
deleted file mode 100644 (file)
index 1246c65..0000000
+++ /dev/null
@@ -1,935 +0,0 @@
-/*
- * lttng-ust-comm.c
- *
- * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; only
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#define _LGPL_SOURCE
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/prctl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <pthread.h>
-#include <semaphore.h>
-#include <time.h>
-#include <assert.h>
-#include <signal.h>
-#include <urcu/uatomic.h>
-#include <urcu/futex.h>
-
-#include <lttng/ust-comm.h>
-#include <lttng/ust-events.h>
-#include <lttng/usterr-signal-safe.h>
-#include <lttng/ust-abi.h>
-#include <lttng/tracepoint.h>
-#include <lttng/tracepoint-internal.h>
-#include <lttng/ust.h>
-#include "ltt-tracer-core.h"
-
-/*
- * Has lttng ust comm constructor been called ?
- */
-static int initialized;
-
-/*
- * The ust_lock/ust_unlock lock is used as a communication thread mutex.
- * Held when handling a command, also held by fork() to deal with
- * removal of threads, and by exit path.
- */
-
-/* Should the ust comm thread quit ? */
-static int lttng_ust_comm_should_quit;
-
-/*
- * Wait for either of these before continuing to the main
- * program:
- * - the register_done message from sessiond daemon
- *   (will let the sessiond daemon enable sessions before main
- *   starts.)
- * - sessiond daemon is not reachable.
- * - timeout (ensuring applications are resilient to session
- *   daemon problems).
- */
-static sem_t constructor_wait;
-/*
- * Doing this for both the global and local sessiond.
- */
-static int sem_count = { 2 };
-
-/*
- * Info about socket and associated listener thread.
- */
-struct sock_info {
-       const char *name;
-       pthread_t ust_listener; /* listener thread */
-       int root_handle;
-       int constructor_sem_posted;
-       int allowed;
-       int global;
-
-       char sock_path[PATH_MAX];
-       int socket;
-
-       char wait_shm_path[PATH_MAX];
-       char *wait_shm_mmap;
-};
-
-/* Socket from app (connect) to session daemon (listen) for communication */
-struct sock_info global_apps = {
-       .name = "global",
-       .global = 1,
-
-       .root_handle = -1,
-       .allowed = 1,
-
-       .sock_path = DEFAULT_GLOBAL_APPS_UNIX_SOCK,
-       .socket = -1,
-
-       .wait_shm_path = DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH,
-};
-
-/* TODO: allow global_apps_sock_path override */
-
-struct sock_info local_apps = {
-       .name = "local",
-       .global = 0,
-       .root_handle = -1,
-       .allowed = 0,   /* Check setuid bit first */
-
-       .socket = -1,
-};
-
-static int wait_poll_fallback;
-
-extern void ltt_ring_buffer_client_overwrite_init(void);
-extern void ltt_ring_buffer_client_discard_init(void);
-extern void ltt_ring_buffer_metadata_client_init(void);
-extern void ltt_ring_buffer_client_overwrite_exit(void);
-extern void ltt_ring_buffer_client_discard_exit(void);
-extern void ltt_ring_buffer_metadata_client_exit(void);
-
-static
-int setup_local_apps(void)
-{
-       const char *home_dir;
-       uid_t uid;
-
-       uid = getuid();
-       /*
-        * Disallow per-user tracing for setuid binaries.
-        */
-       if (uid != geteuid()) {
-               local_apps.allowed = 0;
-               return 0;
-       } else {
-               local_apps.allowed = 1;
-       }
-       home_dir = (const char *) getenv("HOME");
-       if (!home_dir)
-               return -ENOENT;
-       snprintf(local_apps.sock_path, PATH_MAX,
-                DEFAULT_HOME_APPS_UNIX_SOCK, home_dir);
-       snprintf(local_apps.wait_shm_path, PATH_MAX,
-                DEFAULT_HOME_APPS_WAIT_SHM_PATH, uid);
-       return 0;
-}
-
-static
-int register_app_to_sessiond(int socket)
-{
-       ssize_t ret;
-       int prctl_ret;
-       struct {
-               uint32_t major;
-               uint32_t minor;
-               pid_t pid;
-               pid_t ppid;
-               uid_t uid;
-               gid_t gid;
-               char name[16];  /* process name */
-       } reg_msg;
-
-       reg_msg.major = LTTNG_UST_COMM_VERSION_MAJOR;
-       reg_msg.minor = LTTNG_UST_COMM_VERSION_MINOR;
-       reg_msg.pid = getpid();
-       reg_msg.ppid = getppid();
-       reg_msg.uid = getuid();
-       reg_msg.gid = getgid();
-       prctl_ret = prctl(PR_GET_NAME, (unsigned long) reg_msg.name, 0, 0, 0);
-       if (prctl_ret) {
-               ERR("Error executing prctl");
-               return -errno;
-       }
-
-       ret = ustcomm_send_unix_sock(socket, &reg_msg, sizeof(reg_msg));
-       if (ret >= 0 && ret != sizeof(reg_msg))
-               return -EIO;
-       return ret;
-}
-
-static
-int send_reply(int sock, struct ustcomm_ust_reply *lur)
-{
-       ssize_t len;
-
-       len = ustcomm_send_unix_sock(sock, lur, sizeof(*lur));
-       switch (len) {
-       case sizeof(*lur):
-               DBG("message successfully sent");
-               return 0;
-       case -1:
-               if (errno == ECONNRESET) {
-                       printf("remote end closed connection\n");
-                       return 0;
-               }
-               return -1;
-       default:
-               printf("incorrect message size: %zd\n", len);
-               return -1;
-       }
-}
-
-static
-int handle_register_done(struct sock_info *sock_info)
-{
-       int ret;
-
-       if (sock_info->constructor_sem_posted)
-               return 0;
-       sock_info->constructor_sem_posted = 1;
-       if (uatomic_read(&sem_count) <= 0) {
-               return 0;
-       }
-       ret = uatomic_add_return(&sem_count, -1);
-       if (ret == 0) {
-               ret = sem_post(&constructor_wait);
-               assert(!ret);
-       }
-       return 0;
-}
-
-static
-int handle_message(struct sock_info *sock_info,
-               int sock, struct ustcomm_ust_msg *lum)
-{
-       int ret = 0;
-       const struct lttng_ust_objd_ops *ops;
-       struct ustcomm_ust_reply lur;
-       int shm_fd, wait_fd;
-
-       ust_lock();
-
-       memset(&lur, 0, sizeof(lur));
-
-       if (lttng_ust_comm_should_quit) {
-               ret = -EPERM;
-               goto end;
-       }
-
-       ops = objd_ops(lum->handle);
-       if (!ops) {
-               ret = -ENOENT;
-               goto end;
-       }
-
-       switch (lum->cmd) {
-       case LTTNG_UST_REGISTER_DONE:
-               if (lum->handle == LTTNG_UST_ROOT_HANDLE)
-                       ret = handle_register_done(sock_info);
-               else
-                       ret = -EINVAL;
-               break;
-       case LTTNG_UST_RELEASE:
-               if (lum->handle == LTTNG_UST_ROOT_HANDLE)
-                       ret = -EPERM;
-               else
-                       ret = lttng_ust_objd_unref(lum->handle);
-               break;
-       default:
-               if (ops->cmd)
-                       ret = ops->cmd(lum->handle, lum->cmd,
-                                       (unsigned long) &lum->u);
-               else
-                       ret = -ENOSYS;
-               break;
-       }
-
-end:
-       lur.handle = lum->handle;
-       lur.cmd = lum->cmd;
-       lur.ret_val = ret;
-       if (ret >= 0) {
-               lur.ret_code = USTCOMM_OK;
-       } else {
-               //lur.ret_code = USTCOMM_SESSION_FAIL;
-               lur.ret_code = ret;
-       }
-       switch (lum->cmd) {
-       case LTTNG_UST_STREAM:
-               /*
-                * Special-case reply to send stream info.
-                * Use lum.u output.
-                */
-               lur.u.stream.memory_map_size = lum->u.stream.memory_map_size;
-               shm_fd = lum->u.stream.shm_fd;
-               wait_fd = lum->u.stream.wait_fd;
-               break;
-       case LTTNG_UST_METADATA:
-       case LTTNG_UST_CHANNEL:
-               lur.u.channel.memory_map_size = lum->u.channel.memory_map_size;
-               shm_fd = lum->u.channel.shm_fd;
-               wait_fd = lum->u.channel.wait_fd;
-               break;
-       case LTTNG_UST_VERSION:
-               lur.u.version = lum->u.version;
-               break;
-       }
-       ret = send_reply(sock, &lur);
-       if (ret < 0) {
-               perror("error sending reply");
-               goto error;
-       }
-
-       if ((lum->cmd == LTTNG_UST_STREAM
-            || lum->cmd == LTTNG_UST_CHANNEL
-            || lum->cmd == LTTNG_UST_METADATA)
-                       && lur.ret_code == USTCOMM_OK) {
-               /* we also need to send the file descriptors. */
-               ret = ustcomm_send_fds_unix_sock(sock,
-                       &shm_fd, &shm_fd,
-                       1, sizeof(int));
-               if (ret < 0) {
-                       perror("send shm_fd");
-                       goto error;
-               }
-               ret = ustcomm_send_fds_unix_sock(sock,
-                       &wait_fd, &wait_fd,
-                       1, sizeof(int));
-               if (ret < 0) {
-                       perror("send wait_fd");
-                       goto error;
-               }
-       }
-error:
-       ust_unlock();
-       return ret;
-}
-
-static
-void cleanup_sock_info(struct sock_info *sock_info)
-{
-       int ret;
-
-       if (sock_info->socket != -1) {
-               ret = close(sock_info->socket);
-               if (ret) {
-                       ERR("Error closing apps socket");
-               }
-               sock_info->socket = -1;
-       }
-       if (sock_info->root_handle != -1) {
-               ret = lttng_ust_objd_unref(sock_info->root_handle);
-               if (ret) {
-                       ERR("Error unref root handle");
-               }
-               sock_info->root_handle = -1;
-       }
-       sock_info->constructor_sem_posted = 0;
-       if (sock_info->wait_shm_mmap) {
-               ret = munmap(sock_info->wait_shm_mmap, sysconf(_SC_PAGE_SIZE));
-               if (ret) {
-                       ERR("Error unmapping wait shm");
-               }
-               sock_info->wait_shm_mmap = NULL;
-       }
-}
-
-/*
- * Using fork to set umask in the child process (not multi-thread safe).
- * We deal with the shm_open vs ftruncate race (happening when the
- * sessiond owns the shm and does not let everybody modify it, to ensure
- * safety against shm_unlink) by simply letting the mmap fail and
- * retrying after a few seconds.
- * For global shm, everybody has rw access to it until the sessiond
- * starts.
- */
-static
-int get_wait_shm(struct sock_info *sock_info, size_t mmap_size)
-{
-       int wait_shm_fd, ret;
-       pid_t pid;
-
-       /*
-        * Try to open read-only.
-        */
-       wait_shm_fd = shm_open(sock_info->wait_shm_path, O_RDONLY, 0);
-       if (wait_shm_fd >= 0) {
-               goto end;
-       } else if (wait_shm_fd < 0 && errno != ENOENT) {
-               /*
-                * Real-only open did not work, and it's not because the
-                * entry was not present. It's a failure that prohibits
-                * using shm.
-                */
-               ERR("Error opening shm %s", sock_info->wait_shm_path);
-               goto end;
-       }
-       /*
-        * If the open failed because the file did not exist, try
-        * creating it ourself.
-        */
-       pid = fork();
-       if (pid > 0) {
-               int status;
-
-               /*
-                * Parent: wait for child to return, in which case the
-                * shared memory map will have been created.
-                */
-               pid = wait(&status);
-               if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
-                       wait_shm_fd = -1;
-                       goto end;
-               }
-               /*
-                * Try to open read-only again after creation.
-                */
-               wait_shm_fd = shm_open(sock_info->wait_shm_path, O_RDONLY, 0);
-               if (wait_shm_fd < 0) {
-                       /*
-                        * Real-only open did not work. It's a failure
-                        * that prohibits using shm.
-                        */
-                       ERR("Error opening shm %s", sock_info->wait_shm_path);
-                       goto end;
-               }
-               goto end;
-       } else if (pid == 0) {
-               int create_mode;
-
-               /* Child */
-               create_mode = S_IRUSR | S_IWUSR | S_IRGRP;
-               if (sock_info->global)
-                       create_mode |= S_IROTH | S_IWGRP | S_IWOTH;
-               /*
-                * We're alone in a child process, so we can modify the
-                * process-wide umask.
-                */
-               umask(~create_mode);
-               /*
-                * Try creating shm (or get rw access).
-                * We don't do an exclusive open, because we allow other
-                * processes to create+ftruncate it concurrently.
-                */
-               wait_shm_fd = shm_open(sock_info->wait_shm_path,
-                               O_RDWR | O_CREAT, create_mode);
-               if (wait_shm_fd >= 0) {
-                       ret = ftruncate(wait_shm_fd, mmap_size);
-                       if (ret) {
-                               PERROR("ftruncate");
-                               exit(EXIT_FAILURE);
-                       }
-                       exit(EXIT_SUCCESS);
-               }
-               /*
-                * For local shm, we need to have rw access to accept
-                * opening it: this means the local sessiond will be
-                * able to wake us up. For global shm, we open it even
-                * if rw access is not granted, because the root.root
-                * sessiond will be able to override all rights and wake
-                * us up.
-                */
-               if (!sock_info->global && errno != EACCES) {
-                       ERR("Error opening shm %s", sock_info->wait_shm_path);
-                       exit(EXIT_FAILURE);
-               }
-               /*
-                * The shm exists, but we cannot open it RW. Report
-                * success.
-                */
-               exit(EXIT_SUCCESS);
-       } else {
-               return -1;
-       }
-end:
-       if (wait_shm_fd >= 0 && !sock_info->global) {
-               struct stat statbuf;
-
-               /*
-                * Ensure that our user is the owner of the shm file for
-                * local shm. If we do not own the file, it means our
-                * sessiond will not have access to wake us up (there is
-                * probably a rogue process trying to fake our
-                * sessiond). Fallback to polling method in this case.
-                */
-               ret = fstat(wait_shm_fd, &statbuf);
-               if (ret) {
-                       PERROR("fstat");
-                       goto error_close;
-               }
-               if (statbuf.st_uid != getuid())
-                       goto error_close;
-       }
-       return wait_shm_fd;
-
-error_close:
-       ret = close(wait_shm_fd);
-       if (ret) {
-               PERROR("Error closing fd");
-       }
-       return -1;
-}
-
-static
-char *get_map_shm(struct sock_info *sock_info)
-{
-       size_t mmap_size = sysconf(_SC_PAGE_SIZE);
-       int wait_shm_fd, ret;
-       char *wait_shm_mmap;
-
-       wait_shm_fd = get_wait_shm(sock_info, mmap_size);
-       if (wait_shm_fd < 0) {
-               goto error;
-       }
-       wait_shm_mmap = mmap(NULL, mmap_size, PROT_READ,
-                 MAP_SHARED, wait_shm_fd, 0);
-       /* close shm fd immediately after taking the mmap reference */
-       ret = close(wait_shm_fd);
-       if (ret) {
-               PERROR("Error closing fd");
-       }
-       if (wait_shm_mmap == MAP_FAILED) {
-               DBG("mmap error (can be caused by race with sessiond). Fallback to poll mode.");
-               goto error;
-       }
-       return wait_shm_mmap;
-
-error:
-       return NULL;
-}
-
-static
-void wait_for_sessiond(struct sock_info *sock_info)
-{
-       int ret;
-
-       ust_lock();
-       if (lttng_ust_comm_should_quit) {
-               goto quit;
-       }
-       if (wait_poll_fallback) {
-               goto error;
-       }
-       if (!sock_info->wait_shm_mmap) {
-               sock_info->wait_shm_mmap = get_map_shm(sock_info);
-               if (!sock_info->wait_shm_mmap)
-                       goto error;
-       }
-       ust_unlock();
-
-       DBG("Waiting for %s apps sessiond", sock_info->name);
-       /* Wait for futex wakeup */
-       if (uatomic_read((int32_t *) sock_info->wait_shm_mmap) == 0) {
-               ret = futex_async((int32_t *) sock_info->wait_shm_mmap,
-                       FUTEX_WAIT, 0, NULL, NULL, 0);
-               if (ret < 0) {
-                       if (errno == EFAULT) {
-                               wait_poll_fallback = 1;
-                               WARN(
-"Linux kernels 2.6.33 to 3.0 (with the exception of stable versions) "
-"do not support FUTEX_WAKE on read-only memory mappings correctly. "
-"Please upgrade your kernel "
-"(fix is commit 9ea71503a8ed9184d2d0b8ccc4d269d05f7940ae in Linux kernel "
-"mainline). LTTng-UST will use polling mode fallback.");
-                       }
-                       PERROR("futex");
-               }
-       }
-       return;
-
-quit:
-       ust_unlock();
-       return;
-
-error:
-       ust_unlock();
-       return;
-}
-
-/*
- * This thread does not allocate any resource, except within
- * handle_message, within mutex protection. This mutex protects against
- * fork and exit.
- * The other moment it allocates resources is at socket connexion, which
- * is also protected by the mutex.
- */
-static
-void *ust_listener_thread(void *arg)
-{
-       struct sock_info *sock_info = arg;
-       int sock, ret, prev_connect_failed = 0, has_waited = 0;
-
-       /* Restart trying to connect to the session daemon */
-restart:
-       if (prev_connect_failed) {
-               /* Wait for sessiond availability with pipe */
-               wait_for_sessiond(sock_info);
-               if (has_waited) {
-                       has_waited = 0;
-                       /*
-                        * Sleep for 5 seconds before retrying after a
-                        * sequence of failure / wait / failure. This
-                        * deals with a killed or broken session daemon.
-                        */
-                       sleep(5);
-               }
-               has_waited = 1;
-               prev_connect_failed = 0;
-       }
-       ust_lock();
-
-       if (lttng_ust_comm_should_quit) {
-               ust_unlock();
-               goto quit;
-       }
-
-       if (sock_info->socket != -1) {
-               ret = close(sock_info->socket);
-               if (ret) {
-                       ERR("Error closing %s apps socket", sock_info->name);
-               }
-               sock_info->socket = -1;
-       }
-
-       /* Register */
-       ret = ustcomm_connect_unix_sock(sock_info->sock_path);
-       if (ret < 0) {
-               ERR("Error connecting to %s apps socket", sock_info->name);
-               prev_connect_failed = 1;
-               /*
-                * If we cannot find the sessiond daemon, don't delay
-                * constructor execution.
-                */
-               ret = handle_register_done(sock_info);
-               assert(!ret);
-               ust_unlock();
-               goto restart;
-       }
-
-       sock_info->socket = sock = ret;
-
-       /*
-        * Create only one root handle per listener thread for the whole
-        * process lifetime.
-        */
-       if (sock_info->root_handle == -1) {
-               ret = lttng_abi_create_root_handle();
-               if (ret < 0) {
-                       ERR("Error creating root handle");
-                       ust_unlock();
-                       goto quit;
-               }
-               sock_info->root_handle = ret;
-       }
-
-       ret = register_app_to_sessiond(sock);
-       if (ret < 0) {
-               ERR("Error registering to %s apps socket", sock_info->name);
-               prev_connect_failed = 1;
-               /*
-                * If we cannot register to the sessiond daemon, don't
-                * delay constructor execution.
-                */
-               ret = handle_register_done(sock_info);
-               assert(!ret);
-               ust_unlock();
-               goto restart;
-       }
-       ust_unlock();
-
-       for (;;) {
-               ssize_t len;
-               struct ustcomm_ust_msg lum;
-
-               len = ustcomm_recv_unix_sock(sock, &lum, sizeof(lum));
-               switch (len) {
-               case 0: /* orderly shutdown */
-                       DBG("%s ltt-sessiond has performed an orderly shutdown\n", sock_info->name);
-                       goto end;
-               case sizeof(lum):
-                       DBG("message received\n");
-                       ret = handle_message(sock_info, sock, &lum);
-                       if (ret < 0) {
-                               ERR("Error handling message for %s socket", sock_info->name);
-                       }
-                       continue;
-               case -1:
-                       if (errno == ECONNRESET) {
-                               ERR("%s remote end closed connection\n", sock_info->name);
-                               goto end;
-                       }
-                       goto end;
-               default:
-                       ERR("incorrect message size (%s socket): %zd\n", sock_info->name, len);
-                       continue;
-               }
-
-       }
-end:
-       goto restart;   /* try to reconnect */
-quit:
-       return NULL;
-}
-
-/*
- * Return values: -1: don't wait. 0: wait forever. 1: timeout wait.
- */
-static
-int get_timeout(struct timespec *constructor_timeout)
-{
-       long constructor_delay_ms = LTTNG_UST_DEFAULT_CONSTRUCTOR_TIMEOUT_MS;
-       char *str_delay;
-       int ret;
-
-       str_delay = getenv("UST_REGISTER_TIMEOUT");
-       if (str_delay) {
-               constructor_delay_ms = strtol(str_delay, NULL, 10);
-       }
-
-       switch (constructor_delay_ms) {
-       case -1:/* fall-through */
-       case 0:
-               return constructor_delay_ms;
-       default:
-               break;
-       }
-
-       /*
-        * If we are unable to find the current time, don't wait.
-        */
-       ret = clock_gettime(CLOCK_REALTIME, constructor_timeout);
-       if (ret) {
-               return -1;
-       }
-       constructor_timeout->tv_sec += constructor_delay_ms / 1000UL;
-       constructor_timeout->tv_nsec +=
-               (constructor_delay_ms % 1000UL) * 1000000UL;
-       if (constructor_timeout->tv_nsec >= 1000000000UL) {
-               constructor_timeout->tv_sec++;
-               constructor_timeout->tv_nsec -= 1000000000UL;
-       }
-       return 1;
-}
-
-/*
- * sessiond monitoring thread: monitor presence of global and per-user
- * sessiond by polling the application common named pipe.
- */
-/* TODO */
-
-void __attribute__((constructor)) lttng_ust_init(void)
-{
-       struct timespec constructor_timeout;
-       int timeout_mode;
-       int ret;
-
-       if (uatomic_xchg(&initialized, 1) == 1)
-               return;
-
-       /*
-        * We want precise control over the order in which we construct
-        * our sub-libraries vs starting to receive commands from
-        * sessiond (otherwise leading to errors when trying to create
-        * sessiond before the init functions are completed).
-        */
-       init_usterr();
-       init_tracepoint();
-       ltt_ring_buffer_metadata_client_init();
-       ltt_ring_buffer_client_overwrite_init();
-       ltt_ring_buffer_client_discard_init();
-
-       timeout_mode = get_timeout(&constructor_timeout);
-
-       ret = sem_init(&constructor_wait, 0, 0);
-       assert(!ret);
-
-       ret = setup_local_apps();
-       if (ret) {
-               ERR("Error setting up to local apps");
-       }
-       ret = pthread_create(&local_apps.ust_listener, NULL,
-                       ust_listener_thread, &local_apps);
-
-       if (local_apps.allowed) {
-               ret = pthread_create(&global_apps.ust_listener, NULL,
-                               ust_listener_thread, &global_apps);
-       } else {
-               handle_register_done(&local_apps);
-       }
-
-       switch (timeout_mode) {
-       case 1: /* timeout wait */
-               do {
-                       ret = sem_timedwait(&constructor_wait,
-                                       &constructor_timeout);
-               } while (ret < 0 && errno == EINTR);
-               if (ret < 0 && errno == ETIMEDOUT) {
-                       ERR("Timed out waiting for ltt-sessiond");
-               } else {
-                       assert(!ret);
-               }
-               break;
-       case -1:/* wait forever */
-               do {
-                       ret = sem_wait(&constructor_wait);
-               } while (ret < 0 && errno == EINTR);
-               assert(!ret);
-               break;
-       case 0: /* no timeout */
-               break;
-       }
-}
-
-static
-void lttng_ust_cleanup(int exiting)
-{
-       cleanup_sock_info(&global_apps);
-       if (local_apps.allowed) {
-               cleanup_sock_info(&local_apps);
-       }
-       lttng_ust_abi_exit();
-       lttng_ust_events_exit();
-       ltt_ring_buffer_client_discard_exit();
-       ltt_ring_buffer_client_overwrite_exit();
-       ltt_ring_buffer_metadata_client_exit();
-       exit_tracepoint();
-       if (!exiting) {
-               /* Reinitialize values for fork */
-               sem_count = 2;
-               lttng_ust_comm_should_quit = 0;
-               initialized = 0;
-       }
-}
-
-void __attribute__((destructor)) lttng_ust_exit(void)
-{
-       int ret;
-
-       /*
-        * Using pthread_cancel here because:
-        * A) we don't want to hang application teardown.
-        * B) the thread is not allocating any resource.
-        */
-
-       /*
-        * Require the communication thread to quit. Synchronize with
-        * mutexes to ensure it is not in a mutex critical section when
-        * pthread_cancel is later called.
-        */
-       ust_lock();
-       lttng_ust_comm_should_quit = 1;
-       ust_unlock();
-
-       ret = pthread_cancel(global_apps.ust_listener);
-       if (ret) {
-               ERR("Error cancelling global ust listener thread");
-       }
-       if (local_apps.allowed) {
-               ret = pthread_cancel(local_apps.ust_listener);
-               if (ret) {
-                       ERR("Error cancelling local ust listener thread");
-               }
-       }
-       lttng_ust_cleanup(1);
-}
-
-/*
- * We exclude the worker threads across fork and clone (except
- * CLONE_VM), because these system calls only keep the forking thread
- * running in the child.  Therefore, we don't want to call fork or clone
- * in the middle of an tracepoint or ust tracing state modification.
- * Holding this mutex protects these structures across fork and clone.
- */
-void ust_before_fork(ust_fork_info_t *fork_info)
-{
-       /*
-        * Disable signals. This is to avoid that the child intervenes
-        * before it is properly setup for tracing. It is safer to
-        * disable all signals, because then we know we are not breaking
-        * anything by restoring the original mask.
-         */
-       sigset_t all_sigs;
-       int ret;
-
-       /* Disable signals */
-       sigfillset(&all_sigs);
-       ret = sigprocmask(SIG_BLOCK, &all_sigs, &fork_info->orig_sigs);
-       if (ret == -1) {
-               PERROR("sigprocmask");
-       }
-       ust_lock();
-       rcu_bp_before_fork();
-}
-
-static void ust_after_fork_common(ust_fork_info_t *fork_info)
-{
-       int ret;
-
-       DBG("process %d", getpid());
-       ust_unlock();
-       /* Restore signals */
-       ret = sigprocmask(SIG_SETMASK, &fork_info->orig_sigs, NULL);
-       if (ret == -1) {
-               PERROR("sigprocmask");
-       }
-}
-
-void ust_after_fork_parent(ust_fork_info_t *fork_info)
-{
-       DBG("process %d", getpid());
-       rcu_bp_after_fork_parent();
-       /* Release mutexes and reenable signals */
-       ust_after_fork_common(fork_info);
-}
-
-/*
- * After fork, in the child, we need to cleanup all the leftover state,
- * except the worker thread which already magically disappeared thanks
- * to the weird Linux fork semantics. After tyding up, we call
- * lttng_ust_init() again to start over as a new PID.
- *
- * This is meant for forks() that have tracing in the child between the
- * fork and following exec call (if there is any).
- */
-void ust_after_fork_child(ust_fork_info_t *fork_info)
-{
-       DBG("process %d", getpid());
-       /* Release urcu mutexes */
-       rcu_bp_after_fork_child();
-       lttng_ust_cleanup(0);
-       lttng_context_vtid_reset();
-       /* Release mutexes and reenable signals */
-       ust_after_fork_common(fork_info);
-       lttng_ust_init();
-}
diff --git a/libust/probes/lttng-probe-ust.c b/libust/probes/lttng-probe-ust.c
deleted file mode 100644 (file)
index a5fba86..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * probes/lttng-probe-ust.c
- *
- * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * LTTng UST core probes.
- *
- * Dual LGPL v2.1/GPL v2 license.
- */
-
-/*
- * Create LTTng tracepoint probes.
- */
-#define TRACEPOINT_CREATE_PROBES
-
-#include "lttng-probe-ust.h"
diff --git a/libust/probes/lttng-probe-ust.h b/libust/probes/lttng-probe-ust.h
deleted file mode 100644 (file)
index 3394d08..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#undef TRACEPOINT_SYSTEM
-#define TRACEPOINT_SYSTEM lttng_ust
-
-#if !defined(_TRACEPOINT_LTTNG_UST_H) || defined(TRACEPOINT_HEADER_MULTI_READ)
-#define _TRACEPOINT_LTTNG_UST_H
-
-/*
- * Copyright (C) 2011  Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; version 2.1 of
- * the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-#include <lttng/tracepoint.h>
-
-TRACEPOINT_EVENT(lttng_metadata,
-
-       TP_PROTO(const char *str),
-
-       TP_ARGS(str),
-
-       /*
-        * Not exactly a string: more a sequence of bytes (dynamic
-        * array) without the length. This is a dummy anyway: we only
-        * use this declaration to generate an event metadata entry.
-        */
-       TP_FIELDS(
-               ctf_string(str, str)
-       )
-)
-
-#undef TRACEPOINT_INCLUDE_PATH
-#define TRACEPOINT_INCLUDE_PATH ./probes
-#undef TRACEPOINT_INCLUDE_FILE
-#define TRACEPOINT_INCLUDE_FILE lttng-probe-ust
-
-#endif /* _TRACEPOINT_LTTNG_UST_H */
-
-/* This part must be outside protection */
-#include <lttng/tracepoint-event.h>
diff --git a/libust/tracepoint.c b/libust/tracepoint.c
deleted file mode 100644 (file)
index 8bf8752..0000000
+++ /dev/null
@@ -1,669 +0,0 @@
-/*
- * Copyright (C) 2008-2011 Mathieu Desnoyers
- * Copyright (C) 2009 Pierre-Marc Fournier
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Ported to userspace by Pierre-Marc Fournier.
- */
-
-#define _LGPL_SOURCE
-#include <errno.h>
-#include <lttng/tracepoint.h>
-#include <lttng/tracepoint-internal.h>
-#include <lttng/core.h>
-#include <lttng/kcompat/kcompat.h>
-#include <urcu-bp.h>
-#include <urcu/hlist.h>
-#include <urcu/uatomic.h>
-
-#include <lttng/usterr-signal-safe.h>
-#include "ltt-tracer-core.h"
-
-/* Set to 1 to enable tracepoint debug output */
-static const int tracepoint_debug;
-static int initialized;
-static void (*new_tracepoint_cb)(struct tracepoint *);
-
-/* libraries that contain tracepoints (struct tracepoint_lib) */
-static CDS_LIST_HEAD(libs);
-
-/*
- * The UST lock protects the library tracepoints, the hash table, and
- * the library list.
- * All calls to the tracepoint API must be protected by the UST lock,
- * excepts calls to tracepoint_register_lib and
- * tracepoint_unregister_lib, which take the UST lock themselves.
- */
-
-/*
- * Tracepoint hash table, containing the active tracepoints.
- * Protected by tracepoints_mutex.
- */
-#define TRACEPOINT_HASH_BITS 6
-#define TRACEPOINT_TABLE_SIZE (1 << TRACEPOINT_HASH_BITS)
-static struct cds_hlist_head tracepoint_table[TRACEPOINT_TABLE_SIZE];
-
-static CDS_LIST_HEAD(old_probes);
-static int need_update;
-
-/*
- * Note about RCU :
- * It is used to to delay the free of multiple probes array until a quiescent
- * state is reached.
- * Tracepoint entries modifications are protected by the tracepoints_mutex.
- */
-struct tracepoint_entry {
-       struct cds_hlist_node hlist;
-       struct tracepoint_probe *probes;
-       int refcount;   /* Number of times armed. 0 if disarmed. */
-       char name[0];
-};
-
-struct tp_probes {
-       union {
-               struct cds_list_head list;
-       } u;
-       struct tracepoint_probe probes[0];
-};
-
-static inline void *allocate_probes(int count)
-{
-       struct tp_probes *p  = zmalloc(count * sizeof(struct tracepoint_probe)
-                       + sizeof(struct tp_probes));
-       return p == NULL ? NULL : p->probes;
-}
-
-static inline void release_probes(void *old)
-{
-       if (old) {
-               struct tp_probes *tp_probes = _ust_container_of(old,
-                       struct tp_probes, probes[0]);
-               synchronize_rcu();
-               free(tp_probes);
-       }
-}
-
-static void debug_print_probes(struct tracepoint_entry *entry)
-{
-       int i;
-
-       if (!tracepoint_debug || !entry->probes)
-               return;
-
-       for (i = 0; entry->probes[i].func; i++)
-               DBG("Probe %d : %p", i, entry->probes[i].func);
-}
-
-static void *
-tracepoint_entry_add_probe(struct tracepoint_entry *entry,
-                          void *probe, void *data)
-{
-       int nr_probes = 0;
-       struct tracepoint_probe *old, *new;
-
-       WARN_ON(!probe);
-
-       debug_print_probes(entry);
-       old = entry->probes;
-       if (old) {
-               /* (N -> N+1), (N != 0, 1) probes */
-               for (nr_probes = 0; old[nr_probes].func; nr_probes++)
-                       if (old[nr_probes].func == probe &&
-                           old[nr_probes].data == data)
-                               return ERR_PTR(-EEXIST);
-       }
-       /* + 2 : one for new probe, one for NULL func */
-       new = allocate_probes(nr_probes + 2);
-       if (new == NULL)
-               return ERR_PTR(-ENOMEM);
-       if (old)
-               memcpy(new, old, nr_probes * sizeof(struct tracepoint_probe));
-       new[nr_probes].func = probe;
-       new[nr_probes].data = data;
-       new[nr_probes + 1].func = NULL;
-       entry->refcount = nr_probes + 1;
-       entry->probes = new;
-       debug_print_probes(entry);
-       return old;
-}
-
-static void *
-tracepoint_entry_remove_probe(struct tracepoint_entry *entry, void *probe,
-                             void *data)
-{
-       int nr_probes = 0, nr_del = 0, i;
-       struct tracepoint_probe *old, *new;
-
-       old = entry->probes;
-
-       if (!old)
-               return ERR_PTR(-ENOENT);
-
-       debug_print_probes(entry);
-       /* (N -> M), (N > 1, M >= 0) probes */
-       for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
-               if (!probe ||
-                    (old[nr_probes].func == probe &&
-                    old[nr_probes].data == data))
-                       nr_del++;
-       }
-
-       if (nr_probes - nr_del == 0) {
-               /* N -> 0, (N > 1) */
-               entry->probes = NULL;
-               entry->refcount = 0;
-               debug_print_probes(entry);
-               return old;
-       } else {
-               int j = 0;
-               /* N -> M, (N > 1, M > 0) */
-               /* + 1 for NULL */
-               new = allocate_probes(nr_probes - nr_del + 1);
-               if (new == NULL)
-                       return ERR_PTR(-ENOMEM);
-               for (i = 0; old[i].func; i++)
-                       if (probe &&
-                           (old[i].func != probe || old[i].data != data))
-                               new[j++] = old[i];
-               new[nr_probes - nr_del].func = NULL;
-               entry->refcount = nr_probes - nr_del;
-               entry->probes = new;
-       }
-       debug_print_probes(entry);
-       return old;
-}
-
-/*
- * Get tracepoint if the tracepoint is present in the tracepoint hash table.
- * Must be called with tracepoints_mutex held.
- * Returns NULL if not present.
- */
-static struct tracepoint_entry *get_tracepoint(const char *name)
-{
-       struct cds_hlist_head *head;
-       struct cds_hlist_node *node;
-       struct tracepoint_entry *e;
-       u32 hash = jhash(name, strlen(name), 0);
-
-       head = &tracepoint_table[hash & (TRACEPOINT_TABLE_SIZE - 1)];
-       cds_hlist_for_each_entry(e, node, head, hlist) {
-               if (!strcmp(name, e->name))
-                       return e;
-       }
-       return NULL;
-}
-
-/*
- * Add the tracepoint to the tracepoint hash table. Must be called with
- * tracepoints_mutex held.
- */
-static struct tracepoint_entry *add_tracepoint(const char *name)
-{
-       struct cds_hlist_head *head;
-       struct cds_hlist_node *node;
-       struct tracepoint_entry *e;
-       size_t name_len = strlen(name) + 1;
-       u32 hash = jhash(name, name_len-1, 0);
-
-       head = &tracepoint_table[hash & (TRACEPOINT_TABLE_SIZE - 1)];
-       cds_hlist_for_each_entry(e, node, head, hlist) {
-               if (!strcmp(name, e->name)) {
-                       DBG("tracepoint %s busy", name);
-                       return ERR_PTR(-EEXIST);        /* Already there */
-               }
-       }
-       /*
-        * Using zmalloc here to allocate a variable length element. Could
-        * cause some memory fragmentation if overused.
-        */
-       e = zmalloc(sizeof(struct tracepoint_entry) + name_len);
-       if (!e)
-               return ERR_PTR(-ENOMEM);
-       memcpy(&e->name[0], name, name_len);
-       e->probes = NULL;
-       e->refcount = 0;
-       cds_hlist_add_head(&e->hlist, head);
-       return e;
-}
-
-/*
- * Remove the tracepoint from the tracepoint hash table. Must be called with
- * ust_lock held.
- */
-static inline void remove_tracepoint(struct tracepoint_entry *e)
-{
-       cds_hlist_del(&e->hlist);
-       free(e);
-}
-
-/*
- * Sets the probe callback corresponding to one tracepoint.
- */
-static void set_tracepoint(struct tracepoint_entry **entry,
-       struct tracepoint *elem, int active)
-{
-       WARN_ON(strcmp((*entry)->name, elem->name) != 0);
-
-       /*
-        * rcu_assign_pointer has a cmm_smp_wmb() which makes sure that the new
-        * probe callbacks array is consistent before setting a pointer to it.
-        * This array is referenced by __DO_TRACE from
-        * include/linux/tracepoints.h. A matching cmm_smp_read_barrier_depends()
-        * is used.
-        */
-       rcu_assign_pointer(elem->probes, (*entry)->probes);
-       elem->state = active;
-}
-
-/*
- * Disable a tracepoint and its probe callback.
- * Note: only waiting an RCU period after setting elem->call to the empty
- * function insures that the original callback is not used anymore. This insured
- * by preempt_disable around the call site.
- */
-static void disable_tracepoint(struct tracepoint *elem)
-{
-       elem->state = 0;
-       rcu_assign_pointer(elem->probes, NULL);
-}
-
-/**
- * tracepoint_update_probe_range - Update a probe range
- * @begin: beginning of the range
- * @end: end of the range
- *
- * Updates the probe callback corresponding to a range of tracepoints.
- */
-static
-void tracepoint_update_probe_range(struct tracepoint * const *begin,
-                                  struct tracepoint * const *end)
-{
-       struct tracepoint * const *iter;
-       struct tracepoint_entry *mark_entry;
-
-       for (iter = begin; iter < end; iter++) {
-               if (!*iter)
-                       continue;       /* skip dummy */
-               if (!(*iter)->name) {
-                       disable_tracepoint(*iter);
-                       continue;
-               }
-               mark_entry = get_tracepoint((*iter)->name);
-               if (mark_entry) {
-                       set_tracepoint(&mark_entry, *iter,
-                                       !!mark_entry->refcount);
-               } else {
-                       disable_tracepoint(*iter);
-               }
-       }
-}
-
-static void lib_update_tracepoints(void)
-{
-       struct tracepoint_lib *lib;
-
-       cds_list_for_each_entry(lib, &libs, list) {
-               tracepoint_update_probe_range(lib->tracepoints_start,
-                               lib->tracepoints_start + lib->tracepoints_count);
-       }
-}
-
-/*
- * Update probes, removing the faulty probes.
- */
-static void tracepoint_update_probes(void)
-{
-       /* tracepoints registered from libraries and executable. */
-       lib_update_tracepoints();
-}
-
-static struct tracepoint_probe *
-tracepoint_add_probe(const char *name, void *probe, void *data)
-{
-       struct tracepoint_entry *entry;
-       struct tracepoint_probe *old;
-
-       entry = get_tracepoint(name);
-       if (!entry) {
-               entry = add_tracepoint(name);
-               if (IS_ERR(entry))
-                       return (struct tracepoint_probe *)entry;
-       }
-       old = tracepoint_entry_add_probe(entry, probe, data);
-       if (IS_ERR(old) && !entry->refcount)
-               remove_tracepoint(entry);
-       return old;
-}
-
-/**
- * __tracepoint_probe_register -  Connect a probe to a tracepoint
- * @name: tracepoint name
- * @probe: probe handler
- *
- * Returns 0 if ok, error value on error.
- * The probe address must at least be aligned on the architecture pointer size.
- * Called with the UST lock held.
- */
-int __tracepoint_probe_register(const char *name, void *probe, void *data)
-{
-       void *old;
-
-       old = tracepoint_add_probe(name, probe, data);
-       if (IS_ERR(old))
-               return PTR_ERR(old);
-
-       tracepoint_update_probes();             /* may update entry */
-       release_probes(old);
-       return 0;
-}
-
-static void *tracepoint_remove_probe(const char *name, void *probe, void *data)
-{
-       struct tracepoint_entry *entry;
-       void *old;
-
-       entry = get_tracepoint(name);
-       if (!entry)
-               return ERR_PTR(-ENOENT);
-       old = tracepoint_entry_remove_probe(entry, probe, data);
-       if (IS_ERR(old))
-               return old;
-       if (!entry->refcount)
-               remove_tracepoint(entry);
-       return old;
-}
-
-/**
- * tracepoint_probe_unregister -  Disconnect a probe from a tracepoint
- * @name: tracepoint name
- * @probe: probe function pointer
- * @probe: probe data pointer
- *
- * Called with the UST lock held.
- */
-int __tracepoint_probe_unregister(const char *name, void *probe, void *data)
-{
-       void *old;
-
-       old = tracepoint_remove_probe(name, probe, data);
-       if (IS_ERR(old))
-               return PTR_ERR(old);
-
-       tracepoint_update_probes();             /* may update entry */
-       release_probes(old);
-       return 0;
-}
-
-static void tracepoint_add_old_probes(void *old)
-{
-       need_update = 1;
-       if (old) {
-               struct tp_probes *tp_probes = _ust_container_of(old,
-                       struct tp_probes, probes[0]);
-               cds_list_add(&tp_probes->u.list, &old_probes);
-       }
-}
-
-/**
- * tracepoint_probe_register_noupdate -  register a probe but not connect
- * @name: tracepoint name
- * @probe: probe handler
- *
- * caller must call tracepoint_probe_update_all()
- * Called with the UST lock held.
- */
-int tracepoint_probe_register_noupdate(const char *name, void *probe,
-                                      void *data)
-{
-       void *old;
-
-       old = tracepoint_add_probe(name, probe, data);
-       if (IS_ERR(old)) {
-               return PTR_ERR(old);
-       }
-       tracepoint_add_old_probes(old);
-       return 0;
-}
-
-/**
- * tracepoint_probe_unregister_noupdate -  remove a probe but not disconnect
- * @name: tracepoint name
- * @probe: probe function pointer
- *
- * caller must call tracepoint_probe_update_all()
- * Called with the UST lock held.
- */
-int tracepoint_probe_unregister_noupdate(const char *name, void *probe,
-                                        void *data)
-{
-       void *old;
-
-       old = tracepoint_remove_probe(name, probe, data);
-       if (IS_ERR(old)) {
-               return PTR_ERR(old);
-       }
-       tracepoint_add_old_probes(old);
-       return 0;
-}
-
-/**
- * tracepoint_probe_update_all -  update tracepoints
- * Called with the UST lock held.
- */
-void tracepoint_probe_update_all(void)
-{
-       CDS_LIST_HEAD(release_probes);
-       struct tp_probes *pos, *next;
-
-       if (!need_update) {
-               return;
-       }
-       if (!cds_list_empty(&old_probes))
-               cds_list_replace_init(&old_probes, &release_probes);
-       need_update = 0;
-
-       tracepoint_update_probes();
-       cds_list_for_each_entry_safe(pos, next, &release_probes, u.list) {
-               cds_list_del(&pos->u.list);
-               synchronize_rcu();
-               free(pos);
-       }
-}
-
-/*
- * Returns 0 if current not found.
- * Returns 1 if current found.
- *
- * Called with tracepoint mutex held
- */
-int lib_get_iter_tracepoints(struct tracepoint_iter *iter)
-{
-       struct tracepoint_lib *iter_lib;
-       int found = 0;
-
-       cds_list_for_each_entry(iter_lib, &libs, list) {
-               if (iter_lib < iter->lib)
-                       continue;
-               else if (iter_lib > iter->lib)
-                       iter->tracepoint = NULL;
-               found = tracepoint_get_iter_range(&iter->tracepoint,
-                       iter_lib->tracepoints_start,
-                       iter_lib->tracepoints_start + iter_lib->tracepoints_count);
-               if (found) {
-                       iter->lib = iter_lib;
-                       break;
-               }
-       }
-       return found;
-}
-
-/**
- * tracepoint_get_iter_range - Get a next tracepoint iterator given a range.
- * @tracepoint: current tracepoints (in), next tracepoint (out)
- * @begin: beginning of the range
- * @end: end of the range
- *
- * Returns whether a next tracepoint has been found (1) or not (0).
- * Will return the first tracepoint in the range if the input tracepoint is
- * NULL.
- * Called with tracepoint mutex held.
- */
-int tracepoint_get_iter_range(struct tracepoint * const **tracepoint,
-       struct tracepoint * const *begin, struct tracepoint * const *end)
-{
-       if (!*tracepoint && begin != end)
-               *tracepoint = begin;
-       while (*tracepoint >= begin && *tracepoint < end) {
-               if (!**tracepoint)
-                       (*tracepoint)++;        /* skip dummy */
-               else
-                       return 1;
-       }
-       return 0;
-}
-
-/*
- * Called with tracepoint mutex held.
- */
-static void tracepoint_get_iter(struct tracepoint_iter *iter)
-{
-       int found = 0;
-
-       /* tracepoints in libs. */
-       found = lib_get_iter_tracepoints(iter);
-       if (!found)
-               tracepoint_iter_reset(iter);
-}
-
-/*
- * Called with UST lock held.
- */
-void tracepoint_iter_start(struct tracepoint_iter *iter)
-{
-       tracepoint_get_iter(iter);
-}
-
-/*
- * Called with UST lock held.
- */
-void tracepoint_iter_next(struct tracepoint_iter *iter)
-{
-       iter->tracepoint++;
-       /*
-        * iter->tracepoint may be invalid because we blindly incremented it.
-        * Make sure it is valid by marshalling on the tracepoints, getting the
-        * tracepoints from following modules if necessary.
-        */
-       tracepoint_get_iter(iter);
-}
-
-/*
- * Called with UST lock held.
- */
-void tracepoint_iter_stop(struct tracepoint_iter *iter)
-{
-}
-
-void tracepoint_iter_reset(struct tracepoint_iter *iter)
-{
-       iter->tracepoint = NULL;
-}
-
-void tracepoint_set_new_tracepoint_cb(void (*cb)(struct tracepoint *))
-{
-       new_tracepoint_cb = cb;
-}
-
-static void new_tracepoints(struct tracepoint * const *start, struct tracepoint * const *end)
-{
-       if (new_tracepoint_cb) {
-               struct tracepoint * const *t;
-
-               for (t = start; t < end; t++) {
-                       if (*t)
-                               new_tracepoint_cb(*t);
-               }
-       }
-}
-
-int tracepoint_register_lib(struct tracepoint * const *tracepoints_start,
-                           int tracepoints_count)
-{
-       struct tracepoint_lib *pl, *iter;
-
-       init_tracepoint();
-
-       pl = (struct tracepoint_lib *) zmalloc(sizeof(struct tracepoint_lib));
-
-       pl->tracepoints_start = tracepoints_start;
-       pl->tracepoints_count = tracepoints_count;
-
-       ust_lock();
-       /*
-        * We sort the libs by struct lib pointer address.
-        */
-       cds_list_for_each_entry_reverse(iter, &libs, list) {
-               BUG_ON(iter == pl);    /* Should never be in the list twice */
-               if (iter < pl) {
-                       /* We belong to the location right after iter. */
-                       cds_list_add(&pl->list, &iter->list);
-                       goto lib_added;
-               }
-       }
-       /* We should be added at the head of the list */
-       cds_list_add(&pl->list, &libs);
-lib_added:
-       new_tracepoints(tracepoints_start, tracepoints_start + tracepoints_count);
-
-       /* TODO: update just the loaded lib */
-       lib_update_tracepoints();
-       ust_unlock();
-
-       DBG("just registered a tracepoints section from %p and having %d tracepoints",
-               tracepoints_start, tracepoints_count);
-
-       return 0;
-}
-
-int tracepoint_unregister_lib(struct tracepoint * const *tracepoints_start)
-{
-       struct tracepoint_lib *lib;
-
-       ust_lock();
-       cds_list_for_each_entry(lib, &libs, list) {
-               if (lib->tracepoints_start == tracepoints_start) {
-                       struct tracepoint_lib *lib2free = lib;
-                       cds_list_del(&lib->list);
-                       free(lib2free);
-                       break;
-               }
-       }
-       ust_unlock();
-
-       return 0;
-}
-
-void init_tracepoint(void)
-{
-       if (uatomic_xchg(&initialized, 1) == 1)
-               return;
-       init_usterr();
-}
-
-void exit_tracepoint(void)
-{
-       initialized = 0;
-}
diff --git a/libust/ust-core.c b/libust/ust-core.c
deleted file mode 100644 (file)
index b5cc8cf..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * ust-core.c
- *
- * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; only
- * version 2.1 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <lttng/usterr-signal-safe.h>
-#include <stdlib.h>
-
-volatile enum ust_loglevel ust_loglevel;
-
-void init_usterr(void)
-{
-       char *ust_debug;
-
-       if (ust_loglevel == UST_LOGLEVEL_UNKNOWN) {
-               ust_debug = getenv("UST_DEBUG");
-               if (ust_debug)
-                       ust_loglevel = UST_LOGLEVEL_DEBUG;
-               else
-                       ust_loglevel = UST_LOGLEVEL_NORMAL;
-       }
-}
diff --git a/libustctl/Makefile.am b/libustctl/Makefile.am
deleted file mode 100644 (file)
index 8101b57..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/liblttng-ust-comm
-AM_CFLAGS = -fno-strict-aliasing
-
-lib_LTLIBRARIES = libustctl.la
-
-libustctl_la_SOURCES = ustctl.c
-
-libustctl_la_LIBADD = $(top_builddir)/liblttng-ust-comm/liblttng-ust-comm.la \
-       $(top_builddir)/libringbuffer/libringbuffer.la \
-       $(top_builddir)/snprintf/libustsnprintf.la
diff --git a/libustctl/ustctl.c b/libustctl/ustctl.c
deleted file mode 100644 (file)
index 6f3d1ed..0000000
+++ /dev/null
@@ -1,668 +0,0 @@
-/*
- * Copyright (C) 2011 - Julien Desfossez <julien.desfossez@polymtl.ca>
- *                      Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; only version 2
- * of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#include <string.h>
-#include <lttng/ust-ctl.h>
-#include <lttng/ust-abi.h>
-#include <lttng/usterr-signal-safe.h>
-#include <lttng/ust-comm.h>
-
-#include "../libringbuffer/backend.h"
-#include "../libringbuffer/frontend.h"
-
-volatile enum ust_loglevel ust_loglevel;
-
-static
-void init_object(struct lttng_ust_object_data *data)
-{
-       data->handle = -1;
-       data->shm_fd = -1;
-       data->wait_fd = -1;
-       data->memory_map_size = 0;
-}
-
-void release_object(int sock, struct lttng_ust_object_data *data)
-{
-       struct ustcomm_ust_msg lum;
-       struct ustcomm_ust_reply lur;
-       int ret;
-
-       if (data->shm_fd >= 0)
-               close(data->shm_fd);
-       if (data->wait_fd >= 0)
-               close(data->wait_fd);
-       memset(&lum, 0, sizeof(lum));
-       lum.handle = data->handle;
-       lum.cmd = LTTNG_UST_RELEASE;
-       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
-       assert(!ret);
-       free(data);
-}
-
-/*
- * Send registration done packet to the application.
- */
-int ustctl_register_done(int sock)
-{
-       struct ustcomm_ust_msg lum;
-       struct ustcomm_ust_reply lur;
-       int ret;
-
-       DBG("Sending register done command to %d", sock);
-       memset(&lum, 0, sizeof(lum));
-       lum.handle = LTTNG_UST_ROOT_HANDLE;
-       lum.cmd = LTTNG_UST_REGISTER_DONE;
-       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
-       if (ret)
-               return ret;
-       if (lur.ret_code != USTCOMM_OK) {
-               DBG("Return code: %s", ustcomm_get_readable_code(lur.ret_code));
-               goto error;
-       }
-       return 0;
-
-error:
-       return -1;
-}
-
-/*
- * returns session handle.
- */
-int ustctl_create_session(int sock)
-{
-       struct ustcomm_ust_msg lum;
-       struct ustcomm_ust_reply lur;
-       int ret, session_handle;
-
-       /* Create session */
-       memset(&lum, 0, sizeof(lum));
-       lum.handle = LTTNG_UST_ROOT_HANDLE;
-       lum.cmd = LTTNG_UST_SESSION;
-       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
-       if (ret)
-               return ret;
-       session_handle = lur.ret_val;
-       DBG("received session handle %u", session_handle);
-       return session_handle;
-}
-
-/* open the metadata global channel */
-int ustctl_open_metadata(int sock, int session_handle,
-               struct lttng_ust_channel_attr *chops,
-               struct lttng_ust_object_data **_metadata_data)
-{
-       struct ustcomm_ust_msg lum;
-       struct ustcomm_ust_reply lur;
-       struct lttng_ust_object_data *metadata_data;
-       int ret;
-
-       metadata_data = malloc(sizeof(*metadata_data));
-       if (!metadata_data)
-               return -ENOMEM;
-       init_object(metadata_data);
-       /* Create metadata channel */
-       memset(&lum, 0, sizeof(lum));
-       lum.handle = session_handle;
-       lum.cmd = LTTNG_UST_METADATA;
-       lum.u.channel.overwrite = chops->overwrite;
-       lum.u.channel.subbuf_size = chops->subbuf_size;
-       lum.u.channel.num_subbuf = chops->num_subbuf;
-       lum.u.channel.switch_timer_interval = chops->switch_timer_interval;
-       lum.u.channel.read_timer_interval = chops->read_timer_interval;
-       lum.u.channel.output = chops->output;
-       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
-       if (ret) {
-               free(metadata_data);
-               return ret;
-       }
-       if (lur.ret_code != USTCOMM_OK) {
-               free(metadata_data);
-               return lur.ret_code;
-       }
-       metadata_data->handle = lur.ret_val;
-       DBG("received metadata handle %u", metadata_data->handle);
-       metadata_data->memory_map_size = lur.u.channel.memory_map_size;
-       /* get shm fd */
-       ret = ustcomm_recv_fd(sock);
-       if (ret < 0)
-               goto error;
-       metadata_data->shm_fd = ret;
-       /* get wait fd */
-       ret = ustcomm_recv_fd(sock);
-       if (ret < 0)
-               goto error;
-       metadata_data->wait_fd = ret;
-       *_metadata_data = metadata_data;
-       return 0;
-
-error:
-       release_object(sock, metadata_data);
-       return -EINVAL;
-}
-
-int ustctl_create_channel(int sock, int session_handle,
-               struct lttng_ust_channel_attr *chops,
-               struct lttng_ust_object_data **_channel_data)
-{
-       struct ustcomm_ust_msg lum;
-       struct ustcomm_ust_reply lur;
-       struct lttng_ust_object_data *channel_data;
-       int ret;
-
-       channel_data = malloc(sizeof(*channel_data));
-       if (!channel_data)
-               return -ENOMEM;
-       init_object(channel_data);
-       /* Create metadata channel */
-       memset(&lum, 0, sizeof(lum));
-       lum.handle = session_handle;
-       lum.cmd = LTTNG_UST_CHANNEL;
-       lum.u.channel.overwrite = chops->overwrite;
-       lum.u.channel.subbuf_size = chops->subbuf_size;
-       lum.u.channel.num_subbuf = chops->num_subbuf;
-       lum.u.channel.switch_timer_interval = chops->switch_timer_interval;
-       lum.u.channel.read_timer_interval = chops->read_timer_interval;
-       lum.u.channel.output = chops->output;
-       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
-       if (ret) {
-               free(channel_data);
-               return ret;
-       }
-       if (lur.ret_code != USTCOMM_OK) {
-               free(channel_data);
-               return lur.ret_code;
-       }
-       channel_data->handle = lur.ret_val;
-       DBG("received channel handle %u", channel_data->handle);
-       channel_data->memory_map_size = lur.u.channel.memory_map_size;
-       /* get shm fd */
-       ret = ustcomm_recv_fd(sock);
-       if (ret < 0)
-               goto error;
-       channel_data->shm_fd = ret;
-       /* get wait fd */
-       ret = ustcomm_recv_fd(sock);
-       if (ret < 0)
-               goto error;
-       channel_data->wait_fd = ret;
-       *_channel_data = channel_data;
-       return 0;
-
-error:
-       release_object(sock, channel_data);
-       return -EINVAL;
-}
-
-/*
- * Return -ENOENT if no more stream is available for creation.
- * Return 0 on success.
- * Return negative error value on error.
- */
-int ustctl_create_stream(int sock, struct lttng_ust_object_data *channel_data,
-               struct lttng_ust_object_data **_stream_data)
-{
-       struct ustcomm_ust_msg lum;
-       struct ustcomm_ust_reply lur;
-       struct lttng_ust_object_data *stream_data;
-       int ret, fd;
-
-       stream_data = malloc(sizeof(*stream_data));
-       if (!stream_data)
-               return -ENOMEM;
-       init_object(stream_data);
-       memset(&lum, 0, sizeof(lum));
-       lum.handle = channel_data->handle;
-       lum.cmd = LTTNG_UST_STREAM;
-       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
-       if (ret) {
-               free(stream_data);
-               return ret;
-       }
-       if (lur.ret_code != USTCOMM_OK) {
-               free(stream_data);
-               return lur.ret_code;
-       }
-
-       stream_data->handle = lur.ret_val;
-       DBG("received stream handle %u", stream_data->handle);
-       stream_data->memory_map_size = lur.u.stream.memory_map_size;
-       /* get shm fd */
-       fd = ustcomm_recv_fd(sock);
-       if (fd < 0)
-               goto error;
-       stream_data->shm_fd = fd;
-       /* get wait fd */
-       fd = ustcomm_recv_fd(sock);
-       if (fd < 0)
-               goto error;
-       stream_data->wait_fd = fd;
-       *_stream_data = stream_data;
-       return ret;
-
-error:
-       release_object(sock, stream_data);
-       return -EINVAL;
-}
-
-int ustctl_create_event(int sock, struct lttng_ust_event *ev,
-               struct lttng_ust_object_data *channel_data,
-               struct lttng_ust_object_data **_event_data)
-{
-       struct ustcomm_ust_msg lum;
-       struct ustcomm_ust_reply lur;
-       struct lttng_ust_object_data *event_data;
-       int ret;
-
-       event_data = malloc(sizeof(*event_data));
-       if (!event_data)
-               return -ENOMEM;
-       init_object(event_data);
-       memset(&lum, 0, sizeof(lum));
-       lum.handle = channel_data->handle;
-       lum.cmd = LTTNG_UST_EVENT;
-       strncpy(lum.u.event.name, ev->name,
-               LTTNG_UST_SYM_NAME_LEN);
-       lum.u.event.instrumentation = ev->instrumentation;
-       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
-       if (ret) {
-               free(event_data);
-               return ret;
-       }
-       event_data->handle = lur.ret_val;
-       DBG("received event handle %u", event_data->handle);
-       *_event_data = event_data;
-       return 0;
-}
-
-int ustctl_add_context(int sock, struct lttng_ust_context *ctx,
-               struct lttng_ust_object_data *obj_data,
-               struct lttng_ust_object_data **_context_data)
-{
-       struct ustcomm_ust_msg lum;
-       struct ustcomm_ust_reply lur;
-       struct lttng_ust_object_data *context_data;
-       int ret;
-
-       context_data = malloc(sizeof(*context_data));
-       if (!context_data)
-               return -ENOMEM;
-       init_object(context_data);
-       memset(&lum, 0, sizeof(lum));
-       lum.handle = obj_data->handle;
-       lum.cmd = LTTNG_UST_CONTEXT;
-       lum.u.context.ctx = ctx->ctx;
-       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
-       if (ret) {
-               free(context_data);
-               return ret;
-       }
-       context_data->handle = lur.ret_val;
-       DBG("received context handle %u", context_data->handle);
-       *_context_data = context_data;
-       return ret;
-}
-
-/* Enable event, channel and session ioctl */
-int ustctl_enable(int sock, struct lttng_ust_object_data *object)
-{
-       struct ustcomm_ust_msg lum;
-       struct ustcomm_ust_reply lur;
-       int ret;
-
-       memset(&lum, 0, sizeof(lum));
-       lum.handle = object->handle;
-       lum.cmd = LTTNG_UST_ENABLE;
-       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
-       if (ret)
-               return ret;
-       DBG("enabled handle %u", object->handle);
-       return 0;
-}
-
-/* Disable event, channel and session ioctl */
-int ustctl_disable(int sock, struct lttng_ust_object_data *object)
-{
-       struct ustcomm_ust_msg lum;
-       struct ustcomm_ust_reply lur;
-       int ret;
-
-       memset(&lum, 0, sizeof(lum));
-       lum.handle = object->handle;
-       lum.cmd = LTTNG_UST_DISABLE;
-       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
-       if (ret)
-               return ret;
-       DBG("disable handle %u", object->handle);
-       return 0;
-}
-
-int ustctl_start_session(int sock, int handle)
-{
-       struct lttng_ust_object_data obj;
-
-       obj.handle = handle;
-       return ustctl_enable(sock, &obj);
-}
-
-int ustctl_stop_session(int sock, int handle)
-{
-       struct lttng_ust_object_data obj;
-
-       obj.handle = handle;
-       return ustctl_disable(sock, &obj);
-}
-
-
-int ustctl_tracepoint_list(int sock)
-{
-       return -ENOSYS; /* not implemented */
-}
-
-int ustctl_tracer_version(int sock, struct lttng_ust_tracer_version *v)
-{
-       struct ustcomm_ust_msg lum;
-       struct ustcomm_ust_reply lur;
-       int ret;
-
-       memset(&lum, 0, sizeof(lum));
-       lum.handle = LTTNG_UST_ROOT_HANDLE;
-       lum.cmd = LTTNG_UST_TRACER_VERSION;
-       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
-       if (ret)
-               return ret;
-       memcpy(v, &lur.u.version, sizeof(*v));
-       DBG("received tracer version");
-       return 0;
-}
-
-int ustctl_wait_quiescent(int sock)
-{
-       struct ustcomm_ust_msg lum;
-       struct ustcomm_ust_reply lur;
-       int ret;
-
-       memset(&lum, 0, sizeof(lum));
-       lum.handle = LTTNG_UST_ROOT_HANDLE;
-       lum.cmd = LTTNG_UST_WAIT_QUIESCENT;
-       ret = ustcomm_send_app_cmd(sock, &lum, &lur);
-       if (ret)
-               return ret;
-       DBG("waited for quiescent state");
-       return 0;
-}
-
-int ustctl_flush_buffer(int sock, struct lttng_ust_object_data *channel_data)
-{
-       struct ustcomm_ust_msg lum;
-       struct ustcomm_ust_reply lur;
-
-       memset(&lum, 0, sizeof(lum));
-       lum.handle = channel_data->handle;
-       lum.cmd = LTTNG_UST_FLUSH_BUFFER;
-       return ustcomm_send_app_cmd(sock, &lum, &lur);
-}
-
-int ustctl_calibrate(int sock, struct lttng_ust_calibrate *calibrate)
-{
-       return -ENOSYS;
-}
-
-/* Buffer operations */
-
-/* Map channel shm into process memory */
-struct lttng_ust_shm_handle *ustctl_map_channel(struct lttng_ust_object_data *chan_data)
-{
-       struct lttng_ust_shm_handle *handle;
-       struct channel *chan;
-       size_t chan_size;
-
-       handle = channel_handle_create(chan_data->shm_fd,
-               chan_data->wait_fd,
-               chan_data->memory_map_size);
-       if (!handle) {
-               ERR("create handle error");
-               return NULL;
-       }
-       /*
-        * Set to -1 because the lttng_ust_shm_handle destruction will take care
-        * of closing shm_fd and wait_fd.
-        */
-       chan_data->shm_fd = -1;
-       chan_data->wait_fd = -1;
-
-       /*
-        * TODO: add consistency checks to be resilient if the
-        * application try to feed us with incoherent channel structure
-        * values.
-        */
-       chan = shmp(handle, handle->chan);
-       /* chan is object 0. This is hardcoded. */
-       chan_size = handle->table->objects[0].allocated_len;
-       handle->shadow_chan = malloc(chan_size);
-       if (!handle->shadow_chan) {
-               channel_destroy(chan, handle, 1);
-               return NULL;
-       }
-       memcpy(handle->shadow_chan, chan, chan_size);
-       return handle;
-}
-
-/* Add stream to channel shm and map its shm into process memory */
-int ustctl_add_stream(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_object_data *stream_data)
-{
-       int ret;
-
-       if (!stream_data->handle)
-               return -ENOENT;
-       /* map stream */
-       ret = channel_handle_add_stream(handle,
-               stream_data->shm_fd,
-               stream_data->wait_fd,
-               stream_data->memory_map_size);
-       if (ret) {
-               ERR("add stream error\n");
-               return ret;
-       }
-       /*
-        * Set to -1 because the lttng_ust_shm_handle destruction will take care
-        * of closing shm_fd and wait_fd.
-        */
-       stream_data->shm_fd = -1;
-       stream_data->wait_fd = -1;
-       return 0;
-}
-
-void ustctl_unmap_channel(struct lttng_ust_shm_handle *handle)
-{
-       struct channel *chan;
-
-       chan = shmp(handle, handle->chan);
-       channel_destroy(chan, handle, 1);
-}
-
-struct lttng_ust_lib_ring_buffer *ustctl_open_stream_read(struct lttng_ust_shm_handle *handle,
-       int cpu)
-{
-       struct channel *chan = handle->shadow_chan;
-       int shm_fd, wait_fd;
-       uint64_t memory_map_size;
-       struct lttng_ust_lib_ring_buffer *buf;
-       int ret;
-
-       buf = channel_get_ring_buffer(&chan->backend.config,
-               chan, cpu, handle, &shm_fd, &wait_fd, &memory_map_size);
-       if (!buf)
-               return NULL;
-       ret = lib_ring_buffer_open_read(buf, handle, 1);
-       if (ret)
-               return NULL;
-       return buf;
-}
-
-void ustctl_close_stream_read(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_lib_ring_buffer *buf)
-{
-       lib_ring_buffer_release_read(buf, handle, 1);
-}
-
-/* For mmap mode, readable without "get" operation */
-
-void *ustctl_get_mmap_base(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_lib_ring_buffer *buf)
-{
-       return shmp(handle, buf->backend.memory_map);
-}
-
-/* returns the length to mmap. */
-int ustctl_get_mmap_len(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_lib_ring_buffer *buf,
-               unsigned long *len)
-{
-       unsigned long mmap_buf_len;
-       struct channel *chan = handle->shadow_chan;
-
-       if (chan->backend.config.output != RING_BUFFER_MMAP)
-               return -EINVAL;
-       mmap_buf_len = chan->backend.buf_size;
-       if (chan->backend.extra_reader_sb)
-               mmap_buf_len += chan->backend.subbuf_size;
-       if (mmap_buf_len > INT_MAX)
-               return -EFBIG;
-       *len = mmap_buf_len;
-       return 0;
-}
-
-/* returns the maximum size for sub-buffers. */
-int ustctl_get_max_subbuf_size(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_lib_ring_buffer *buf,
-               unsigned long *len)
-{
-       struct channel *chan = handle->shadow_chan;
-
-       *len = chan->backend.subbuf_size;
-       return 0;
-}
-
-/*
- * For mmap mode, operate on the current packet (between get/put or
- * get_next/put_next).
- */
-
-/* returns the offset of the subbuffer belonging to the mmap reader. */
-int ustctl_get_mmap_read_offset(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_lib_ring_buffer *buf, unsigned long *off)
-{
-       struct channel *chan = handle->shadow_chan;
-       unsigned long sb_bindex;
-
-       if (chan->backend.config.output != RING_BUFFER_MMAP)
-               return -EINVAL;
-       sb_bindex = subbuffer_id_get_index(&chan->backend.config,
-                                          buf->backend.buf_rsb.id);
-       *off = shmp(handle, shmp_index(handle, buf->backend.array, sb_bindex)->shmp)->mmap_offset;
-       return 0;
-}
-
-/* returns the size of the current sub-buffer, without padding (for mmap). */
-int ustctl_get_subbuf_size(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_lib_ring_buffer *buf, unsigned long *len)
-{
-       struct channel *chan = handle->shadow_chan;
-
-       *len = lib_ring_buffer_get_read_data_size(&chan->backend.config, buf,
-               handle);
-       return 0;
-}
-
-/* returns the size of the current sub-buffer, without padding (for mmap). */
-int ustctl_get_padded_subbuf_size(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_lib_ring_buffer *buf, unsigned long *len)
-{
-       struct channel *chan = handle->shadow_chan;
-
-       *len = lib_ring_buffer_get_read_data_size(&chan->backend.config, buf,
-               handle);
-       *len = PAGE_ALIGN(*len);
-       return 0;
-}
-
-/* Get exclusive read access to the next sub-buffer that can be read. */
-int ustctl_get_next_subbuf(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_lib_ring_buffer *buf)
-{
-       return lib_ring_buffer_get_next_subbuf(buf, handle);
-}
-
-
-/* Release exclusive sub-buffer access, move consumer forward. */
-int ustctl_put_next_subbuf(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_lib_ring_buffer *buf)
-{
-       lib_ring_buffer_put_next_subbuf(buf, handle);
-       return 0;
-}
-
-/* snapshot */
-
-/* Get a snapshot of the current ring buffer producer and consumer positions */
-int ustctl_snapshot(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_lib_ring_buffer *buf)
-{
-       return lib_ring_buffer_snapshot(buf, &buf->cons_snapshot,
-                       &buf->prod_snapshot, handle);
-}
-
-/* Get the consumer position (iteration start) */
-int ustctl_snapshot_get_consumed(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_lib_ring_buffer *buf, unsigned long *pos)
-{
-       *pos = buf->cons_snapshot;
-       return 0;
-}
-
-/* Get the producer position (iteration end) */
-int ustctl_snapshot_get_produced(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_lib_ring_buffer *buf, unsigned long *pos)
-{
-       *pos = buf->prod_snapshot;
-       return 0;
-}
-
-/* Get exclusive read access to the specified sub-buffer position */
-int ustctl_get_subbuf(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_lib_ring_buffer *buf, unsigned long *pos)
-{
-       return lib_ring_buffer_get_subbuf(buf, *pos, handle);
-}
-
-/* Release exclusive sub-buffer access */
-int ustctl_put_subbuf(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_lib_ring_buffer *buf)
-{
-       lib_ring_buffer_put_subbuf(buf, handle);
-       return 0;
-}
-
-int ustctl_buffer_flush(struct lttng_ust_shm_handle *handle,
-               struct lttng_ust_lib_ring_buffer *buf)
-{
-       lib_ring_buffer_switch_slow(buf, SWITCH_ACTIVE, handle);
-       return 0;
-}
diff --git a/libustfork/Makefile.am b/libustfork/Makefile.am
deleted file mode 100644 (file)
index f2a9996..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-AM_CPPFLAGS = -I$(top_srcdir)/include
-AM_CFLAGS = -fno-strict-aliasing
-
-lib_LTLIBRARIES = libustfork.la
-libustfork_la_SOURCES = ustfork.c
-libustfork_la_LIBADD = \
-       -ldl \
-       $(top_builddir)/libust/libust.la
-libustfork_CFLAGS = -DUST_COMPONENT=libustfork -fno-strict-aliasing
diff --git a/libustfork/ustfork.c b/libustfork/ustfork.c
deleted file mode 100644 (file)
index 5e6acba..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2009  Pierre-Marc Fournier
- * Copyright (C) 2011  Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; version 2.1 of
- * the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-#define _GNU_SOURCE
-#include <dlfcn.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <signal.h>
-#include <sched.h>
-#include <stdarg.h>
-#include "usterr.h"
-
-#include <lttng/ust.h>
-
-struct user_desc;
-
-pid_t fork(void)
-{
-       static pid_t (*plibc_func)(void) = NULL;
-       ust_fork_info_t fork_info;
-       pid_t retval;
-
-       if (plibc_func == NULL) {
-               plibc_func = dlsym(RTLD_NEXT, "fork");
-               if (plibc_func == NULL) {
-                       fprintf(stderr, "libustfork: unable to find \"fork\" symbol\n");
-                       return -1;
-               }
-       }
-
-       ust_before_fork(&fork_info);
-       /* Do the real fork */
-       retval = plibc_func();
-       if (retval == 0) {
-               /* child */
-               ust_after_fork_child(&fork_info);
-       } else {
-               ust_after_fork_parent(&fork_info);
-       }
-       return retval;
-}
-
-struct ustfork_clone_info {
-       int (*fn)(void *);
-       void *arg;
-       ust_fork_info_t fork_info;
-};
-
-static int clone_fn(void *arg)
-{
-       struct ustfork_clone_info *info = (struct ustfork_clone_info *) arg;
-
-       /* clone is now done and we are in child */
-       ust_after_fork_child(&info->fork_info);
-       return info->fn(info->arg);
-}
-
-int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...)
-{
-       static int (*plibc_func)(int (*fn)(void *), void *child_stack,
-                       int flags, void *arg, pid_t *ptid,
-                       struct user_desc *tls, pid_t *ctid) = NULL;
-       /* var args */
-       pid_t *ptid;
-       struct user_desc *tls;
-       pid_t *ctid;
-       /* end of var args */
-       va_list ap;
-       int retval;
-
-       va_start(ap, arg);
-       ptid = va_arg(ap, pid_t *);
-       tls = va_arg(ap, struct user_desc *);
-       ctid = va_arg(ap, pid_t *);
-       va_end(ap);
-
-       if (plibc_func == NULL) {
-               plibc_func = dlsym(RTLD_NEXT, "clone");
-               if (plibc_func == NULL) {
-                       fprintf(stderr, "libustfork: unable to find \"clone\" symbol.\n");
-                       return -1;
-               }
-       }
-
-       if (flags & CLONE_VM) {
-               /*
-                * Creating a thread, no need to intervene, just pass on
-                * the arguments.
-                */
-               retval = plibc_func(fn, child_stack, flags, arg, ptid,
-                               tls, ctid);
-       } else {
-               /* Creating a real process, we need to intervene. */
-               struct ustfork_clone_info info = { fn: fn, arg: arg };
-
-               ust_before_fork(&info.fork_info);
-               retval = plibc_func(clone_fn, child_stack, flags, &info,
-                               ptid, tls, ctid);
-               /* The child doesn't get here. */
-               ust_after_fork_parent(&info.fork_info);
-       }
-       return retval;
-}
diff --git a/libustinstr-malloc/Makefile.am b/libustinstr-malloc/Makefile.am
deleted file mode 100644 (file)
index 26c73e0..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-AM_CPPFLAGS = -I$(top_srcdir)/include
-AM_CFLAGS = -fno-strict-aliasing
-
-lib_LTLIBRARIES = libustinstr-malloc.la
-libustinstr_malloc_la_SOURCES = mallocwrap.c
-libustinstr_malloc_la_LIBADD = -ldl
-
-noinst_SCRIPTS = run
-EXTRA_DIST = run
diff --git a/libustinstr-malloc/README b/libustinstr-malloc/README
deleted file mode 100644 (file)
index c58a7e6..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-libustinstr-malloc is used for instrumenting calls to malloc(3) in a program,
-without need for recompiling it.
-
-libustinstr-malloc defines a malloc() function that is instrumented with a
-marker. It also calls the libc malloc afterwards. When loaded with LD_PRELOAD,
-it replaces the libc malloc() function, in effect instrumenting all calls to
-malloc().
-
-See the "run" script for a usage example.
diff --git a/libustinstr-malloc/mallocwrap.c b/libustinstr-malloc/mallocwrap.c
deleted file mode 100644 (file)
index 6e66856..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2009  Pierre-Marc Fournier
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-#define _GNU_SOURCE
-#include <dlfcn.h>
-#include <sys/types.h>
-#include <stdio.h>
-#include <ust/marker.h>
-
-void *malloc(size_t size)
-{
-       static void *(*plibc_malloc)(size_t size) = NULL;
-       void *retval;
-
-       if (plibc_malloc == NULL) {
-               plibc_malloc = dlsym(RTLD_NEXT, "malloc");
-               if (plibc_malloc == NULL) {
-                       fprintf(stderr, "mallocwrap: unable to find malloc\n");
-                       return NULL;
-               }
-       }
-
-       retval = plibc_malloc(size);
-
-       ust_marker(malloc, "size %d ptr %p", (int)size, retval);
-
-       return retval;
-}
-
-void free(void *ptr)
-{
-       static void *(*plibc_free)(void *ptr) = NULL;
-
-       if (plibc_free == NULL) {
-               plibc_free = dlsym(RTLD_NEXT, "free");
-               if (plibc_free == NULL) {
-                       fprintf(stderr, "mallocwrap: unable to find free\n");
-                       return;
-               }
-       }
-
-       ust_marker(free, "ptr %p", ptr);
-
-       plibc_free(ptr);
-}
-
-UST_MARKER_LIB
diff --git a/libustinstr-malloc/run b/libustinstr-malloc/run
deleted file mode 100644 (file)
index ce4fd10..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-LD_VERBOSE=1 LD_LIBRARY_PATH=.:../libust/.libs:../../liburcu LD_PRELOAD=liburcu.so:libust.so:.libs/libmallocwrap.so $1
diff --git a/libustjava/.gitignore b/libustjava/.gitignore
deleted file mode 100644 (file)
index ab97d04..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-UST.class
-UST.h
diff --git a/libustjava/Makefile.am b/libustjava/Makefile.am
deleted file mode 100644 (file)
index cb2c1b8..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-if BUILD_JNI_INTERFACE
-
-AM_CPPFLAGS = -I$(top_srcdir)/include
-
-lib_LTLIBRARIES = libustjava.la
-libustjava_la_SOURCES = UST.c UST.h ust_java.h
-dist_noinst_DATA = UST.java
-libustjava_la_LIBADD = -lc -L$(top_builddir)/libust/.libs -lust
-
-all: UST.class UST.h
-
-clean-local:
-       rm -rf UST.h UST.class
-
-UST.class: UST.java
-       javac -d "$(builddir)" "$(srcdir)/UST.java"
-
-UST.h: UST.class
-       javah -jni UST
-
-endif
diff --git a/libustjava/README b/libustjava/README
deleted file mode 100644 (file)
index 37834e6..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-This directory contains a simple API for instrumenting java applications.
-
-Configuration examples to build this library:
-
-dependency: sun-java6-jdk
-./configure --with-java-jdk=/usr/lib/jvm/java-6-sun --with-jni-interface
-
-dependency: openjdk-6-jdk
-./configure --with-java-jdk=/usr/lib/jvm/java-6-openjdk --with-jni-interface
-
-dependency: gcj-4.4-jdk
-./configure --with-java-jdk=/usr/lib/jvm/java-gcj --with-jni-interface
diff --git a/libustjava/UST.c b/libustjava/UST.c
deleted file mode 100644 (file)
index 7ad1c71..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <jni.h>
-
-#define TRACEPOINT_CREATE_PROBES
-#include "ust_java.h"
-
-JNIEXPORT void JNICALL Java_UST_ust_1java_1event (JNIEnv *env, jobject jobj,
-                                               jstring ev_name, jstring args)
-{
-       jboolean iscopy;
-       const char *ev_name_cstr = (*env)->GetStringUTFChars(env, ev_name,
-                                                       &iscopy);
-       const char *args_cstr = (*env)->GetStringUTFChars(env, args, &iscopy);
-
-       tracepoint(ust_java_event, ev_name_cstr, args_cstr);
-}
diff --git a/libustjava/UST.java b/libustjava/UST.java
deleted file mode 100644 (file)
index be5f7c7..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-import java.util.*;
-
-class UST {
-       public static native void ust_java_event(String name, String arg);
-       static {
-               System.loadLibrary("ustjava");
-       }
-}
-
diff --git a/libustjava/ust_java.h b/libustjava/ust_java.h
deleted file mode 100644 (file)
index 366b373..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#undef TRACEPOINT_SYSTEM
-#define TRACEPOINT_SYSTEM ust_java
-
-#if !defined(_TRACEPOINT_UST_JAVA_H) || defined(TRACEPOINT_HEADER_MULTI_READ)
-#define _TRACEPOINT_UST_JAVA_H
-
-/*
- * Copyright (C) 2011  Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; version 2.1 of
- * the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-#include <ust/tracepoint.h>
-
-TRACEPOINT_EVENT(ust_java_event,
-       TP_PROTO(const char *name, const char *args),
-       TP_ARGS(name, args),
-       TP_FIELDS(
-               ctf_string(name, name)
-               ctf_string(args, args)
-       )
-)
-
-#endif /* _TRACEPOINT_UST_JAVA_H */
-
-#undef TRACEPOINT_INCLUDE_PATH
-#define TRACEPOINT_INCLUDE_PATH .
-#undef TRACEPOINT_INCLUDE_FILE
-#define TRACEPOINT_INCLUDE_FILE ust_java
-
-/* This part must be outside protection */
-#include <ust/tracepoint-event.h>
index 1898f2197d02510dbfb086f3f115fc747fd4b750..29464f41495593485e073b29427e88c96464f55b 100644 (file)
@@ -2,9 +2,11 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
 
 noinst_PROGRAMS = fork fork2
 fork_SOURCES = fork.c ust_tests_fork.h
-fork_LDADD = $(top_builddir)/libust/libust.la $(top_builddir)/libustfork/libustfork.la
+fork_LDADD = $(top_builddir)/liblttng-ust/liblttng-ust.la \
+               $(top_builddir)/liblttng-ust-fork/liblttng-ust-fork.la
 fork2_SOURCES = fork2.c
-fork2_LDADD = $(top_builddir)/libust/libust.la $(top_builddir)/libustfork/libustfork.la
+fork2_LDADD = $(top_builddir)/liblttng-ust/liblttng-ust.la \
+               $(top_builddir)/liblttng-ust-fork/liblttng-ust-fork.la
 
 noinst_SCRIPTS = run
 EXTRA_DIST = run
index 8447e24a4909952e4f34fa282bce8ad6b56bdb93..9afe38742fcaf236350f568906849051b44aafee 100644 (file)
@@ -1,8 +1,8 @@
-AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/libust
+AM_CPPFLAGS = -I$(top_srcdir)/include
 
 noinst_PROGRAMS = hello
 hello_SOURCES = hello.c tp.c tp.h
-hello_LDADD = $(top_builddir)/libust/libust.la
+hello_LDADD = $(top_builddir)/liblttng-ust/liblttng-ust.la
 
 noinst_SCRIPTS = run
 EXTRA_DIST = run
This page took 0.23055 seconds and 4 git commands to generate.