Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 8d64f28127d28a1c8a99eee73c0fac0310423436 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
/*******************************************************************************
 * Copyright (c) 2004, 2018 Red Hat, Inc.
 * 
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *    Keith Seitz <keiths@redhat.com> - initial API and implementation
 *    Kent Sebastian <ksebasti@redhat.com> -
 *******************************************************************************/

package org.eclipse.linuxtools.internal.oprofile.core;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;

import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.linuxtools.internal.oprofile.core.daemon.OpEvent;
import org.eclipse.linuxtools.internal.oprofile.core.daemon.OpInfo;
import org.eclipse.linuxtools.internal.oprofile.core.model.OpModelImage;
import org.eclipse.linuxtools.internal.oprofile.core.model.OpModelSession;
import org.eclipse.linuxtools.internal.oprofile.core.opxml.checkevent.CheckEventsProcessor;
import org.eclipse.linuxtools.profiling.launch.IRemoteFileProxy;
import org.eclipse.linuxtools.profiling.launch.RemoteProxyManager;
import org.eclipse.linuxtools.tools.launch.core.factory.RuntimeProcessFactory;

/**
 * Common class wrapper for all things Oprofile.
 */
public class Oprofile {
	// Ugh. Need to know whether the module is loaded without running oprofile
	// commands...
	private static final String[] OPROFILE_CPU_TYPE_FILES = { "/dev/oprofile/cpu_type", //$NON-NLS-1$
			"/proc/sys/dev/oprofile/cpu_type" //$NON-NLS-1$
	};

	/**
	 * Oprofile information
	 */
	private static OpInfo info;

	/**
	 * Make sure that oprofile is ready to go
	 */
	static {
		initializeOprofileModule();
	}

	/**
	 * Initialize the oprofile module
	 *
	 * This function will check if the kernel module is loaded. If it is not, it
	 * will attempt to load it (which will cause the system to prompt the user for
	 * root access).
	 */
	static private void initializeOprofileModule() {
		if (OprofileProject.getProfilingBinary().equals(OprofileProject.OPERF_BINARY) || isKernelModuleLoaded()) {
			initializeOprofileCore();
		}
	}

