Blame view

kernel/gcov/base.c 3.85 KB
2521f2c22   Peter Oberparleiter   gcov: add gcov pr...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  /*
   *  This code maintains a list of active profiling data structures.
   *
   *    Copyright IBM Corp. 2009
   *    Author(s): Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
   *
   *    Uses gcc-internal data definitions.
   *    Based on the gcov-kernel patch by:
   *		 Hubertus Franke <frankeh@us.ibm.com>
   *		 Nigel Hinds <nhinds@us.ibm.com>
   *		 Rajan Ravindran <rajancr@us.ibm.com>
   *		 Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
   *		 Paul Larson
   */
  
  #define pr_fmt(fmt)	"gcov: " fmt
  
  #include <linux/init.h>
  #include <linux/module.h>
  #include <linux/mutex.h>
9d796e662   Andrey Ryabinin   gcov: fix softloc...
21
  #include <linux/sched.h>
2521f2c22   Peter Oberparleiter   gcov: add gcov pr...
22
  #include "gcov.h"
2521f2c22   Peter Oberparleiter   gcov: add gcov pr...
23
24
25
26
27
28
29
30
31
32
33
34
35
  static int gcov_events_enabled;
  static DEFINE_MUTEX(gcov_lock);
  
  /*
   * __gcov_init is called by gcc-generated constructor code for each object
   * file compiled with -fprofile-arcs.
   */
  void __gcov_init(struct gcov_info *info)
  {
  	static unsigned int gcov_version;
  
  	mutex_lock(&gcov_lock);
  	if (gcov_version == 0) {
8cbce376e   Frantisek Hrbata   gcov: move gcov s...
36
  		gcov_version = gcov_info_version(info);
2521f2c22   Peter Oberparleiter   gcov: add gcov pr...
37
38
39
40
41
42
43
44
45
46
47
  		/*
  		 * Printing gcc's version magic may prove useful for debugging
  		 * incompatibility reports.
  		 */
  		pr_info("version magic: 0x%x
  ", gcov_version);
  	}
  	/*
  	 * Add new profiling data structure to list and inform event
  	 * listener.
  	 */
8cbce376e   Frantisek Hrbata   gcov: move gcov s...
48
  	gcov_info_link(info);
2521f2c22   Peter Oberparleiter   gcov: add gcov pr...
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  	if (gcov_events_enabled)
  		gcov_event(GCOV_ADD, info);
  	mutex_unlock(&gcov_lock);
  }
  EXPORT_SYMBOL(__gcov_init);
  
  /*
   * These functions may be referenced by gcc-generated profiling code but serve
   * no function for kernel profiling.
   */
  void __gcov_flush(void)
  {
  	/* Unused. */
  }
  EXPORT_SYMBOL(__gcov_flush);
  
  void __gcov_merge_add(gcov_type *counters, unsigned int n_counters)
  {
  	/* Unused. */
  }
  EXPORT_SYMBOL(__gcov_merge_add);
  
  void __gcov_merge_single(gcov_type *counters, unsigned int n_counters)
  {
  	/* Unused. */
  }
  EXPORT_SYMBOL(__gcov_merge_single);
  
  void __gcov_merge_delta(gcov_type *counters, unsigned int n_counters)
  {
  	/* Unused. */
  }
  EXPORT_SYMBOL(__gcov_merge_delta);
5f41ea038   Frantisek Hrbata   gcov: add support...
82
83
84
85
86
  void __gcov_merge_ior(gcov_type *counters, unsigned int n_counters)
  {
  	/* Unused. */
  }
  EXPORT_SYMBOL(__gcov_merge_ior);
a992bf836   Yuan Pengfei   gcov: add support...
87
88
89
90
91
  void __gcov_merge_time_profile(gcov_type *counters, unsigned int n_counters)
  {
  	/* Unused. */
  }
  EXPORT_SYMBOL(__gcov_merge_time_profile);
3e44c471a   Lorenzo Stoakes   gcov: add support...
92
93
94
95
96
  void __gcov_merge_icall_topn(gcov_type *counters, unsigned int n_counters)
  {
  	/* Unused. */
  }
  EXPORT_SYMBOL(__gcov_merge_icall_topn);
053842134   Martin Liska   gcov: support GCC...
97
98
99
100
101
  void __gcov_exit(void)
  {
  	/* Unused. */
  }
  EXPORT_SYMBOL(__gcov_exit);
2521f2c22   Peter Oberparleiter   gcov: add gcov pr...
102
103
104
105
106
107
108
109
110
111
  /**
   * gcov_enable_events - enable event reporting through gcov_event()
   *
   * Turn on reporting of profiling data load/unload-events through the
   * gcov_event() callback. Also replay all previous events once. This function
   * is needed because some events are potentially generated too early for the
   * callback implementation to handle them initially.
   */
  void gcov_enable_events(void)
  {
8cbce376e   Frantisek Hrbata   gcov: move gcov s...
112
  	struct gcov_info *info = NULL;
2521f2c22   Peter Oberparleiter   gcov: add gcov pr...
113
114
115
  
  	mutex_lock(&gcov_lock);
  	gcov_events_enabled = 1;
8cbce376e   Frantisek Hrbata   gcov: move gcov s...
116

2521f2c22   Peter Oberparleiter   gcov: add gcov pr...
117
  	/* Perform event callback for previously registered entries. */
9d796e662   Andrey Ryabinin   gcov: fix softloc...
118
  	while ((info = gcov_info_next(info))) {
2521f2c22   Peter Oberparleiter   gcov: add gcov pr...
119
  		gcov_event(GCOV_ADD, info);
9d796e662   Andrey Ryabinin   gcov: fix softloc...
120
121
  		cond_resched();
  	}
8cbce376e   Frantisek Hrbata   gcov: move gcov s...
122

2521f2c22   Peter Oberparleiter   gcov: add gcov pr...
123
124
125
126
  	mutex_unlock(&gcov_lock);
  }
  
  #ifdef CONFIG_MODULES
2521f2c22   Peter Oberparleiter   gcov: add gcov pr...
127
128
129
130
131
  /* Update list and generate events when modules are unloaded. */
  static int gcov_module_notifier(struct notifier_block *nb, unsigned long event,
  				void *data)
  {
  	struct module *mod = data;
8cbce376e   Frantisek Hrbata   gcov: move gcov s...
132
133
  	struct gcov_info *info = NULL;
  	struct gcov_info *prev = NULL;
2521f2c22   Peter Oberparleiter   gcov: add gcov pr...
134
135
136
137
  
  	if (event != MODULE_STATE_GOING)
  		return NOTIFY_OK;
  	mutex_lock(&gcov_lock);
8cbce376e   Frantisek Hrbata   gcov: move gcov s...
138

2521f2c22   Peter Oberparleiter   gcov: add gcov pr...
139
  	/* Remove entries located in module from linked list. */
8cbce376e   Frantisek Hrbata   gcov: move gcov s...
140
  	while ((info = gcov_info_next(info))) {
c65abf358   Rusty Russell   gcov: use within_...
141
  		if (within_module((unsigned long)info, mod)) {
8cbce376e   Frantisek Hrbata   gcov: move gcov s...
142
  			gcov_info_unlink(prev, info);
2521f2c22   Peter Oberparleiter   gcov: add gcov pr...
143
144
145
146
147
  			if (gcov_events_enabled)
  				gcov_event(GCOV_REMOVE, info);
  		} else
  			prev = info;
  	}
8cbce376e   Frantisek Hrbata   gcov: move gcov s...
148

2521f2c22   Peter Oberparleiter   gcov: add gcov pr...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
  	mutex_unlock(&gcov_lock);
  
  	return NOTIFY_OK;
  }
  
  static struct notifier_block gcov_nb = {
  	.notifier_call	= gcov_module_notifier,
  };
  
  static int __init gcov_init(void)
  {
  	return register_module_notifier(&gcov_nb);
  }
  device_initcall(gcov_init);
  #endif /* CONFIG_MODULES */