lttng-context-vpid.o lttng-context-tid.o \
lttng-context-vtid.o lttng-context-ppid.o \
lttng-context-vppid.o lttng-context-cpu-id.o \
- lttng-calibrate.o \
+ lttng-context-interruptible.o \
+ lttng-context-need-reschedule.o lttng-calibrate.o \
lttng-context-hostname.o wrapper/random.o \
probes/lttng.o wrapper/trace-clock.o \
wrapper/page_alloc.o \
echo "lttng-context-perf-counters.o" ; fi;)
endif # CONFIG_PERF_EVENTS
+ifneq ($(CONFIG_PREEMPT_RT_FULL),)
+lttng-tracer-objs += lttng-context-migratable.o
+lttng-tracer-objs += lttng-context-preemptible.o
+endif # CONFIG_PREEMPT_RT_FULL
+
+ifneq ($(CONFIG_PREEMPT),)
+lttng-tracer-objs += lttng-context-preemptible.o
+endif
+
lttng-tracer-objs += $(shell \
if [ $(VERSION) -ge 4 \
-o \( $(VERSION) -eq 3 -a $(PATCHLEVEL) -ge 15 -a $(SUBLEVEL) -ge 0 \) ] ; then \
return lttng_add_hostname_to_ctx(ctx);
case LTTNG_KERNEL_CONTEXT_CPU_ID:
return lttng_add_cpu_id_to_ctx(ctx);
+ case LTTNG_KERNEL_CONTEXT_INTERRUPTIBLE:
+ return lttng_add_interruptible_to_ctx(ctx);
+ case LTTNG_KERNEL_CONTEXT_NEED_RESCHEDULE:
+ return lttng_add_need_reschedule_to_ctx(ctx);
+ case LTTNG_KERNEL_CONTEXT_PREEMPTIBLE:
+ return lttng_add_preemptible_to_ctx(ctx);
+ case LTTNG_KERNEL_CONTEXT_MIGRATABLE:
+ return lttng_add_migratable_to_ctx(ctx);
default:
return -EINVAL;
}
LTTNG_KERNEL_CONTEXT_VPPID = 9,
LTTNG_KERNEL_CONTEXT_HOSTNAME = 10,
LTTNG_KERNEL_CONTEXT_CPU_ID = 11,
+ LTTNG_KERNEL_CONTEXT_INTERRUPTIBLE = 12,
+ LTTNG_KERNEL_CONTEXT_PREEMPTIBLE = 13,
+ LTTNG_KERNEL_CONTEXT_NEED_RESCHEDULE = 14,
+ LTTNG_KERNEL_CONTEXT_MIGRATABLE = 15,
};
struct lttng_kernel_perf_counter_ctx {
static
void cpu_id_get_value(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
union lttng_ctx_value *value)
{
value->s64 = smp_processor_id();
static
void hostname_get_value(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
union lttng_ctx_value *value)
{
struct nsproxy *nsproxy;
--- /dev/null
+/*
+ * lttng-context-interruptible.c
+ *
+ * LTTng interruptible context.
+ *
+ * Copyright (C) 2009-2015 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 <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/irqflags.h>
+#include "lttng-events.h"
+#include "wrapper/ringbuffer/frontend_types.h"
+#include "wrapper/vmalloc.h"
+#include "lttng-tracer.h"
+
+/*
+ * Interruptible at value -1 means "unknown".
+ */
+
+static
+size_t interruptible_get_size(size_t offset)
+{
+ size_t size = 0;
+
+ size += lib_ring_buffer_align(offset, lttng_alignof(int8_t));
+ size += sizeof(int8_t);
+ return size;
+}
+
+static
+void interruptible_record(struct lttng_ctx_field *field,
+ struct lib_ring_buffer_ctx *ctx,
+ struct lttng_channel *chan)
+{
+ struct lttng_probe_ctx *lttng_probe_ctx = ctx->priv;
+ int8_t interruptible = lttng_probe_ctx->interruptible;
+
+ lib_ring_buffer_align_ctx(ctx, lttng_alignof(interruptible));
+ chan->ops->event_write(ctx, &interruptible, sizeof(interruptible));
+}
+
+static
+void interruptible_get_value(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
+ union lttng_ctx_value *value)
+{
+ int8_t interruptible = lttng_probe_ctx->interruptible;
+
+ value->s64 = interruptible;
+}
+
+int lttng_add_interruptible_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, "interruptible")) {
+ lttng_remove_context_field(ctx, field);
+ return -EEXIST;
+ }
+ field->event_field.name = "interruptible";
+ field->event_field.type.atype = atype_integer;
+ field->event_field.type.u.basic.integer.size = sizeof(int8_t) * CHAR_BIT;
+ field->event_field.type.u.basic.integer.alignment = lttng_alignof(int8_t) * CHAR_BIT;
+ field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(int8_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 = interruptible_get_size;
+ field->record = interruptible_record;
+ field->get_value = interruptible_get_value;
+ lttng_context_update(*ctx);
+ wrapper_vmalloc_sync_all();
+ return 0;
+}
+EXPORT_SYMBOL_GPL(lttng_add_interruptible_to_ctx);
+
+MODULE_LICENSE("GPL and additional rights");
+MODULE_AUTHOR("Mathieu Desnoyers");
+MODULE_DESCRIPTION("Linux Trace Toolkit interruptible Context");
+MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "."
+ __stringify(LTTNG_MODULES_MINOR_VERSION) "."
+ __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION)
+ LTTNG_MODULES_EXTRAVERSION);
--- /dev/null
+/*
+ * lttng-context-migratable.c
+ *
+ * LTTng migratable context.
+ *
+ * Copyright (C) 2009-2015 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 <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/irqflags.h>
+#include "lttng-events.h"
+#include "wrapper/ringbuffer/frontend_types.h"
+#include "wrapper/vmalloc.h"
+#include "lttng-tracer.h"
+
+static
+size_t migratable_get_size(size_t offset)
+{
+ size_t size = 0;
+
+ size += lib_ring_buffer_align(offset, lttng_alignof(uint8_t));
+ size += sizeof(uint8_t);
+ return size;
+}
+
+static
+void migratable_record(struct lttng_ctx_field *field,
+ struct lib_ring_buffer_ctx *ctx,
+ struct lttng_channel *chan)
+{
+ uint8_t migratable = !__migrate_disabled(current);
+
+ lib_ring_buffer_align_ctx(ctx, lttng_alignof(migratable));
+ chan->ops->event_write(ctx, &migratable, sizeof(migratable));
+}
+
+static
+void migratable_get_value(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
+ union lttng_ctx_value *value)
+{
+ value->s64 = !__migrate_disabled(current);
+}
+
+int lttng_add_migratable_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, "migratable")) {
+ lttng_remove_context_field(ctx, field);
+ return -EEXIST;
+ }
+ field->event_field.name = "migratable";
+ field->event_field.type.atype = atype_integer;
+ field->event_field.type.u.basic.integer.size = sizeof(uint8_t) * CHAR_BIT;
+ field->event_field.type.u.basic.integer.alignment = lttng_alignof(uint8_t) * CHAR_BIT;
+ field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(uint8_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 = migratable_get_size;
+ field->record = migratable_record;
+ field->get_value = migratable_get_value;
+ lttng_context_update(*ctx);
+ wrapper_vmalloc_sync_all();
+ return 0;
+}
+EXPORT_SYMBOL_GPL(lttng_add_migratable_to_ctx);
+
+MODULE_LICENSE("GPL and additional rights");
+MODULE_AUTHOR("Mathieu Desnoyers");
+MODULE_DESCRIPTION("Linux Trace Toolkit migratable Context");
+MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "."
+ __stringify(LTTNG_MODULES_MINOR_VERSION) "."
+ __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION)
+ LTTNG_MODULES_EXTRAVERSION);
--- /dev/null
+/*
+ * lttng-context-need-reschedule.c
+ *
+ * LTTng need_reschedule context.
+ *
+ * Copyright (C) 2009-2015 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 <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/irqflags.h>
+#include "lttng-events.h"
+#include "wrapper/ringbuffer/frontend_types.h"
+#include "wrapper/vmalloc.h"
+#include "lttng-tracer.h"
+
+static
+size_t need_reschedule_get_size(size_t offset)
+{
+ size_t size = 0;
+
+ size += lib_ring_buffer_align(offset, lttng_alignof(uint8_t));
+ size += sizeof(uint8_t);
+ return size;
+}
+
+static
+void need_reschedule_record(struct lttng_ctx_field *field,
+ struct lib_ring_buffer_ctx *ctx,
+ struct lttng_channel *chan)
+{
+ uint8_t need_reschedule = test_tsk_need_resched(current);
+
+ lib_ring_buffer_align_ctx(ctx, lttng_alignof(need_reschedule));
+ chan->ops->event_write(ctx, &need_reschedule, sizeof(need_reschedule));
+}
+
+static
+void need_reschedule_get_value(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
+ union lttng_ctx_value *value)
+{
+ value->s64 = test_tsk_need_resched(current);;
+}
+
+int lttng_add_need_reschedule_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, "need_reschedule")) {
+ lttng_remove_context_field(ctx, field);
+ return -EEXIST;
+ }
+ field->event_field.name = "need_reschedule";
+ field->event_field.type.atype = atype_integer;
+ field->event_field.type.u.basic.integer.size = sizeof(uint8_t) * CHAR_BIT;
+ field->event_field.type.u.basic.integer.alignment = lttng_alignof(uint8_t) * CHAR_BIT;
+ field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(uint8_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 = need_reschedule_get_size;
+ field->record = need_reschedule_record;
+ field->get_value = need_reschedule_get_value;
+ lttng_context_update(*ctx);
+ wrapper_vmalloc_sync_all();
+ return 0;
+}
+EXPORT_SYMBOL_GPL(lttng_add_need_reschedule_to_ctx);
+
+MODULE_LICENSE("GPL and additional rights");
+MODULE_AUTHOR("Mathieu Desnoyers");
+MODULE_DESCRIPTION("Linux Trace Toolkit need_reschedule Context");
+MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "."
+ __stringify(LTTNG_MODULES_MINOR_VERSION) "."
+ __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION)
+ LTTNG_MODULES_EXTRAVERSION);
static
void nice_get_value(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
union lttng_ctx_value *value)
{
value->s64 = task_nice(current);
static
void pid_get_value(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
union lttng_ctx_value *value)
{
value->s64 = task_tgid_nr(current);
static
void ppid_get_value(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
union lttng_ctx_value *value)
{
pid_t ppid;
--- /dev/null
+/*
+ * lttng-context-preemptible.c
+ *
+ * LTTng preemptible context.
+ *
+ * Copyright (C) 2009-2015 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 <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/irqflags.h>
+#include "lttng-events.h"
+#include "wrapper/ringbuffer/frontend_types.h"
+#include "wrapper/vmalloc.h"
+#include "lttng-tracer.h"
+
+/*
+ * We nest twice in preempt disabling within LTTng: one nesting is done
+ * by the instrumentation (tracepoint, kprobes, kretprobes, syscall
+ * tracepoint), and the second is within the lib ring buffer
+ * lib_ring_buffer_get_cpu().
+ */
+#define LTTNG_PREEMPT_DISABLE_NESTING 2
+
+static
+size_t preemptible_get_size(size_t offset)
+{
+ size_t size = 0;
+
+ size += lib_ring_buffer_align(offset, lttng_alignof(uint8_t));
+ size += sizeof(uint8_t);
+ return size;
+}
+
+static
+void preemptible_record(struct lttng_ctx_field *field,
+ struct lib_ring_buffer_ctx *ctx,
+ struct lttng_channel *chan)
+{
+ int pc = preempt_count();
+ uint8_t preemptible = 0;
+
+ WARN_ON_ONCE(pc < LTTNG_PREEMPT_DISABLE_NESTING);
+ if (pc == LTTNG_PREEMPT_DISABLE_NESTING)
+ preemptible = 1;
+ lib_ring_buffer_align_ctx(ctx, lttng_alignof(preemptible));
+ chan->ops->event_write(ctx, &preemptible, sizeof(preemptible));
+}
+
+static
+void preemptible_get_value(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
+ union lttng_ctx_value *value)
+{
+ int pc = preempt_count();
+
+ WARN_ON_ONCE(pc < LTTNG_PREEMPT_DISABLE_NESTING);
+ if (pc == LTTNG_PREEMPT_DISABLE_NESTING)
+ value->s64 = 1;
+ else
+ value->s64 = 0;
+}
+
+int lttng_add_preemptible_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, "preemptible")) {
+ lttng_remove_context_field(ctx, field);
+ return -EEXIST;
+ }
+ field->event_field.name = "preemptible";
+ field->event_field.type.atype = atype_integer;
+ field->event_field.type.u.basic.integer.size = sizeof(uint8_t) * CHAR_BIT;
+ field->event_field.type.u.basic.integer.alignment = lttng_alignof(uint8_t) * CHAR_BIT;
+ field->event_field.type.u.basic.integer.signedness = lttng_is_signed_type(uint8_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 = preemptible_get_size;
+ field->record = preemptible_record;
+ field->get_value = preemptible_get_value;
+ lttng_context_update(*ctx);
+ wrapper_vmalloc_sync_all();
+ return 0;
+}
+EXPORT_SYMBOL_GPL(lttng_add_preemptible_to_ctx);
+
+MODULE_LICENSE("GPL and additional rights");
+MODULE_AUTHOR("Mathieu Desnoyers");
+MODULE_DESCRIPTION("Linux Trace Toolkit preemptible Context");
+MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "."
+ __stringify(LTTNG_MODULES_MINOR_VERSION) "."
+ __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION)
+ LTTNG_MODULES_EXTRAVERSION);
static
void prio_get_value(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
union lttng_ctx_value *value)
{
value->s64 = wrapper_task_prio_sym(current);
static
void procname_get_value(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
union lttng_ctx_value *value)
{
value->str = current->comm;
static
void tid_get_value(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
union lttng_ctx_value *value)
{
pid_t tid;
static
void vpid_get_value(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
union lttng_ctx_value *value)
{
pid_t vpid;
static
void vppid_get_value(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
union lttng_ctx_value *value)
{
struct task_struct *parent;
static
void vtid_get_value(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
union lttng_ctx_value *value)
{
pid_t vtid;
if (ret) {
printk(KERN_WARNING "Cannot add context lttng_add_cpu_id_to_ctx");
}
+ ret = lttng_add_interruptible_to_ctx(<tng_static_ctx);
+ if (ret) {
+ printk(KERN_WARNING "Cannot add context lttng_add_interruptible_to_ctx");
+ }
+ ret = lttng_add_need_reschedule_to_ctx(<tng_static_ctx);
+ if (ret) {
+ printk(KERN_WARNING "Cannot add context lttng_add_need_reschedule_to_ctx");
+ }
+#if defined(CONFIG_PREEMPT_RT_FULL) || defined(CONFIG_PREEMPT)
+ ret = lttng_add_preemptible_to_ctx(<tng_static_ctx);
+ if (ret != -ENOSYS) {
+ printk(KERN_WARNING "Cannot add context lttng_add_preemptible_to_ctx");
+ }
+#endif
+#ifdef CONFIG_PREEMPT_RT_FULL
+ ret = lttng_add_migratable_to_ctx(<tng_static_ctx);
+ if (ret != -ENOSYS) {
+ printk(KERN_WARNING "Cannot add context lttng_add_migratable_to_ctx");
+ }
+#endif
/* TODO: perf counters for filtering */
return 0;
}
struct perf_event **e; /* per-cpu array */
};
+struct lttng_probe_ctx {
+ struct lttng_event *event;
+ uint8_t interruptible;
+};
+
struct lttng_ctx_field {
struct lttng_event_field event_field;
size_t (*get_size)(size_t offset);
struct lib_ring_buffer_ctx *ctx,
struct lttng_channel *chan);
void (*get_value)(struct lttng_ctx_field *field,
+ struct lttng_probe_ctx *lttng_probe_ctx,
union lttng_ctx_value *value);
union {
struct lttng_perf_counter_field *perf_counter;
struct lttng_bytecode_runtime {
/* Associated bytecode */
struct lttng_filter_bytecode_node *bc;
- uint64_t (*filter)(void *filter_data, const char *filter_stack_data);
+ uint64_t (*filter)(void *filter_data, struct lttng_probe_ctx *lttng_probe_ctx,
+ const char *filter_stack_data);
int link_failed;
struct list_head node; /* list of bytecode runtime in event */
};
int lttng_add_ppid_to_ctx(struct lttng_ctx **ctx);
int lttng_add_vppid_to_ctx(struct lttng_ctx **ctx);
int lttng_add_hostname_to_ctx(struct lttng_ctx **ctx);
+int lttng_add_interruptible_to_ctx(struct lttng_ctx **ctx);
+int lttng_add_need_reschedule_to_ctx(struct lttng_ctx **ctx);
+#if defined(CONFIG_PREEMPT_RT_FULL) || defined(CONFIG_PREEMPT)
+int lttng_add_preemptible_to_ctx(struct lttng_ctx **ctx);
+#else
+static inline
+int lttng_add_preemptible_to_ctx(struct lttng_ctx **ctx)
+{
+ return -ENOSYS;
+}
+#endif
+#ifdef CONFIG_PREEMPT_RT_FULL
+int lttng_add_migratable_to_ctx(struct lttng_ctx **ctx);
+#else
+static inline
+int lttng_add_migratable_to_ctx(struct lttng_ctx **ctx)
+{
+ return -ENOSYS;
+}
+#endif
#if defined(CONFIG_PERF_EVENTS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
int lttng_add_perf_counter_to_ctx(uint32_t type,
uint64_t config,
}
uint64_t lttng_filter_false(void *filter_data,
+ struct lttng_probe_ctx *lttng_probe_ctx,
const char *filter_stack_data)
{
return 0;
* effect.
*/
uint64_t lttng_filter_interpret_bytecode(void *filter_data,
+ struct lttng_probe_ctx *lttng_probe_ctx,
const char *filter_stack_data)
{
struct bytecode_runtime *bytecode = filter_data;
dbg_printk("get context ref offset %u type string\n",
ref->offset);
ctx_field = <tng_static_ctx->fields[ref->offset];
- ctx_field->get_value(ctx_field, &v);
+ ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
estack_push(stack, top, ax, bx);
estack_ax(stack, top)->u.s.str = v.str;
if (unlikely(!estack_ax(stack, top)->u.s.str)) {
dbg_printk("get context ref offset %u type s64\n",
ref->offset);
ctx_field = <tng_static_ctx->fields[ref->offset];
- ctx_field->get_value(ctx_field, &v);
+ ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
estack_push(stack, top, ax, bx);
estack_ax_v = v.s64;
dbg_printk("ref get context s64 %lld\n",
int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode);
uint64_t lttng_filter_false(void *filter_data,
+ struct lttng_probe_ctx *lttng_probe_ctx,
const char *filter_stack_data);
uint64_t lttng_filter_interpret_bytecode(void *filter_data,
+ struct lttng_probe_ctx *lttng_probe_ctx,
const char *filter_stack_data);
#endif /* _LTTNG_FILTER_H */
struct lib_ring_buffer_ctx *ctx)
{
struct lttng_channel *lttng_chan = channel_get_private(chan);
- struct lttng_event *event = ctx->priv;
+ struct lttng_probe_ctx *lttng_probe_ctx = ctx->priv;
+ struct lttng_event *event = lttng_probe_ctx->event;
size_t orig_offset = offset;
size_t padding;
uint32_t event_id)
{
struct lttng_channel *lttng_chan = channel_get_private(ctx->chan);
- struct lttng_event *event = ctx->priv;
+ struct lttng_probe_ctx *lttng_probe_ctx = ctx->priv;
+ struct lttng_event *event = lttng_probe_ctx->event;
if (unlikely(ctx->rflags))
goto slow_path;
uint32_t event_id)
{
struct lttng_channel *lttng_chan = channel_get_private(ctx->chan);
- struct lttng_event *event = ctx->priv;
+ struct lttng_probe_ctx *lttng_probe_ctx = ctx->priv;
+ struct lttng_event *event = lttng_probe_ctx->event;
switch (lttng_chan->header_type) {
case 1: /* compact */
{ \
struct probe_local_vars { _locvar }; \
struct lttng_event *__event = __data; \
+ struct lttng_probe_ctx __lttng_probe_ctx = { \
+ .event = __event, \
+ .interruptible = irqs_disabled(), \
+ }; \
struct lttng_channel *__chan = __event->chan; \
struct lttng_session *__session = __chan->session; \
struct lib_ring_buffer_ctx __ctx; \
__event_prepare_filter_stack__##_name(__stackvar.__filter_stack_data, \
tp_locvar, _args); \
lttng_list_for_each_entry_rcu(bc_runtime, &__event->bytecode_runtime_head, node) { \
- if (unlikely(bc_runtime->filter(bc_runtime, \
+ if (unlikely(bc_runtime->filter(bc_runtime, &__lttng_probe_ctx, \
__stackvar.__filter_stack_data) & LTTNG_FILTER_RECORD_FLAG)) \
__filter_record = 1; \
} \
__event_len = __event_get_size__##_name(__stackvar.__dynamic_len, \
tp_locvar, _args); \
__event_align = __event_get_align__##_name(tp_locvar, _args); \
- lib_ring_buffer_ctx_init(&__ctx, __chan->chan, __event, __event_len, \
+ lib_ring_buffer_ctx_init(&__ctx, __chan->chan, &__lttng_probe_ctx, __event_len, \
__event_align, -1); \
__ret = __chan->ops->event_reserve(&__ctx, __event->id); \
if (__ret < 0) \
{ \
struct probe_local_vars { _locvar }; \
struct lttng_event *__event = __data; \
+ struct lttng_probe_ctx __lttng_probe_ctx = { \
+ .event = __event, \
+ .interruptible = irqs_disabled(), \
+ }; \
struct lttng_channel *__chan = __event->chan; \
struct lttng_session *__session = __chan->session; \
struct lib_ring_buffer_ctx __ctx; \
__event_prepare_filter_stack__##_name(__stackvar.__filter_stack_data, \
tp_locvar); \
lttng_list_for_each_entry_rcu(bc_runtime, &__event->bytecode_runtime_head, node) { \
- if (unlikely(bc_runtime->filter(bc_runtime, \
+ if (unlikely(bc_runtime->filter(bc_runtime, &__lttng_probe_ctx, \
__stackvar.__filter_stack_data) & LTTNG_FILTER_RECORD_FLAG)) \
__filter_record = 1; \
} \
} \
__event_len = __event_get_size__##_name(__stackvar.__dynamic_len, tp_locvar); \
__event_align = __event_get_align__##_name(tp_locvar); \
- lib_ring_buffer_ctx_init(&__ctx, __chan->chan, __event, __event_len, \
+ lib_ring_buffer_ctx_init(&__ctx, __chan->chan, &__lttng_probe_ctx, __event_len, \
__event_align, -1); \
__ret = __chan->ops->event_reserve(&__ctx, __event->id); \
if (__ret < 0) \
void lttng_ftrace_handler(unsigned long ip, unsigned long parent_ip, void **data)
{
struct lttng_event *event = *data;
+ struct lttng_probe_ctx lttng_probe_ctx = {
+ .event = event,
+ .interruptible = irqs_disabled(),
+ };
struct lttng_channel *chan = event->chan;
struct lib_ring_buffer_ctx ctx;
struct {
if (unlikely(!ACCESS_ONCE(event->enabled)))
return;
- lib_ring_buffer_ctx_init(&ctx, chan->chan, event,
+ lib_ring_buffer_ctx_init(&ctx, chan->chan, <tng_probe_ctx,
sizeof(payload), lttng_alignof(payload), -1);
ret = chan->ops->event_reserve(&ctx, event->id);
if (ret < 0)
#include "../lttng-events.h"
#include "../wrapper/ringbuffer/frontend_types.h"
#include "../wrapper/vmalloc.h"
+#include "../wrapper/irqflags.h"
#include "../lttng-tracer.h"
static
{
struct lttng_event *event =
container_of(p, struct lttng_event, u.kprobe.kp);
+ struct lttng_probe_ctx lttng_probe_ctx = {
+ .event = event,
+ .interruptible = lttng_regs_irqs_disabled(regs),
+ };
struct lttng_channel *chan = event->chan;
struct lib_ring_buffer_ctx ctx;
int ret;
if (unlikely(!ACCESS_ONCE(event->enabled)))
return 0;
- lib_ring_buffer_ctx_init(&ctx, chan->chan, event, sizeof(data),
+ lib_ring_buffer_ctx_init(&ctx, chan->chan, <tng_probe_ctx, sizeof(data),
lttng_alignof(data), -1);
ret = chan->ops->event_reserve(&ctx, event->id);
if (ret < 0)
#include "../lttng-events.h"
#include "../wrapper/ringbuffer/frontend_types.h"
#include "../wrapper/vmalloc.h"
+#include "../wrapper/irqflags.h"
#include "../lttng-tracer.h"
enum lttng_kretprobe_type {
container_of(krpi->rp, struct lttng_krp, krp);
struct lttng_event *event =
lttng_krp->event[type];
+ struct lttng_probe_ctx lttng_probe_ctx = {
+ .event = event,
+ .interruptible = lttng_regs_irqs_disabled(regs),
+ };
struct lttng_channel *chan = event->chan;
struct lib_ring_buffer_ctx ctx;
int ret;
payload.ip = (unsigned long) krpi->rp->kp.addr;
payload.parent_ip = (unsigned long) krpi->ret_addr;
- lib_ring_buffer_ctx_init(&ctx, chan->chan, event, sizeof(payload),
+ lib_ring_buffer_ctx_init(&ctx, chan->chan, <tng_probe_ctx, sizeof(payload),
lttng_alignof(payload), -1);
ret = chan->ops->event_reserve(&ctx, event->id);
if (ret < 0)
--- /dev/null
+#ifndef _LTTNG_WRAPPER_IRQFLAGS_H
+#define _LTTNG_WRAPPER_IRQFLAGS_H
+
+/*
+ * wrapper/irqflags.h
+ *
+ * wrapper around IRQ flags.
+ *
+ * Copyright (C) 2015 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 <linux/version.h>
+#include <linux/irqflags.h>
+
+#ifdef CONFIG_X86
+
+static inline
+int lttng_regs_irqs_disabled(struct pt_regs *regs)
+{
+ unsigned long flags = regs->flags;
+
+ return arch_irqs_disabled_flags(flags);
+}
+
+#else
+/*
+ * lttng_regs_irqs_disabled() returns -1 if irqoff state is unknown.
+ * TODO: should implement lttng_regs_irqs_disabled for each architecture
+ * to add interruptible context for kprobes and kretprobes.
+ */
+
+static inline
+int lttng_regs_irqs_disabled(struct pt_regs *regs)
+{
+ return -1;
+}
+#endif
+
+#endif /* _LTTNG_WRAPPER_IRQFLAGS_H */