3 /* Copyright (c) 2002,2003,2004 Arnaud Legrand. All rights reserved. */
5 /* This program is free software; you can redistribute it and/or modify it
6 * under the terms of the license (GNU LGPL) which comes with this package. */
10 #include "xbt/error.h"
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(m_process, msg,
12 "Logging specific to MSG (process)");
14 /** \defgroup m_process_management Management Functions of Agents
15 * \brief This section describes the agent structure of MSG
16 * (#m_process_t) and the functions for managing it.
18 * We need to simulate many independent scheduling decisions, so
19 * the concept of <em>process</em> is at the heart of the
20 * simulator. A process may be defined as a <em>code</em>, with
21 * some <em>private data</em>, executing in a <em>location</em>.
25 /******************************** Process ************************************/
26 /** \ingroup m_process_management
27 * \brief Creates and runs a new #m_process_t.
29 * Does exactly the same as #MSG_process_create_with_arguments but without
30 providing standard arguments (\a argc, \a argv, \a start_time, \a kill_time).
31 * \sa MSG_process_create_with_arguments
33 m_process_t MSG_process_create(const char *name,
34 m_process_code_t code, void *data,
37 return MSG_process_create_with_arguments(name, code, data, host, -1, NULL);
40 static void MSG_process_cleanup(void *arg)
43 while(((m_process_t)arg)->simdata->paje_state) {
44 PAJE_PROCESS_POP_STATE((m_process_t)arg);
47 PAJE_PROCESS_FREE(arg);
49 xbt_fifo_remove(msg_global->process_list, arg);
50 xbt_fifo_remove(msg_global->process_to_run, arg);
51 xbt_fifo_remove(((m_process_t) arg)->simdata->host->simdata->process_list, arg);
52 free(((m_process_t) arg)->name);
53 free(((m_process_t) arg)->simdata);
57 /** \ingroup m_process_management
58 * \brief Creates and runs a new #m_process_t.
60 * A constructor for #m_process_t taking four arguments and returning the
61 * corresponding object. The structure (and the corresponding thread) is
62 * created, and put in the list of ready process.
63 * \param name a name for the object. It is for user-level information
65 * \param code is a function describing the behavior of the agent. It
66 should then only use functions described in \ref
67 m_process_management (to create a new #m_process_t for example),
68 in \ref m_host_management (only the read-only functions i.e. whose
69 name contains the word get), in \ref m_task_management (to create
70 or destroy some #m_task_t for example) and in \ref
71 msg_gos_functions (to handle file transfers and task processing).
72 * \param data a pointer to any data may want to attach to the new
73 object. It is for user-level information and can be NULL. It can
74 be retrieved with the function \ref MSG_process_get_data.
75 * \param host the location where the new agent is executed.
76 * \param argc first argument passed to \a code
77 * \param argv second argument passed to \a code
79 * \return The new corresponding object.
81 m_process_t MSG_process_create_with_arguments(const char *name,
82 m_process_code_t code, void *data,
83 m_host_t host, int argc, char **argv)
85 simdata_process_t simdata = xbt_new0(s_simdata_process_t,1);
86 m_process_t process = xbt_new0(s_m_process_t,1);
87 m_process_t self = NULL;
89 xbt_assert0(((code != NULL) && (host != NULL)), "Invalid parameters");
92 simdata->PID = msg_global->PID++;
94 simdata->waiting_task = NULL;
97 simdata->context = xbt_context_new(code, NULL, NULL,
98 MSG_process_cleanup, process,
99 simdata->argc, simdata->argv);
101 if((self=msg_global->current_process)) {
102 simdata->PPID = MSG_process_get_PID(self);
106 simdata->last_errno=MSG_OK;
109 /* Process structure */
110 process->name = xbt_strdup(name);
111 process->simdata = simdata;
112 process->data = data;
114 xbt_fifo_push(host->simdata->process_list, process);
116 /* /////////////// FIX du current_process !!! ////////////// */
117 self = msg_global->current_process;
118 xbt_context_start(process->simdata->context);
119 msg_global->current_process = self;
121 xbt_fifo_push(msg_global->process_list, process);
122 xbt_fifo_push(msg_global->process_to_run, process);
124 PAJE_PROCESS_NEW(process);
129 /** \ingroup m_process_management
130 * \param process poor victim
132 * This function simply kills a \a process... scarry isn't it ? :)
134 void MSG_process_kill(m_process_t process)
137 simdata_process_t p_simdata = process->simdata;
138 simdata_host_t h_simdata= p_simdata->host->simdata;
140 /* fprintf(stderr,"Killing %s(%d) on %s.\n",process->name, */
141 /* p_simdata->PID,p_simdata->host->name); */
143 for (i=0; i<msg_global->max_channel; i++) {
144 if (h_simdata->sleeping[i] == process) {
145 h_simdata->sleeping[i] = NULL;
149 if (i==msg_global->max_channel) {
150 if(p_simdata->waiting_task) {
151 if(p_simdata->waiting_task->simdata->compute)
152 surf_workstation_resource->common_public->
153 action_free(p_simdata->waiting_task->simdata->compute);
154 else if (p_simdata->waiting_task->simdata->comm)
155 surf_workstation_resource->common_public->
156 action_change_state(p_simdata->waiting_task->simdata->comm,SURF_ACTION_FAILED);
158 CRITICAL0("UNKNOWN STATUS. Please report this bug.");
159 } else { /* Must be trying to put a task somewhere */
160 if(process==MSG_process_self()) {
163 CRITICAL0("UNKNOWN STATUS. Please report this bug.");
168 xbt_fifo_remove(msg_global->process_to_run,process);
169 xbt_fifo_remove(msg_global->process_list,process);
170 xbt_context_free(process->simdata->context);
173 /** \ingroup m_process_management
174 * \brief Migrates an agent to another location.
176 * This functions checks whether \a process and \a host are valid pointers
177 and change the value of the #m_host_t on which \a process is running.
179 MSG_error_t MSG_process_change_host(m_process_t process, m_host_t host)
181 simdata_process_t simdata = NULL;
185 xbt_assert0(((process) && (process->simdata)
186 && (host)), "Invalid parameters");
187 simdata = process->simdata;
189 xbt_fifo_remove(simdata->host->simdata->process_list,process);
190 simdata->host = host;
191 xbt_fifo_push(host->simdata->process_list,process);
196 /** \ingroup m_process_management
197 * \brief Return the user data of a #m_process_t.
199 * This functions checks whether \a process is a valid pointer or not
200 and return the user data associated to \a process if it is possible.
202 void *MSG_process_get_data(m_process_t process)
204 xbt_assert0((process != NULL), "Invalid parameters");
206 return (process->data);
209 /** \ingroup m_process_management
210 * \brief Set the user data of a #m_process_t.
212 * This functions checks whether \a process is a valid pointer or not
213 and set the user data associated to \a process if it is possible.
215 MSG_error_t MSG_process_set_data(m_process_t process,void *data)
217 xbt_assert0((process != NULL), "Invalid parameters");
218 xbt_assert0((process->data == NULL), "Data already set");
220 process->data = data;
225 /** \ingroup m_process_management
226 * \brief Return the location on which an agent is running.
228 * This functions checks whether \a process is a valid pointer or not
229 and return the m_host_t corresponding to the location on which \a
232 m_host_t MSG_process_get_host(m_process_t process)
234 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
236 return (((simdata_process_t) process->simdata)->host);
239 /** \ingroup m_process_management
241 * \brief Return a #m_process_t given its PID.
243 * This functions search in the list of all the created m_process_t for a m_process_t
244 whose PID is equal to \a PID. If no host is found, \c NULL is returned.
245 Note that the PID are uniq in the whole simulation, not only on a given host.
247 m_process_t MSG_process_from_PID(int PID)
249 xbt_fifo_item_t i = NULL;
250 m_process_t process = NULL;
252 xbt_fifo_foreach(msg_global->process_list,i,process,m_process_t) {
253 if(MSG_process_get_PID(process) == PID) return process;
258 /** \ingroup m_process_management
259 * \brief Returns the process ID of \a process.
261 * This functions checks whether \a process is a valid pointer or not
264 int MSG_process_get_PID(m_process_t process)
266 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
268 return (((simdata_process_t) process->simdata)->PID);
271 /** \ingroup m_process_management
272 * \brief Returns the process ID of the parent of \a process.
274 * This functions checks whether \a process is a valid pointer or not
275 and return its PID. Returns -1 if the agent has not been created by
278 int MSG_process_get_PPID(m_process_t process)
280 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
282 return (((simdata_process_t) process->simdata)->PPID);
285 /** \ingroup m_process_management
286 * \brief Return the name of an agent.
288 * This functions checks whether \a process is a valid pointer or not
291 const char *MSG_process_get_name(m_process_t process)
293 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
295 return (process->name);
298 /** \ingroup m_process_management
299 * \brief Return the PID of the current agent.
301 * This functions returns the PID of the currently running #m_process_t.
303 int MSG_process_self_PID(void)
305 return (MSG_process_get_PID(MSG_process_self()));
308 /** \ingroup m_process_management
309 * \brief Return the PPID of the current agent.
311 * This functions returns the PID of the parent of the currently
312 * running #m_process_t.
314 int MSG_process_self_PPID(void)
316 return (MSG_process_get_PPID(MSG_process_self()));
319 /** \ingroup m_process_management
320 * \brief Return the current agent.
322 * This functions returns the currently running #m_process_t.
324 m_process_t MSG_process_self(void)
326 return msg_global ? msg_global->current_process : NULL;
329 /** \ingroup m_process_management
330 * \brief Suspend the process.
332 * This functions suspend the process by suspending the task on which
333 * it was waiting for the completion.
335 MSG_error_t MSG_process_suspend(m_process_t process)
337 simdata_process_t simdata = NULL;
338 simdata_task_t simdata_task = NULL;
341 xbt_assert0(((process) && (process->simdata)), "Invalid parameters");
343 PAJE_PROCESS_PUSH_STATE(process,"S");
345 if(process!=MSG_process_self()) {
346 simdata = process->simdata;
348 xbt_assert0(simdata->waiting_task,"Process not waiting for anything else. Weird !");
350 simdata_task = simdata->waiting_task->simdata;
352 simdata->suspended = 1;
353 if(simdata->blocked) return MSG_OK;
355 xbt_assert0(((simdata_task->compute)||(simdata_task->comm))&&
356 !((simdata_task->compute)&&(simdata_task->comm)),
357 "Got a problem in deciding which action to choose !");
358 simdata->suspended = 1;
359 if(simdata_task->compute)
360 surf_workstation_resource->common_public->suspend(simdata_task->compute);
362 surf_workstation_resource->common_public->suspend(simdata_task->comm);
364 m_task_t dummy = MSG_TASK_UNINITIALIZED;
365 dummy = MSG_task_create("suspended", 0.0, 0, NULL);
367 simdata = process->simdata;
368 simdata->suspended = 1;
369 __MSG_task_execute(process,dummy);
370 surf_workstation_resource->common_public->suspend(dummy->simdata->compute);
371 __MSG_wait_for_computation(process,dummy);
372 simdata->suspended = 0;
374 MSG_task_destroy(dummy);
379 /** \ingroup m_process_management
380 * \brief Resume a suspended process.
382 * This functions resume a suspended process by resuming the task on
383 * which it was waiting for the completion.
385 MSG_error_t MSG_process_resume(m_process_t process)
387 simdata_process_t simdata = NULL;
388 simdata_task_t simdata_task = NULL;
391 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
394 simdata = process->simdata;
397 if(simdata->blocked) {
398 PAJE_PROCESS_POP_STATE(process);
400 simdata->suspended = 0; /* He'll wake up by itself */
404 if(!(simdata->waiting_task)) {
405 xbt_assert0(0,"Process not waiting for anything else. Weird !");
408 simdata_task = simdata->waiting_task->simdata;
411 if(simdata_task->compute) {
412 surf_workstation_resource->common_public->resume(simdata_task->compute);
413 PAJE_PROCESS_POP_STATE(process);
416 PAJE_PROCESS_POP_STATE(process);
417 surf_workstation_resource->common_public->resume(simdata_task->comm);
423 /** \ingroup m_process_management
424 * \brief Returns true if the process is suspended .
426 * This checks whether a process is suspended or not by inspecting the
427 * task on which it was waiting for the completion.
429 int MSG_process_isSuspended(m_process_t process)
431 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
433 return (process->simdata->suspended);
436 MSG_error_t __MSG_process_block(void)
438 m_process_t process = MSG_process_self();
440 m_task_t dummy = MSG_TASK_UNINITIALIZED;
441 dummy = MSG_task_create("blocked", 0.0, 0, NULL);
443 PAJE_PROCESS_PUSH_STATE(process,"B");
445 process->simdata->blocked=1;
446 __MSG_task_execute(process,dummy);
447 surf_workstation_resource->common_public->suspend(dummy->simdata->compute);
448 __MSG_wait_for_computation(process,dummy);
449 process->simdata->blocked=0;
451 if(process->simdata->suspended)
452 MSG_process_suspend(process);
454 MSG_task_destroy(dummy);
459 MSG_error_t __MSG_process_unblock(m_process_t process)
461 simdata_process_t simdata = NULL;
462 simdata_task_t simdata_task = NULL;
465 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
468 simdata = process->simdata;
469 if(!(simdata->waiting_task)) {
470 xbt_assert0(0,"Process not waiting for anything else. Weird !");
473 simdata_task = simdata->waiting_task->simdata;
475 xbt_assert0(simdata->blocked,"Process not blocked");
477 surf_workstation_resource->common_public->resume(simdata_task->compute);
479 PAJE_PROCESS_POP_STATE(process);
484 int __MSG_process_isBlocked(m_process_t process)
486 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
488 return (process->simdata->blocked);