X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=libust%2Fmarker.c;h=4a3e16b96c7dd365aa352be1b0882f59390ff6d2;hb=17bb07b445acdef0034194bdcebe113988a8db60;hp=47b6d11fc0c65f29873c951049d33a4ddbf7ccd9;hpb=c93858f1db9c8fedb9cb3dc751c95ce77083c7ee;p=ust.git diff --git a/libust/marker.c b/libust/marker.c index 47b6d11..4a3e16b 100644 --- a/libust/marker.c +++ b/libust/marker.c @@ -15,27 +15,16 @@ * 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 -//ust// #include -//ust// #include -//#include "jhash.h" -//#include "list.h" -//#include "rcupdate.h" -//ust// #include -#include -//ust// #include -//ust// #include -//ust// #include -//ust// #include -//ust// #include -//ust// #include +#include +#include #define _LGPL_SOURCE #include +#include #include - #include + #include "usterr.h" #include "channels.h" #include "tracercore.h" @@ -46,8 +35,6 @@ 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"))); -extern struct marker_addr __start___marker_addr[] __attribute__((visibility("hidden"))); -extern struct marker_addr __stop___marker_addr[] __attribute__((visibility("hidden"))); /* Set to 1 to enable marker debug output */ static const int marker_debug; @@ -250,7 +237,7 @@ static void free_old_closure(struct rcu_head *head) { struct marker_entry *entry = container_of(head, struct marker_entry, rcu); - kfree(entry->oldptr); + free(entry->oldptr); /* Make sure we free the data before setting the pending flag to 0 */ smp_wmb(); entry->rcu_pending = 0; @@ -264,12 +251,12 @@ static void debug_print_probes(struct marker_entry *entry) return; if (!entry->ptype) { - printk(KERN_DEBUG "Single probe : %p %p\n", + DBG("Single probe : %p %p", entry->single.func, entry->single.probe_private); } else { for (i = 0; entry->multi[i].func; i++) - printk(KERN_DEBUG "Multi probe %d : %p %p\n", i, + DBG("Multi probe %d : %p %p", i, entry->multi[i].func, entry->multi[i].probe_private); } @@ -312,8 +299,7 @@ marker_entry_add_probe(struct marker_entry *entry, return ERR_PTR(-EBUSY); } /* + 2 : one for new probe, one for NULL func */ - new = kzalloc((nr_probes + 2) * sizeof(struct marker_probe_closure), - GFP_KERNEL); + new = zmalloc((nr_probes + 2) * sizeof(struct marker_probe_closure)); if (new == NULL) return ERR_PTR(-ENOMEM); if (!old) @@ -378,8 +364,7 @@ marker_entry_remove_probe(struct marker_entry *entry, int j = 0; /* N -> M, (N > 1, M > 1) */ /* + 1 for NULL */ - new = kzalloc((nr_probes - nr_del + 1) - * sizeof(struct marker_probe_closure), GFP_KERNEL); + new = zmalloc((nr_probes - nr_del + 1) * sizeof(struct marker_probe_closure)); if (new == NULL) return ERR_PTR(-ENOMEM); for (i = 0; old[i].func; i++) @@ -438,18 +423,16 @@ static struct marker_entry *add_marker(const char *channel, const char *name, head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)]; hlist_for_each_entry(e, node, head, hlist) { if (!strcmp(channel, e->channel) && !strcmp(name, e->name)) { - printk(KERN_NOTICE - "Marker %s.%s busy\n", channel, name); + DBG("Marker %s.%s busy", channel, name); return ERR_PTR(-EBUSY); /* Already there */ } } /* - * Using kmalloc here to allocate a variable length element. Could + * Using malloc here to allocate a variable length element. Could * cause some memory fragmentation if overused. */ - e = kmalloc(sizeof(struct marker_entry) - + channel_len + name_len + format_len, - GFP_KERNEL); + e = malloc(sizeof(struct marker_entry) + + channel_len + name_len + format_len); if (!e) return ERR_PTR(-ENOMEM); memcpy(e->channel, channel, channel_len); @@ -509,13 +492,13 @@ static int remove_marker(const char *channel, const char *name) return -EBUSY; hlist_del(&e->hlist); if (e->format_allocated) - kfree(e->format); + free(e->format); ret = ltt_channels_unregister(e->channel); WARN_ON(ret); /* Make sure the call_rcu has been executed */ //ust// if (e->rcu_pending) //ust// rcu_barrier_sched(); - kfree(e); + free(e); return 0; } @@ -524,7 +507,7 @@ static int remove_marker(const char *channel, const char *name) */ static int marker_set_format(struct marker_entry *entry, const char *format) { - entry->format = kstrdup(format, GFP_KERNEL); + entry->format = strdup(format); if (!entry->format) return -ENOMEM; entry->format_allocated = 1; @@ -546,9 +529,7 @@ static int set_marker(struct marker_entry *entry, struct marker *elem, if (entry->format) { if (strcmp(entry->format, elem->format) != 0) { - printk(KERN_NOTICE - "Format mismatch for probe %s " - "(%s), marker (%s)\n", + DBG("Format mismatch for probe %s (%s), marker (%s)", entry->name, entry->format, elem->format); @@ -669,6 +650,24 @@ static void disable_marker(struct marker *elem) */ } +/* + * is_marker_enabled - Check if a marker is enabled + * @channel: channel name + * @name: marker name + * + * Returns 1 if the marker is enabled, 0 if disabled. + */ +int is_marker_enabled(const char *channel, const char *name) +{ + struct marker_entry *entry; + + mutex_lock(&markers_mutex); + entry = get_marker(channel, name); + mutex_unlock(&markers_mutex); + + return entry && !!entry->refcount; +} + /** * marker_update_probe_range - Update a probe range * @begin: beginning of the range @@ -958,7 +957,7 @@ int marker_probe_unregister_private_data(marker_probe_func *probe, struct marker_entry *entry; int ret = 0; struct marker_probe_closure *old; - const char *channel = NULL, *name = NULL; + char *channel = NULL, *name = NULL; mutex_lock(&markers_mutex); entry = get_marker_from_private_data(probe, probe_private); @@ -969,8 +968,8 @@ int marker_probe_unregister_private_data(marker_probe_func *probe, //ust// if (entry->rcu_pending) //ust// rcu_barrier_sched(); old = marker_entry_remove_probe(entry, NULL, probe_private); - channel = kstrdup(entry->channel, GFP_KERNEL); - name = kstrdup(entry->name, GFP_KERNEL); + channel = strdup(entry->channel); + name = strdup(entry->name); mutex_unlock(&markers_mutex); marker_update_probes(); @@ -991,8 +990,8 @@ int marker_probe_unregister_private_data(marker_probe_func *probe, remove_marker(channel, name); end: mutex_unlock(&markers_mutex); - kfree(channel); - kfree(name); + free(channel); + free(name); return ret; } //ust// EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data); @@ -1187,196 +1186,55 @@ static void free_user_marker(char __user *state, struct hlist_head *head) hlist_for_each_entry_safe(umark, pos, n, head, hlist) { if (umark->state == state) { hlist_del(&umark->hlist); - kfree(umark); + free(umark); } } } -//ust// asmlinkage long sys_marker(char __user *name, char __user *format, -//ust// char __user *state, int reg) +/* + * Update current process. + * Note that we have to wait a whole scheduler period before we are sure that + * every running userspace threads have their markers updated. + * (synchronize_sched() can be used to insure this). + */ +//ust// void marker_update_process(void) //ust// { //ust// struct user_marker *umark; -//ust// long len; +//ust// struct hlist_node *pos; //ust// struct marker_entry *entry; -//ust// int ret = 0; //ust// -//ust// printk(KERN_DEBUG "Program %s %s marker [%p, %p]\n", -//ust// current->comm, reg ? "registers" : "unregisters", -//ust// name, state); -//ust// if (reg) { -//ust// umark = kmalloc(sizeof(struct user_marker), GFP_KERNEL); -//ust// umark->name[MAX_USER_MARKER_NAME_LEN - 1] = '\0'; -//ust// umark->format[MAX_USER_MARKER_FORMAT_LEN - 1] = '\0'; -//ust// umark->state = state; -//ust// len = strncpy_from_user(umark->name, name, -//ust// MAX_USER_MARKER_NAME_LEN - 1); -//ust// if (len < 0) { -//ust// ret = -EFAULT; -//ust// goto error; -//ust// } -//ust// len = strncpy_from_user(umark->format, format, -//ust// MAX_USER_MARKER_FORMAT_LEN - 1); -//ust// if (len < 0) { -//ust// ret = -EFAULT; -//ust// goto error; -//ust// } -//ust// printk(KERN_DEBUG "Marker name : %s, format : %s", umark->name, -//ust// umark->format); -//ust// mutex_lock(&markers_mutex); +//ust// mutex_lock(&markers_mutex); +//ust// mutex_lock(¤t->group_leader->user_markers_mutex); +//ust// if (strcmp(current->comm, "testprog") == 0) +//ust// DBG("do update pending for testprog"); +//ust// hlist_for_each_entry(umark, pos, +//ust// ¤t->group_leader->user_markers, hlist) { +//ust// DBG("Updating marker %s in %s", umark->name, current->comm); //ust// entry = get_marker("userspace", umark->name); //ust// if (entry) { //ust// if (entry->format && //ust// strcmp(entry->format, umark->format) != 0) { -//ust// printk(" error, wrong format in process %s", +//ust// WARN("error, wrong format in process %s", //ust// current->comm); -//ust// ret = -EPERM; -//ust// goto error_unlock; +//ust// break; //ust// } -//ust// printk(" %s", !!entry->refcount -//ust// ? "enabled" : "disabled"); -//ust// if (put_user(!!entry->refcount, state)) { -//ust// ret = -EFAULT; -//ust// goto error_unlock; +//ust// if (put_user(!!entry->refcount, umark->state)) { +//ust// WARN("Marker in %s caused a fault", +//ust// current->comm); +//ust// break; //ust// } -//ust// printk("\n"); //ust// } else { -//ust// printk(" disabled\n"); //ust// if (put_user(0, umark->state)) { -//ust// printk(KERN_WARNING -//ust// "Marker in %s caused a fault\n", -//ust// current->comm); -//ust// goto error_unlock; +//ust// WARN("Marker in %s caused a fault", current->comm); +//ust// break; //ust// } //ust// } -//ust// mutex_lock(¤t->group_leader->user_markers_mutex); -//ust// hlist_add_head(&umark->hlist, -//ust// ¤t->group_leader->user_markers); -//ust// current->group_leader->user_markers_sequence++; -//ust// mutex_unlock(¤t->group_leader->user_markers_mutex); -//ust// mutex_unlock(&markers_mutex); -//ust// } else { -//ust// mutex_lock(¤t->group_leader->user_markers_mutex); -//ust// free_user_marker(state, -//ust// ¤t->group_leader->user_markers); -//ust// current->group_leader->user_markers_sequence++; -//ust// mutex_unlock(¤t->group_leader->user_markers_mutex); -//ust// } -//ust// goto end; -//ust// error_unlock: -//ust// mutex_unlock(&markers_mutex); -//ust// error: -//ust// kfree(umark); -//ust// end: -//ust// return ret; -//ust// } -//ust// -//ust// /* -//ust// * Types : -//ust// * string : 0 -//ust// */ -//ust// asmlinkage long sys_trace(int type, uint16_t id, -//ust// char __user *ubuf) -//ust// { -//ust// long ret = -EPERM; -//ust// char *page; -//ust// int len; -//ust// -//ust// switch (type) { -//ust// case 0: /* String */ -//ust// ret = -ENOMEM; -//ust// page = (char *)__get_free_page(GFP_TEMPORARY); -//ust// if (!page) -//ust// goto string_out; -//ust// len = strncpy_from_user(page, ubuf, PAGE_SIZE); -//ust// if (len < 0) { -//ust// ret = -EFAULT; -//ust// goto string_err; -//ust// } -//ust// trace_mark(userspace, string, "string %s", page); -//ust// string_err: -//ust// free_page((unsigned long) page); -//ust// string_out: -//ust// break; -//ust// default: -//ust// break; //ust// } -//ust// return ret; -//ust// } - -//ust// static void marker_update_processes(void) -//ust// { -//ust// struct task_struct *g, *t; -//ust// -//ust// /* -//ust// * markers_mutex is taken to protect the p->user_markers read. -//ust// */ -//ust// mutex_lock(&markers_mutex); -//ust// read_lock(&tasklist_lock); -//ust// for_each_process(g) { -//ust// WARN_ON(!thread_group_leader(g)); -//ust// if (hlist_empty(&g->user_markers)) -//ust// continue; -//ust// if (strcmp(g->comm, "testprog") == 0) -//ust// printk(KERN_DEBUG "set update pending for testprog\n"); -//ust// t = g; -//ust// do { -//ust// /* TODO : implement this thread flag in each arch. */ -//ust// set_tsk_thread_flag(t, TIF_MARKER_PENDING); -//ust// } while ((t = next_thread(t)) != g); -//ust// } -//ust// read_unlock(&tasklist_lock); +//ust// clear_thread_flag(TIF_MARKER_PENDING); +//ust// mutex_unlock(¤t->group_leader->user_markers_mutex); //ust// mutex_unlock(&markers_mutex); //ust// } -/* - * Update current process. - * Note that we have to wait a whole scheduler period before we are sure that - * every running userspace threads have their markers updated. - * (synchronize_sched() can be used to insure this). - */ -void marker_update_process(void) -{ - struct user_marker *umark; - struct hlist_node *pos; - struct marker_entry *entry; - - mutex_lock(&markers_mutex); - mutex_lock(¤t->group_leader->user_markers_mutex); - if (strcmp(current->comm, "testprog") == 0) - printk(KERN_DEBUG "do update pending for testprog\n"); - hlist_for_each_entry(umark, pos, - ¤t->group_leader->user_markers, hlist) { - printk(KERN_DEBUG "Updating marker %s in %s\n", - umark->name, current->comm); - entry = get_marker("userspace", umark->name); - if (entry) { - if (entry->format && - strcmp(entry->format, umark->format) != 0) { - printk(KERN_WARNING - " error, wrong format in process %s\n", - current->comm); - break; - } - if (put_user(!!entry->refcount, umark->state)) { - printk(KERN_WARNING - "Marker in %s caused a fault\n", - current->comm); - break; - } - } else { - if (put_user(0, umark->state)) { - printk(KERN_WARNING - "Marker in %s caused a fault\n", - current->comm); - break; - } - } - } - clear_thread_flag(TIF_MARKER_PENDING); - mutex_unlock(¤t->group_leader->user_markers_mutex); - mutex_unlock(&markers_mutex); -} - /* * Called at process exit and upon do_execve(). * We assume that when the leader exits, no more references can be done to the @@ -1392,7 +1250,7 @@ void exit_user_markers(struct task_struct *p) mutex_lock(&p->user_markers_mutex); hlist_for_each_entry_safe(umark, pos, n, &p->user_markers, hlist) - kfree(umark); + free(umark); INIT_HLIST_HEAD(&p->user_markers); p->user_markers_sequence++; mutex_unlock(&p->user_markers_mutex); @@ -1444,7 +1302,7 @@ struct notifier_block marker_module_nb = { #endif /* CONFIG_MODULES */ -void ltt_dump_marker_state(struct ltt_trace_struct *trace) +void ltt_dump_marker_state(struct ust_trace *trace) { struct marker_entry *entry; struct ltt_probe_private_data call_data; @@ -1501,22 +1359,15 @@ static void new_markers(struct marker *start, struct marker *end) } } -int marker_register_lib(struct marker *markers_start, struct marker_addr *marker_addr_start, int markers_count) +int marker_register_lib(struct marker *markers_start, int markers_count) { struct lib *pl; - struct marker_addr *addr; pl = (struct lib *) malloc(sizeof(struct lib)); pl->markers_start = markers_start; - pl->markers_addr_start = marker_addr_start; pl->markers_count = markers_count; - lock_markers(); - for(addr = marker_addr_start; addr < marker_addr_start + markers_count; addr++) - addr->marker->location = addr->addr; - unlock_markers(); - /* FIXME: maybe protect this with its own mutex? */ lock_markers(); list_add(&pl->list, &libs); @@ -1545,7 +1396,7 @@ static int initialized = 0; void __attribute__((constructor)) init_markers(void) { if(!initialized) { - marker_register_lib(__start___markers, __start___marker_addr, (((long)__stop___markers)-((long)__start___markers))/sizeof(struct marker)); + marker_register_lib(__start___markers, (((long)__stop___markers)-((long)__start___markers))/sizeof(struct marker)); //DBG("markers_start: %p, markers_stop: %p\n", __start___markers, __stop___markers); initialized = 1; }