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 simdata->last_errno=SIMIX_OK;
97 /* Process structure */
98 process->name = xbt_strdup(name);
99 process->simdata = simdata;
100 process->data = data;
102 xbt_swag_insert(process, host->simdata->process_list);
104 /* *************** FIX du current_process !!! *************** */
105 self = simix_global->current_process;
106 xbt_context_start(process->simdata->context);
107 simix_global->current_process = self;
109 // xbt_swag_insert(process,simix_global->process_list);
110 DEBUG2("Inserting %s(%s) in the to_run list",process->name,
112 xbt_swag_insert(process,simix_global->process_to_run);
117 /** \ingroup m_process_management
118 * \param process poor victim
120 * This function simply kills a \a process... scarry isn't it ? :)
122 void SIMIX_process_kill(smx_process_t process)
125 simdata_process_t p_simdata = process->simdata;
126 //simdata_host_t h_simdata= p_simdata->host->simdata;
128 //smx_process_t proc = NULL;
130 DEBUG2("Killing %s on %s",process->name, p_simdata->host->name);
134 if(p_simdata->waiting_task) {
135 xbt_dynar_foreach(p_simdata->waiting_task->simdata->sleeping,_cursor,proc) {
137 xbt_dynar_remove_at(p_simdata->waiting_task->simdata->sleeping,_cursor,&proc);
139 if(p_simdata->waiting_task->simdata->compute)
140 surf_workstation_resource->common_public->
141 action_free(p_simdata->waiting_task->simdata->compute);
142 else if (p_simdata->waiting_task->simdata->comm) {
143 surf_workstation_resource->common_public->
144 action_change_state(p_simdata->waiting_task->simdata->comm,SURF_ACTION_FAILED);
145 surf_workstation_resource->common_public->
146 action_free(p_simdata->waiting_task->simdata->comm);
148 xbt_die("UNKNOWN STATUS. Please report this bug.");
152 if ((i==msg_global->max_channel) && (process!=MSG_process_self()) &&
153 (!p_simdata->waiting_task)) {
154 xbt_die("UNKNOWN STATUS. Please report this bug.");
157 xbt_swag_remove(process,simix_global->process_to_run);
158 xbt_swag_remove(process,simix_global->process_list);
159 xbt_context_free(process->simdata->context);
161 if(process==SIMIX_process_self()) {
162 /* I just killed myself */
167 /** \ingroup m_process_management
168 * \brief Migrates an agent to another location.
170 * This functions checks whether \a process and \a host are valid pointers
171 and change the value of the #m_host_t on which \a process is running.
173 SIMIX_error_t SIMIX_process_change_host(smx_process_t process, smx_host_t host)
175 simdata_process_t simdata = NULL;
179 xbt_assert0(((process) && (process->simdata)
180 && (host)), "Invalid parameters");
181 simdata = process->simdata;
183 xbt_swag_remove(process,simdata->host->simdata->process_list);
184 simdata->host = host;
185 xbt_swag_insert(process,host->simdata->process_list);
190 /** \ingroup m_process_management
191 * \brief Return the user data of a #m_process_t.
193 * This functions checks whether \a process is a valid pointer or not
194 and return the user data associated to \a process if it is possible.
196 void *SIMIX_process_get_data(smx_process_t process)
198 xbt_assert0((process != NULL), "Invalid parameters");
200 return (process->data);
203 /** \ingroup m_process_management
204 * \brief Set the user data of a #m_process_t.
206 * This functions checks whether \a process is a valid pointer or not
207 and set the user data associated to \a process if it is possible.
209 SIMIX_error_t SIMIX_process_set_data(smx_process_t process,void *data)
211 xbt_assert0((process != NULL), "Invalid parameters");
212 xbt_assert0((process->data == NULL), "Data already set");
214 process->data = data;
219 /** \ingroup m_process_management
220 * \brief Return the location on which an agent is running.
222 * This functions checks whether \a process is a valid pointer or not
223 and return the m_host_t corresponding to the location on which \a
226 smx_host_t SIMIX_process_get_host(smx_process_t process)
228 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
230 return (((simdata_process_t) process->simdata)->host);
233 /** \ingroup m_process_management
234 * \brief Return the name of an agent.
236 * This functions checks whether \a process is a valid pointer or not
239 const char *SIMIX_process_get_name(smx_process_t process)
241 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
243 return (process->name);
246 /** \ingroup m_process_management
247 * \brief Return the current agent.
249 * This functions returns the currently running #m_process_t.
251 smx_process_t SIMIX_process_self(void)
253 return simix_global ? simix_global->current_process : NULL;
256 /** \ingroup m_process_management
257 * \brief Suspend the process.
259 * This functions suspend the process by suspending the task on which
260 * it was waiting for the completion.
262 SIMIX_error_t SIMIX_process_suspend(smx_process_t process)
264 simdata_process_t simdata = NULL;
266 char name[] = "dummy";
268 xbt_assert0(((process) && (process->simdata)), "Invalid parameters");
270 if(process!=SIMIX_process_self()) {
271 simdata = process->simdata;
273 if ( (simdata->mutex == NULL) && (simdata->cond == NULL) ) {
274 /* Ops, I don't know what to do yet. */
277 else if (simdata->mutex) {
278 /* process blocked on a mutex, only set suspend=1 */
279 simdata->suspended = 1;
281 else if (simdata->cond){
282 /* process blocked cond, suspend all actions */
284 /* temporaries variables */
289 simdata->suspended = 1;
291 xbt_fifo_foreach(c->actions,i,act, smx_action_t) {
292 surf_workstation_resource->common_public->suspend(act->simdata->surf_action);
295 else xbt_assert0(0, "Unknown process status");
299 /* process executing, I can create an action and suspend it */
300 dummy = SIMIX_execute(SIMIX_process_get_host(process)->simdata->host, name, 0);
301 process->simdata->block_action = dummy;
303 process->simdata->suspended = 1;
304 surf_workstation_resource->common_public->suspend(dummy->simdata->surf_action);
305 __SIMIX_wait_for_action(process,dummy);
306 SIMIX_action_destroy(dummy);
307 process->simdata->suspended = 0;
313 /** \ingroup m_process_management
314 * \brief Resume a suspended process.
316 * This functions resume a suspended process by resuming the task on
317 * which it was waiting for the completion.
319 SIMIX_error_t SIMIX_process_resume(smx_process_t process)
321 simdata_process_t simdata = NULL;
323 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
326 if(process == SIMIX_process_self()) {
327 SIMIX_RETURN(SIMIX_OK);
330 simdata = process->simdata;
333 simdata->suspended = 0; /* He'll wake up by itself */
334 SIMIX_RETURN(SIMIX_OK);
336 else if (simdata->cond) {
337 /* temporaries variables */
342 simdata->suspended = 0;
344 xbt_fifo_foreach(c->actions,i,act, smx_action_t) {
345 surf_workstation_resource->common_public->resume(act->simdata->surf_action);
347 SIMIX_RETURN(SIMIX_OK);
349 else if (simdata->block_action){
350 simdata->suspended = 0;
351 surf_workstation_resource->common_public->resume(simdata->block_action->simdata->surf_action);
352 SIMIX_RETURN(SIMIX_OK);
354 else xbt_assert0(0, "Unknown process status");
358 /** \ingroup m_process_management
359 * \brief Returns true if the process is suspended .
361 * This checks whether a process is suspended or not by inspecting the
362 * task on which it was waiting for the completion.
364 int SIMIX_process_is_suspended(smx_process_t process)
366 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
368 return (process->simdata->suspended);
371 int __SIMIX_process_block(double max_duration)
374 smx_process_t process = SIMIX_process_self();
375 smx_action_t dummy = NULL;
376 char name[] = "dummy";
378 dummy = SIMIX_execute(SIMIX_process_get_host(process)->simdata->host, name, 0);
379 process->simdata->block_action = dummy;
381 process->simdata->blocked=1;
383 surf_workstation_resource->common_public->suspend(dummy->simdata->surf_action);
385 surf_workstation_resource->common_public->set_max_duration(dummy->simdata->surf_action,
387 __SIMIX_wait_for_action(process,dummy);
388 SIMIX_action_destroy(dummy);
389 process->simdata->blocked=0;
391 if(process->simdata->suspended) {
392 DEBUG0("I've been suspended in the meantime");
393 SIMIX_process_suspend(process);
394 DEBUG0("I've been resumed, let's keep going");
398 m_task_t dummy = SIMIX_TASK_UNINITIALIZED;
399 char blocked_name[512];
400 snprintf(blocked_name,512,"blocked [%s] (%s:%s)",
401 info, process->name, process->simdata->host->name);
403 XBT_IN1(": max_duration=%g",max_duration);
405 dummy = MSG_task_create(blocked_name, 0.0, 0, NULL);
407 PAJE_PROCESS_PUSH_STATE(process,"B",NULL);
409 process->simdata->blocked=1;
410 __MSG_task_execute(process,dummy);
411 surf_workstation_resource->common_public->suspend(dummy->simdata->compute);
413 surf_workstation_resource->common_public->set_max_duration(dummy->simdata->compute,
415 __MSG_wait_for_computation(process,dummy);
416 MSG_task_destroy(dummy);
417 process->simdata->blocked=0;
419 if(process->simdata->suspended) {
420 DEBUG0("I've been suspended in the meantime");
421 SIMIX_process_suspend(process);
422 DEBUG0("I've been resumed, let's keep going");
425 PAJE_PROCESS_POP_STATE(process);
432 SIMIX_error_t __SIMIX_process_unblock(smx_process_t process)
434 simdata_process_t simdata = NULL;
435 simdata_action_t simdata_action = NULL;
437 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
440 simdata = process->simdata;
441 if(!(simdata->block_action)) {
442 xbt_assert0(0,"Process is not blocked !");
443 return SIMIX_WARNING;
445 simdata_action = simdata->block_action->simdata;
446 xbt_assert0(simdata->blocked,"Process not blocked");
447 surf_workstation_resource->common_public->resume(simdata_action->surf_action);
448 SIMIX_RETURN(SIMIX_OK);
451 simdata_process_t simdata = NULL;
452 simdata_task_t simdata_task = NULL;
454 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
457 XBT_IN2(": %s unblocking %s", SIMIX_process_self()->name,process->name);
459 simdata = process->simdata;
460 if(!(simdata->waiting_task)) {
461 xbt_assert0(0,"Process not waiting for anything else. Weird !");
463 return SIMIX_WARNING;
465 simdata_task = simdata->waiting_task->simdata;
467 xbt_assert0(simdata->blocked,"Process not blocked");
469 surf_workstation_resource->common_public->resume(simdata_task->compute);
475 int __SIMIX_process_isBlocked(smx_process_t process)
477 xbt_assert0(((process != NULL) && (process->simdata)), "Invalid parameters");
479 return (process->simdata->blocked);