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. */
9 #include "xbt/sysdep.h"
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_process, simix,
12 "Logging specific to SIMIX (process)");
13 /** \defgroup m_process_management Management Functions of Agents
14 * \brief This section describes the agent structure of MSG
15 * (#m_process_t) and the functions for managing it.
16 * \htmlonly <!-- DOXYGEN_NAVBAR_LABEL="Agents" --> \endhtmlonly
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 smx_process_t SIMIX_process_create(const char *name,
34 smx_process_code_t code, void *data,
37 return SIMIX_process_create_with_arguments(name, code, data, host, -1, NULL);
40 static void SIMIX_process_cleanup(void *arg)
42 xbt_swag_remove(arg, simix_global->process_list);
43 xbt_swag_remove(arg, simix_global->process_to_run);
44 xbt_swag_remove(arg, ((smx_process_t) arg)->simdata->host->simdata->process_list);
45 free(((smx_process_t) arg)->name);
46 ((smx_process_t) arg)->name = NULL;
47 free(((smx_process_t) arg)->simdata);
48 ((smx_process_t) arg)->simdata = NULL;
52 /** \ingroup m_process_management
53 * \brief Creates and runs a new #m_process_t.
55 * A constructor for #m_process_t taking four arguments and returning the
56 * corresponding object. The structure (and the corresponding thread) is
57 * created, and put in the list of ready process.
58 * \param name a name for the object. It is for user-level information
60 * \param code is a function describing the behavior of the agent. It
61 should then only use functions described in \ref
62 m_process_management (to create a new #m_process_t for example),
63 in \ref m_host_management (only the read-only functions i.e. whose
64 name contains the word get), in \ref m_task_management (to create
65 or destroy some #m_task_t for example) and in \ref
66 msg_gos_functions (to handle file transfers and task processing).
67 * \param data a pointer to any data one may want to attach to the new
68 object. It is for user-level information and can be NULL. It can
69 be retrieved with the function \ref MSG_process_get_data.
70 * \param host the location where the new agent is executed.
71 * \param argc first argument passed to \a code
72 * \param argv second argument passed to \a code
74 * \return The new corresponding object.
76 smx_process_t SIMIX_process_create_with_arguments(const char *name,
77 smx_process_code_t code, void *data,
78 smx_host_t host, int argc, char **argv)
80 simdata_process_t simdata = xbt_new0(s_simdata_process_t,1);
81 smx_process_t process = xbt_new0(s_smx_process_t,1);
82 smx_process_t self = NULL;
84 xbt_assert0(((code != NULL) && (host != NULL)), "Invalid parameters");
90 simdata->context = xbt_context_new(code, NULL, NULL,
91 SIMIX_process_cleanup, process,
92 simdata->argc, simdata->argv);
94 if((self=simix_global->current_process)) {
95 //simdata->PPID = MSG_process_get_PID(self);
97 // simdata->PPID = -1;
99 simdata->last_errno=SIMIX_OK;
102 /* Process structure */
103 process->name = xbt_strdup(name);
104 process->simdata = simdata;
105 process->data = data;
107 xbt_swag_insert_at_head(process, host->simdata->process_list);
109 /* *************** FIX du current_process !!! *************** */
110 self = simix_global->current_process;
111 xbt_context_start(process->simdata->context);
112 simix_global->current_process = self;
114 xbt_swag_insert_at_head(process,simix_global->process_list);
115 DEBUG2("Inserting %s(%s) in the to_run list",process->name,
117 xbt_swag_insert_at_head(process,simix_global->process_to_run);
122 /** \ingroup m_process_management
123 * \param process poor victim
125 * This function simply kills a \a process... scarry isn't it ? :)
127 void SIMIX_process_kill(smx_process_t process)
130 simdata_process_t p_simdata = process->simdata;
131 //simdata_host_t h_simdata= p_simdata->host->simdata;
133 //smx_process_t proc = NULL;
135 DEBUG2("Killing %s on %s",process->name, p_simdata->host->name);
139 if(p_simdata->waiting_task) {
140 xbt_dynar_foreach(p_simdata->waiting_task->simdata->sleeping,_cursor,proc) {
142 xbt_dynar_remove_at(p_simdata->waiting_task->simdata->sleeping,_cursor,&proc);
144 if(p_simdata->waiting_task->simdata->compute)
145 surf_workstation_resource->common_public->
146 action_free(p_simdata->waiting_task->simdata->compute);
147 else if (p_simdata->waiting_task->simdata->comm) {
148 surf_workstation_resource->common_public->
149 action_change_state(p_simdata->waiting_task->simdata->comm,SURF_ACTION_FAILED);
150 surf_workstation_resource->common_public->
151 action_free(p_simdata->waiting_task->simdata->comm);
153 xbt_die("UNKNOWN STATUS. Please report this bug.");
157 if ((i==msg_global->max_channel) && (process!=MSG_process_self()) &&
158 (!p_simdata->waiting_task)) {
159 xbt_die("UNKNOWN STATUS. Please report this bug.");
162 xbt_swag_remove(process,simix_global->process_to_run);
163 xbt_swag_remove(process,simix_global->process_list);
164 xbt_context_free(process->simdata->context);
166 if(process==SIMIX_process_self()) {
167 /* I just killed myself */
172 /** \ingroup m_process_management
173 * \brief Migrates an agent to another location.
175 * This functions checks whether \a process and \a host are valid pointers
176 and change the value of the #m_host_t on which \a process is running.
178 SIMIX_error_t SIMIX_process_change_host(smx_process_t process, smx_host_t host)
180 simdata_process_t simdata = NULL;
184 xbt_assert0(((process) && (process->simdata)
185 && (host)), "Invalid parameters");
186 simdata = process->simdata;
188 xbt_swag_remove(process,simdata->host->simdata->process_list);
189 simdata->host = host;
190 xbt_swag_insert_at_head(process,host->simdata->process_list);
195 /** \ingroup m_process_management
196 * \brief Return the user data of a #m_process_t.
198 * This functions checks whether \a process is a valid pointer or not
199 and return the user data associated to \a process if it is possible.
201 void *SIMIX_process_get_data(smx_process_t process)
203 xbt_assert0((process != NULL), "Invalid parameters");
205 return (process->data);
208 /** \ingroup m_process_management
209 * \brief Set the user data of a #m_process_t.
211 * This functions checks whether \a process is a valid pointer or not
212 and set the user data associated to \a process if it is possible.
214 SIMIX_error_t SIMIX_process_set_data(smx_process_t process,void *data)
216 xbt_assert0((process != NULL), "Invalid parameters");
217 xbt_assert0((process->data == NULL), "Data already set");
219 process->data = data;
224 /** \ingroup m_process_management
225 * \brief Return the location on which an agent is running.
227 * This functions checks whether \a process is a valid pointer or not
228 and return the m_host_t corresponding to the location on which \a
231 smx_host_t SIMIX_process_get_host(smx_process_t process)
233 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
235 return (((simdata_process_t) process->simdata)->host);
238 /** \ingroup m_process_management
240 * \brief Return a #m_process_t given its PID.
242 * This functions search in the list of all the created m_process_t for a m_process_t
243 whose PID is equal to \a PID. If no host is found, \c NULL is returned.
244 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;
259 /** \ingroup m_process_management
260 * \brief Returns the process ID of \a process.
262 * This functions checks whether \a process is a valid pointer or not
266 int MSG_process_get_PID(m_process_t process)
268 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
270 return (((simdata_process_t) process->simdata)->PID);
273 /** \ingroup m_process_management
274 * \brief Returns the process ID of the parent of \a process.
276 * This functions checks whether \a process is a valid pointer or not
277 and return its PID. Returns -1 if the agent has not been created by
281 int MSG_process_get_PPID(m_process_t process)
283 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
285 return (((simdata_process_t) process->simdata)->PPID);
288 /** \ingroup m_process_management
289 * \brief Return the name of an agent.
291 * This functions checks whether \a process is a valid pointer or not
294 const char *SIMIX_process_get_name(smx_process_t process)
296 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
298 return (process->name);
301 /** \ingroup m_process_management
302 * \brief Return the PID of the current agent.
304 * This functions returns the PID of the currently running #m_process_t.
307 int MSG_process_self_PID(void)
309 return (MSG_process_get_PID(MSG_process_self()));
312 /** \ingroup m_process_management
313 * \brief Return the PPID of the current agent.
315 * This functions returns the PID of the parent of the currently
316 * running #m_process_t.
319 int MSG_process_self_PPID(void)
321 return (MSG_process_get_PPID(MSG_process_self()));
324 /** \ingroup m_process_management
325 * \brief Return the current agent.
327 * This functions returns the currently running #m_process_t.
329 smx_process_t SIMIX_process_self(void)
331 return simix_global ? simix_global->current_process : NULL;
334 /** \ingroup m_process_management
335 * \brief Suspend the process.
337 * This functions suspend the process by suspending the task on which
338 * it was waiting for the completion.
340 SIMIX_error_t SIMIX_process_suspend(smx_process_t process)
343 simdata_process_t simdata = NULL;
344 simdata_task_t simdata_task = NULL;
346 XBT_IN2("(%p(%s))", process, process->name);
348 xbt_assert0(((process) && (process->simdata)), "Invalid parameters");
350 PAJE_PROCESS_PUSH_STATE(process,"S",NULL);
352 if(process!=SIMIX_process_self()) {
353 simdata = process->simdata;
355 xbt_assert0(simdata->waiting_task,"Process not waiting for anything else. Weird !");
357 simdata_task = simdata->waiting_task->simdata;
359 simdata->suspended = 1;
360 if(simdata->blocked) {
365 xbt_assert0(((simdata_task->compute)||(simdata_task->comm))&&
366 !((simdata_task->compute)&&(simdata_task->comm)),
367 "Got a problem in deciding which action to choose !");
368 simdata->suspended = 1;
369 if(simdata_task->compute)
370 surf_workstation_resource->common_public->suspend(simdata_task->compute);
372 surf_workstation_resource->common_public->suspend(simdata_task->comm);
374 m_task_t dummy = MSG_TASK_UNINITIALIZED;
375 dummy = MSG_task_create("suspended", 0.0, 0, NULL);
377 simdata = process->simdata;
378 simdata->suspended = 1;
379 __MSG_task_execute(process,dummy);
380 surf_workstation_resource->common_public->suspend(dummy->simdata->compute);
381 __MSG_wait_for_computation(process,dummy);
382 simdata->suspended = 0;
384 MSG_task_destroy(dummy);
391 /** \ingroup m_process_management
392 * \brief Resume a suspended process.
394 * This functions resume a suspended process by resuming the task on
395 * which it was waiting for the completion.
397 SIMIX_error_t SIMIX_process_resume(smx_process_t process)
400 simdata_process_t simdata = NULL;
401 simdata_task_t simdata_task = NULL;
403 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
406 XBT_IN2("(%p(%s))", process, process->name);
408 if(process == SIMIX_process_self()) {
410 SIMIX_RETURN(SIMIX_OK);
413 simdata = process->simdata;
415 if(simdata->blocked) {
416 PAJE_PROCESS_POP_STATE(process);
418 simdata->suspended = 0; *//* He'll wake up by itself */
420 SIMIX_RETURN(SIMIX_OK);
423 if(!(simdata->waiting_task)) {
424 xbt_assert0(0,"Process not waiting for anything else. Weird !");
426 return SIMIX_WARNING;
428 simdata_task = simdata->waiting_task->simdata;
431 if(simdata_task->compute) {
432 surf_workstation_resource->common_public->resume(simdata_task->compute);
433 PAJE_PROCESS_POP_STATE(process);
436 PAJE_PROCESS_POP_STATE(process);
437 surf_workstation_resource->common_public->resume(simdata_task->comm);
442 SIMIX_RETURN(SIMIX_OK);
445 /** \ingroup m_process_management
446 * \brief Returns true if the process is suspended .
448 * This checks whether a process is suspended or not by inspecting the
449 * task on which it was waiting for the completion.
451 int SIMIX_process_is_suspended(smx_process_t process)
453 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
455 return (process->simdata->suspended);
458 int __SIMIX_process_block(double max_duration, const char *info)
461 smx_process_t process = SIMIX_process_self();
462 m_task_t dummy = SIMIX_TASK_UNINITIALIZED;
463 char blocked_name[512];
464 snprintf(blocked_name,512,"blocked [%s] (%s:%s)",
465 info, process->name, process->simdata->host->name);
467 XBT_IN1(": max_duration=%g",max_duration);
469 dummy = MSG_task_create(blocked_name, 0.0, 0, NULL);
471 PAJE_PROCESS_PUSH_STATE(process,"B",NULL);
473 process->simdata->blocked=1;
474 __MSG_task_execute(process,dummy);
475 surf_workstation_resource->common_public->suspend(dummy->simdata->compute);
477 surf_workstation_resource->common_public->set_max_duration(dummy->simdata->compute,
479 __MSG_wait_for_computation(process,dummy);
480 MSG_task_destroy(dummy);
481 process->simdata->blocked=0;
483 if(process->simdata->suspended) {
484 DEBUG0("I've been suspended in the meantime");
485 SIMIX_process_suspend(process);
486 DEBUG0("I've been resumed, let's keep going");
489 PAJE_PROCESS_POP_STATE(process);
496 SIMIX_error_t __SIMIX_process_unblock(smx_process_t process)
499 simdata_process_t simdata = NULL;
500 simdata_task_t simdata_task = NULL;
502 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
505 XBT_IN2(": %s unblocking %s", SIMIX_process_self()->name,process->name);
507 simdata = process->simdata;
508 if(!(simdata->waiting_task)) {
509 xbt_assert0(0,"Process not waiting for anything else. Weird !");
511 return SIMIX_WARNING;
513 simdata_task = simdata->waiting_task->simdata;
515 xbt_assert0(simdata->blocked,"Process not blocked");
517 surf_workstation_resource->common_public->resume(simdata_task->compute);
521 SIMIX_RETURN(SIMIX_OK);
524 int __SIMIX_process_isBlocked(smx_process_t process)
526 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
528 return (process->simdata->blocked);