	// This requires more inside knowledge about Oprofile than one would like,
	// but it is the only way of knowing whether the module is loaded (and we can
	// succesfully call into the oprofile wrapper library without causing it to
	// print out
	// a lot of warnings).
	/**
	 * Check whether oprofile kernel module is loaded
	 * 
	 * @return true if the module is loaded, otherwise false
	 */
	private static boolean isKernelModuleLoaded() {
		IRemoteFileProxy proxy = null;
		try {
			proxy = RemoteProxyManager.getInstance().getFileProxy(Oprofile.OprofileProject.getProject());
		} catch (CoreException e) {
			e.printStackTrace();
		}

		for (int i = 0; i < OPROFILE_CPU_TYPE_FILES.length; ++i) {
			IFileStore f = proxy.getResource(OPROFILE_CPU_TYPE_FILES[i]);
			if (f.fetchInfo().exists()) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Initializes static data for oprofile.
	 */
	private static void initializeOprofileCore() {
		info = OpInfo.getInfo();

		if (info == null) {
			throw new ExceptionInInitializerError(OprofileProperties.getString("fatal.opinfoNotParsed")); //$NON-NLS-1$
		}
	}

	/**
	 * Queries oprofile for the number of counters on the current CPU. Used only in
	 * launch config tabs.
	 * 
	 * @return the number of counters
	 */
	public static int getNumberOfCounters() {
		// If operf is not found, set no counters
		try {
			Process p = RuntimeProcessFactory.getFactory().exec(new String[] { "operf", "--version" }, //$NON-NLS-1$ //$NON-NLS-2$
					OprofileProject.getProject());
			if (p == null) {
				return 0;
			}
		} catch (IOException e) {
			return 0;
		}
		return info.getNrCounters();
	}

	/**
	 * Returns the CPU speed of the current configuration.
	 * 
	 * @return the cpu speed in MHz
	 */
	public static double getCpuFrequency() {
		return info.getCPUSpeed();
	}

	/**
	 * Get all the events that may be collected on the given counter.
	 * 
	 * @param num the counter number
	 * @return an array of all valid events -- NEVER RETURNS NULL!
	 */
	public static OpEvent[] getEvents(int num) {
		return info.getEvents(num);
	}

	/**
	 * Returns the default location of the opcontrol samples directory or the
	 * project directory if the profiler is operf.
	 * 
	 * @return the default samples directory
	 */
	public static String getDefaultSamplesDirectory() {
		return info.getDefault(OpInfo.DEFAULT_SAMPLE_DIR);
	}

	/**
	 * Returns the oprofile daemon log file.
	 * 
	 * @return the log file (absolute pathname)
	 */
	public static String getLogFile() {
		return info.getDefault(OpInfo.DEFAULT_LOG_FILE);
	}

	/**
	 * Returns whether or not oprofile is in timer mode.
	 * 
	 * @return true if oprofile is in timer mode, false otherwise
	 */
	public static boolean getTimerMode() {
		return info.getTimerMode();
	}

	/**
	 * Checks the requested counter, event, and unit mask for validity.
	 * 
	 * @param ctr   the counter
	 * @param event the event name
	 * @param um    the unit mask
	 * @return whether the requested event is valid
	 */
	public static Boolean checkEvent(int ctr, String event, int um) {
		int[] validResult = new int[1];
		try {
			IRunnableWithProgress opxml = OprofileCorePlugin.getDefault().getOpxmlProvider().checkEvents(ctr, event, um,
					validResult);
			opxml.run(null);
		} catch (InvocationTargetException | InterruptedException e) {
		}

		return (validResult[0] == CheckEventsProcessor.EVENT_OK);
	}

	/**
	 * Returns a list of all the session collected on the system, as well as the
	 * event under each of them.
	 * 
	 * @since 3.0
	 * @returns a list of all collected events
	 */
	public static OpModelSession[] getSessions() {
		OpModelSession[] events = null;

		ArrayList<OpModelSession> sessionList = new ArrayList<>();
		try {
			IRunnableWithProgress opxml = OprofileCorePlugin.getDefault().getOpxmlProvider().sessions(sessionList);
			opxml.run(null);
			events = new OpModelSession[sessionList.size()];
			sessionList.toArray(events);
		} catch (InvocationTargetException | InterruptedException e) {
		}
		return events;
	}

	/**
	 * Return a list of all the Samples in the given session.
	 * 
	 * @param session the session for which to get samples
	 * @param shell   the composite shell to use for the progress dialog
	 */
	public static OpModelImage getModelData(String eventName, String sessionName) {
		OpModelImage image = new OpModelImage();

		final IRunnableWithProgress opxml;
		try {
			opxml = OprofileCorePlugin.getDefault().getOpxmlProvider().modelData(eventName, sessionName, image);
			opxml.run(null);
		} catch (InvocationTargetException | InterruptedException e) {
		}

		return image;
	}

	/**
	 * Check if oprofile kernel module is loaded and update Oprofile's information.
	 * 
	 * @since 1.1
	 */
	public static void updateInfo() {
		info = OpInfo.getInfo();
	}

	// Oprofile class has a static initializer and the code inside it needs to know
	// which project
	// is being profiled in order to get the path for the Linux Tools' binaries set
	// for that project.
	// For this reason the project property has to be set outside the Oprofile class
	/**
	 * OProfileProject class to set/get which project is being profiled
	 * 
	 * @since 1.1
	 */
	public static class OprofileProject {
		private static IProject project;
		public final static String OPERF_BINARY = "operf"; //$NON-NLS-1$
		public final static String OCOUNT_BINARY = "ocount"; //$NON-NLS-1$
		private static String binary = OPERF_BINARY;
		public final static String OPERF_DATA = "oprofile_data"; //$NON-NLS-1$

		/**
		 * Set the project to be profiled
		 * 
		 * @param project
		 */
		public static void setProject(IProject project) {
			OprofileProject.project = project;

		}

		/**
		 * Get the project to be profiled
		 * 
		 * @return project
		 */
		public static IProject getProject() {
			return project;
		}

		/**
		 * Set the profiling binary to be used (operf or opcontrol)
		 * 
		 * @param binary
		 * @since 2.1
		 */
		public static void setProfilingBinary(String binary) {
			OprofileProject.binary = binary;

		}

		/**
		 * Get the profiling binary (operf or opcontrol)
		 * 
		 * @return binary
		 * @since 2.1
		 */
		public static String getProfilingBinary() {
			return binary;
		}

	}

}

Back to the top