/******************************************************************************* * Copyright (c) 2004, 2008, 2009 Red Hat, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * 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; } } }