/*
* Copyright (C) 2007 Mathieu Desnoyers
*
- * 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; either version 2 of the License, or
- * (at your option) any later version.
+ * 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 program is distributed in the hope that it will be useful,
+ * 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 General Public License for more details.
+ * 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 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.
+ * 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
*/
//ust// #include <linux/module.h>
//ust// #include <linux/mutex.h>
//ust// #include <linux/ltt-tracer.h>
#define _LGPL_SOURCE
-#include <urcu.h>
+#include <urcu-bp.h>
-#include "kernelcompat.h"
+#include <ust/kernelcompat.h>
-#include "marker.h"
+#include <ust/marker.h>
#include "usterr.h"
#include "channels.h"
#include "tracercore.h"
#include "tracer.h"
+__thread long ust_reg_stack[500];
+volatile __thread long *ust_reg_stack_ptr = (long *) 0;
+
extern struct marker __start___markers[] __attribute__((visibility("hidden")));
extern struct marker __stop___markers[] __attribute__((visibility("hidden")));
+#ifdef CONFIG_UST_GDB_INTEGRATION
+extern struct marker_addr __start___marker_addr[] __attribute__((visibility("hidden")));
+extern struct marker_addr __stop___marker_addr[] __attribute__((visibility("hidden")));
+#endif
+
/* Set to 1 to enable marker debug output */
static const int marker_debug;
*/
static DEFINE_MUTEX(markers_mutex);
+static LIST_HEAD(libs);
+
+
void lock_markers(void)
{
mutex_lock(&markers_mutex);
char *format;
char *name;
/* Probe wrapper */
- void (*call)(const struct marker *mdata, void *call_private, ...);
+ void (*call)(const struct marker *mdata, void *call_private, struct registers *regs, ...);
struct marker_probe_closure single;
struct marker_probe_closure *multi;
int refcount; /* Number of times armed. 0 if disarmed. */
* operations that modifies the execution flow of preemptible code.
*/
notrace void __mark_empty_function(const struct marker *mdata,
- void *probe_private, void *call_private, const char *fmt, va_list *args)
+ void *probe_private, struct registers *regs, void *call_private, const char *fmt, va_list *args)
{
}
//ust// EXPORT_SYMBOL_GPL(__mark_empty_function);
* rcu_dereference() for the pointer read.
*/
notrace void marker_probe_cb(const struct marker *mdata,
- void *call_private, ...)
+ void *call_private, struct registers *regs, ...)
{
va_list args;
char ptype;
/* Must read the ptr before private data. They are not data
* dependant, so we put an explicit smp_rmb() here. */
smp_rmb();
- va_start(args, call_private);
- func(mdata, mdata->single.probe_private, call_private,
+ va_start(args, regs);
+ func(mdata, mdata->single.probe_private, regs, call_private,
mdata->format, &args);
va_end(args);
} else {
*/
smp_read_barrier_depends();
for (i = 0; multi[i].func; i++) {
- va_start(args, call_private);
+ va_start(args, regs);
multi[i].func(mdata, multi[i].probe_private,
- call_private, mdata->format, &args);
+ regs, call_private, mdata->format, &args);
va_end(args);
}
}
* Should be connected to markers "MARK_NOARGS".
*/
static notrace void marker_probe_cb_noarg(const struct marker *mdata,
- void *call_private, ...)
+ void *call_private, struct registers *regs, ...)
{
va_list args; /* not initialized */
char ptype;
/* Must read the ptr before private data. They are not data
* dependant, so we put an explicit smp_rmb() here. */
smp_rmb();
- func(mdata, mdata->single.probe_private, call_private,
+ func(mdata, mdata->single.probe_private, regs, call_private,
mdata->format, &args);
} else {
struct marker_probe_closure *multi;
*/
smp_read_barrier_depends();
for (i = 0; multi[i].func; i++)
- multi[i].func(mdata, multi[i].probe_private,
+ multi[i].func(mdata, multi[i].probe_private, regs,
call_private, mdata->format, &args);
}
//ust// rcu_read_unlock_sched_notrace();
*/
static void disable_marker(struct marker *elem)
{
- int ret;
-
- /* leave "call" as is. It is known statically. */
+//ust// int ret;
+//ust//
+//ust// /* leave "call" as is. It is known statically. */
//ust// if (elem->tp_name && _imv_read(elem->state)) {
//ust// WARN_ON(!elem->tp_cb);
//ust// /*
mutex_unlock(&markers_mutex);
}
+static void lib_update_markers(void)
+{
+ struct lib *lib;
+
+ /* FIXME: we should probably take a mutex here on libs */
+//ust// mutex_lock(&module_mutex);
+ list_for_each_entry(lib, &libs, list)
+ marker_update_probe_range(lib->markers_start,
+ lib->markers_start + lib->markers_count);
+//ust// mutex_unlock(&module_mutex);
+}
+
/*
* Update probes, removing the faulty probes.
*
}
mutex_unlock(&markers_mutex);
+ /* Activate marker if necessary */
marker_update_probes();
mutex_lock(&markers_mutex);
//ust//#ifdef CONFIG_MODULES
+/*
+ * Returns 0 if current not found.
+ * Returns 1 if current found.
+ */
+int lib_get_iter_markers(struct marker_iter *iter)
+{
+ struct lib *iter_lib;
+ int found = 0;
+
+//ust// mutex_lock(&module_mutex);
+ list_for_each_entry(iter_lib, &libs, list) {
+ if (iter_lib < iter->lib)
+ continue;
+ else if (iter_lib > iter->lib)
+ iter->marker = NULL;
+ found = marker_get_iter_range(&iter->marker,
+ iter_lib->markers_start,
+ iter_lib->markers_start + iter_lib->markers_count);
+ if (found) {
+ iter->lib = iter_lib;
+ break;
+ }
+ }
+//ust// mutex_unlock(&module_mutex);
+ return found;
+}
+
/**
* marker_get_iter_range - Get a next marker iterator given a range.
* @marker: current markers (in), next marker (out)
void ltt_dump_marker_state(struct ltt_trace_struct *trace)
{
- struct marker_iter iter;
+ struct marker_entry *entry;
struct ltt_probe_private_data call_data;
- const char *channel;
+ struct hlist_head *head;
+ struct hlist_node *node;
+ unsigned int i;
+ mutex_lock(&markers_mutex);
call_data.trace = trace;
call_data.serializer = NULL;
- marker_iter_reset(&iter);
- marker_iter_start(&iter);
- for (; iter.marker != NULL; marker_iter_next(&iter)) {
- if (!_imv_read(iter.marker->state))
- continue;
- channel = ltt_channels_get_name_from_index(
- iter.marker->channel_id);
- __trace_mark(0, metadata, core_marker_id,
- &call_data,
- "channel %s name %s event_id %hu "
- "int #1u%zu long #1u%zu pointer #1u%zu "
- "size_t #1u%zu alignment #1u%u",
- channel,
- iter.marker->name,
- iter.marker->event_id,
- sizeof(int), sizeof(long),
- sizeof(void *), sizeof(size_t),
- ltt_get_alignment());
- if (iter.marker->format)
- __trace_mark(0, metadata,
- core_marker_format,
+ for (i = 0; i < MARKER_TABLE_SIZE; i++) {
+ head = &marker_table[i];
+ hlist_for_each_entry(entry, node, head, hlist) {
+ __trace_mark(0, metadata, core_marker_id,
&call_data,
- "channel %s name %s format %s",
- channel,
- iter.marker->name,
- iter.marker->format);
- }
- marker_iter_stop(&iter);
-}
-//ust// EXPORT_SYMBOL_GPL(ltt_dump_marker_state);
-
-
-static LIST_HEAD(libs);
-
-/*
- * Returns 0 if current not found.
- * Returns 1 if current found.
- */
-int lib_get_iter_markers(struct marker_iter *iter)
-{
- struct lib *iter_lib;
- int found = 0;
-
-//ust// mutex_lock(&module_mutex);
- list_for_each_entry(iter_lib, &libs, list) {
- if (iter_lib < iter->lib)
- continue;
- else if (iter_lib > iter->lib)
- iter->marker = NULL;
- found = marker_get_iter_range(&iter->marker,
- iter_lib->markers_start,
- iter_lib->markers_start + iter_lib->markers_count);
- if (found) {
- iter->lib = iter_lib;
- break;
+ "channel %s name %s event_id %hu "
+ "int #1u%zu long #1u%zu pointer #1u%zu "
+ "size_t #1u%zu alignment #1u%u",
+ entry->channel,
+ entry->name,
+ entry->event_id,
+ sizeof(int), sizeof(long),
+ sizeof(void *), sizeof(size_t),
+ ltt_get_alignment());
+ if (entry->format)
+ __trace_mark(0, metadata,
+ core_marker_format,
+ &call_data,
+ "channel %s name %s format %s",
+ entry->channel,
+ entry->name,
+ entry->format);
}
}
-//ust// mutex_unlock(&module_mutex);
- return found;
-}
-
-void lib_update_markers(void)
-{
- struct lib *lib;
-
-//ust// mutex_lock(&module_mutex);
- list_for_each_entry(lib, &libs, list)
- marker_update_probe_range(lib->markers_start,
- lib->markers_start + lib->markers_count);
-//ust// mutex_unlock(&module_mutex);
+ mutex_unlock(&markers_mutex);
}
+//ust// EXPORT_SYMBOL_GPL(ltt_dump_marker_state);
static void (*new_marker_cb)(struct marker *) = NULL;
}
}
-int marker_register_lib(struct marker *markers_start, int markers_count)
+int marker_register_lib(struct marker *markers_start, struct marker_addr *marker_addr_start, int markers_count)
{
struct lib *pl;
+ struct marker_addr *addr;
pl = (struct lib *) malloc(sizeof(struct lib));
pl->markers_start = markers_start;
+#ifdef CONFIG_UST_GDB_INTEGRATION
+ pl->markers_addr_start = marker_addr_start;
+#endif
pl->markers_count = markers_count;
+#ifdef CONFIG_UST_GDB_INTEGRATION
+ lock_markers();
+ for(addr = marker_addr_start; addr < marker_addr_start + markers_count; addr++)
+ addr->marker->location = addr->addr;
+ unlock_markers();
+#endif
+
/* FIXME: maybe protect this with its own mutex? */
lock_markers();
list_add(&pl->list, &libs);
void __attribute__((constructor)) init_markers(void)
{
if(!initialized) {
- marker_register_lib(__start___markers, (((long)__stop___markers)-((long)__start___markers))/sizeof(struct marker));
- printf("markers_start: %p, markers_stop: %p\n", __start___markers, __stop___markers);
+#ifdef CONFIG_UST_GDB_INTEGRATION
+ marker_register_lib(__start___markers, __start___marker_addr, (((long)__stop___markers)-((long)__start___markers))/sizeof(struct marker));
+#else
+ marker_register_lib(__start___markers, NULL, (((long)__stop___markers)-((long)__start___markers))/sizeof(struct marker));
+#endif
+ //DBG("markers_start: %p, markers_stop: %p\n", __start___markers, __stop___markers);
initialized = 1;
}
}