Implement getcpu override
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 2 Oct 2014 21:03:35 +0000 (17:03 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 10 Apr 2015 20:44:17 +0000 (16:44 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
doc/examples/Makefile.am
doc/examples/getcpu-override/Makefile [new file with mode: 0644]
doc/examples/getcpu-override/README [new file with mode: 0644]
doc/examples/getcpu-override/lttng-ust-getcpu-override-example.c [new file with mode: 0644]
doc/examples/getcpu-override/run-getcpu-override [new file with mode: 0755]
include/Makefile.am
include/lttng/ust-getcpu.h [new file with mode: 0644]
liblttng-ust/Makefile.am
liblttng-ust/lttng-getcpu.c [new file with mode: 0644]
liblttng-ust/lttng-ust-comm.c
libringbuffer/getcpu.h

index 328c6b0f0432c6c4139b1fc951169e198887298b..0ae14b98eb00ad330b1fdf0bd1cf25987a571f4f 100644 (file)
@@ -5,6 +5,7 @@ doc_examples_demodir = ${docdir}/examples/demo
 doc_examples_hello_static_libdir = ${docdir}/examples/hello-static-lib
 doc_examples_demo_tracefdir = ${docdir}/examples/demo-tracef
 doc_examples_clock_overridedir = ${docdir}/examples/clock-override
+doc_examples_getcpu_overridedir = ${docdir}/examples/getcpu-override
 
 if BUILD_JAVA_AGENT
 doc_examples_java_juldir = ${docdir}/examples/java-jul
@@ -49,12 +50,18 @@ dist_doc_examples_clock_override_DATA = clock-override/Makefile \
        clock-override/run-clock-override \
        clock-override/README
 
+dist_doc_examples_getcpu_override_DATA = getcpu-override/Makefile \
+       getcpu-override/lttng-ust-getcpu-override-example.c \
+       getcpu-override/run-getcpu-override \
+       getcpu-override/README
+
 if NO_SHARED
 # Don't build examples if shared libraries support was explicitly
 # disabled.
 else
 # Copies are for VPATH build support
-SUBDIRS_PROXY = easy-ust demo hello-static-lib demo-tracef clock-override
+SUBDIRS_PROXY = easy-ust demo hello-static-lib demo-tracef clock-override \
+               getcpu-override
 
 if BUILD_GEN_TP_EXAMPLES
 SUBDIRS_PROXY += gen-tp
diff --git a/doc/examples/getcpu-override/Makefile b/doc/examples/getcpu-override/Makefile
new file mode 100644 (file)
index 0000000..ec752d7
--- /dev/null
@@ -0,0 +1,38 @@
+# Copyright (C) 2013  Jérémie Galarneau <jeremie.galarneau@efficios.com>
+# Copyright (C) 2014  Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program for any
+# purpose, provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is
+# granted, provided the above notices are retained, and a notice that
+# the code was modified is included with the above copyright notice.
+#
+# This Makefile is not using automake so that users may see how to build
+# a program with tracepoint provider probes as stand-alone shared objects.
+#
+# This makefile is purposefully kept simple to support GNU and BSD make.
+
+ifdef AM_CC
+       CC = $(AM_CC)
+endif
+
+LIBS = -ldl    # On Linux
+#LIBS = -lc    # On BSD
+LOCAL_CPPFLAGS += -I.
+
+all: lttng-ust-getcpu-override-example.so
+
+lttng-ust-getcpu-override-example.o: lttng-ust-getcpu-override-example.c
+       $(CC) $(CPPFLAGS) $(LOCAL_CPPFLAGS) $(CFLAGS) $(AM_CPPFLAGS) \
+               $(AM_CFLAGS) -fpic -c -o $@ $<
+
+lttng-ust-getcpu-override-example.so: lttng-ust-getcpu-override-example.o
+       $(CC) -shared -Wl,--no-as-needed -o $@ $(LDFLAGS) $(CFLAGS) \
+               $(AM_LDFLAGS) $(AM_CFLAGS) lttng-ust-getcpu-override-example.o
+
+.PHONY: clean
+clean:
+       rm -f *.o *.so
diff --git a/doc/examples/getcpu-override/README b/doc/examples/getcpu-override/README
new file mode 100644 (file)
index 0000000..05c8e32
--- /dev/null
@@ -0,0 +1,5 @@
+This getcpu override example shows how to implement and load a getcpu
+override plugin for LTTng-UST. This can be useful in cases where direct
+hardware access is available for architecture-specific registers holding
+the CPU number, and where it should be used rather than the Linux kernel
+sched_getcpu() vDSO/syscall.
diff --git a/doc/examples/getcpu-override/lttng-ust-getcpu-override-example.c b/doc/examples/getcpu-override/lttng-ust-getcpu-override-example.c
new file mode 100644 (file)
index 0000000..b067beb
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * lttng-getcpu-override-example.c
+ *
+ * Copyright (c) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <lttng/ust-getcpu.h>
+
+static
+int plugin_getcpu(void)
+{
+       /* Dummy: always return CPU 0. */
+       return 0;
+}
+
+void lttng_ust_getcpu_plugin_init(void)
+{
+       int ret;
+
+       ret = lttng_ust_getcpu_override(plugin_getcpu);
+       if (ret) {
+               fprintf(stderr, "Error enabling getcpu override: %s\n",
+                       strerror(-ret));
+               goto error;
+       }
+       return;
+
+error:
+       exit(EXIT_FAILURE);
+}
diff --git a/doc/examples/getcpu-override/run-getcpu-override b/doc/examples/getcpu-override/run-getcpu-override
new file mode 100755 (executable)
index 0000000..d053233
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# launch with: run-getcpu-override progname args
+
+DIR=$(dirname $0)
+DIR=$(readlink -f $DIR)
+
+LTTNG_UST_GETCPU_PLUGIN="$DIR/lttng-ust-getcpu-override-example.so" ${*}
index b3598ffc859b24fc1c377baed07e7e9d142eb9d9..2fc11b5afb6451cbf8fa6e91f994b2541e2c7763 100644 (file)
@@ -21,7 +21,8 @@ nobase_include_HEADERS = \
        lttng/ust-error.h \
        lttng/tracef.h \
        lttng/lttng-ust-tracef.h \
-       lttng/ust-clock.h
+       lttng/ust-clock.h \
+       lttng/ust-getcpu.h
 
 # note: usterr-signal-safe.h, core.h and share.h need namespace cleanup.
 
diff --git a/include/lttng/ust-getcpu.h b/include/lttng/ust-getcpu.h
new file mode 100644 (file)
index 0000000..b7ece89
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef LTTNG_UST_GETCPU_H
+#define LTTNG_UST_GETCPU_H
+
+/*
+ * Copyright (C) 2014  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 <stdint.h>
+#include <stddef.h>
+
+/*
+ * Set getcpu override read callback. This callback should return the
+ * current CPU number.
+ */
+int lttng_ust_getcpu_override(int (*getcpu)(void));
+
+#endif /* LTTNG_UST_GETCPU_H */
index 796ce5b3837fe939cb3599d50275d8eadb195a7e..bc71358fe55482d4b40b474c950f190ab9f58c70 100644 (file)
@@ -65,7 +65,7 @@ liblttng_ust_support_la_SOURCES = \
        lttng-ring-buffer-client-overwrite-rt.c \
        lttng-ring-buffer-metadata-client.h \
        lttng-ring-buffer-metadata-client.c \
-       lttng-clock.c
+       lttng-clock.c lttng-getcpu.c
 
 liblttng_ust_la_SOURCES =
 
diff --git a/liblttng-ust/lttng-getcpu.c b/liblttng-ust/lttng-getcpu.c
new file mode 100644 (file)
index 0000000..8f4c0fe
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014  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 <error.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <usterr-signal-safe.h>
+#include <lttng/ust-getcpu.h>
+#include <urcu/system.h>
+#include <urcu/arch.h>
+
+#include "../libringbuffer/getcpu.h"
+
+int (*lttng_get_cpu)(void);
+
+int lttng_ust_getcpu_override(int (*getcpu)(void))
+{
+       CMM_STORE_SHARED(lttng_get_cpu, getcpu);
+       return 0;
+}
+
+void lttng_ust_getcpu_init(void)
+{
+       const char *libname;
+       void *handle;
+       void (*libinit)(void);
+
+       libname = secure_getenv("LTTNG_UST_GETCPU_PLUGIN");
+       if (!libname)
+               return;
+       handle = dlopen(libname, RTLD_NOW);
+       if (!handle) {
+               PERROR("Cannot load LTTng UST getcpu override library %s",
+                       libname);
+               return;
+       }
+       dlerror();
+       libinit = (void (*)(void)) dlsym(handle,
+               "lttng_ust_getcpu_plugin_init");
+       if (!libinit) {
+               PERROR("Cannot find LTTng UST getcpu override library %s initialization function lttng_ust_getcpu_plugin_init()",
+                       libname);
+               return;
+       }
+       libinit();
+}
index 97ecdf1e99001bac3ddda7b7476d2e5a08b6c566..cc5188f6112cb744ddd45297973cef532201d9a6 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #define _LGPL_SOURCE
+#define _GNU_SOURCE
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/mman.h>
@@ -53,6 +54,7 @@
 #include "../libringbuffer/tlsfixup.h"
 #include "lttng-ust-baddr.h"
 #include "clock.h"
+#include "../libringbuffer/getcpu.h"
 
 /*
  * Has lttng ust comm constructor been called ?
@@ -1446,6 +1448,7 @@ void __attribute__((constructor)) lttng_ust_init(void)
        init_usterr();
        init_tracepoint();
        lttng_ust_clock_init();
+       lttng_ust_getcpu_init();
        lttng_ust_baddr_statedump_init();
        lttng_ring_buffer_metadata_client_init();
        lttng_ring_buffer_client_overwrite_init();
index 190eae6c3d39bf131815e57b05c079c772ff103f..fbddb7989336b71235ba238eff9ae860c41a3d6e 100644 (file)
  */
 
 #include <urcu/compiler.h>
+#include <urcu/system.h>
+#include <urcu/arch.h>
+
+void lttng_ust_getcpu_init(void);
+
+extern int (*lttng_get_cpu)(void);
 
 #ifdef LTTNG_UST_DEBUG_VALGRIND
 
@@ -29,7 +35,7 @@
  * migration, so it is only statistically accurate.
  */
 static inline
-int lttng_ust_get_cpu(void)
+int lttng_ust_get_cpu_internal(void)
 {
        return 0;
 }
@@ -51,7 +57,7 @@ int lttng_ust_get_cpu(void)
  * If getcpu is not implemented in the kernel, use cpu 0 as fallback.
  */
 static inline
-int lttng_ust_get_cpu(void)
+int lttng_ust_get_cpu_internal(void)
 {
        int cpu, ret;
 
@@ -67,7 +73,7 @@ int lttng_ust_get_cpu(void)
  * If getcpu is not implemented in the kernel, use cpu 0 as fallback.
  */
 static inline
-int lttng_ust_get_cpu(void)
+int lttng_ust_get_cpu_internal(void)
 {
        int cpu;
 
@@ -85,7 +91,7 @@ int lttng_ust_get_cpu(void)
  * number 0, with the assocated performance degradation on SMP.
  */
 static inline
-int lttng_ust_get_cpu(void)
+int lttng_ust_get_cpu_internal(void)
 {
        return 0;
 }
@@ -96,4 +102,16 @@ int lttng_ust_get_cpu(void)
 
 #endif
 
+static inline
+int lttng_ust_get_cpu(void)
+{
+       int (*getcpu)(void) = CMM_LOAD_SHARED(lttng_get_cpu);
+
+       if (caa_likely(!getcpu)) {
+               return lttng_ust_get_cpu_internal();
+       } else {
+               return getcpu();
+       }
+}
+
 #endif /* _LTTNG_GETCPU_H */
This page took 0.031289 seconds and 4 git commands to generate.