* Nils Carlson ([email protected]) wrote:
> RCU now dereferences an array of probe structs containing data pointers and
> function pointers, and passes the data pointer as the first argument to the
> probe.
> 
> Due to this change void prototypes are no longer allowed, which has incurred
> changes to libust-initializer.c .
> 
> This patch also fixes a problem where non-existent tracepoints are present
> in the __tracepoints section and with a name pointer pointing at NULL.

Thanks!

Acked-by: Mathieu Desnoyers <[email protected]>

> ---
>  include/ust/tracepoint.h |   68 +++++++++++++++++++++---------
>  include/ust/ust_trace.h  |    5 +-
>  lgpl-relicensing.txt     |    1 +
>  libust-initializer.c     |    5 +-
>  libust/tracepoint.c      |  103 ++++++++++++++++++++++++++-------------------
>  5 files changed, 113 insertions(+), 69 deletions(-)
> 
> diff --git a/include/ust/tracepoint.h b/include/ust/tracepoint.h
> index 1a91b79..9c7c091 100644
> --- a/include/ust/tracepoint.h
> +++ b/include/ust/tracepoint.h
> @@ -33,10 +33,15 @@
>  struct module;
>  struct tracepoint;
>  
> +struct probe {
> +     void *func;
> +     void *data;
> +};
> +
>  struct tracepoint {
>       const char *name;               /* Tracepoint name */
>       DEFINE_IMV(char, state);        /* State. */
> -     void **funcs;
> +     struct probe *probes;
>  } __attribute__((aligned(32)));              /*
>                                        * Aligned on 32 bytes because it is
>                                        * globally visible and gcc happily
> @@ -58,16 +63,20 @@ struct tracepoint {
>   */
>  #define __DO_TRACE(tp, proto, args)                                  \
>       do {                                                            \
> -             void **it_func;                                         \
> +             struct probe *it_probe_ptr;                             \
> +             void *it_func;                                          \
> +             void *__data;                                           \
>                                                                       \
> -             rcu_read_lock(); /*ust rcu_read_lock_sched_notrace();   */      
>                 \
> -             it_func = rcu_dereference((tp)->funcs);                 \
> -             if (it_func) {                                          \
> +             rcu_read_lock();                                        \
> +             it_probe_ptr = rcu_dereference((tp)->probes);           \
> +             if (it_probe_ptr) {                                     \
>                       do {                                            \
> -                             ((void(*)(proto))(*it_func))(args);     \
> -                     } while (*(++it_func));                         \
> +                             it_func = (it_probe_ptr)->func;         \
> +                             __data = (it_probe_ptr)->data;          \
> +                             ((void(*)(proto))(it_func))(args);      \
> +                     } while ((++it_probe_ptr)->func);               \
>               }                                                       \
> -             rcu_read_unlock(); /*ust rcu_read_unlock_sched_notrace(); */    
>                 \
> +             rcu_read_unlock();                                      \
>       } while (0)
>  
>  #define __CHECK_TRACE(name, generic, proto, args)                    \
> @@ -93,37 +102,47 @@ struct tracepoint {
>   * If generic is true, a variable read is used.
>   * If generic is false, immediate values are used.
>   */
> -#define DECLARE_TRACE(name, proto, args)                             \
> +#define __DECLARE_TRACE(name, proto, args, data_proto, data_args)    \
>       extern struct tracepoint __tracepoint_##name;                   \
>       static inline void trace_##name(proto)                          \
>       {                                                               \
> -             __CHECK_TRACE(name, 0, TP_PROTO(proto), TP_ARGS(args)); \
> +             __CHECK_TRACE(name, 0, TP_PROTO(data_proto),            \
> +                           TP_ARGS(data_args));                      \
>       }                                                               \
>       static inline void _trace_##name(proto)                         \
>       {                                                               \
> -             __CHECK_TRACE(name, 1, TP_PROTO(proto), TP_ARGS(args)); \
> +             __CHECK_TRACE(name, 1, TP_PROTO(data_proto),            \
> +                           TP_ARGS(data_args));                      \
>       }                                                               \
> -     static inline int register_trace_##name(void (*probe)(proto))   \
> +     static inline int                                               \
> +     register_trace_##name(void (*probe)(data_proto), void *data)    \
>       {                                                               \
> -             return tracepoint_probe_register(#name, (void *)probe); \
> +             return tracepoint_probe_register(#name, (void *)probe,  \
> +                                              data);                 \
> +                                                                     \
>       }                                                               \
> -     static inline int unregister_trace_##name(void (*probe)(proto)) \
> +     static inline int                                               \
> +     unregister_trace_##name(void (*probe)(data_proto), void *data)  \
>       {                                                               \
> -             return tracepoint_probe_unregister(#name, (void *)probe);\
> +             return tracepoint_probe_unregister(#name, (void *)probe, \
> +                                                data);               \
>       }
>  
> -#define DEFINE_TRACE(name)                                           \
> +#define DEFINE_TRACE_FN(name, reg, unreg)                                    
> \
>       static const char __tpstrtab_##name[]                           \
>       __attribute__((section("__tracepoints_strings"))) = #name;      \
>       struct tracepoint __tracepoint_##name                           \
>       __attribute__((section("__tracepoints"), aligned(32))) =        \
>               { __tpstrtab_##name, 0, NULL }
>  
> +#define DEFINE_TRACE(name)                                           \
> +     DEFINE_TRACE_FN(name, NULL, NULL);
> +
>  extern void tracepoint_update_probe_range(struct tracepoint *begin,
>       struct tracepoint *end);
>  
>  #else /* !CONFIG_TRACEPOINTS */
> -#define DECLARE_TRACE(name, proto, args)                             \
> +#define __DECLARE_TRACE(name, proto, args)                           \
>       static inline void trace_##name(proto)                          \
>       { }                                                             \
>       static inline void _trace_##name(proto)                         \
> @@ -146,20 +165,27 @@ static inline void tracepoint_update_probe_range(struct 
> tracepoint *begin,
>  { }
>  #endif /* CONFIG_TRACEPOINTS */
>  
> +#define DECLARE_TRACE(name, proto, args)                     \
> +     __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),      \
> +                     PARAMS(void *__data, proto),            \
> +                     PARAMS(__data, args))
> +
>  /*
>   * Connect a probe to a tracepoint.
>   * Internal API, should not be used directly.
>   */
> -extern int tracepoint_probe_register(const char *name, void *probe);
> +extern int tracepoint_probe_register(const char *name, void *probe, void 
> *data);
>  
>  /*
>   * Disconnect a probe from a tracepoint.
>   * Internal API, should not be used directly.
>   */
> -extern int tracepoint_probe_unregister(const char *name, void *probe);
> +extern int tracepoint_probe_unregister(const char *name, void *probe, void 
> *data);
>  
> -extern int tracepoint_probe_register_noupdate(const char *name, void *probe);
> -extern int tracepoint_probe_unregister_noupdate(const char *name, void 
> *probe);
> +extern int tracepoint_probe_register_noupdate(const char *name, void *probe,
> +                                           void *data);
> +extern int tracepoint_probe_unregister_noupdate(const char *name, void 
> *probe,
> +                                             void *data);
>  extern void tracepoint_probe_update_all(void);
>  
>  struct tracepoint_iter {
> diff --git a/include/ust/ust_trace.h b/include/ust/ust_trace.h
> index 098c5f8..e1b0257 100644
> --- a/include/ust/ust_trace.h
> +++ b/include/ust/ust_trace.h
> @@ -58,7 +58,7 @@
>       struct trace_raw_##name {                                       \
>               tstruct                                                 \
>       };                                                              \
> -     static void trace_printf_##name(proto)                          \
> +     static void trace_printf_##name(void *dummy, proto)             \
>       {                                                               \
>               struct trace_raw_##name entry_struct, *__entry;         \
>               __entry = &entry_struct;                                \
> @@ -68,8 +68,9 @@
>       }                                                               \
>       static void __attribute__((constructor)) init_##name()          \
>       {                                                               \
> +             void *dummy;                                            \
>               printf("connecting tracepoint " #name "\n");            \
> -             register_trace_##name(trace_printf_##name);             \
> +             register_trace_##name(trace_printf_##name, dummy);      \
>       }
>  
>  
> diff --git a/lgpl-relicensing.txt b/lgpl-relicensing.txt
> index 0393851..753f453 100644
> --- a/lgpl-relicensing.txt
> +++ b/lgpl-relicensing.txt
> @@ -10,6 +10,7 @@ Steven Rostedt                     <[email protected]>
>  Frederic Weisbecker         <[email protected]>
>  Xiao Guangrong                      <[email protected]>
>  Josh Stone                  <[email protected]>
> +Lai Jiangshan                       <[email protected]>
>  
>  The following copyright holders have agreed to LGPLv2.1+ re-licensing
>  of their contributions to linux/include/stringify.h.
> diff --git a/libust-initializer.c b/libust-initializer.c
> index ec39932..390218e 100644
> --- a/libust-initializer.c
> +++ b/libust-initializer.c
> @@ -18,13 +18,14 @@
>   * avoid this.
>   */
>  
> -DECLARE_TRACE(ust_dummytp, TP_PROTO(void), TP_ARGS());
> +DECLARE_TRACE(ust_dummytp, TP_PROTO(int anint), TP_ARGS(anint));
>  DEFINE_TRACE(ust_dummytp);
>  
>  void dummy_libust_initializer_func(void)
>  {
> +     int i;
>       trace_mark(ust, dummymark, MARK_NOARGS);
> -     trace_ust_dummytp();
> +     trace_ust_dummytp(i);
>  }
>  
>  MARKER_LIB;
> diff --git a/libust/tracepoint.c b/libust/tracepoint.c
> index 6155e29..620a009 100644
> --- a/libust/tracepoint.c
> +++ b/libust/tracepoint.c
> @@ -59,7 +59,7 @@ static struct hlist_head 
> tracepoint_table[TRACEPOINT_TABLE_SIZE];
>   */
>  struct tracepoint_entry {
>       struct hlist_node hlist;
> -     void **funcs;
> +     struct probe *probes;
>       int refcount;   /* Number of times armed. 0 if disarmed. */
>       char name[0];
>  };
> @@ -69,12 +69,12 @@ struct tp_probes {
>  //ust//              struct rcu_head rcu;
>               struct list_head list;
>       } u;
> -     void *probes[0];
> +     struct probe probes[0];
>  };
>  
>  static inline void *allocate_probes(int count)
>  {
> -     struct tp_probes *p  = malloc(count * sizeof(void *)
> +     struct tp_probes *p  = malloc(count * sizeof(struct probe)
>                       + sizeof(struct tp_probes));
>       return p == NULL ? NULL : p->probes;
>  }
> @@ -99,27 +99,29 @@ static void debug_print_probes(struct tracepoint_entry 
> *entry)
>  {
>       int i;
>  
> -     if (!tracepoint_debug || !entry->funcs)
> +     if (!tracepoint_debug || !entry->probes)
>               return;
>  
> -     for (i = 0; entry->funcs[i]; i++)
> -             DBG("Probe %d : %p", i, entry->funcs[i]);
> +     for (i = 0; entry->probes[i].func; i++)
> +             DBG("Probe %d : %p", i, entry->probes[i].func);
>  }
>  
>  static void *
> -tracepoint_entry_add_probe(struct tracepoint_entry *entry, void *probe)
> +tracepoint_entry_add_probe(struct tracepoint_entry *entry,
> +                        void *probe, void *data)
>  {
>       int nr_probes = 0;
> -     void **old, **new;
> +     struct probe *old, *new;
>  
>       WARN_ON(!probe);
>  
>       debug_print_probes(entry);
> -     old = entry->funcs;
> +     old = entry->probes;
>       if (old) {
>               /* (N -> N+1), (N != 0, 1) probes */
> -             for (nr_probes = 0; old[nr_probes]; nr_probes++)
> -                     if (old[nr_probes] == probe)
> +             for (nr_probes = 0; old[nr_probes].func; nr_probes++)
> +                     if (old[nr_probes].func == probe &&
> +                         old[nr_probes].data == data)
>                               return ERR_PTR(-EEXIST);
>       }
>       /* + 2 : one for new probe, one for NULL func */
> @@ -127,36 +129,40 @@ tracepoint_entry_add_probe(struct tracepoint_entry 
> *entry, void *probe)
>       if (new == NULL)
>               return ERR_PTR(-ENOMEM);
>       if (old)
> -             memcpy(new, old, nr_probes * sizeof(void *));
> -     new[nr_probes] = probe;
> -     new[nr_probes + 1] = NULL;
> +             memcpy(new, old, nr_probes * sizeof(struct probe));
> +     new[nr_probes].func = probe;
> +     new[nr_probes].data = data;
> +     new[nr_probes + 1].func = NULL;
>       entry->refcount = nr_probes + 1;
> -     entry->funcs = new;
> +     entry->probes = new;
>       debug_print_probes(entry);
>       return old;
>  }
>  
>  static void *
> -tracepoint_entry_remove_probe(struct tracepoint_entry *entry, void *probe)
> +tracepoint_entry_remove_probe(struct tracepoint_entry *entry, void *probe,
> +                           void *data)
>  {
>       int nr_probes = 0, nr_del = 0, i;
> -     void **old, **new;
> +     struct probe *old, *new;
>  
> -     old = entry->funcs;
> +     old = entry->probes;
>  
>       if (!old)
>               return ERR_PTR(-ENOENT);
>  
>       debug_print_probes(entry);
>       /* (N -> M), (N > 1, M >= 0) probes */
> -     for (nr_probes = 0; old[nr_probes]; nr_probes++) {
> -             if ((!probe || old[nr_probes] == probe))
> +     for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
> +             if ((!probe ||
> +                  old[nr_probes].func == probe &&
> +                  old[nr_probes].data == data))
>                       nr_del++;
>       }
>  
>       if (nr_probes - nr_del == 0) {
>               /* N -> 0, (N > 1) */
> -             entry->funcs = NULL;
> +             entry->probes = NULL;
>               entry->refcount = 0;
>               debug_print_probes(entry);
>               return old;
> @@ -167,12 +173,13 @@ tracepoint_entry_remove_probe(struct tracepoint_entry 
> *entry, void *probe)
>               new = allocate_probes(nr_probes - nr_del + 1);
>               if (new == NULL)
>                       return ERR_PTR(-ENOMEM);
> -             for (i = 0; old[i]; i++)
> -                     if ((probe && old[i] != probe))
> +             for (i = 0; old[i].func; i++)
> +                     if (probe &&
> +                         (old[i].func != probe || old[i].data != data))
>                               new[j++] = old[i];
> -             new[nr_probes - nr_del] = NULL;
> +             new[nr_probes - nr_del].func = NULL;
>               entry->refcount = nr_probes - nr_del;
> -             entry->funcs = new;
> +             entry->probes = new;
>       }
>       debug_print_probes(entry);
>       return old;
> @@ -225,7 +232,7 @@ static struct tracepoint_entry *add_tracepoint(const char 
> *name)
>       if (!e)
>               return ERR_PTR(-ENOMEM);
>       memcpy(&e->name[0], name, name_len);
> -     e->funcs = NULL;
> +     e->probes = NULL;
>       e->refcount = 0;
>       hlist_add_head(&e->hlist, head);
>       return e;
> @@ -256,7 +263,7 @@ static void set_tracepoint(struct tracepoint_entry 
> **entry,
>        * include/linux/tracepoints.h. A matching smp_read_barrier_depends()
>        * is used.
>        */
> -     rcu_assign_pointer(elem->funcs, (*entry)->funcs);
> +     rcu_assign_pointer(elem->probes, (*entry)->probes);
>       elem->state__imv = active;
>  }
>  
> @@ -269,7 +276,7 @@ static void set_tracepoint(struct tracepoint_entry 
> **entry,
>  static void disable_tracepoint(struct tracepoint *elem)
>  {
>       elem->state__imv = 0;
> -     rcu_assign_pointer(elem->funcs, NULL);
> +     rcu_assign_pointer(elem->probes, NULL);
>  }
>  
>  /**
> @@ -280,13 +287,17 @@ static void disable_tracepoint(struct tracepoint *elem)
>   * Updates the probe callback corresponding to a range of tracepoints.
>   */
>  void tracepoint_update_probe_range(struct tracepoint *begin,
> -     struct tracepoint *end)
> +                                struct tracepoint *end)
>  {
>       struct tracepoint *iter;
>       struct tracepoint_entry *mark_entry;
>  
>       pthread_mutex_lock(&tracepoints_mutex);
>       for (iter = begin; iter < end; iter++) {
> +             if (!iter->name) {
> +                     disable_tracepoint(iter);
> +                     continue;
> +             }
>               mark_entry = get_tracepoint(iter->name);
>               if (mark_entry) {
>                       set_tracepoint(&mark_entry, iter,
> @@ -324,18 +335,19 @@ static void tracepoint_update_probes(void)
>  //ust//      module_imv_update();
>  }
>  
> -static void *tracepoint_add_probe(const char *name, void *probe)
> +static struct probe *
> +tracepoint_add_probe(const char *name, void *probe, void *data)
>  {
>       struct tracepoint_entry *entry;
> -     void *old;
> +     struct probe *old;
>  
>       entry = get_tracepoint(name);
>       if (!entry) {
>               entry = add_tracepoint(name);
>               if (IS_ERR(entry))
> -                     return entry;
> +                     return (struct probe *)entry;
>       }
> -     old = tracepoint_entry_add_probe(entry, probe);
> +     old = tracepoint_entry_add_probe(entry, probe, data);
>       if (IS_ERR(old) && !entry->refcount)
>               remove_tracepoint(entry);
>       return old;
> @@ -349,12 +361,12 @@ static void *tracepoint_add_probe(const char *name, 
> void *probe)
>   * Returns 0 if ok, error value on error.
>   * The probe address must at least be aligned on the architecture pointer 
> size.
>   */
> -int tracepoint_probe_register(const char *name, void *probe)
> +int tracepoint_probe_register(const char *name, void *probe, void *data)
>  {
>       void *old;
>  
>       pthread_mutex_lock(&tracepoints_mutex);
> -     old = tracepoint_add_probe(name, probe);
> +     old = tracepoint_add_probe(name, probe, data);
>       pthread_mutex_unlock(&tracepoints_mutex);
>       if (IS_ERR(old))
>               return PTR_ERR(old);
> @@ -365,7 +377,7 @@ int tracepoint_probe_register(const char *name, void 
> *probe)
>  }
>  //ust// EXPORT_SYMBOL_GPL(tracepoint_probe_register);
>  
> -static void *tracepoint_remove_probe(const char *name, void *probe)
> +static void *tracepoint_remove_probe(const char *name, void *probe, void 
> *data)
>  {
>       struct tracepoint_entry *entry;
>       void *old;
> @@ -373,7 +385,7 @@ static void *tracepoint_remove_probe(const char *name, 
> void *probe)
>       entry = get_tracepoint(name);
>       if (!entry)
>               return ERR_PTR(-ENOENT);
> -     old = tracepoint_entry_remove_probe(entry, probe);
> +     old = tracepoint_entry_remove_probe(entry, probe, data);
>       if (IS_ERR(old))
>               return old;
>       if (!entry->refcount)
> @@ -385,18 +397,19 @@ static void *tracepoint_remove_probe(const char *name, 
> void *probe)
>   * tracepoint_probe_unregister -  Disconnect a probe from a tracepoint
>   * @name: tracepoint name
>   * @probe: probe function pointer
> + * @probe: probe data pointer
>   *
>   * We do not need to call a synchronize_sched to make sure the probes have
>   * finished running before doing a module unload, because the module unload
>   * itself uses stop_machine(), which insures that every preempt disabled 
> section
>   * have finished.
>   */
> -int tracepoint_probe_unregister(const char *name, void *probe)
> +int tracepoint_probe_unregister(const char *name, void *probe, void *data)
>  {
>       void *old;
>  
>       pthread_mutex_lock(&tracepoints_mutex);
> -     old = tracepoint_remove_probe(name, probe);
> +     old = tracepoint_remove_probe(name, probe, data);
>       pthread_mutex_unlock(&tracepoints_mutex);
>       if (IS_ERR(old))
>               return PTR_ERR(old);
> @@ -427,12 +440,13 @@ static void tracepoint_add_old_probes(void *old)
>   *
>   * caller must call tracepoint_probe_update_all()
>   */
> -int tracepoint_probe_register_noupdate(const char *name, void *probe)
> +int tracepoint_probe_register_noupdate(const char *name, void *probe,
> +                                    void *data)
>  {
>       void *old;
>  
>       pthread_mutex_lock(&tracepoints_mutex);
> -     old = tracepoint_add_probe(name, probe);
> +     old = tracepoint_add_probe(name, probe, data);
>       if (IS_ERR(old)) {
>               pthread_mutex_unlock(&tracepoints_mutex);
>               return PTR_ERR(old);
> @@ -450,12 +464,13 @@ int tracepoint_probe_register_noupdate(const char 
> *name, void *probe)
>   *
>   * caller must call tracepoint_probe_update_all()
>   */
> -int tracepoint_probe_unregister_noupdate(const char *name, void *probe)
> +int tracepoint_probe_unregister_noupdate(const char *name, void *probe,
> +                                      void *data)
>  {
>       void *old;
>  
>       pthread_mutex_lock(&tracepoints_mutex);
> -     old = tracepoint_remove_probe(name, probe);
> +     old = tracepoint_remove_probe(name, probe, data);
>       if (IS_ERR(old)) {
>               pthread_mutex_unlock(&tracepoints_mutex);
>               return PTR_ERR(old);
> @@ -662,7 +677,7 @@ int tracepoint_register_lib(struct tracepoint 
> *tracepoints_start, int tracepoint
>       lib_update_tracepoints();
>  
>       DBG("just registered a tracepoints section from %p and having %d 
> tracepoints", tracepoints_start, tracepoints_count);
> -     
> +
>       return 0;
>  }
>  
> -- 
> 1.7.1
> 
> 
> _______________________________________________
> ltt-dev mailing list
> [email protected]
> http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev
> 

-- 
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com

_______________________________________________
ltt-dev mailing list
[email protected]
http://lists.casi.polymtl.ca/cgi-bin/mailman/listinfo/ltt-dev

Reply via email to