From 5e1b7b8bac9f038e681906b269c1422611c6376d Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 2 Oct 2014 17:03:35 -0400 Subject: [PATCH] Implement getcpu override Signed-off-by: Mathieu Desnoyers --- doc/examples/Makefile.am | 9 ++- doc/examples/getcpu-override/Makefile | 38 ++++++++++++ doc/examples/getcpu-override/README | 5 ++ .../lttng-ust-getcpu-override-example.c | 52 ++++++++++++++++ .../getcpu-override/run-getcpu-override | 8 +++ include/Makefile.am | 3 +- include/lttng/ust-getcpu.h | 31 ++++++++++ liblttng-ust/Makefile.am | 2 +- liblttng-ust/lttng-getcpu.c | 62 +++++++++++++++++++ liblttng-ust/lttng-ust-comm.c | 3 + libringbuffer/getcpu.h | 26 ++++++-- 11 files changed, 232 insertions(+), 7 deletions(-) create mode 100644 doc/examples/getcpu-override/Makefile create mode 100644 doc/examples/getcpu-override/README create mode 100644 doc/examples/getcpu-override/lttng-ust-getcpu-override-example.c create mode 100755 doc/examples/getcpu-override/run-getcpu-override create mode 100644 include/lttng/ust-getcpu.h create mode 100644 liblttng-ust/lttng-getcpu.c diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am index 328c6b0f..0ae14b98 100644 --- a/doc/examples/Makefile.am +++ b/doc/examples/Makefile.am @@ -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 index 00000000..ec752d72 --- /dev/null +++ b/doc/examples/getcpu-override/Makefile @@ -0,0 +1,38 @@ +# Copyright (C) 2013 Jérémie Galarneau +# Copyright (C) 2014 Mathieu Desnoyers +# +# 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 index 00000000..05c8e321 --- /dev/null +++ b/doc/examples/getcpu-override/README @@ -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 index 00000000..b067bebd --- /dev/null +++ b/doc/examples/getcpu-override/lttng-ust-getcpu-override-example.c @@ -0,0 +1,52 @@ +/* + * lttng-getcpu-override-example.c + * + * Copyright (c) 2014 Mathieu Desnoyers + * + * 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 +#include +#include +#include +#include + +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 index 00000000..d0532334 --- /dev/null +++ b/doc/examples/getcpu-override/run-getcpu-override @@ -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" ${*} diff --git a/include/Makefile.am b/include/Makefile.am index b3598ffc..2fc11b5a 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -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 index 00000000..b7ece89c --- /dev/null +++ b/include/lttng/ust-getcpu.h @@ -0,0 +1,31 @@ +#ifndef LTTNG_UST_GETCPU_H +#define LTTNG_UST_GETCPU_H + +/* + * Copyright (C) 2014 Mathieu Desnoyers + * + * 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 +#include + +/* + * 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 */ diff --git a/liblttng-ust/Makefile.am b/liblttng-ust/Makefile.am index 796ce5b3..bc71358f 100644 --- a/liblttng-ust/Makefile.am +++ b/liblttng-ust/Makefile.am @@ -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 index 00000000..8f4c0fe7 --- /dev/null +++ b/liblttng-ust/lttng-getcpu.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2014 Mathieu Desnoyers + * + * 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 +#include +#include +#include +#include +#include +#include + +#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(); +} diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c index 97ecdf1e..cc5188f6 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -20,6 +20,7 @@ */ #define _LGPL_SOURCE +#define _GNU_SOURCE #include #include #include @@ -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(); diff --git a/libringbuffer/getcpu.h b/libringbuffer/getcpu.h index 190eae6c..fbddb798 100644 --- a/libringbuffer/getcpu.h +++ b/libringbuffer/getcpu.h @@ -20,6 +20,12 @@ */ #include +#include +#include + +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 */ -- 2.34.1