1 /* Copyright (c) 2006-2019. The SimGrid Team. All rights reserved. */
3 /* This program is free software; you can redistribute it and/or modify it
4 * under the terms of the license (GNU LGPL) which comes with this package. */
6 package org.simgrid.msg;
8 import java.lang.management.ManagementFactory;
9 import java.lang.management.ThreadInfo;
10 import java.lang.management.ThreadMXBean;
11 import java.util.ArrayList;
12 import java.util.Arrays;
13 import java.util.List;
16 * A process may be defined as a code, with some private data, executing
17 * in a location (host). All the process used by your simulation must be
18 * declared in the deployment file (XML format).
19 * To create your own process you must inherit your own process from this
20 * class and override the method "main()". For example if you want to use
21 * a process named Slave proceed as it :
23 * (1) import the class Process of the package simgrid.msg
24 * import simgrid.msg.Process;
26 * public class Slave extends simgrid.msg.Process {
28 * (2) Override the method function
31 * public void main(String[] args) {
32 * System.out.println("Hello MSG");
36 * The name of your process must be declared in the deployment file of your simulation.
37 * For the example, for the previous process Slave this file must contains a line :
38 * <process host="Maxims" function="Slave"/>, where Maxims is the host of the process
39 * Slave. All the process of your simulation are automatically launched and managed by Msg.
40 * A process use tasks to simulate communications or computations with another process.
41 * For more information see Task. For more information on host concept
46 public abstract class Process implements Runnable {
48 * This attribute represents a bind between a java process object and
49 * a native process. Even if this attribute is public you must never
50 * access to it. It is set automatically during the build of the object.
52 private long bind = 0;
53 /** Indicates if the process is started */
55 /** Time at which the process should be created */
56 protected double startTime = 0;
57 /** Time at which the process should be killed */
58 private double killTime = -1; // Used from the C world
60 private String name = null;
63 private int ppid = -1;
64 private Host host = null;
66 /** The arguments of the method function of the process. */
67 private ArrayList<String> args = new ArrayList<>();
70 * Constructs a new process from the name of a host and his name. The method
71 * function of the process doesn't have argument.
73 * @param hostname Where to create the process.
74 * @param name The name of the process.
76 * @exception HostNotFoundException if no host with this name exists.
80 public Process(String hostname, String name) throws HostNotFoundException {
81 this(Host.getByName(hostname), name, null);
84 * Constructs a new process from the name of a host and his name. The arguments
85 * of the method function of the process are specified by the parameter args.
87 * @param hostname Where to create the process.
88 * @param name The name of the process.
89 * @param args The arguments of the main function of the process.
91 * @exception HostNotFoundException if no host with this name exists.
94 public Process(String hostname, String name, String[] args) throws HostNotFoundException {
95 this(Host.getByName(hostname), name, args);
98 * Constructs a new process from a host and his name. The method function of the
99 * process doesn't have argument.
101 * @param host Where to create the process.
102 * @param name The name of the process.
105 public Process(Host host, String name) {
106 this(host, name, null);
109 * Constructs a new process from a host and his name, the arguments of here method function are
110 * specified by the parameter args.
112 * @param host Where to create the process.
113 * @param name The name of the process.
114 * @param argsParam The arguments of main method of the process.
116 public Process(Host host, String name, String[]argsParam)
119 throw new IllegalArgumentException("Cannot create a process on the null host");
121 throw new IllegalArgumentException("Process name cannot be null");
126 this.args = new ArrayList<>();
127 if (null != argsParam)
128 this.args.addAll(Arrays.asList(argsParam));
131 * Constructs a new process from a host and his name, the arguments of here method function are
132 * specified by the parameter args.
134 * @param host Where to create the process.
135 * @param name The name of the process.
136 * @param args The arguments of main method of the process.
137 * @param startTime Start time of the process
138 * @param killTime Kill time of the process
141 public Process(Host host, String name, String[]args, double startTime, double killTime) {
142 this(host, name, args);
143 this.startTime = startTime;
144 this.killTime = killTime;
147 * The native method to create an MSG process.
148 * @param host where to create the process.
150 protected native void create(Host host);
153 * This method kills all running process of the simulation.
155 public static native void killAll();
157 /** Simply kills the receiving process.
159 * SimGrid sometimes have issues when you kill processes that are currently communicating and such. We are working on it to fix the issues.
161 public native void kill();
162 public static void kill(Process p) {
166 /** Suspends the process. See {@link #resume()} to resume it afterward */
167 public native void suspend();
168 /** Resume a process that was suspended by {@link #suspend()}. */
169 public native void resume();
170 /** Tests if a process is suspended.
175 public native boolean isSuspended();
177 /** Yield the current process. All other processes that are ready at the same timestamp will be executed first */
178 public static native void yield();
181 * Specify whether the process should restart when its host restarts after a failure
183 * A process naturally stops when its host stops. It starts again only if autoRestart is set to true.
184 * Otherwise, it just disappears when the host stops.
186 public native void setAutoRestart(boolean autoRestart);
187 /** Restarts the process from the beginning */
188 public native void restart();
190 * Returns the name of the process
192 public String getName() {
196 * Returns the host of the process.
197 * @return The host instance of the process.
199 public Host getHost() {
203 * This static method gets a process from a PID.
205 * @param pid The process identifier of the process to get.
207 * @return The process with the specified PID.
209 public static native Process fromPID(int pid);
211 * This method returns the PID of the process.
213 * @return The PID of the process.
216 public int getPID() {
217 if (pid == -1) // Don't traverse the JNI barrier if you already have the answer
218 pid = nativeGetPID();
221 // This should not be used: the PID is supposed to be initialized from the C directly when the actor is created,
222 // but this sometimes fail, so let's play nasty but safe here.
223 private native int nativeGetPID();
225 * This method returns the PID of the parent of a process.
227 * @return The PID of the parent of the process.
230 public int getPPID() {
234 * Returns the value of a given process property.
236 public native String getProperty(String name);
239 * Set the kill time of the process
240 * @param killTime the time when the process is killed
242 public native void setKillTime(double killTime);
245 * This static method returns the currently running process.
247 * @return The current process.
250 public static native Process getCurrentProcess();
252 * Migrates a process to another host.
254 * @param host The host where to migrate the process.
257 public native void migrate(Host host);
259 * Makes the current process sleep until millis milliseconds have elapsed.
260 * You should note that unlike "waitFor" which takes seconds, this method takes milliseconds.
261 * FIXME: Not optimal, maybe we should have two native functions.
262 * @param millis the length of time to sleep in milliseconds.
264 public static void sleep(long millis) throws HostFailureException {
268 * Makes the current process sleep until millis milliseconds and nanos nanoseconds
270 * Unlike {@link #waitFor(double)} which takes seconds, this method takes
271 * milliseconds and nanoseconds.
272 * Overloads Thread.sleep.
273 * @param millis the length of time to sleep in milliseconds.
274 * @param nanos additional nanoseconds to sleep.
276 public static native void sleep(long millis, int nanos) throws HostFailureException;
278 * Makes the current process sleep until time seconds have elapsed.
279 * @param seconds The time the current process must sleep.
281 public native void waitFor(double seconds) throws HostFailureException;
283 * This method actually creates and run the process.
284 * It is a noop if the process is already launched.
286 public final void start() {
291 /** This method runs the process. It calls the method function that you must overwrite. */
296 String[] argsArray = new String[this.args.size()];
297 this.args.toArray(argsArray);
299 this.main(argsArray);
301 catch(MsgException e) {
303 Msg.info("Unexpected behavior. Stopping now");
306 catch(ProcessKilledError pk) {
307 /* The process was killed before its end. With a kill() or something. */
308 //Msg.info("Forwarding a PKE");
314 * The main function of the process (to implement by the user).
317 * @throws MsgException
319 public abstract void main(String[]args) throws MsgException;
321 /** Stops the execution of the current actor */
326 * Class initializer, to initialize various JNI stuff
328 private static native void nativeInit();
330 org.simgrid.NativeLib.nativeInit();
334 * This static method returns the current amount of processes running
336 * @return The count of the running processes
338 public static native int getCount();
340 public static void debugAllThreads() {
341 final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
342 long[] deads = threadMXBean.findDeadlockedThreads();
344 for (long dead : deads)
345 System.err.println("Thread deadlocked: "+dead);
347 // Search remaining threads that are not main nor daemon
348 List<Long> ids = new ArrayList<>();
349 for (Thread t : Thread.getAllStackTraces().keySet()) {
350 if (! t.isDaemon() && !t.getName().equals("main"))
353 if (ids.size() > 0) {
354 long[] id_array = new long[ids.size()];
355 for (int i=0; i<ids.size(); i++)
356 id_array[i] = ids.get(i);
358 final ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(id_array, true, true);
359 final StringBuilder dump = new StringBuilder();
360 for (ThreadInfo threadInfo : threadInfos) {
362 dump.append(threadInfo.getThreadName());
364 final Thread.State state = threadInfo.getThreadState();
365 dump.append("\n java.lang.Thread.State: ");
367 final StackTraceElement[] stackTraceElements = threadInfo.getStackTrace();
368 for (final StackTraceElement stackTraceElement : stackTraceElements) {
369 dump.append("\n at ");
370 dump.append(stackTraceElement);
372 dump.append("\n In native? "+threadInfo.isInNative()+"\n");
373 dump.append(" Suspended? "+threadInfo.isSuspended()+"\n");
374 dump.append(" Waiting for: "+threadInfo.getLockInfo()+"\n");
377 System.err.println(dump);